Nuxeo supported modules handle English translations for each of their bundles. Other translations are managed on Crowdin and synchronized automatically with the Nuxeo source code.
Here are some instructions to help you contributing or changing translations, in English or other languages.
Instructions for Translators
Editing on Crowdin (Non-English Translations)
There is a Nuxeo project on Crowdin. To join the project, create an account on Crowdin and follow this link: http://crowdin.net/project/nuxeo/invite.
If you are not familiar with Crowdin, take a look at their quick start guide .
Basically here are the steps to contribute:
- Join the Nuxeo translation group of your choice at crowdin.net/project/nuxeo. Pick a language you want to translate and start by clicking “translate”.
- In the Crowdin translation view you will find all the phrases to translate to the left. (To view only the ones that still need translation, use the “missing translations” filter.)
- Click on a phrase you want to translate. You see the original phrase in the top, and a box to fill out your translation beneath.
- Enter the translation and by clicking “save”, and optionally, if you're a proofreader, you can approve the translation.
- Contact one or several of the Crowdin project managers to be credited for your contribution.
By default, new users have the translator status. It means you can propose new translations, but can't validate them. To gain the proofreader status and have the validation permission, please contact one or several of the Crowdin project managers.
Now here's a couple of tips:
Some phrases have placeholders in them (like {0}). These are placeholders for values that are added later. E.g. a name: “Hello, {0}”, could be “Hello, Peter” on the website. They must remain in the translation as well, although placement may vary.
If the context of a label is unclear, please request the context from the Nuxeo team. These comments are also visible for anyone else that translates or approves translations.
Before every release, the translations are exported from Crowdin to the nuxeo-platform-lang-ext addon by Nuxeo.
Adding a New Language
Please contact one or several managers of the project if you'd like to contribute translations to a language that's not available on Crowdin yet.
Nuxeo developers will perform the additional steps for this language to be added to the Nuxeo source code.
Manual Editing (English Translations)
For now, English translations are managed only on GitHub. Looking at the reference messages.properties file at can help you understand in which GitHub repository or module the original translation is. For instance, look for the following sample lines:
## DO NOT EDIT FOLLOWING LINE # Translations from ./nuxeo/nuxeo-features/nuxeo-platform-lang/src/main/resources/web/nuxeo.war/WEB-INF/classes/messages_en_US.properties [...] ## DO NOT EDIT FOLLOWING LINE # Translations from ./nuxeo/addons/nuxeo-agenda/src/main/resources/OSGI-INF/l10n/messages_en_US.properties [...]
If the module is under the
addons
directory, it will be in a specific GitHub repository. Otherwise, it will be in the main Nuxeo repository.Use any standard Java i18n tool to edit the files.
- Make a pull-request on GitHub.
If you'd like to include quotes in a translation that is holding placeholders, this quote should be doubled. Note that Crowdin will handle that double-quoting at export on its own, so you can disregard this warning if you are using the Crowdin UI.
Testing Translations
To test a translation file provided by Crowdin against your Nuxeo server, you can benefit from messages labels hot reload by following these instructions:
- Download the messages.properties file in your language from Crowdin (after some changes to translations for instance).
As an alternative, you can pick the current messages.properties file on your server at
$SERVER/nxserver/nuxeo.war/WEB-INF/classes/messages_xx_XX.properties
and edit it manually. Start your Nuxeo server in development mode:
Go to ADMIN > Update Center > Nuxeo Studio and click on the dedicated button.
Or add the following to the
$SERVER/bin/nuxeo.conf
file.org.nuxeo.dev=true
Log in as Administrator.
- Replace the file at
$SERVER/nxserver/nuxeo.war/WEB-INF/classes/messages_xx_XX.properties
by the one you downloaded from Crowdin or edit it. Click on Dev mode: force flush next to the Logout button in the UI. Your translations are displayed in the UI.
If you haven't changed the default language in your preferences, you can add
?language=xx_XX
at the end of the page URL to see the page in your target language. For instance https://nightly.nuxeo.com/nuxeo/nxpath/default/default-domain@view_documents?language=pt_BR.- If you downloaded translations from Crowdin, do not forget to upload back your changes!
Files at $SERVER/nxserver/nuxeo.war
are re-computed from Nuxeo bundles at each server startup: make sure that you have a copy of your file before restarting your server, to avoid losing your work. If you'd like these translations to be kept after a restart, follow instructions below to make translations part of a Nuxeo bundle.
Identifying a Specific Label to Translate
If you want to translate or update a specific label you saw in the UI but you can identify it in Crowdin between several messages, follow the steps below:
Activate the Dev mode on your Nuxeo server:
Go to ADMIN > Update Center > Nuxeo Studio and click on the dedicated button.
Or add the following to the
$SERVER/bin/nuxeo.conf
file.org.nuxeo.dev=true
Log in as Administrator.
- Edit the file
$SERVER/nxserver/nuxeo.war/WEB-INF/classes/messages_xx_XX.properties
and replace the labels you want to identify and translate by their id in order to get something likeaction.view.rights.management=action.view.rights.management
. Click on Dev mode: force flush next to the Logout button in the UI.
If you haven't changed the default language in your preferences, you can add
?language=xx_XX
at the end of the page URL to see the page in your target language. For instance https://nightly.nuxeo.com/nuxeo/nxpath/default/default-domain@view_documents?language=pt_BR.The label you want to translate is replaced by its id.
Contributions
Contributions on Crowdin side will be synchronized daily to the Nuxeo master source code. Translations that are not approved will also be taken into account.
If you are not using Crowdin, please contribute your translation work back to Nuxeo so that other users can benefit from it.
Instructions for Developers
In documentation below, the xx_XX
notation will be used to reference the four letter code name for your language.
Updating or Creating Localized Messages for a Custom Nuxeo Bundle
- Place your custom messages.properties file in your bundle at
src/main/resources/OSGI-INF/l10n/messages_xx_XX.properties
. Create of edit the file at
src/main/resources/OSGI-INF/deployment-fragment.xml
to contribute the translations to the main aggregated translation files used by the application:<?xml version="1.0"?> <fragment version="1"> <require>org.nuxeo.ecm.platform.lang</require> <require>org.nuxeo.ecm.platform.lang.ext</require> <install> <delete path="${bundle.fileName}.tmp" /> <mkdir path="${bundle.fileName}.tmp" /> <unzip from="${bundle.fileName}" to="${bundle.fileName}.tmp" /> <append from="${bundle.fileName}.tmp/OSGI-INF/l10n/messages_xx_XX.properties" to="nuxeo.war/WEB-INF/classes/messages.properties" addNewLine="true" /> <append from="${bundle.fileName}.tmp/OSGI-INF/l10n/messages_xx_XX.properties" to="nuxeo.war/WEB-INF/classes/messages_xx.properties" addNewLine="true" /> <append from="${bundle.fileName}.tmp/OSGI-INF/l10n/messages_en_US.properties" to="nuxeo.war/WEB-INF/classes/messages_xx_XX.properties" addNewLine="true" /> <delete path="${bundle.fileName}.tmp" /> </install> </fragment>
In the above example, translations from the file at
messages_xx_XX.properties
are also contributed to the mainmessages.properties
file (used as a fallback when translation is not defined for a given language). Translations are also contributed to themessages_xx.properties
file, as well as the original mainmessages_xx_XX.properties
file. You can adapt this behavior depending on your use case.
Note:
The require
tag ensures that you are contributing to existing files, already created thanks to the default nuxeo-platform-lang
and nuxeo-platform-lang-ext
modules. If you are not contributing to an existing file, you should create it:
<copy from="${bundle.fileName}.tmp/OSGI-INF/l10n/messages_xx_XX.properties"
to="nuxeo.war/WEB-INF/classes/messages_xx_XX.properties"/>
You can also use the require tag to control ordering of contributions to the final nuxeo.war/WEB-INF/classes/messages_xx_XX.properties
file, so that you can override values for existing translations: if a duplicate key is present in the final file, the last value will be taken into account.
Adding a New Language to a Nuxeo Application
You can add your new properties file similarly, you just need to modify the deployment-fragment.xml
file adding a new entry with your locale:
<extension target="faces-config#APPLICATION_LOCALE">
<locale-config>
<supported-locale>xx_XX</supported-locale>
</locale-config>
</extension>
Understanding Locale and Lookup of Translations
Here's the resolving order when looking for a label in Brazilian, for instance.
messages_pt_BR.properties -> messages_pt_PT.properties -> messages_en.properties -> messages.properties
Brazilian is a 'dialect' of Portuguese, so there is first a fallback on Portuguese, then a fallback to the default language of the application ("en" for Nuxeo) then to messages.properties.
Most of the fallback is actually handled directly by Crowdin, the tool we use for translations. When downloading a file from Crowdin, like messages_pt_BR.properties for instance, the missing labels will be replaced by the ones from file messages_pt_PT.properties (if it exists), then by the reference English file used by Crowdin. This is why you'll see English translations by default in some non-English files.
What's with these two letter files like messages_pt.properties? Well those are actually an automatic copy of the four letter version. It's only here to have a two letter fallback when browsers language are set to a two letter format.
Unit-Testing Translations
Test cases are available to test for default translations provided in Nuxeo bundles. To check your translation file, you can just add the following test case to your bundle:
package org.nuxeo.ecm.collections.lang.test;
import org.nuxeo.ecm.platform.test.TranslationTestCase;
/**
* Simple integrity tests on messages file(s).
*/
public class TestMessages extends TranslationTestCase {
}
The TranslationTestCase
file is defined in the nuxeo-platform-test
module, so you should add the following to your project pom.xml
file:
<dependency>
<groupId>org.nuxeo.ecm.platform</groupId>
<artifactId>nuxeo-platform-test</artifactId>
<scope>test</scope>
</dependency>
This test case will assume that the English translation file is at the "usual" location, you can override method getEnTranslationsPath
if you placed your properties file elsewhere. It will check for simple things: syntax errors (errors in unicode characters can prevent the file from being loaded, for instance) and duplicate entries (that can happen easily when copy/pasting translations).
Additional test cases exist if you'd like to check for consistency between translations of two different languages for instance, you can check the TranslationEnFrTestCase logics or the TestExtMessages parametrized tests on the nuxeo-platform-lang-ext
module.
Nuxeo Crowdin Translations Synchronization Process
Nuxeo - Crowdin Synchronization
Since a Nuxeo application is composed of several bundles, which can contribute their own translations to the main translation file, all translation files for supported modules are aggregated and pushed to Crowdin as a "reference" file.
Only the master branch is handled by Crowdin: changes to translation files in maintenance branches will have to be committed manually in GitHub.
The generated aggregate file at https://github.com/nuxeo/nuxeo-platform-lang-ext/blob/release-7.10/src/main/resources/crowdin/messages.properties is generated from all supported Nuxeo modules that hold a crowdin.ini file, referencing the relative path to their messages_en_US.properties file. Here is a sample
crowdin.ini
file content:[nuxeo] en_US=src/main/resources/OSGI-INF/l10n/messages_en_US.properties
So to add or remove a module translation files to the main aggregated file, you should just add or remove the crowdin.ini file from the root of the module.
This file is generated daily and pushed to Crowdin as the new "reference" file: you should not make any manual changes to it, otherwise they will be lost at next automatic update. You should modify the original
messages_en_US.properties
file instead.- If the aggregated file holds duplicate keys, or syntax errors, it will not be pushed to Crowdin (unit tests are run on the lang-ext module before pushing).
- Modifications to the reference file have the following result on Crowdin side:
- Existing approved translations do not change if the reference value did not change.
- Existing approved translations are unapproved if the reference value changed (but current value is kept). Crowdin helps detecting these translations for proofreading.
- New translations are marked as untranslated (they will present the reference English value at export).
- Removed translations are not presented on the Crowdin UI anymore.
Crowdin - Nuxeo Synchronization
- Daily, non-English translations from Crowdin are pushed to the Nuxeo source code, inside the nuxeo-platform-lang-ext module.
- All translations are exported, even unapproved.
- Untranslated labels take the reference English value by default.
- If exported files hold duplicate keys, or syntax errors, they will not be pushed to GitHub (unit test are run on the lang-ext module before pushing).
An export of translations files from Crowdin requires the project to be "built" first. This build is quite costly on Crowdin side, so it will not be performed more than once every 30 minutes via the API (used by automated synchronization). In this case, you should ask one of the Crowdin project managers to build the project directly on the Crowdin UI (or wait 30 minutes) before launching the synchronization again.
Jenkins Automated Builds
The job at http://qa.nuxeo.org/jenkins/job/nuxeo-crowdin-synchro-check-master/ generates the aggregated messages.properties file and runs unit tests on it: this helps detecting duplicate entries in the aggregated file.
The job at https://qapriv.nuxeo.org/jenkins/job/trigger-sync-nuxeo-crowdin/ (requires authentication) triggers the daily synchronizations from/to Nuxeo/Crowdin. This synchronization can also be triggered manually by running the job at https://qapriv.nuxeo.org/jenkins/job/sync-nuxeo-crowdin/ (requires authentication).
Localization and Translation How-To Index How to Upload Labels Translations in Nuxeo Studio (i18n)