This document describes the internationalization (i18n) system used in the Memos frontend, including supported languages, translation file structure, locale loading mechanisms, and how to add or modify translations.
The Memos frontend supports 49 locales with translation files managed as JSON resources. All supported locales are defined in web/src/i18n.ts6-50 as the locales array:
| Category | Locales |
|---|---|
| Common | en, zh-Hans, zh-Hant, ja, ko, fr, de, es, ru, tr, vi, pt-BR |
| European | bg, ca, cs, da, el, en-GB, et, fi, gl, hr, hu, it, lt, lv, nb, nl, pl, pt-PT, ro, sk, sl, sr, sv, uk |
| Asian & Other | ar, fa, hi, id, ka-GE, mr, th |
The system includes fallback logic for locale variants. For example, zh-HK and zh-TW fall back to zh-Hant, while zh falls back to zh-Hans web/src/i18n.ts52-56
Sources: web/src/i18n.ts6-56
The i18n system bridges the Natural Language Space (user-facing strings) to the Code Entity Space (i18next modules and React hooks).
i18n System Logic Flow
Architecture Summary:
The i18n system uses i18next with a custom lazy-loading backend that dynamically imports translation files only when needed. The LazyImportPlugin web/src/i18n.ts58-77 performs asynchronous imports from ./locales/${matchedLanguage}.json.
Key design decisions:
import() statements web/src/i18n.ts63 reducing initial bundle size.zh-HK → zh-Hant → en) web/src/i18n.ts52-56navigator web/src/i18n.ts84Sources: web/src/i18n.ts1-93 web/src/locales/en.json1-10
Translation files are JSON documents with a hierarchical namespace structure. Each file follows the same schema for consistency.
JSON Structure Hierarchy
Key Namespaces:
| Namespace | Purpose | Example Keys |
|---|---|---|
common | Frequently used terms across app | save, cancel, delete, confirm, settings web/src/locales/en.json80-182 |
memo | Memo-related UI strings | delete-confirm, visibility, comment.self web/src/locales/en.json224-263 |
editor | Memo editor interface | any-thoughts, save, saving, focus-mode web/src/locales/en.json187-218 |
message | Toast/notification messages | copied, deleted-successfully, archived-successfully web/src/locales/ko.json242-250 |
auth | Authentication pages | sign-in-tip, sign-up-tip, create-your-account web/src/locales/en.json17-41 |
attachment-library | Media management | tabs.media, labels.unused, actions.retry web/src/locales/en.json48-78 |
Translation keys support nested objects and variable interpolation using the {{variable}} syntax:
Access patterns in code:
t("editor.audio-recorder.title") → "Audio recorder" web/src/locales/en.json214t("common.sign-in-with", { provider: "GitHub" }) → "Sign in with GitHub" web/src/locales/en.json140 (Note: In some files, this is mapped as continue-with web/src/locales/en.json21).Sources: web/src/locales/en.json21-214 web/src/locales/zh-Hans.json88-210
The following diagram maps the loading flow from the i18n instance initialization to the dynamic file resolution.
Locale Loading Sequence
Loading Flow Details:
Initialization web/src/i18n.ts79-93:
LazyImportPlugin and initReactI18next.navigator web/src/i18n.ts84en web/src/i18n.ts91Lazy Import Plugin web/src/i18n.ts58-77:
BackendModule.read.findNearestMatchedLanguage to resolve variants like en-US to en web/src/i18n.ts62import() which triggers a network request for the JSON chunk web/src/i18n.ts63 If a specific locale fails to load, it attempts to load en.json as a hard fallback web/src/i18n.ts68Sources: web/src/i18n.ts58-93 web/src/utils/i18n.ts
1. Add Locale Code
Add the locale identifier to the locales array in alphabetical order in web/src/i18n.ts6-50
2. Create Translation File
Create web/src/locales/{locale}.json using en.json as the reference template. The file must include all core namespaces such as about, auth, common, editor, inbox, markdown, memo, and message.
3. Translate String Values
en.json).{{variable}}.Example from ja.json web/src/locales/ja.json102:
4. Handle Variants
For locale variants, add fallback configuration in the fallbacks object web/src/i18n.ts52-56
Sources: web/src/i18n.ts6-56 web/src/locales/en.json1-183 web/src/locales/ja.json1-237
The useTranslate hook is the primary way to access localized strings. It provides the t function for translation lookup.
The audio recorder subsystem uses specific keys for state management and user feedback web/src/locales/en.json225-257:
editor.audio-recorder.recording: "Recording" web/src/locales/zh-Hans.json192editor.audio-recorder.transcribing: "Transcribing..." web/src/locales/zh-Hans.json204editor.audio-recorder.error: "Microphone unavailable" web/src/locales/zh-Hans.json183Sources: web/src/locales/en.json187-218 web/src/locales/zh-Hans.json178-208
Language selection is handled by the LocaleSelect and LocalePicker components.
locales array exported from web/src/i18n.ts web/src/i18n.ts6-50Refresh this wiki
This wiki was recently refreshed. Please wait 6 days to refresh again.