Adding a new locale
Once the Weblate translations for a single language have reached ~50% in coverage, it's time to add it to the application.
To do so:
- In
packages/commonslook fori18n.tsand add a new entry toUNSORTED_LOCALESfor the language. - In
packages/commonslook fordayjs.tsand add a mapping for the new language inDAYJS_LOADER. Sort the entire list. - In
apps/client, look forcollections/calendar/index.tsxand modifyLOCALE_MAPPINGSto add support to the new language. - In
apps/client, look forwidgets/type_widgets/canvas/i18n.tsand modifyLANGUAGE_MAPPINGS. A unit test ensures that the language is actually loadable. - In
packages/ckeditor5, look fori18n.tsand modifyLOCALE_MAPPINGS. The import validation should already check if the new value is supported by CKEditor, and there's also a test to ensure it. The test ini18n.spec.tspins every locale by hand rather than iterating them, so add the new one there as well. - In
apps/client, look forwidgets/type_widgets/spreadsheet/locales.tsand modifyUNIVER_LOCALES, either with a source (if Univer ships a bundle for the language) or with an explicitnullto fall back to English. Every preset inSPREADSHEET_PRESET_PACKAGESmust have a bundle for the locale, whichlocales.spec.tschecks. - Locale mappings for PDF.js might need adjustment. To do so, in
packages/pdfjs-viewer/scripts/build.tsthere isLOCALE_MAPPINGS. No entry is needed when the locale'selectronLocalealready names a directory underpackages/pdfjs-viewer/viewer/locale.
Steps 1 to 6 are keyed by DISPLAYABLE_LOCALE_IDS, so pnpm typecheck reports each one still missing after step 1.
The website#
The website tracks its own Weblate component and its own list, so a locale added to the application above is not offered on triliumnotes.org until it is added there too.
- In
apps/website, look forlocales.tsand add an entry toLOCALES, using the language's own name and settingrtlwhere it applies. The id must match the folder underapps/website/src/translations, which Weblate creates. - A locale carrying a region, such as
pt-BR, is resolved bymapLocale()ini18n.tsby matchingLOCALES, so it needs no further mapping. Chinese is the exception: it is selected by script, which browsers report only through the region, andmapLocale()special-cases it.
The coverage gate#
scripts/translation/check-translation-coverage.ts fails CI once Weblate reports a language above 50% that is missing from either list. It runs on the weblate:* branches, so the pull request that brings the translations in is where it fires.
The gate only catches a language that is translated but not offered. It does not notice one that is offered and has since fallen behind, and it does not check that the locale renders — only that the id is listed.