Skip to content

Fix/return data contracts - #114

Merged
andrewtavis merged 9 commits into
scribe-org:mainfrom
DeleMike:fix/return-data-contracts
Oct 20, 2026
Merged

andrewtavis merged 9 commits into
scribe-org:mainfrom
DeleMike:fix/return-data-contracts

Conversation

@DeleMike

@DeleMike DeleMike commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Contributor checklist

  • This pull request is on a separate branch and not the main branch
  • I have ran the ./pre-commit executable as well as make lint and have fixed all reported issues

Description

  • update_data.sh now copies the exported contracts into the server's contracts/ folder. They're copied into a temporary folder first, so a failed copy keeps the current contracts.
  • update_scribe_data.yml also packages the contracts with the SQLite packs, uploads both as the artifact, sends both to Toolforge, and replaces ./contracts during deployment. A failed extraction keeps the current contracts.
  • /contracts returns 503 "Data contracts are not available" if the contracts are missing, instead of a generic 500.
  • Downloads are named by language: contracts_en.yaml, contracts_de.yaml, or contracts.yaml for all languages.

Testing

  • I ran the new update_data.sh step with real scribe-data ec output, and the Toolforge extraction with a good and a corrupt package.
  • I ran the server locally: /contracts, ?lang=en and ?lang=de return 200 with the expected file names, and 503 without contracts.

Related issue

@DeleMike DeleMike self-assigned this Oct 19, 2026
@DeleMike
DeleMike requested a review from andrewtavis October 19, 2026 10:58
@DeleMike

Copy link
Copy Markdown
Member Author

Hi @andrewtavis, could you review this when you have a moment? 😊

The contracts endpoint is working again on Toolforge. You can test it here:

- English: https://scribe-server.toolforge.org/api/v1/contracts?lang=en
- All languages: https://scribe-server.toolforge.org/api/v1/contracts

Both return the contracts as YAML, exactly as exported by Scribe-Data. For now, the contracts on Toolforge were copied over manually from Scribe-Data main. With this PR, update_data.sh copies the exported contracts to the server and the monthly update_scribe_data.yml run deploys them to Toolforge, so they stay in sync with the data. Once it's merged and the server is rebuilt, downloads are also named by language (contracts_en.yaml, or contracts.yaml for all).

This means @angrezichatterbox can now use the contracts endpoint for Android.

The root cause of this issue is #70; I didn't add this process. I was focused on removing the hardcoded contracts.

@DeleMike DeleMike added the -priority- High priority label Oct 19, 2026
@andrewtavis andrewtavis added -next release- Included in the next release and removed -priority- High priority labels Oct 19, 2026
@andrewtavis

andrewtavis commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Hey @DeleMike and @angrezichatterbox: I think that the changes here are almost there :) One thing I'm wondering about though is the contracts.yaml file as this isn't something that we'd be able to use in the apps in the current way they're written.

Quick note, @DeleMike: https://scribe-server.toolforge.org/api/v1/contracts?lang=en returns contracts.yaml with only en included, not contracts_en.yaml as I believe is expected. That contracts.yaml file further starts with contracts: at the top, which I don't believe is intended (my expectation is that it should just be the English contract from Scribe-Data).

My suggestion:

  • Switch the language endpoints so that we're only getting a single contract file that's exactly what Scribe-Data is producing - i.e. en.yaml that only has the English contract
  • Switch the v1/contracts global endpoint to get a zipped directory with all data contracts

In this way we can always get the contract with individual data packs, and we have the global endpoint for all of them that could be unzipped in an application if for some reason in the future we want to get all contracts (or for instance we want to get more than one, so we zip the ones we want and send that).

Does this make sense? Please let me know as I'm also not 100%! :)

@DeleMike

Copy link
Copy Markdown
Member Author

Thanks @andrewtavis for the feedback. I think for contracts_en.yaml, I added the change local but it seems it might not matter.

I will sit back later and digest all of your comments and then extend the functionality of this PR.

BTW, json is always better for clients. I will try to see what works and we will reconvene here.

Thanks!

@andrewtavis

andrewtavis commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

I'm sure it'd be fine for us to convert the contracts into a JSON file for the request and then back into YAML once they reach the clients, @DeleMike! It's just important that we maintain them as YAML files so they're more human readable.

@andrewtavis

andrewtavis commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

