Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Orion/Internationalization"

m (Message files distribution and configuration)
m (Using messages in your plugin)
Line 133: Line 133:
  
 
=== Using messages in your plugin ===
 
=== Using messages in your plugin ===
Now you want to use those 3 messages in your plugin. Your plugin file should look like as the following:<br>
+
Now you want to use those 3 messages in your plugin. Your plugin file should look like this:<br>
 
[[Image:SampleNLSPlugin_distribution03.png]]
 
[[Image:SampleNLSPlugin_distribution03.png]]
  

Revision as of 15:04, 8 June 2015

This page is a hub for resources relating to preparing Orion for use in other languages and locales (also known by the abbreviation i18n). This work involves translating strings into other languages (often called NLS for Natural Language Support), handling bi-directional text (BIDI), and preparing content such as dates and times in a format appropriate for a given locale.

Overview

The Orion i18n framework enforces a separation between defining translatable messages, providing translations, and the job of mapping definitions to translations.

Defining messages
Message modules (or message bundles) are JavaScript objects mapping keys to values. The messages are defined by the keys. The values are localized strings in some language. The Orion client source ships with message modules for the default English localization of Orion.
Providing translation
Translations are provided by adding separate translation messages files related to the default English message file. The RequireJS's i18n plugin rule is used for the file structure of the translated files. For example if the default English message file is called someFolder/nls/root/messages.js, the Chinese translation has to be someFolder/nls/zh/messages.js.
Performing translation
Orion uses RequireJS's i18n plugin to perform translation. The plugin will use the browser's navigator.language or navigator.userLanguage property to determine what locale values to use if the translation of the browser's locale is provided.

Browsing Orion in a different language

Under the hood, Orion uses RequireJS's i18n plugin to implement bundle loading. This means that your browser's navigator language (in other words, the navigator.language or navigator.userLanguage property) determines the language Orion is displayed in.

The steps required to change the navigator language vary depending on browser and platform. Moreover, most browsers treat the navigator language as an independent setting from the Accept-Language header sent to the server, meaning that Orion may display in a different language from the one you're accustomed to seeing during everyday browsing (as most websites will rely on Accept-Language).

To verify the navigator language, evaluate this expression in your browser's JavaScript console:

    navigator.language || navigator.userLanguage

Below is an overview of how to change the navigator language.

Firefox (Windows)
  1. Go to Tools > Options > Content > Languages, then click Choose...
  2. Put your preferred language at the top of the list.

Firefox keeps things simple by having the ordering of languages in the list determine both the Accept-Language header and the navigator.language property (the first value in the list is used as the navigator language).

Google Chrome (Windows)
  1. Go to Settings > Show Advanced Settings > Languages then click Language and Input Settings...
  2. Add your preferred language to the list, then click Display Google Chrome in this language and restart Chrome.
Internet Explorer 10 (Windows)
  1. Go to Control Panel > Regional and Language > Formats and select your preferred language from the Format menu.
  2. Click Apply and restart Internet Explorer.

If you previously accessed Orion in your browser, you must perform localStorage.clear() from a JS console window on an Orion page before the new language will take effect. (This flushes the translation cache for the old language.)

Note that the Orion deployment you are using must have a language pack installed that provides translation for your preferred language. Orion ships with an English language translation, but additional translations may be installed by end users, or by the Orion server administrator on a server-wide basis.

See also

Client - adding new messages file

If you want to create a new messages file you need to add an "nls" directory with a given file structure:

nls/
   messages.js
   root/
      messages.js

Instead of "messages.js" we may use a different file name, but both *.js files need to have the same name.

The nls/messages.js file does not contain any strings for translation and will not be sent for translation. This file serves as a configuration file and should have the initial format as follows:

define({
    root:true
});

The root:true means the default English messages.js is under the root folder. The translated files will be also configured in this file. We will describe how to do this in a later section.

The nls/root/messages.js file is the root messages file, it contains externalized strings and is sent for translation. For this reason it is very important that the format is kept as follows:

OrionGlobalization.png

Client - using messages

To use the messages defined in the external file we should import them using i18n! prefix.

OrionGlobalizedFileHeader.png

Please take into account dependencies between our bundles. Editor cannot use messages from our Client, but Git client can.

