Localization guide
April 23, 2026 ยท View on GitHub
This guide will help you contribute translations to Zen.
Overview of the localization system
- Zen uses the i18next framework for localization, as well as react-i18next for easy integration with React.
- Translation files are stored as JSON files in the
frontend/src/i18n/localesdirectory. - The main language is English, and the default locale is
en-US. - Zen uses locales rather than languages. Learn more about the difference.
Currently supported locales
Currently supported locales can be found in the LOCALE_LABELS array in frontend/src/i18n/index.ts.
Adding a new locale
To add a new locale to Zen, you'll need to:
- Fork the repository
- Set up your development environment
- Create a new translation file
- Update the i18n configuration
- Test your translations
- Submit a Pull Request
Step 1: Fork the repository
Follow these instructions to create a fork of Zen.
Step 2: Set up your development environment
- Install Go, Node.js with npm, Wails, and optionally Task as described in requirements.md
- In the project root directory, run
wails dev(ortaskif you have Task installed) to start the development server
Step 3: Create a new translation file
- Copy the English template at
en-US.jsonto a new file named according to your locale code (e.g.,de-DE.jsonfor German) - Translate all strings in the new file, keeping the JSON structure intact
Step 4: Update the i18n configuration
You'll need to modify two files:
- In
frontend/i18next.config.ts, add your locale code to thelocalesarray:
locales: ['en-US', ..., 'your-locale-code'],
-
Add an import for your translation file:
import aaAA from './locales/aa-AA.json'; // Replace aa-AA with your locale code -
Add your locale to the
SUPPORTED_LOCALESarray. Since a user's preferred locale may not include a region code, include both the base language and the full locale code:export const SUPPORTED_LOCALES = [ ..., // Existing locales 'aa', 'aa-AA', ] as const; -
Add a label for your locale to the
LOCALE_LABELSarray:export const LOCALE_LABELS: LocaleItem[] = [ ..., // Existing labels { value: 'aa-AA', label: 'Lingua AA' }, ]; -
Add your translation to the
resourcesobject in theinitI18nfunction. Since a user's preferred locale may not include a region code, you should also provide a fallback for the base language (e.g.,deforde-DE).return i18n.use(initReactI18next).init({ resources: { ..., 'aa': { translation: aaAA }, 'aa-AA': { translation: aaAA }, },
Step 5: Test your translations
- Navigate to Settings > Language to switch to your locale
- Test the application thoroughly with your locale enabled
Step 6: Submit a Pull Request
Follow this guide to submit a Pull Request with your changes.
Important
By contributing translations, you agree that your work will be licensed under the MIT License as used by the project.
Translation best practices
- Maintain variables: Keep special placeholders like
{{error}}intact - Preserve HTML: If the original string contains HTML tags, maintain them in your translation
- Test your translations: Run the application to verify your translations appear correctly
- Keep similar length: Try to keep translations similar in length to the original
Extracting translation keys
If you're a developer adding new text to the application, you can run:
task frontend:extract-translations
This will scan the source code and update the translation files with new keys.
Need help?
If you have any questions about the translation process, feel free to ask in the Discussions section of the GitHub repository, join our Discord server, or contact one of the project leads directly via email.