Localization
From Jin
Starting with version 2.14, Jin is almost entirely internationalized. This means that (almost) no language or country specific information is hard-coded in Jin's source. All such information is stored in separate files which are loaded by Jin at runtime.
Contents |
Overview
Jin can be localized (translated to a specific language) by translating the various localization.properties files spread throughout Jin's source code. A properties file is a basically a mapping of keys to values, separated by a '='. Here's an example from the file which localizes Jin's login panel to English:
LoginPanel.title = Login Information LoginPanel.connectButton.text = Connect LoginPanel.registerButton.text = Register LoginPanel.registerButton.tooltip = Register an account
When Jin needs to display the login panel, it loads this file and looks up the values of the required. The keys are, obviously, hard-coded and the values are specific to each localization. For example, when Jin creates the login panel's "Register" button, it will look up the value corresponding to the LoginPanel.registerButton.text and LoginPanel.registerButton.tooltip keys, and create the button with the text and tooltip set to these values.
Getting Started
Before you begin localizing, make sure you have Jin's source code and it compiles and runs. Refer to the Development Setup page for help with downloading and compiling Jin's source code.
This section will walk you through the process of translating (to Russian) a single Jin button - the "Connect" button on the login panel. It will tell you what to do, while the following sections will tell you why and expand on other things you can do.
To begin, we need to create the localization file. The default localization file for the login button is free/jin/ui/localization.properties (under the src directory), and we're translating to Russian, so we'll need to create the file free/jin/ui/localization_ru.properties. Now, add this line to it:
LoginPanel.connectButton.text = Подключиться
and save the file with the encoding UTF-8. Now, recompile Jin and then run it with "java -jar jin.jar locale.language=ru". You should now see that the connect button displays "Подключиться". If, instead, it displays question marks or other weird characters, you've most likely forgotten to set the encoding of the localization file to UTF-8.
You can now finish translating this file and then go on to others. When you are done, contact the current maintainer of Jin and ask him to add your localization.
Localization In Depth
Localization File Naming
For each source package (you can think of it as directory, if you don't know Java) which needs to be translated, Jin has a default localization file, named localization.properties, in that package's directory. As a localizer, your overall task is to translate all these files to whatever language you chose.
The translation of each localization file should go into a new file, placed in the same directory as the translated one, and whose name depends on the language you're translating to. The file should be named as follows:
localization_language_country.properties
where
- language
- An ISO Language Code. This is a lower-case, two-letter code as defined by ISO-639. You can find a full list of these codes at http://www.loc.gov/standards/iso639-2/englangn.html. The code for English, for example, is "en"; for Russian - "ru".
- country
- An ISO Country Code. This is an upper-case, two-letter code as defined by ISO-3166. You can find a full list of these codes at http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html. The code for the United Kingdom, for example, is "GB"; for Russia - "RU".
The country code is optional, but can be used if you want different translations for different countries using the same language. The canonical example is French/France (fr_FR) and French/Canada (fr_CA).
Localization File Format
The localization file is a list of key/value pairs, each on a separate line. The format is, actually, the Properties File Format, but we will use only those features of it which we need. Important: Contrary to the properties file format spec, localization files in Jin need to be in the UTF-8 encoding (they are converted to ISO 8859-1 with Unicode escapes automatically by Ant).
Basics
A basic key/value pair is specified as the key, followed by an equals sign, followed by the value (whitespace is ignored where it is expected to be ignored). For example:
LoginPanel.connectButton.text = Connect
The key here is "LoginPanel.connectButton.text" while the value is "Connect". As you can see, the keys are prefixed with the name of the class that uses them. There are also semi-standard naming conventions for specifying properties of various UI elements, but more on that later.
Mnemonics
When specifying the text of a button or a label, the translation sometimes specifies the mnemonic as well, by putting an ampersand (&) before the letter that is to become the mnemonic. For example:
LoginPanel.registerButton.text = Regis&ter
sets the text of the register button to "Register" and the mnemonic to 't'. It is highly recommended for a translation to specify a mnemonic if the default localization does, and vice versa. It is up to the translator to keep mnemonics from clashing - each mnemonic should be unique at the place where it can be activated.
Escapes
Escapes allow you to specify characters you would not be able to specify otherwise. For example:
LoginPanel.membersBorder.title = \ Members LoginPanel.invalidPortsDialog.message = \ The ports text field must contain a\n\ nonempty, space separated, list of ports.\n\ A valid port is a number between 0 and 65535.
The "LoginPanel.membersBorder.title" value demonstrates creating a space character (which would be ignored without the escape). The "LoginPanel.invalidPortsDialog.message" value demonstrates creating a newline character (with "\n") and getting rid of a real newline (by putting a backslash at the end of a line), which would otherwise end the value.
Comments
You can write comments by starting a line with the '#' character. Everything that follows it, until the end of the line, is ignored by Jin.
Compound Values
Sometimes a value is required, parts of which are only known at runtime. For example, preferences dialogs have a title of "[Plugin Name] Preferences" where [Plugin Name] is the name of the actual plugin. To do this, it is possible for translation values to include special strings, which tell Jin where to put the parts that are not known ahead. The special strings have the form {number} (including the curly braces) where number is a 0-based index of the part to put in (there may be more than one). In our example it looks like this:
# {0} is the plugin name
PrefsMenu.pluginPrefsDialog.title = {0} Preferences
Like in this example, the default localization has a comment explaining the meaning of the replacement at each value that has one.
Commandline Arguments
To determine the language and country to use for localization, Jin takes two arguments on the commandline - "locale.language" and "locale.country" (both optional). The two arguments correspond to the language and country codes we've mentioned in the section on naming localization files. For example, to use the French/Canada localization, run Jin with:
java -jar jin.jar locale.language=fr locale.country=CA
This will ask Jin to look up translations in the following localization files, in order (until both the file and a translation are found):
- localization_fr_CA.properties
- localization_fr.properties
- localization.properties