The result of this import is that the 'messages' variable is an object containing all messages. The message keys are not translated, but the message values are translated into an appropriate locale, if translation is available. If a translation file exists, but it doesn't contain some of the messages, the missing messages will be taken directly from the root translation. There are two formats to get the message under key "Navigator":

messages.Navigator
messages["Navigator"]

For messages containing parameters we have a convenient helper method in 'orion/i18nUtil' for client bundles and in 'orion/textview/util' for editor. This is the use of the function:

i18nUtil.formatMessage(message, param0, param1, param2...)

The message parameter needs to be already globalized. Example use:

i18nUtil.formatMessage(messages.lineColumn, lineIndex + 1, offsetInLine + 1)

Deploy and configure translated files

Translated message files have to be added at deploy time. Let's take the Orion Git repository page as an example on how to add them. The Git repository page defines all of its messages in org.eclipse.orion.client.git/web/git/nls/root/gitmessages.js file. The translation configuration file is called org.eclipse.orion.client.git/web/git/nls/gitmessages.js. Let's say you have the Japanese and Chinese translation files and want them to be displayed in the page when the browser locale changes to Japanese or Chinese. You need the following 2 steps:

Add translated message files

Create 2 sibling folders to the root folder called jp and zh. Put the Japanese and Chinese messages files into the 2 folders, respectively. The file structure will look like this:

nls/
   gitmessages.js
   root/
      gitmessages.js
   jp/
      gitmessages.js
   zh/
      gitmessages.js

The folder names have to use the web browser language identification codes. The translated files have to be named the same file name as the one in the root folder.

Configure translations

Add 2 lines of code for jp:true and zh:true in the /nls/gitmessages.js (configuration) file. The file should look like this:

define({
    root:true,
    "jp":true,
    "zh":true
});

Deploy and restart the Orion server

Once all the translation files are copied and configured, restarting the Orion server will bring up the translations according to the browser's locale setting.

Translating a plugin

Any plugin that contributes user-facing strings to the UI (for example, by providing a command, or a validation message) is expected to return strings translated into the user's locale, whenever possible.

Internally, the Orion UI uses RequireJS's i18n feature to determine the user's locale and to load translations. However, the Orion framework does not force this particular approach; a plugin can use other strategies if desired. For example, a plugin might make use of server-side technology that relies on the client's X-Accept-Language header to determine the locale. This is fine (although it could cause the Orion UI and the plugin to decide on different locales in some cases).

The following sample plugin shows how to use the RequireJS i18n strategy to translate a plugin. Note that the structure of the messages files, and the configuration, is identical to the previous section.

Sample plugin overview

Let's say you want to write a plugin to contribute customized commands to extend the "orion.edit.command" category. Your command will insert some text inside the Orion editor at the current cursor. You want your command to appear in the Tools menu in the Orion tool bar with tooltips. After you click on the command you want a piece of fixed text pasted in the editor. You also want the command, tooltips and the fixed text to be translated.
SampleNLSPlugin overview01.png

SampleNLSPlugin overview02.png

Message files distribution and configuration

First you need to define the English message file. Then you want to provide the Japanese and Chinese translations. Your file structure and the configuration file should look like this:
SampleNLSPlugin distribution01.png

Your English message file should look like this:
SampleNLSPlugin distribution02.png

Using messages in your plugin

Now you want to use those 3 messages in your plugin. Your plugin file should look like this:
SampleNLSPlugin distribution03.png

Reload your plugin when browser locale changes

After installing the plugin you can change the browser's locale and verify the translations. Please note that if you are providing translations that are loaded during the plugin loading time you need to reload the plugin when your browser's locale changes. In the sample plugin, the command name and tooltips are loaded during the plugin loading. However the fixed text executed by the plugin is dynamic that does not need the plugin reload.

Verify Japanese translation

Change your browser's locale to Japanese and reload the plugin. You should see all the messages are translated in Japanese:
SampleNLSPlugin transaltion 01.png
SampleNLSPlugin transaltion 02.png

Verify Chinese translation

Change your browser's locale to Chinese and reload the plugin. You should see all the messages are translated in Chinese:
SampleNLSPlugin transaltion zh01.png
SampleNLSPlugin transaltion zh02.png

Download the sample plugin

You can download the File:ThirdPartyNLSPlugin.zip and host it somewhere and test by yourself.

String Xtrnalizr