So we can of course have v1/contracts?lang=en send en.json that's been converted from en.yaml, and similarly we can send a zipped directory data_contracts with all the contracts as JSONs come from v1/contracts.

@DeleMike

Copy link
Copy Markdown
Member Author

I'm sure it'd be fine for us to convert the contracts into a JSON file for the request and then back into YAML once they reach the clients, @DeleMike! It's just important that we maintain them as YAML files so they're more human readable.

Totally agree, @andrewtavis! I will apply all suggestions here. Thank you :)

@andrewtavis

Copy link
Copy Markdown
Member

I think that sending JSON for the v1/contracts?lang=en makes a lot of sense, but do give the idea of a zipped directory a thought and flag if it's not sensible. I'm just trying to avoid a contracts.json/contracts.yaml file that we won't actually be using in the clients.

@andrewtavis

Copy link
Copy Markdown
Member

As the clients will be hard coded to fulfill the contracts that are specific to the language, and the extra keys for contracts: en: ... in the contracts.yaml will thus break things.

@DeleMike

Copy link
Copy Markdown
Member Author

No problem. I will update all my decisions here. 🙌🏾

@DeleMike

Copy link
Copy Markdown
Member Author

Hi @andrewtavis , been researching this for a few hours, and when I checked Scribe-Android, its "download all languages" loops over languages and calls GET data/{lang} per language, and contracts are loaded per language (loadContract("de") => de.yaml). So the natural fit for the app is fetching GET contracts?lang=de -> de.json alongside each language's data, and "download all" would work as is. I don't think the app would use the zip as will be returned by GET contracts -> data_contracts -> ls data_contracts -> en.json de.json ... ru.json

I'd still add the zip at GET /contracts for tooling, e.g. to download all contracts and update the files bundled in the apps.

Also, currently the Android DataContract model uses the old flat format (numbers, genders, conjugations at the top level), while the Scribe-Data 6.0.5 data contracts nest them (nouns.genders, nouns.numbers.1.singular/plural, verbs.conjugations) so the model will need updating when switching to the API.

@DeleMike

Copy link
Copy Markdown
Member Author

Hi @andrewtavis, I've updated this based on your suggestions:

  • GET /api/v1/contracts?lang=en => en.json: only the English contract, exactly as Scribe-Data exports it, as JSON with the YAML's key order kept (no contracts: / en: wrapper).
  • GET /api/v1/contracts => data_contracts.zip: a data_contracts/ directory with one <lang>.json per contract, each byte-identical to the single-language response.

The contracts stay as YAML on the server and are only converted when sent.

Please note that Toolforge will show the new responses once this is merged and the server is rebuilt. Please test on local.

What do you think?

See example of output:

