Internationalization (i18n) - civiform/civiform GitHub Wiki
Table of contents
Types of i18n in CiviForm
CiviForm has two different types of strings, which have independent internationalization processes:
- Admin-generated strings (e.g. program names, question text) - translations are managed by admins via the CiviForm UI
- Application strings (e.g. buttons, page titles) - these are compiled into CiviForm itself and translations are managed in Transifex
Admin-generated strings
Admins are responsible for translating all content that they create. They configure translations in the CiviForm UI and they are saved in the CiviForm database. The CiviForm documentation provides detailed instructions.
Application strings
Application strings include button text, page titles, and validation messages compiled into CiviForm. Note that only public-facing CiviForm surfaces are localized - admin surfaces are only presented in English.
CiviForm uses Play framework i18n support to manage localization in code, and Transifex to interface with translators.
Adding new strings
To add a localized string:
- Add the English string to
messages. Include a comment above each line with extra context for the translators (example). - Add the key from the messages file to MessageKey.java
- After merging your change, go to the Transifex project and add a context string to your new key. Your source string should appear on the dashboard within a few minutes after merging your change.
- If your string is not yet ready to be translated, apply the "locked" tag to it.
Notes:
- Do not touch the other
messages.xxfiles, such asmessages.tl. Transifex will update these files automatically when translations are available. In the meantime, all languages will fall back to English strings. - Single quotes/apostrophes in strings must be escaped with a second single quote. For example, to produce
can't, writecan''tin the messages file.
Changing existing strings
You should not change an existing string, because Transifex will overwrite the existing translations with the new English version. Instead:
- Follow the instructions above for adding a new string, appending
.v2to the name (_V2for the MessageKey name). - Wait for translations to be completed.
- Update all usages from the old MessageKey to the new one, then follow the instructions below to remove the old string. You may also want to rename the new MessageKey to the old MessageKey to avoid unnecessary diffs.
Changing existing keys
You should not change an existing key, because Transifex will overwrite the existing translations with the English version.
Removing localized strings
To remove a localized string
- Remove all usages.
- Remove the string from
MessageKey.javaand themessagesfiles for all languages.
Using localized strings
You can use a localized string by calling messages.at(MessageKey.YOUR_KEY_NAME.getKeyName()).
You should not release un-translated content to users. You have two options to avoid this:
- Submit your changes to
messagesandMessageKey.javain a pull request, then wait to submit any pull requests that use those strings until the translations are completed. - Guard all usages of the strings behind a feature flag, and don't enable the flag until translations are completed.
Translating strings
CiviForm's Transifex project monitors the messages file for new strings and reflects changes in its UI. When a new string is added:
- Transifex generates a pull request on the CiviForm source code to copy the default English string into all the other language files. We don't actually want this (the localization framework already defaults to English when a translation is not available, and it's a big reason you can't edit an existing string) but we haven't found a way to disable it.
- Exygy periodically sends source strings for translations. If your translations are urgent, ping an Exygy engineer to let them know.
- Once translations come back, Transifex automatically opens a pull request and assigns it to civiform/developers to update CiviForm source code with the new translations. Once this pull request is merged, translation is complete.
Related notes:
- To get access to Transifex, ask an Exygy engineer to add you to the project as a Project Maintainer.
- You can watch the project in Transifex to get notified when there are new untranslated strings.
- If Transifex is not opening pull requests as expected, you can debug by initiating a manual sync on the GitHub integration page (navigate to Settings > Integrations > GitHub > Manage). You will need to connect your GitHub account the first time you access this page. Set the threshold percentage to 1% for a manual sync.
Adding a new CiviForm supported language
To add support for a new language:
- Look up the language code for the new language. We use Java's Locale class, which uses the IANA Language Subtag Registry. You can search the list of valid language subtags to find the correct one (hint: look for "Type: language").
- Add the language tag to list in application.conf (under
play.i18n). IMPORTANT - the first language code is considered the default for the application, so do not insert at the beginning. Instead, we keep the list ordered alphabetically by the English name of the language (ex: "Chinese" comes before "Korean", even though the language code for Chinese is "zh-TW"). - Add a new messages file under /conf/i18n (see messages.en-US for an example). Note that the file extension must match the language tag exactly. The file can be empty to start with. Merge it.
- Add the language to the Transifex project. Wait for it to sync the default, English "translations" and approve the pull request that Transifex generates.
Need help? See Play's i18n documentation for more guidance.