mirror of
https://github.com/mattermost/mattermost.git
synced 2026-11-01 09:28:09 -06:00
* Report a catalog that cannot be read or is not an object, rather than crash A locale catalog whose top level was null, a number or a string made check_icu.mjs throw, and an array was checked as if it were an empty catalog; a catalog it could not read threw too. Either way the run ended at that file, so the catalogs after it went unchecked. Each is now an error against its file, and the rest are checked. en.json is held to the same shape: an array or a number left nothing to check, and every catalog passed. mmgotool i18n verify already reports each of these and carries on. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> * Keep a copy of go-i18n's server plural forms, pinned by a Go test The translation rules check a server plural map in Node, before the catalog is written, so they need go-i18n's plural categories for each locale. i18n/scripts/lib/server_plurals.json holds them, and a Go test fails if it disagrees with go-i18n for any server catalog, or lists a locale with none. The server translation job runs the test, so a PR that adds a server locale has to add it to the table. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> * Hold a new translation to the structural rules, and test them in CI i18n/scripts/lib/rules.mjs checks one translation, before it is written to a catalog. Webapp messages go through icu_rules.mjs, the code check_icu.mjs runs, so the two cannot disagree; what CI tolerates as a warning in the catalogs as they stand is an error for new work, except an arrow in a right-to-left locale, which is soft. Server messages get the per-string checks mmgotool i18n verify makes, with plural forms held to go-i18n's table rather than CLDR. icu_rules.mjs gains plural-unused-category, a plural arm the locale never selects. check_icu.mjs does not report it: it is dead text, not something a user sees, so it is left to the pipeline. A new job runs the pipeline's tests, and the workflow now runs for a change under i18n/. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> * Flag a translation that leaves out a name the glossary keeps in English A doNotTranslate term (Mattermost, GitLab, Markdown) dropped from a translation is a soft finding: usually a mistake, sometimes a sentence that is better leaving the brand implicit, so it lands only with a stated reason. Channels, Playbooks, Boards and Calls are product names that are also ordinary English words. The English reads the same whether a string names the product or starts a sentence about channels, so they are marked commonWord and not flagged; the translator decides from the description. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> * Catch English left untranslated A translation identical to its English is an error once the English has three ordinary lowercase words, a sentence nobody translated, and soft below that, where it may be a name or a word the language shares with English. In a language not written in Latin script, lowercase English words kept from the source are soft too. Only words a translator would translate count: ICU arguments and tags, template actions, URLs, email addresses, glossary names, quoted values and anything shaped like an identifier are left out. en-* locales are not checked. icu_rules.mjs exports its parser and options, so the rules read a message's literal text the way check_icu.mjs parses it. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> * Flag the wrong form of address i18n/style.json records, for each locale where the choice matters, how its catalogs address the user, formally or informally, and the pronouns that would mean the other. A translation that uses one is soft: a pronoun can be quoted text or mean someone else, as German "Sie" can at the start of a sentence, so a stated reason lets it land. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> * Check the glossary and style files in CI The translation rules read i18n/glossary/ and i18n/style.json, so a malformed entry would quietly change what a translation is held to. check_glossary.mjs holds them to their shape: canonical JSON, the known fields only, one owner per term or alias, a glossary file for exactly the locales with catalogs, terms in en.json order, a doNotTranslate term's target the term itself, and no pronoun both used and avoided. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> * Run every translation check through make i18n-verify-all CI ran the i18n checks as three jobs of inline commands: the webapp checker, make i18n-verify plus the plural-table test in the build container, and the pipeline's tests and glossary check. Nobody could run that set locally without copying it out of the workflow. make i18n-verify-all in server/ now runs all of them, and CI runs only that, in one job on the runner. Go comes from setup-go at mmgotool's go.mod version, as Tools CI does, so the build container, and with it the Docker Hub secrets and id-token permission it needed, are gone. The workflow also runs when server/Makefile changes. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> * Run make i18n-verify-all in the build environment again The previous commit swapped the build environment for setup-go, for no reason that holds up: the image has the Node .nvmrc pins as well as the Go mmgotool needs, it reuses the Go caches Server CI warms, and it mounts the checkout, so it sees the node_modules webapp-setup installs. Server CI builds and checks in it too. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> * Drop comments that only restate the code Each said what the line under it already says: a path list, a setup step, a target its help text describes, a function its name and body describe, and how to run tests the Makefile now runs. Comments that give a reason the code cannot show stay. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> * Fail on a glossary or style file that is not a JSON object readGlossary and readStyle read an array or a number as an empty glossary or no style, which turned the do-not-translate and form-of- address rules off without a word, and threw an unrelated TypeError on null. check_glossary.mjs rejects these shapes in CI, but the rules read the files on their own. Each is now an error naming the file; a file that does not exist still means none. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>