GET /api/v1/contracts?lang=en response
{
  "nouns": {
    "genders": {
      "canonical": [],
      "feminines": [],
      "masculines": [],
      "commons": [],
      "neuters": []
    },
    "numbers": {
      "1": {
        "singular": "singular",
        "plural": "plural"
      }
    }
  },
  "verbs": {
    "conjugations": {
      "1": {
        "sectionTitle": "Present",
        "tenses": {
          "1": {
            "tenseTitle": "Pr. Simple",
            "tenseForms": {
              "1": {
                "label": "I/you/plural",
                "value": "simplePresent"
              },
              "2": {
                "label": "he/she/it",
                "value": "simplePresentThirdPersonSingular"
              }
            }
          },
          "2": {
            "tenseTitle": "Pr. Perfect",
            "tenseForms": {
              "1": {
                "label": "I/you/plural",
                "value": "[have] englishPastParticiple"
              },
              "2": {
                "label": "he/she/it",
                "value": "[has] englishPastParticiple"
              }
            }
          },
          "3": {
            "tenseTitle": "Pr. Continuous",
            "tenseForms": {
              "1": {
                "label": "I",
                "value": "[am] presentParticiple"
              },
              "2": {
                "label": "you/plural",
                "value": "[are] presentParticiple"
              },
              "3": {
                "label": "he/she/it",
                "value": "[is] presentParticiple"
              }
            }
          },
          "4": {
            "tenseTitle": "Pr. Perf. Continuous",
            "tenseForms": {
              "1": {
                "label": "I/you/plural",
                "value": "[have been] presentParticiple"
              },
              "2": {
                "label": "he/she/it",
                "value": "[has been] presentParticiple"
              }
            }
          }
        }
      },
      "2": {
        "sectionTitle": "Past",
        "tenses": {
          "1": {
            "tenseTitle": "Past Simple",
            "tenseForms": {
              "1": {
                "label": "all",
                "value": "simplePast"
              }
            }
          },
          "2": {
            "tenseTitle": "Past Perfect",
            "tenseForms": {
              "1": {
                "label": "all",
                "value": "[had] englishPastParticiple"
              }
            }
          },
          "3": {
            "tenseTitle": "Past Continuous",
            "tenseForms": {
              "1": {
                "label": "I/he/she/it",
                "value": "[was] presentParticiple"
              },
              "2": {
                "label": "you/plural",
                "value": "[were] presentParticiple"
              }
            }
          },
          "4": {
            "tenseTitle": "Past Perf. Continuous",
            "tenseForms": {
              "1": {
                "label": "all",
                "value": "[had been] presentParticiple"
              }
            }
          }
        }
      },
      "3": {
        "sectionTitle": "Future",
        "tenses": {
          "1": {
            "tenseTitle": "Fut. Simple",
            "tenseForms": {
              "1": {
                "label": "all",
                "value": "[will] infinitive"
              }
            }
          },
          "2": {
            "tenseTitle": "Fut. Perfect",
            "tenseForms": {
              "1": {
                "label": "all",
                "value": "[will have] englishPastParticiple"
              }
            }
          },
          "3": {
            "tenseTitle": "Fut. Continuous",
            "tenseForms": {
              "1": {
                "label": "all",
                "value": "[will be] presentParticiple"
              }
            }
          },
          "4": {
            "tenseTitle": "Fut. Perf. Continuous",
            "tenseForms": {
              "1": {
                "label": "all",
                "value": "[will have been] presentParticiple"
              }
            }
          }
        }
      },
      "4": {
        "sectionTitle": "Conditional",
        "tenses": {
          "1": {
            "tenseTitle": "Cond. Simple",
            "tenseForms": {
              "1": {
                "label": "all",
                "value": "[would] infinitive"
              }
            }
          },
          "2": {
            "tenseTitle": "Cond. Perfect",
            "tenseForms": {
              "1": {
                "label": "all",
                "value": "[would have] englishPastParticiple"
              }
            }
          },
          "3": {
            "tenseTitle": "Cond. Continuous",
            "tenseForms": {
              "1": {
                "label": "all",
                "value": "[would be] presentParticiple"
              }
            }
          },
          "4": {
            "tenseTitle": "Cond. Perf. Continuous",
            "tenseForms": {
              "1": {
                "label": "all",
                "value": "[would have been] presentParticiple"
              }
            }
          }
        }
      }
    }
  },
  "translations": {
    "wordType": {
      "sectionTitle": "Select translation word type",
      "adjective": {
        "displayValue": "adjective",
        "sectionTitle": "Select adjective translation"
      },
      "adverb": {
        "displayValue": "adverb",
        "sectionTitle": "Select adverb translation"
      },
      "article": {
        "displayValue": "article",
        "sectionTitle": "Select article translation"
      },
      "conjunction": {
        "displayValue": "conjunction",
        "sectionTitle": "Select conjunction translation"
      },
      "noun": {
        "displayValue": "noun",
        "sectionTitle": "Select noun translation"
      },
      "postposition": {
        "displayValue": "postposition",
        "sectionTitle": "Select postposition translation"
      },
      "preposition": {
        "displayValue": "preposition",
        "sectionTitle": "Select preposition translation"
      },
      "proper_noun": {
        "displayValue": "proper noun",
        "sectionTitle": "Select proper noun translation"
      },
      "pronoun": {
        "displayValue": "pronoun",
        "sectionTitle": "Select pronoun translation"
      },
      "verb": {
        "displayValue": "verb",
        "sectionTitle": "Select verb infinitive"
      }
    }
  }
}

See for German(de):

