l10n

Every interface text of the apps and the console in German (default) and English, plus the helpers every screen needs: problem code texts, formatting per locale, the language choice and the fixed term table.

Kind: Flutter package, a member of the Dart workspace at the repository root (resolution: workspace, publish_to: none). Specification: docs/spec/01-product.md section 9; rulings D-M4-06-1 to D-M4-06-7 in docs/DECISIONS.md.

Dependencies

Allowed members (docs/spec/15-client-architecture.md, 3.1; tools/arch-check/rules.yaml): none: no arrow of the diagram leaves this package. Every other member is out of reach; make arch fails on a dependency or an import of it. External packages: flutter_localizations (SDK), intl (formatting), timezone (IANA time zones for times in users.time_zone).

Further rules checked by make arch:

  • no native source (rule 4).

Layout

Path Content
l10n.yaml options of flutter gen-l10n (template app_en.arb, output lib/src/generated/)
lib/l10n/app_en.arb, lib/l10n/app_de.arb the texts; English is the template, German the default locale
lib/src/generated/ AppLocalizations, generated by flutter gen-l10n and checked in
lib/src/problem_text.dart problemText: the text of a server problem code
lib/src/formatting.dart L10nFormat: money, counts, percent, durations, times, relative days
lib/src/locale_resolution.dart resolveAppLocale: users.locale, else the system language, else German
lib/src/term_pair.dart, lib/src/term_table.dart the term table of 01 section 9 (term_table.dart is generated)
tool/term_table.dart the generator of term_table.dart
test/ the gates over the ARB files and the tests of the helpers

Add a text

  1. Add the key to lib/l10n/app_en.arb with an @key entry that has a description (where the text appears) and, for each argument, a placeholders entry with its type. Key names are lowerCamelCase with a screen or component prefix (liveBoxStateRunning, e1ServerAddressLabel).
  2. Add the same key to lib/l10n/app_de.arb with the German text and the same ICU arguments.
  3. Use ICU for plurals and selects ({count, plural, =1{...} other{...}}). A text that names a limit takes the value as an argument the caller fills from the configuration; never write the number into the text.
  4. Run flutter gen-l10n in this directory and commit the changed files in lib/src/generated/.
  5. Widgets read texts through AppLocalizations.of(context), never as literals. Agent content is never translated.

No en dash (U+2013), no em dash (U+2014) and no emoji in a text; use a hyphen or rephrase.

Gates

  • test/completeness_test.dart: every key in both files, the same ICU arguments, the same placeholder types, a description for every template key, no empty message.
  • test/arb_lint_test.dart: no dash and no emoji (Unicode Extended_Pictographic, regional indicators, U+FE0F) in a message; no dash in a description.
  • test/term_table_test.dart: lib/src/term_table.dart equals the table of 01 section 9, and an English message that uses an English term of the table has the German term of the same row in its German message. Exceptions need a reason in the test's exceptions map.
  • test/problem_text_test.dart: every code of x-problem-codes in docs/api/openapi.yaml has its own text.
  • make codegen-check (tools/ci/l10n_check.py): flutter gen-l10n in a temporary copy fails on an untranslated message and on a checked-in lib/src/generated/ that differs from the fresh generation.

Term table

The table between the language-check markers of 01 section 9 is the source. After a change there, run dart run tool/term_table.dart in this directory and commit lib/src/term_table.dart. A row with alternatives ("Forum, Beitrag" and "Forum, Post") gives one pair per alternative; a parenthesis in the German cell is a note.

Problem codes

problemText(l, code, reason: reason) maps every code of x-problem-codes to its message problem<Code>; a reason that 07 names selects problem<Code><Reason>. Any other code gives problemFallback with the code, so a code the app does not know yet stays visible. A new code in docs/api/openapi.yaml needs its message in both ARB files and a case in lib/src/problem_text.dart in the same change, or test/problem_text_test.dart fails.

Formatting

L10nFormat(locale) formats per app locale: money(1.84, 'USD') is 1,84 USD in German and USD 1.84 in English, with a non-breaking space; elapsed is the running clock (4:12), durationShort the finished duration (28 min, 2 h 5 min); time and relativeDay take the IANA time zone of the person and, for relativeDay, the current time from the caller.

Run from the repository root: make lint test coverage arch codegen-check COMPONENTS=apps. The API pages come from make docs (Dart API reference).

Libraries

l10n
Every interface text of the apps and the console in German (default) and English.