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"

(Add translated message files)
m (Verify Chinese translation)
 
(25 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{warning|The information on this page applies only to Orion 7.0 and earlier releases. The document is in the process of being updated for Orion 8.0.}}
 
 
 
This page is a hub for resources relating to preparing Orion for use in other languages and locales (also known by the abbreviation [http://en.wikipedia.org/wiki/I18n 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.  
 
This page is a hub for resources relating to preparing Orion for use in other languages and locales (also known by the abbreviation [http://en.wikipedia.org/wiki/I18n 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 ==
 
== Overview ==
The Orion i18n framework enforces a separation between defining translate-able messages, providing translations, and the job of mapping definitions to translations.
+
The Orion i18n framework enforces a separation between defining translatable messages, providing translations, and the job of mapping definitions to translations.
  
 
; Defining messages
 
; Defining messages
Line 63: Line 61:
 
});
 
});
 
</pre>
 
</pre>
The <b>root:true</b> 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 the later section.
+
The <b>root:true</b> 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:  
 
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:  
Line 75: Line 73:
 
[[Image:OrionGlobalizedFileHeader.png]]
 
[[Image:OrionGlobalizedFileHeader.png]]
  
Please take into account dependencies between out bundles. Editor cannot use messages from our Client, but Git client can.
+
Please take into account dependencies between our bundles. Editor cannot use messages from our Client, but Git client can.
  
In result of this import messages variable is an object containing all messages. The key of messages stay the same, but the message value is translated into a appropriate locale, if translation is available. If 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":
+
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":
 
<pre>messages.Navigator</pre>
 
<pre>messages.Navigator</pre>
 
<pre>messages["Navigator"]</pre>
 
<pre>messages["Navigator"]</pre>
  
For messages containing parameters we can use dojo.substitute, but we also have more convenient helper method that is available in 'orion/util' for client bundles and in 'orion/textview/util' for editor. This is the use of the function:
+
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:
<pre>mUtil.formatMessage(message, param0, param1, param2...)</pre>
+
<pre>i18nUtil.formatMessage(message, param0, param1, param2...)</pre>
 
The message parameter needs to be already globalized. Example use:
 
The message parameter needs to be already globalized. Example use:
<pre>mUtil.formatMessage(messages.lineColumn, lineIndex + 1, offsetInLine + 1)</pre>
+
<pre>i18nUtil.formatMessage(messages.lineColumn, lineIndex + 1, offsetInLine + 1)</pre>
  
 
== Deploy and configure translated files ==
 
== Deploy and configure translated files ==
Translated message files have to be added at the deploy time. Let's take the Orion Git repository page as an example on how to add them.
+
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 the messages in <b>org.eclipse.orion.client.git/web/git/nls/root/gitmessages.js</b> file. The translation configuration file is called <b>org.eclipse.orion.client.git/web/git/nls/gitmessages.js</b>. 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 2 steps as the following:
+
The Git repository page defines all of its messages in <b>org.eclipse.orion.client.git/web/git/nls/root/gitmessages.js</b> file. The translation configuration file is called <b>org.eclipse.orion.client.git/web/git/nls/gitmessages.js</b>. 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 ===
 
=== Add translated message files ===
 
Create 2 sibling folders to the root folder called <b>jp</b> and <b>zh</b>. Put the Japanese and Chinese messages files into the 2 folders, respectively.
 
Create 2 sibling folders to the root folder called <b>jp</b> and <b>zh</b>. Put the Japanese and Chinese messages files into the 2 folders, respectively.
The file structure will look like the following:
+
The file structure will look like this:
 
<pre>nls/
 
<pre>nls/
 
   gitmessages.js
 
   gitmessages.js
Line 104: Line 102:
  
 
=== Configure translations ===
 
=== Configure translations ===
 
+
Add 2 lines of code for '''jp:true''' and '''zh:true''' in the <b>/nls/gitmessages.js</b> (configuration) file.
== Orion Editor  ==
+
The file should look like this:
 