GET /api/v1/contracts?lang=de response
{
  "nouns": {
    "genders": {
      "canonical": [
        "gender"
      ],
      "feminines": [],
      "masculines": [],
      "commons": [],
      "neuters": []
    },
    "numbers": {
      "1": {
        "singular": "nominativeSingular",
        "plural": "nominativePlural"
      }
    }
  },
  "verbs": {
    "conjugations": {
      "1": {
        "sectionTitle": "Präsens",
        "tenses": {
          "1": {
            "tenseTitle": "Präsens",
            "tenseForms": {
              "1": {
                "label": "ich",
                "value": "indicativePresentFirstPersonSingular"
              },
              "2": {
                "label": "du",
                "value": "indicativePresentSecondPersonSingular"
              },
              "3": {
                "label": "er/sie/es",
                "value": "indicativePresentThirdPersonSingular"
              },
              "4": {
                "label": "wir",
                "value": "indicativePresentFirstPersonPlural"
              },
              "5": {
                "label": "ihr",
                "value": "indicativePresentSecondPersonPlural"
              },
              "6": {
                "label": "sie/Sie",
                "value": "indicativePresentThirdPersonPlural"
              }
            }
          }
        }
      },
      "2": {
        "sectionTitle": "Preterite",
        "tenses": {
          "1": {
            "tenseTitle": "Preterite",
            "tenseForms": {
              "1": {
                "label": "ich",
                "value": "indicativePreteriteFirstPersonSingular"
              },
              "2": {
                "label": "du",
                "value": "indicativePreteriteSecondPersonSingular"
              },
              "3": {
                "label": "er/sie/es",
                "value": "indicativePreteriteThirdPersonSingular"
              },
              "4": {
                "label": "wir",
                "value": "indicativePreteriteFirstPersonPlural"
              },
              "5": {
                "label": "ihr",
                "value": "indicativePreteriteSecondPersonPlural"
              },
              "6": {
                "label": "sie/Sie",
                "value": "indicativePreteriteThirdPersonPlural"
              }
            }
          }
        }
      },
      "3": {
        "sectionTitle": "Perfekt",
        "tenses": {
          "1": {
            "tenseTitle": "Perfekt",
            "tenseForms": {
              "1": {
                "label": "ich",
                "value": "{indicativePresentFirstPersonSingular auxiliaryVerb} pastParticiple"
              },
              "2": {
                "label": "du",
                "value": "{indicativePresentSecondPersonSingular auxiliaryVerb} pastParticiple"
              },
              "3": {
                "label": "er/sie/es",
                "value": "{indicativePresentThirdPersonSingular auxiliaryVerb} pastParticiple"
              },
              "4": {
                "label": "wir",
                "value": "{indicativePresentFirstPersonPlural auxiliaryVerb} pastParticiple"
              },
              "5": {
                "label": "ihr",
                "value": "{indicativePresentSecondPersonPlural auxiliaryVerb} pastParticiple"
              },
              "6": {
                "label": "sie/Sie",
                "value": "{indicativePresentThirdPersonPlural auxiliaryVerb} pastParticiple"
              }
            }
          }
        }
      }
    }
  },
  "translations": {
    "wordType": {
      "sectionTitle": "Übersetzungsworttyp auswählen",
      "adjective": {
        "displayValue": "Adjektiv",
        "sectionTitle": "Adjektiv Übersetzung auswählen"
      },
      "adverb": {
        "displayValue": "Adverb",
        "sectionTitle": "Adverb Übersetzung auswählen"
      },
      "article": {
        "displayValue": "Artikel",
        "sectionTitle": "Artikel Übersetzung auswählen"
      },
      "conjunction": {
        "displayValue": "Konjunktion",
        "sectionTitle": "Konjunktion Übersetzung auswählen"
      },
      "noun": {
        "displayValue": "Nomen",
        "sectionTitle": "Nomen Übersetzung auswählen"
      },
      "postposition": {
        "displayValue": "Postposition",
        "sectionTitle": "Postposition Übersetzung auswählen"
      },
      "preposition": {
        "displayValue": "Preposition",
        "sectionTitle": "Preposition Übersetzung auswählen"
      },
      "proper_noun": {
        "displayValue": "Eigenname",
        "sectionTitle": "Eigenname Übersetzung auswählen"
      },
      "pronoun": {
        "displayValue": "Pronomen",
        "sectionTitle": "Pronomen Übersetzung auswählen"
      },
      "verb": {
        "displayValue": "Verb",
        "sectionTitle": "Verb Übersetzung auswählen"
      }
    }
  },
  "prepositions": {
    "case": "grammaticalCase"
  },
  "declensions": {
    "1": {
      "sectionTitle": "Akkusativ Definitpronomen",
      "declensionForms": {
        "1": {
          "label": "M",
          "value": "den"
        },
        "2": {
          "label": "F",
          "value": "die"
        },
        "3": {
          "label": "N",
          "value": "das"
        },
        "4": {
          "label": "PL",
          "value": "die"
        }
      }
    },
    "2": {
      "sectionTitle": "Akkusativ Indefinitpronomen",
      "declensionForms": {
        "1": {
          "label": "M",
          "value": "einen"
        },
        "2": {
          "label": "F",
          "value": "eine"
        },
        "3": {
          "label": "N",
          "value": "ein"
        },
        "4": {
          "label": "PL",
          "value": "welche"
        }
      }
    },
    "3": {
      "sectionTitle": "Akkusativ Personalpronomen",
      "declensionForms": {
        "1": {
          "label": "ich",
          "value": "mich"
        },
        "2": {
          "label": "du/Sie",
          "displayValue": "dich/Sie",
          "title": "Formalität des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "informell",
              "value": "dich"
            },
            "2": {
              "label": "formell",
              "value": "Sie"
            }
          }
        },
        "3": {
          "label": "er/sie/es",
          "displayValue": "ihn/sie/es",
          "title": "Geschlecht des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "er",
              "value": "ihn"
            },
            "2": {
              "label": "sie",
              "value": "sie"
            },
            "3": {
              "label": "es",
              "value": "es"
            }
          }
        },
        "4": {
          "label": "wir",
          "value": "uns"
        },
        "5": {
          "label": "ihr",
          "value": "euch"
        },
        "6": {
          "label": "sie",
          "value": "sie"
        }
      }
    },
    "4": {
      "sectionTitle": "Akkusativ Possessivpronomen",
      "declensionForms": {
        "1": {
          "label": "ich",
          "displayValue": "mein*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "meinen"
            },
            "2": {
              "label": "F",
              "value": "meine"
            },
            "3": {
              "label": "N",
              "value": "mein"
            },
            "4": {
              "label": "PL",
              "value": "meine"
            }
          }
        },
        "2": {
          "label": "du/Sie",
          "displayValue": "dein*/Ihr*",
          "title": "Formalität des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "informell",
              "displayValue": "dein*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "deinen"
                },
                "2": {
                  "label": "F",
                  "value": "deine"
                },
                "3": {
                  "label": "N",
                  "value": "dein"
                },
                "4": {
                  "label": "PL",
                  "value": "deine"
                }
              }
            },
            "2": {
              "label": "formell",
              "displayValue": "Ihr*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "Ihren"
                },
                "2": {
                  "label": "F",
                  "value": "Ihre"
                },
                "3": {
                  "label": "N",
                  "value": "Ihr"
                },
                "4": {
                  "label": "PL",
                  "value": "Ihre"
                }
              }
            }
          }
        },
        "3": {
          "label": "er/sie/es",
          "displayValue": "sein*/ihr*/sein*",
          "title": "Geschlecht des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "er",
              "displayValue": "sein*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "seinen"
                },
                "2": {
                  "label": "F",
                  "value": "seine"
                },
                "3": {
                  "label": "N",
                  "value": "sein"
                },
                "4": {
                  "label": "PL",
                  "value": "seine"
                }
              }
            },
            "2": {
              "label": "sie",
              "displayValue": "ihr*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "ihren"
                },
                "2": {
                  "label": "F",
                  "value": "ihre"
                },
                "3": {
                  "label": "N",
                  "value": "ihr"
                },
                "4": {
                  "label": "PL",
                  "value": "ihre"
                }
              }
            },
            "3": {
              "label": "es",
              "displayValue": "sein*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "seinen"
                },
                "2": {
                  "label": "F",
                  "value": "seine"
                },
                "3": {
                  "label": "N",
                  "value": "sein"
                },
                "4": {
                  "label": "PL",
                  "value": "seine"
                }
              }
            }
          }
        },
        "4": {
          "label": "wir",
          "displayValue": "unser*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "unsren"
            },
            "2": {
              "label": "F",
              "value": "unsre"
            },
            "3": {
              "label": "N",
              "value": "unser"
            },
            "4": {
              "label": "PL",
              "value": "unsre"
            }
          }
        },
        "5": {
          "label": "ihr",
          "displayValue": "euer*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "euren"
            },
            "2": {
              "label": "F",
              "value": "eure"
            },
            "3": {
              "label": "N",
              "value": "euer"
            },
            "4": {
              "label": "PL",
              "value": "eure"
            }
          }
        },
        "6": {
          "label": "sie",
          "displayValue": "ihr*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "ihren"
            },
            "2": {
              "label": "F",
              "value": "ihre"
            },
            "3": {
              "label": "N",
              "value": "ihr"
            },
            "4": {
              "label": "PL",
              "value": "ihre"
            }
          }
        }
      }
    },
    "5": {
      "sectionTitle": "Akkusativ Demonstrativpronomen",
      "declensionForms": {
        "1": {
          "label": "M",
          "value": "diesen"
        },
        "2": {
          "label": "F",
          "value": "diese"
        },
        "3": {
          "label": "N",
          "value": "dieses"
        },
        "4": {
          "label": "PL",
          "value": "diese"
        }
      }
    },
    "6": {
      "sectionTitle": "Dativ Definitpronomen",
      "declensionForms": {
        "1": {
          "label": "M",
          "value": "dem"
        },
        "2": {
          "label": "F",
          "value": "der"
        },
        "3": {
          "label": "N",
          "value": "dem"
        },
        "4": {
          "label": "PL",
          "value": "den"
        }
      }
    },
    "7": {
      "sectionTitle": "Dativ Indefinitpronomen",
      "declensionForms": {
        "1": {
          "label": "M",
          "value": "einem"
        },
        "2": {
          "label": "F",
          "value": "einer"
        },
        "3": {
          "label": "N",
          "value": "einem"
        },
        "4": {
          "label": "PL",
          "value": "welchen"
        }
      }
    },
    "8": {
      "sectionTitle": "Dativ Personalpronomen",
      "declensionForms": {
        "1": {
          "label": "ich",
          "value": "mir"
        },
        "2": {
          "label": "du/Sie",
          "displayValue": "dir/Ihnen",
          "title": "Formalität des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "informell",
              "value": "dir"
            },
            "2": {
              "label": "formell",
              "value": "Ihnen"
            }
          }
        },
        "3": {
          "label": "er/sie/es",
          "displayValue": "ihm/ihr/ihm",
          "title": "Geschlecht des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "er",
              "value": "ihm"
            },
            "2": {
              "label": "sie",
              "value": "ihr"
            },
            "3": {
              "label": "es",
              "value": "ihm"
            }
          }
        },
        "4": {
          "label": "wir",
          "value": "uns"
        },
        "5": {
          "label": "ihr",
          "value": "euch"
        },
        "6": {
          "label": "sie",
          "value": "ihnen"
        }
      }
    },
    "9": {
      "sectionTitle": "Dativ Possessivpronomen",
      "declensionForms": {
        "1": {
          "label": "ich",
          "displayValue": "mein*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "meinem"
            },
            "2": {
              "label": "F",
              "value": "meiner"
            },
            "3": {
              "label": "N",
              "value": "meinem"
            },
            "4": {
              "label": "PL",
              "value": "meinen"
            }
          }
        },
        "2": {
          "label": "du/Sie",
          "displayValue": "dein*/Ihr*",
          "title": "Formalität des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "informell",
              "displayValue": "dein*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "deinem"
                },
                "2": {
                  "label": "F",
                  "value": "deiner"
                },
                "3": {
                  "label": "N",
                  "value": "deinem"
                },
                "4": {
                  "label": "PL",
                  "value": "deinen"
                }
              }
            },
            "2": {
              "label": "formell",
              "displayValue": "Ihr*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "Ihrem"
                },
                "2": {
                  "label": "F",
                  "value": "Ihrer"
                },
                "3": {
                  "label": "N",
                  "value": "Ihrem"
                },
                "4": {
                  "label": "PL",
                  "value": "Ihren"
                }
              }
            }
          }
        },
        "3": {
          "label": "er/sie/es",
          "displayValue": "sein*/ihr*/sein*",
          "title": "Geschlecht des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "er",
              "displayValue": "sein*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "seinem"
                },
                "2": {
                  "label": "F",
                  "value": "seiner"
                },
                "3": {
                  "label": "N",
                  "value": "seinem"
                },
                "4": {
                  "label": "PL",
                  "value": "seinen"
                }
              }
            },
            "2": {
              "label": "sie",
              "displayValue": "ihr*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "ihrem"
                },
                "2": {
                  "label": "F",
                  "value": "ihrer"
                },
                "3": {
                  "label": "N",
                  "value": "ihrem"
                },
                "4": {
                  "label": "PL",
                  "value": "ihren"
                }
              }
            },
            "3": {
              "label": "es",
              "displayValue": "sein*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "seinem"
                },
                "2": {
                  "label": "F",
                  "value": "seiner"
                },
                "3": {
                  "label": "N",
                  "value": "seinem"
                },
                "4": {
                  "label": "PL",
                  "value": "seinen"
                }
              }
            }
          }
        },
        "4": {
          "label": "wir",
          "displayValue": "unser*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "unsrem"
            },
            "2": {
              "label": "F",
              "value": "unsrer"
            },
            "3": {
              "label": "N",
              "value": "unsrem"
            },
            "4": {
              "label": "PL",
              "value": "unsren"
            }
          }
        },
        "5": {
          "label": "ihr",
          "displayValue": "euer*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "eurem"
            },
            "2": {
              "label": "F",
              "value": "eurer"
            },
            "3": {
              "label": "N",
              "value": "eurem"
            },
            "4": {
              "label": "PL",
              "value": "euren"
            }
          }
        },
        "6": {
          "label": "sie",
          "displayValue": "ihr*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "ihrem"
            },
            "2": {
              "label": "F",
              "value": "ihrer"
            },
            "3": {
              "label": "N",
              "value": "ihrem"
            },
            "4": {
              "label": "PL",
              "value": "ihren"
            }
          }
        }
      }
    },
    "10": {
      "sectionTitle": "Dativ Demonstrativpronomen",
      "declensionForms": {
        "1": {
          "label": "M",
          "value": "diesem"
        },
        "2": {
          "label": "F",
          "value": "dieser"
        },
        "3": {
          "label": "N",
          "value": "diesem"
        },
        "4": {
          "label": "PL",
          "value": "diesen"
        }
      }
    },
    "11": {
      "sectionTitle": "Genitiv Definitpronomen",
      "declensionForms": {
        "1": {
          "label": "M",
          "value": "des"
        },
        "2": {
          "label": "F",
          "value": "der"
        },
        "3": {
          "label": "N",
          "value": "des"
        },
        "4": {
          "label": "PL",
          "value": "der"
        }
      }
    },
    "12": {
      "sectionTitle": "Genitiv Indefinitpronomen",
      "declensionForms": {
        "1": {
          "label": "M",
          "value": "eines"
        },
        "2": {
          "label": "F",
          "value": "einer"
        },
        "3": {
          "label": "N",
          "value": "eines"
        },
        "4": {
          "label": "PL",
          "value": "welcher"
        }
      }
    },
    "13": {
      "sectionTitle": "Genitiv Personalpronomen",
      "declensionForms": {
        "1": {
          "label": "ich",
          "value": "meiner"
        },
        "2": {
          "label": "du/Sie",
          "displayValue": "deiner/Ihrer",
          "title": "Formalität des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "informell",
              "value": "deiner"
            },
            "2": {
              "label": "formell",
              "value": "Ihrer"
            }
          }
        },
        "3": {
          "label": "er/sie/es",
          "displayValue": "seiner/ihrer/seiner",
          "title": "Geschlecht des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "er",
              "value": "seiner"
            },
            "2": {
              "label": "sie",
              "value": "ihrer"
            },
            "3": {
              "label": "es",
              "value": "seiner"
            }
          }
        },
        "4": {
          "label": "wir",
          "value": "unser"
        },
        "5": {
          "label": "ihr",
          "value": "euer"
        },
        "6": {
          "label": "sie",
          "value": "ihrer"
        }
      }
    },
    "14": {
      "sectionTitle": "Genitiv Possessivpronomen",
      "declensionForms": {
        "1": {
          "label": "ich",
          "displayValue": "mein*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "meines"
            },
            "2": {
              "label": "F",
              "value": "meiner"
            },
            "3": {
              "label": "N",
              "value": "meines"
            },
            "4": {
              "label": "PL",
              "value": "meiner"
            }
          }
        },
        "2": {
          "label": "du/Sie",
          "displayValue": "dein*/Ihr*",
          "title": "Formalität des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "informell",
              "displayValue": "dein*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "deines"
                },
                "2": {
                  "label": "F",
                  "value": "deiner"
                },
                "3": {
                  "label": "N",
                  "value": "deines"
                },
                "4": {
                  "label": "PL",
                  "value": "deiner"
                }
              }
            },
            "2": {
              "label": "formell",
              "displayValue": "Ihr*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "Ihres"
                },
                "2": {
                  "label": "F",
                  "value": "Ihrer"
                },
                "3": {
                  "label": "N",
                  "value": "Ihres"
                },
                "4": {
                  "label": "PL",
                  "value": "Ihrer"
                }
              }
            }
          }
        },
        "3": {
          "label": "er/sie/es",
          "displayValue": "sein*/ihr*/sein*",
          "title": "Geschlecht des Subjekts?",
          "declensionForms": {
            "1": {
              "label": "er",
              "displayValue": "sein*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "seines"
                },
                "2": {
                  "label": "F",
                  "value": "seiner"
                },
                "3": {
                  "label": "N",
                  "value": "seines"
                },
                "4": {
                  "label": "PL",
                  "value": "seiner"
                }
              }
            },
            "2": {
              "label": "sie",
              "displayValue": "ihr*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "ihres"
                },
                "2": {
                  "label": "F",
                  "value": "ihr"
                },
                "3": {
                  "label": "N",
                  "value": "ihres"
                },
                "4": {
                  "label": "PL",
                  "value": "ihr"
                }
              }
            },
            "3": {
              "label": "es",
              "displayValue": "sein*",
              "title": "Geschlecht des Objekts?",
              "declensionForms": {
                "1": {
                  "label": "M",
                  "value": "seines"
                },
                "2": {
                  "label": "F",
                  "value": "seiner"
                },
                "3": {
                  "label": "N",
                  "value": "seines"
                },
                "4": {
                  "label": "PL",
                  "value": "seiner"
                }
              }
            }
          }
        },
        "4": {
          "label": "wir",
          "displayValue": "unser*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "unsres"
            },
            "2": {
              "label": "F",
              "value": "unsrer"
            },
            "3": {
              "label": "N",
              "value": "unsres"
            },
            "4": {
              "label": "PL",
              "value": "unsrer"
            }
          }
        },
        "5": {
          "label": "ihr",
          "displayValue": "euer*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "eures"
            },
            "2": {
              "label": "F",
              "value": "eurer"
            },
            "3": {
              "label": "N",
              "value": "eures"
            },
            "4": {
              "label": "PL",
              "value": "eurer"
            }
          }
        },
        "6": {
          "label": "sie",
          "displayValue": "ihr*",
          "title": "Geschlecht des Objekts?",
          "declensionForms": {
            "1": {
              "label": "M",
              "value": "ihres"
            },
            "2": {
              "label": "F",
              "value": "ihrer"
            },
            "3": {
              "label": "N",
              "value": "ihres"
            },
            "4": {
              "label": "PL",
              "value": "ihrer"
            }
          }
        }
      }
    },
    "15": {
      "sectionTitle": "Genitiv Demonstrativpronomen",
      "declensionForms": {
        "1": {
          "label": "M",
          "value": "dieses"
        },
        "2": {
          "label": "F",
          "value": "dieser"
        },
        "3": {
          "label": "N",
          "value": "dieses"
        },
        "4": {
          "label": "PL",
          "value": "dieser"
        }
      }
    }
  }
}

@andrewtavis

Copy link
Copy Markdown
Member

Also, currently the Android DataContract model uses the old flat format (numbers, genders, conjugations at the top level), while the Scribe-Data 6.0.5 data contracts nest them (nouns.genders, nouns.numbers.1.singular/plural, verbs.conjugations) so the model will need updating when switching to the API.

Thanks for bringing this up, @DeleMike! We have scribe-org/Scribe-Android#715 that's fixing scribe-org/Scribe-Android#714 that should finalize this once this PR is in 😊

@andrewtavis andrewtavis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: All's looking amazing here, @DeleMike! 🤩 Can't wait to see how this goes in scribe-org/Scribe-Android#715! 😊

@andrewtavis
andrewtavis merged commit fc5285a into scribe-org:main Oct 20, 2026
3 checks passed
@DeleMike

Copy link
Copy Markdown
Member Author

Glad to have this in!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

-next release- Included in the next release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Contracts endpoint returns 500 because data contracts are never copied to the server Add handler tests for GET /api/v1/contracts

2 participants