Overview
Proton WebClients usesttag for internationalization and the @proton/i18n package for translation management. Translations are managed through Crowdin and extracted from the codebase.
Translation System
ttag
JavaScript i18n library for marking translatable strings
@proton/i18n
CLI tool for extracting, validating, and managing translations
Crowdin
Translation management platform for collaborating with translators
gettext
PO file format for storing translations
proton-i18n CLI
The@proton/i18n package provides the proton-i18n command-line tool:
Building i18n Tools
Before using i18n commands, build the i18n package:The build script runs automatically via Turbo when needed by dependent tasks.
Translation Workflow
1. Extract Translations
Extract translatable strings from source code:- Mail
- Drive
- Calendar
- Pass
Extraction creates or updates
.po files in the po/ directory.2. Validate Translations
Validate translation strings for common issues:- Lint Functions
- Context Validation
Validate that translatable strings follow best practices:This runs:Can also target specific directories:
3. Update Crowdin
Upload translations to Crowdin for translator collaboration:4. Get Latest Translations
Download latest translations from Crowdin:This downloads updated
.po files from Crowdin into your po/ directory.Common i18n Scripts
All applications follow these script conventions:| Script | Description | Command |
|---|---|---|
i18n:extract:web | Extract strings | proton-i18n extract |
i18n:validate | Validate lint functions | proton-i18n validate lint-functions |
i18n:validate:context:web | Validate context | proton-i18n validate |
i18n:upgrade | Extract & upload to Crowdin | proton-i18n extract && crowdin -u |
i18n:getlatest | Download from Crowdin | proton-i18n upgrade |
Application Examples
Mail
package.json
Drive
Drive
package.json
Calendar
Calendar
package.json
Pass
Pass
package.json
Shared Package
Shared Package
Using ttag in Code
Basic Translation
Translation with Variables
Plural Forms
Context
Provide context to help translators:Translation File Structure
PO Files
Translations are stored in.po files in the po/ directory:
PO File Format
Turbo Configuration
Translation tasks are orchestrated through Turbo:Turbo ensures i18n tools are built before extraction and caches translation outputs.
Validation Rules
Lint Functions
Thevalidate lint-functions command checks for:
- Missing context: All strings should have context (e.g.,
c('Action')) - Invalid placeholders: Variables must use valid syntax
- Concatenation issues: Strings should not be concatenated
- HTML in strings: Avoid raw HTML in translatable strings
Context Validation
Thevalidate command checks:
- Consistent translations: Same source string with different contexts
- Variable consistency: Placeholders match across translations
- Plural forms: Correct plural form syntax
Best Practices
Crowdin Integration
Upload to Crowdin
- Extracts latest strings from source
- Uploads
.pofiles to Crowdin - Makes strings available for translation
Download from Crowdin
- Downloads translated
.pofiles - Updates local
po/directory - Translations become available in the app
Troubleshooting
Extraction fails
Extraction fails
Ensure the application is built first:Or use the local extraction script:
Validation errors
Validation errors
Fix reported issues in source code:
- Add missing context:
c('Context').t - Fix placeholder syntax: Use
${variable} - Avoid concatenation: Use template literals
Missing translations
Missing translations
Download latest from Crowdin:If still missing, strings may not be translated yet in Crowdin.
PO file conflicts
PO file conflicts
PO files can have merge conflicts. Use gettext tools to resolve:Or download fresh from Crowdin:
Additional Resources
ttag Documentation
Official ttag library documentation
Crowdin
Translation management platform
GNU gettext
PO file format specification
Translation Community
Proton’s translation community blog post
For contributing translations, visit the Proton translation community page to learn how you can help translate Proton products into your language.