Internationalization of Strings in Code
The purpose of this page is to describe the mechanisms by which we externalize strings in the platform to make sure that all of engineering externalizes their strings in the same way.
Overall Standards
What strings get externalized?
All java code should have their strings externalized except for the following:
- Test Cases - we do not need to externalize strings in test case classes
- DEBUG/Trace messages do not need externalized either.
Concatenation
Concatenation of strings to formulate a message is a no-no in an internationalized application. To support this, you need to use replaceable parameters. This is because the subject and verb are in different places depending upon the language.
Instead of
String in messages.properties: SomeClass.FILE_NOT_FOUND_MSG=File was not found:
Line of code: error(Messages.getString("SomeClass.FILE_NOT_FOUND_MSG") + theFileName);
Use this
String in messages.properties: SomeClass.FILE_NOT_FOUND_MSG=File was not found: {0}
Line of code: error(Messages.getString("SomeClass.FILE_NOT_FOUND_MSG", theFileName));
All messages need meaningful names
In the Eclipse string externalization dialog, Eclipse will default to simply numbering the un-externalized strings from zero. You need to replace that number with a meaningful name, using underscores for spaces, and using all uppercase letters:
Instead of
SomeClass.0=File was not found
Use this
SomeClass.FILE_NOT_FOUND_MSG=File was not found
Error Messages use getErrorString, not getString
For errors, we've determined that it's way easier for us to find where the problem is if the user has an error number to work from. That error number should be unique to the class prefix. The formatErrorMessage method in MessageUtil will produce a message that includes the error number, only if you remember to call getErrorString instead of getString. For example:
System.out.println(getString("ChartEngine.ERROR_0002_COULD_NOT_CREATE_CHART")); Invalid chart definition System.out.println(getErrorString("ChartEngine.ERROR_0002_COULD_NOT_CREATE_CHART")); ChartEngine.ERROR_0002 - Invalid chart definition
Note that getErrorString will show the actual error number in the log. This lets us hone right in on the code that threw the message to the server log.
Message Prefixes
When creating messages for externalization, we have standards that are used to help the translator decide what strings to translate first. Here are the standards:
Prefix |
Description |
---|---|
USER_ |
This is a message that appears in the user interface somewhere. It may be a message, a description, anything. If it shows up in the UI, it should begin with a USER_ prefix. For example: GlobalListsPublisher.USER_DESCRIPTION |
ERROR_xxxx |
For error messages. The xxxx is a sequential number for the specific class it's associated with. For example: Email.ERROR_0001_TO_NOT_DEFINED |
CODE_ |
This indicates a string that shouldn't be translated. |
DEBUG_ |
As it sounds, this is a DEBUG-level string that appears in the server log - internationalization not required for debug strings |
TRACE_ |
As it sounds, this is a TRACE-level string that appears in the server log - internationalization not required for trace strings |
WARN_ |
As it sounds, this is a WARN-level string that appears in the server log |
INFO_ |
As it sounds, this is a INFO-level string that appears in the server log |
Single Quotes
As much as possible, single-quotes need to be avoided in messages that contain replaceable parameters ({n}). In cases where it cannot be avoided, then you need to be sure to escape them (use two single-quotes). Simply re-wording the message is usually sufficient. Instead of using quotes to highlight a value in the text is not recommended - I suggest using square brackets. This could also be extremely problematic if the string ends up in the client as a piece of Javascript.
Here are some examples:
Instead of
The system couldn't find the file '{0}'
Use This
The file [{0}] could not be found.
Example of using Eclipse to externalize an error string
Step 1 - Find a string needing externalization
Assume you've created a new error string, or you're working through warnings in the application and stumble on a string requiring externalization. Here is what it should look like in the Java editor (assuming your compiler warnings are set properly - see Compiler Warning Settings).
Step 2 - Go into Externalize strings
Right-click in the source window, and follow the menus.
Step 3 - Set up the External Strings Dialog
There are some really important things to make sure of when you get to the Externalize Strings dialog. Here is approximately what it should look like:
IMPORTANT Stuff to Note
- Notice the first red-outlined box - the common prefix. This is, by convention, the name of the class.
- Next red box is the Key to be created. Notice the .0 part. This needs renaming
- The most important thing on this dialog is the Accessor class. This must be set to org.pentaho.messages.Messages or com.pentaho.messages.ProMessages.
Step 4 - Find the biggest error number in use
To locate the largest error number already in use, you should un-check the upper-right check-box for filtering out existing externalized entries. Then, you can see the error numbers already in use. If you're doing this on a class that has never had the strings externalized, then you won't have to worry about this step - you can just start numbering from 0001. In the case below, ERROR_0006 is the highest number in use.
Step 5 - Create the error string identifier
Now you know that you're creating ERROR_0007_<meaningful name> - create the name, all in uppercase using underscore (_) for spaces.
Step 6 - Click finish.
The next page of the process should show you a before-and-after look at the source. If it is prompting you to create a file, then you know you forgot to set the accessor class on the previous page. Go back and fix it if this is the case.
Step 7 - Fix the error message method call
When externalizing messages, be sure to correct the method call used for error messages. It should be getErrorString, not getString.
Using Eclipse to find broken externalized strings
This feature seems to have shown up in recent Eclipse releases (3.2 or later). You can use this feature to remove strings which are no longer being used.