Overview
The i18n system is designed to work seamlessly across:- Backend: Go-based translation using
internal/i18npackage - Frontend: Vue.js with vue-i18n plugin
- Email Templates: Template variables for multilingual content
- Public Pages: Subscription forms, archive pages, unsubscribe pages
The same JSON language map is used by both the Go backend and Vue.js frontend, ensuring consistency across the application.
Language File Structure
All language files are located in the/i18n directory at the root of the project.
File Format
Each language file is a JSON file named with its language code:Language File Structure
Every language file must contain the following metadata fields:Currently Available Languages
listmonk currently supports 34+ languages:- English (en)
- Spanish (es)
- French (fr, fr-CA)
- German (de)
- Chinese (zh-CN, zh-TW)
- Portuguese (pt, pt-BR)
- Russian (ru)
- Japanese (jp)
- Korean (ko)
- Italian (it)
- Dutch (nl)
- Polish (pl)
- Turkish (tr)
- Czech (cs-cz)
- And many more…
Adding a New Language
Copy the English template
Start with the English language file as your template:For example, for Swedish:
Translate strings
Translate all the string values while keeping the keys unchanged:
Keep placeholder variables like
{error}, {name}, {count} exactly as they appear in the English version.Test your translation
- Rebuild the application:
make dist - Start listmonk:
./listmonk - Go to Settings → Language in the admin UI
- Select your new language from the dropdown
Submit your translation
See the Contributing Guide for instructions on submitting your translation as a pull request.
Translation Variables
Placeholder Syntax
Translation strings can contain placeholder variables that are substituted at runtime:{variableName}
Plural Forms
Use the pipe character| to separate singular and plural forms:
The backend’s
Tc() function and frontend’s $tc() function automatically select the correct form based on the count.Nested References
You can reference other translation keys within strings:Backend i18n Implementation
The Go backend uses a custom i18n package located atinternal/i18n/i18n.go.
Translation Functions
T() - Simple Translation
Ts() - Translation with Substitution
Tc() - Translation with Count (Pluralization)
Loading Language Files
Language files are automatically loaded from thei18n/ directory when embedded in the binary:
Frontend i18n Implementation
The frontend uses the vue-i18n plugin for translations.Using Translations in Vue Components
Simple Translation
Translation with Variables
Pluralization
Translation in JavaScript
Admin UI Translations
The admin interface is fully translatable. Key areas include:Navigation and Menus
Forms and Buttons
Messages and Notifications
Public Page Translations
Public-facing pages also support i18n:Subscription Forms
Archive Pages
Email Template Translations
Email templates can use translation variables:.L object provides access to the i18n context in templates:
.L.T- Simple translation.L.Ts- Translation with substitution.L.Tc- Translation with count
Testing Translations
Visual Testing
- Build the application with your translations:
make dist - Start listmonk:
./listmonk - Change language in Settings → Language
- Navigate through all admin pages to verify translations
Check for Missing Keys
Compare your language file with The counts should match (excluding the metadata fields).
en.json to ensure all keys are present:Test Variable Substitution
Verify that all placeholder variables work correctly by testing features that use them:
- Create/delete items (uses
{name}) - Trigger errors (uses
{error}) - View counts and stats (uses
{count})
Translation Workflow
For New Languages
- Check existing issues/PRs to avoid duplicate work
- Copy
en.jsonas your template - Translate all strings (this can take several hours)
- Test thoroughly in a local instance
- Submit a pull request
For Updating Existing Translations
- Compare with latest
en.jsonto find new/changed keys - Add missing translations
- Update any changed strings
- Test the changes
- Submit a pull request
Translation Guidelines
Best Practices
- Keep it concise: Admin interfaces work best with short, clear labels
- Maintain consistency: Use the same terms throughout for actions like “Save”, “Delete”, etc.
- Preserve variables: Never translate placeholder names like
{name},{error},{count} - Test thoroughly: Check all UI areas to ensure translations fit properly
- Consider context: Some English words have different meanings in different contexts
Common Translation Keys
Resources
- English base file:
i18n/en.json- Always the most up-to-date reference - Backend implementation:
internal/i18n/i18n.go - Frontend integration:
frontend/main.js(vue-i18n setup) - Translation tool: Use the UI at listmonk docs for easier translation workflow
Contributing Translations
Translations are a valuable contribution to listmonk! See the Contributing Guide for details on:- Submitting new language files
- Updating existing translations
- Translation review process
- Getting help from the community