I18n player

=Internationalizing the Player Interface=

Overview
All text that is generated by VASSAL and displayed while playing a module must be made Translatable. For background, review the I18n tutorial at java.sun.com.

Vassal has two PropertyResourceBundles in VASSAL.i18n
 * VASSAL.properties contains all strings for the User Interface
 * Editor.properties contains strings for the Module Editor Interface

Even though Module Editor i18n is not happening yet, I have created the necessary support to enable it.

Basic Text Translation
Anywhere in VASSAL that generates a string that will be seen by a user during play, must be converted to pass through the i18n interface.

Here is a typical example from NotesWindow.java setting the title of the window to the word 'Notes':

 frame.setTitle("Notes");

This is converted to:

 frame.setTitle(Resources.getString("Notes.notes"));

with the corresponding property entry in VASSAL.properties:

 # Notes Window  Notes.notes=Notes

Commonly Used Strings
There are a number of strings that are used again and again in different places in VASSAL. So that these do not need to be translated numerous times, they have been grouped together in the properties file:

''# General Strings General.VASSAL=VASSAL General.add=Add General.save=Save General.cancel=Cancel ...''

And corresponding Constants created in Resources.java:

'' /*   */   public static final String VASSAL = "General.VASSAL"; public static final String ADD = "General.add"; public static final String SAVE = "General.save"; public static final String CANCEL = "General.cancel";''
 * Commonly used keys

So that in your code

JButton canButton = new JButton("Cancel");

becomes:

JButton canButton = new JButton(Resources.getString(Resources.CANCEL))

Compound Messages
Messages that combine several pieces of information and strings together must be treated specially. In a different language, the parts of the message may need to be placed in a different order to make sense.

Place holders are used in the message text that are replaced at translation time. For example:

String mess = gameName + " version " + moduleVersion);

becomes:

String mess = Resources.getString("BasicModule.version_message", gameName, moduleVersion);

with a corresponding VASSAL.properties entry of:

BasicModule.version_message={0} version {1}</tt>

Resources.java contains two convenience methods for translating compound messages with one or two components. Just use Resources.getString with the additional String aruments as required. If you have a compound message with more than 2 components, you need to pass the message components as a String Array:

String mess = Resources.getString("Builder.create_error", new String[] { className, classPath, errorMessage };</tt>

Property file entry:

Builder.create_error=Unable to create class {0} in {1}\n{2}</tt>

Testing and Translating
Copy VASSAL.properties into your VASSAL home directory (not documenation directory). On windows, this is usually C:/Documents and Settings/ /VASSAL.

Download a suitable translation tool and create a new Properties file containing the translation. I would recommend the free program Attesoro available from http://attesoro.org/

This will create a Localized properties file name VASAL_xx.properties or VASSAL_xx_YY.properties
 * xx is a 2 character language identifier
 * YY is a 2 character Country identifier (needed if you want to make English dialect translations)

Ultimately, this file will be committed to VASSAL.i18n and become a standard translation available within VASSAL and will automatically activate for users whose Locale matchs the language/country specified. For testing, this file can be placed into the VASSAL home directory.