+
<pre>define({
The Orion editor also needs to make sure stuff like BIDI, IME, DBSC and Unicode Surrogates are all working properly. We paid some attention to these when we were first designing the editor, but there is lots of work to make the Orion editor BIDI aware to the same level of the Eclipse Desktop editor.
+
     root:true,
 
+
     "jp":true,
== Plugins ==
+
     "zh":true
=== Translating a plugin ===
+
 
+
In the Orion i18n framework, [[#Client_-_using_messages|page UI code]] is responsible for loading message modules and looking up translated strings. Plugins '''cannot perform this work themselves'''. Therefore, plugins '''cannot load any i18n! modules''' using Orion's i18n loader.
+
 
+
However, plugins can indirectly refer to messages. Here's an example of a plugin-contributed service that refers to the "Navigator" message key from the '''orion/nls/messages''' messages module:
+
 
+
<source lang="javascript" line="line">
+
// Primary navigation links
+
provider.registerServiceProvider("orion.page.link", serviceImpl, {
+
     id: "orion.navigator",
+
     nls: "orion/nls/messages", // message module
+
     nameKey: "Navigator",      // key
+
    uriTemplate: "{OrionHome}/navigate/table.html#"
+
 
});
 
});
</source>
+
</pre>
  
At display time, the Orion UI loads and caches the "orion/nls/messages" module, and looks up the key "Navigator" in that module to obtain the translated string.
+
=== 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.
  
When externalizing a service definition from a plugin, the usual pattern is to add an '''nls''' property giving the path to the messages module, and indicate to-be-translated properties by appending '''Key''' to the property name.  For example, to externalize string a service that normally has '''name''' and '''tooltip''' properties, we add an '''nls''' property to the service definition, and replace the '''name''' and '''tooltip''' properties with '''nameKey''' and '''tooltipKey'''. The '''nls''' property should gives the messages module path (don't include "i18n!", "root" or ".js") and the values of '''nameKey''' and '''tooltipKey''' properties are the keys of the translated messages in that module.
+
== 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.
  
Here's a partial list of services that can currently be localized in this manner:
+
Internally, the Orion UI uses [http://requirejs.org/docs/api.html#i18n 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 <tt>X-Accept-Language</tt> 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).
* orion.page.link
+
* orion.page.link.related
+
* orion.edit.command
+
* orion.edit.editor
+
* orion.edit.outliner
+
* orion.navigate.command
+
* orion.navigate.openWith
+
* orion.core.setting
+
  
Plugin authors may opt to use their own localization methods instead of Orion's, in which case any technology can be used. In this case they should not include an '''nls''' property in their service definitions, but simply provide already-translated strings as the value of '''name''' and '''tooltip'''.
+
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 [[Orion/Internationalization#Deploy_and_configure_translated_files|previous section]].
  
 +
=== Sample plugin overview ===
 +
Let's say you want to write a plugin to contribute customized commands to extend the <b>"orion.edit.command"</b> category. Your command will insert some text inside the Orion editor at the current cursor. You want your command to appear in the <b>Tools</b> 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 <b>command, tooltips and the fixed text</b> to be translated.<br>[[Image:SampleNLSPlugin_overview01.png]]<br><br>
 +
[[Image:SampleNLSPlugin_overview02.png]]
  
=== Providing translation from a plugin ===
+
=== Message files distribution and configuration ===
The <tt>'''orion.i18n.message'''</tt> service allows a plugin to contribute a translated message bundle. This service is of interest to plugin developers that want to provide translations of their plugin messages, as well as developers intending to write a [[Internationalization#Overview|language pack]] for Orion.
+
First you need to define the English message file. Then you want to provide the Japanese and Chinese translations. Your <b>file structure</b> and the <b>configuration file</b> should look like this:<br>
 +
[[Image:SampleNLSPlugin_distribution01.png]]<br><br>
 +
Your <b>English message file</b> should look like this:<br>
 +
[[Image:SampleNLSPlugin_distribution02.png]]
  
==== Service properties ====
+
=== Using messages in your plugin ===
; '''name'''
+
Now you want to use those 3 messages in your plugin. Your plugin file should look like this:<br>
: <tt>String</tt> The name of the message bundle that this service provides. The name has the general form <tt>{prefix}/nls/{suffix}</tt> for a master bundle, and <tt>{prefix}/nls/{locale}/{suffix}</tt> for a particular locale, where:
+
[[Image:SampleNLSPlugin_distribution03.png]]
* <tt>{prefix}</tt> is any prefix (by convention, a path).
+
* <tt>{locale}</tt> is a locale identifier (de, en-us, fr, pt-br, etc.)
+
* <tt>{suffix}</tt> is any suffix (by convention, a filename.)
+
  
For example, a master bundle might be named <tt>my/stuff/nls/catalog</tt>, and a French translation of that bundle would be <tt>my/stuff/nls/'''fr'''/catalog</tt>. Here are some more examples:
+
=== Reload your plugin when browser locale changes ===
 +
After installing the plugin you can change the browser's locale and verify the translations.
 +
<b>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.</b>
 +
In the sample plugin, the <b>command name and tooltip</b> are loaded during the plugin loading. However the <b>fixed text</b> inserted by the plugin is dynamic and does not need the plugin reload.
  
<!--
+
=== Verify Japanese translation ===
| <tt>orion/editor/nls/messages</tt>
+
Change your browser's locale to Japanese and reload the plugin. You should see all the messages translated to <b>Japanese</b>:<br>[[Image:SampleNLSPlugin_transaltion_01.png]]
| <tt>orion/editor/nls/messages</tt>
+
<br>[[Image:SampleNLSPlugin_transaltion_02.png]]
| <tt>orion/nls/messages</tt>
+
-->
+
{| class="wikitable" border="1" cellspacing="0" cellpadding="4"
+
! Bundle name
+
! Language
+
|-
+
| <tt>orion/editor/nls/messages</tt>
+
| master
+
|-
+
| <tt>foo/nls/'''de'''/strings</tt>
+
| German
+
|-
+
| <tt>orion/navigate/nls/'''fr'''/messages</tt>
+
| French
+
|-
+
| <tt>myplugin/widgets/nls/'''pt-br'''/messages</tt>
+
| Portuguese (Brazilian)
+
|-
+
|}
+
  
==== Service methods ====
+
=== Verify Chinese translation ===
; <tt>getMessageBundle()</tt>
+
Change your browser's locale to Chinese and reload the plugin. You should see all the messages translated to <b>Chinese</b>:<br>[[Image:SampleNLSPlugin_transaltion_zh01.png]]
: Returns the message bundle.
+
<br>[[Image:SampleNLSPlugin_transaltion_zh02.png]]
 
+
==== Example: providing a master bundle and zh translation ====
+
This example plugin code registers a master bundle <tt>example/nls/messages</tt>, and a Chinese (Simplified) translation <tt>example/nls/'''zh'''/messages</tt>. In this case, the master bundle happens to contain English values, but that is not required.
+
 
+
<source lang="javascript" line="line">
+
// Register the "master" message bundle
+
pluginProvider.registerService("orion.i18n.message", {
+
    getMessageBundle: function() {
+
        return {
+
            root: { // Note 'root' property here
+
                "GetPlugins": "Get plugins",
+
                "GetPluginsTooltip": "Find more plugins",
+
            }
+
        };
+
    }
+
}, {
+
    name: "example/nls/messages"
+
});
+
 
+
// Register the Chinese (Simplified) translation
+
pluginProvider.registerService("orion.i18n.message", {
+
    getMessageBundle: function() {
+
        return {
+
            "GetPlugins": "获取插件",
+
            "GetPluginsTooltip": "查找更多插件",
+
        };
+
    }
+
}, {
+
    name: "example/nls/zh/messages"
+
});
+
</source>
+
 
+
As always, the framework invokes getMessageBundle() in an asynchronous manner: the implementer can [[Orion/Documentation/Developer_Guide/Architecture#Communication_with_Services|return a Promise]] or other "then-able" object to defer computation. This enables the actual message strings to be downloaded lazily on demand using any async technique (XMLHttpRequest, AMD <tt>require()</tt>, etc.)
+
 
+
 
+
==== Example 2: referencing translated strings ====
+
Assume that the services shown in the previous example have been registered. The code below shows how an Orion [[Orion/Documentation/Developer Guide/Plugging into the editor#orion.edit.command|editor command]] extension could be registered, referencing strings from the message bundle to provide its name and tooltip. The command does not have to be registered in the same plugin as the message bundles.
+
 
+
<source lang="javascript" line="line">
+
    provider.registerService("orion.edit.command", {
+
        execute: function() {
+
            // Command implementation goes here
+
        }
+
    }, {
+
        id: "example.linkaccount",
+
        nls: "example/nls/messages", // Refer to the master bundle
+
        nameKey: "GetPlugins",
+
        tooltipKey: "GetPluginsTooltip",
+
    });
+
</source>
+
  
Note that when referring to the strings, we've used the master bundle name <tt>example/nls/messages</tt>, as we do not want to specify which particular locale is ultimately loaded. The i18n loader will make that decision for us.
+
=== Download the sample plugin ===
 +
You can download the [[File:ThirdPartyNLSPlugin.zip]] and host it somewhere and test by yourself.
  
 
== String Xtrnalizr ==
 
== String Xtrnalizr ==
Line 263: Line 181:
 
#When you are done click "Apply Changes" button to generate the messages file.
 
#When you are done click "Apply Changes" button to generate the messages file.
 
#'''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 [http://dojotoolkit.org/documentation/tutorials/1.6/i18n/] to learn creating dojo 1.7 i18n files. See also [[https://wiki.eclipse.org/Orion/Meeting_minutes/20121220 Editor no longer requires dijit/dojo * Close to getting navigator dijit/dojo free]]
 
#'''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 [http://dojotoolkit.org/documentation/tutorials/1.6/i18n/] to learn creating dojo 1.7 i18n files. See also [[https://wiki.eclipse.org/Orion/Meeting_minutes/20121220 Editor no longer requires dijit/dojo * Close to getting navigator dijit/dojo free]]
#Recovering from accidental localization - I 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.
+
#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  ==
 
== Server  ==

Latest revision as of 15:11, 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 tooltip are loaded during the plugin loading. However the fixed text inserted by the plugin is dynamic and 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 translated to 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 translated to 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