You don't have to externalize strings manually, we have a tool that helps you do this.

Install localization plugin

  1. Choose "Get Plugins" from Orion toolbar
    GetPlugins.png
  2. Find "String Externalizer" on the plugins list and click Install
    StringExternalizerInstall.png
  3. Confirm installing the plugin by clicking "Submit"
    SubmitInstallingStringExternalizer.png
  4. Installing plugin gives you a warning about not externalized strings and provides access to String Xtrnalizr

Usage of String Xtrnalizr

String Xtrnalizr can help you externalize strings from chosen JavaScript files from a folder to one messages file at a time.

Please beware of bug 428373 (Strings Xtrnlizr silently fails to generate messages file when run on single file).

  1. To externalize strings first choose the folder you wish to modify and from the "More" menu ("View Related" in Orion 5.0) choose "String Xtrnalizr"
    OpenXtrnalizr.png
    Try to choose folders with enclosed functionality without any unnecessary content, for instance processing the whole Orion client repository can take long, but choosing only org.eclipse.orion.server.git should be just fine.
  2. You should be redirected to the String Xtrnalizr site. Wait a moment until the folder you chose is parsed, Xtrnalizr is searching for not externalized strings, this may take a while.
  3. The left menu contains configuration that needs to be changed each time you are externalizing strings to a new file. The configuration will be saved and the next time you externalize strings from the same folder the last configuration will be filled for you.
    ExternalizeStringsConfiguration.png
    1. Messages directory - the main directory of the messages file. If you choose 'orion/nls' your messages will be externalized to 'orion/nls/root/messages.js' file
    2. Messages file name - the name of the file to externalize strings. By default strings will be externalized to 'messages.js', but you may as well change the name, using for instance 'gitmessages.js'
    3. Messages module - the requireJS module name that should be added to your file's define section. Xtrnalizr does not try to guess the module name, so please, set the module name manually. If you choose to externalize your strings to 'orion/nls/root/messages.js' please set the header to 'i18n!orion/nls/messages'
    4. Mark not exported as NON-NLS - if you externalized all nls strings from chosen files and any strings left are non-nls check this property. All non externalized strings will be marked with NON-NLS end of line comments and you won't be seeing them in the Xtrnalizr report the next time you run it.
  4. Choose strings to be externalized
    StringXtrnalizr.png
    String Xtrnalizr shows you the list of non externalized strings grouped by files. Selecting each file will show you a preview of the changes that will be made after the string externalization is completed.
    1. Expand the file nodes to see the non externalized strings found
    2. Select the string node to see it in the preview
    3. Uncheck the file to omit it in string externalization. Files that are not checked will not be modified.
    4. Check/uncheck the changes to decide if they should be externalized. Depending of how you checked 'Mark not exported as NON-NLS' property the unchecked changes will be marked as NON-NLS or left unchanged.
    5. If you check the file node, but none of the changes will be checked, the only changes added to the file are NON-NLS marks.
  5. When you are done click "Apply Changes" button to generate the messages file.
  6. Important! - if you were creating a new messages file you still have to finish it up. Go to the directory you chose in "Messages directory", it should contain a "root" folder. You need to create a master messages file. If you were externalizing files from Orion then you just need to copy any messages.js file that already exists and change the module name in "define" function to match the one you chose in "Messages module" property. If you are externalizing files that use dojo 1.7 messages bundle see this dojo tutorial [1] to learn creating dojo 1.7 i18n files. See also [Editor no longer requires dijit/dojo * Close to getting navigator dijit/dojo free]
  7. Recovering from accidental localization - If you find a string was externalized to message["key"] by mistake you can look up the original message value under "key": "value" in the nls/root/messages.js file. Just replace message["key"] with "value" in the source file and remove the key value entry from messages.js. It's best to start the NLS work with a unmodified git workspace. That way all changes made by Strings Xtrnlizr can easily be reviewed and reverted.

Server

Most server strings are not currently externalized, but could easily be done using current Equinox API. The easy case is single language servers, where the natural language is provided when the server starts and it never changes. More complex would be multi-language servers where each request can have a different language and server uses the HTTP Accept-Language header to determine response language for that request. Equinox has not come up with a well performing way to do this (see bug 226340), and any prerequisite dependencies such as org.eclipse.* libraries won't support it.


Related Links

Back to the top