Memories / Documentation

On this page

Localization

The Flutter client and CLI support English (en), Simplified Chinese (zh), Japanese (ja), German (de), and French (fr). English is the fallback. Chinese system variants resolve to the Simplified Chinese translation.

Flutter

mobile/l10n.yaml configures Flutter's official localization generator. Add messages to mobile/lib/l10n/app_en.arb and translate the same keys in the other four ARB files. Use descriptive keys and named placeholders for entire messages; use ICU plurals when counts change the wording. Declare placeholder types in the English template. Run flutter gen-l10n after editing resources.

Widgets obtain strings through context.l10n. The library state refreshes its localization reference in didChangeDependencies, allowing asynchronous operations to use strings without retaining a BuildContext across awaits. flutter_localizations supplies Material/Cupertino labels and intl formats dates and counts. Keep English first in preferred-supported-locales so unknown system languages have a deterministic fallback. iOS declares supported languages in Runner/Info.plist.

The language menu is available before unlock. SharedPreferences stores only the non-secret language preference; system removes that preference. A failed save leaves the existing selection in place and displays a localized error. Language changes do not recreate the backend or alter the unlocked session. With no saved preference, system language changes update both the interface and font fallback while the app is running. A saved choice stays fixed until changed or reset to the system default.

Local errors are translated when displayed, so an existing banner changes with the language. Native errors use their stable codes for a translated fallback. Do not translate protocol values, identifiers, URLs, account metadata, user titles, bodies, tags, relationships, signed audit records, or secret values. Protected previews must continue using the explicit field allowlist and fixed masks in protected_cards.dart.

CLI

crates/cli/src/i18n.rs resolves the language before Clap renders help. Precedence:

  1. --lang en|zh|ja|de|fr, supported at the top level and on subcommands.
  2. Nonempty MEMORIES_LANG.
  3. The saved preference in the selected Memories home directory.
  4. The first nonempty LC_ALL, LC_MESSAGES, or LANG.
  5. Windows user locale, or English on other platforms without locale variables.
memories language zh       # Save a language for subsequent commands
memories language          # Show the saved choice and effective language
memories language system   # Clear the choice and follow the system

The non-secret preference is saved as language.txt under --home / MEMORIES_HOME (or the default memories data directory). Saving uses an atomic file replacement. It works before initialization and without a running daemon. No preference file is created just by detecting the system language. Missing, unreadable, or invalid preferences fall back to the system; failed writes report an error. Temporary --lang and MEMORIES_LANG overrides do not alter the file.

Locale variants such as ja_JP.UTF-8 normalize to their base language. Unsupported environment/system languages fall back to English. Explicit invalid --lang values are rejected by Clap. The initial scan stops at --, preserving language-like arguments passed to captured programs.

UTF-8 catalogs in crates/cli/locales/ are embedded at compile time; installed binaries do not need resource files alongside them. Catalog keys are the original English messages. Keep both full and period-stripped variants of Clap doc comments because short help removes the final period. Translate both short and long help. Add a catalog entry for every new CLI-owned error and prompt.

Use i18n::format for named placeholders. Substitution processes the template once, so user text containing braces cannot become another placeholder. Password and secret capture still use hidden input. USE and APPROVE remain literal confirmation tokens and must appear unchanged in their translated prompts.

JSON output keeps the existing version, field names, error codes, and exit status. Only human-facing messages are localized. Unmapped native/OS diagnostics retain their original text after a localized summary; Clap parsing diagnostics include a localized introduction and the original argument details. MCP schemas, tool names, and protocol messages remain stable and do not depend on CLI locale.

Validation

cargo test -p memories --locked
cd mobile
flutter gen-l10n
flutter analyze
flutter test

Rust tests cover all catalogs, help coverage, placeholder preservation, locale precedence, forwarded arguments, nested help, and localized errors with stable JSON fields. Flutter tests cover catalog parity, all five system locales, unsupported-locale fallback, preference persistence, session preservation, localized dialogs at phone widths, and masked protected-card previews.

On hosts with an HTTP proxy, exclude localhost, 127.0.0.1, and ::1 from the proxy while running widget tests; Flutter's local test WebSocket must connect directly. Device testing remains necessary to verify platform font fallback, native file pickers, and OAuth browser UI, whose language is managed by the OS or provider.