Prepare a Java Source File for Localization
This guide explains how to prepare a Java source file in Jenkins core or a plugin for localization.
Step 1: Identify messages
First, we need to identify the localizable strings that should be translated. In general, everything shown on any user interface should be internationalized (i.e. prepared for localization into the user’s language).
Historically, log messages to be written to the Jenkins server log file from a logger aren’t translated, but could also be.
Let’s consider the following example, taken from the sample HelloWorldBuilder
:
public FormValidation doCheckName(@QueryParameter String value)
throws IOException, ServletException {
if (value.length() == 0)
return FormValidation.error("Please set a name"); (1)
if (value.length() < 4)
return FormValidation.warning("Isn't the name too short?"); (2)
return FormValidation.ok();
}
...
/**
* This human readable name is used in the configuration screen.
*/
public String getDisplayName() {
return "Say hello world"; (3)
}
@Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
// To persist global configuration information,
// set that to properties and call save().
useFrench = formData.getBoolean("useFrench"); (4)
// ^Can also use req.bindJSON(this, formData);
// (easier when there are many fields; need set* methods for this, like setUseFrench)
save();
return super.configure(req,formData);
}
1 | This string should be internationalized, as it is used as a form validation response. |
2 | This string should also be internationalized, as it is another form validation response. |
3 | This is the display name of the build step on the UI, and should also be internationalized. |
4 | This is an internal identifier for a form configuration option and must not be internationalized. |
Step 2: Prepare the Messages.properties
file
See IDE Configuration for plugins that make this and the following steps easier. |
The localized strings for the default language (typically English), unless they are reused within the same component, are typically added to a Messages.properties
file in the same package as the class that uses it.
Do not reference other components (e.g. core’s) |
Using the default Maven project layout, the HelloWorldBuilder
class stored in the source file src/main/java/org/jenkinsci/plugins/example/HelloWorldBuilder.java
would use the localized strings in the resources file src/main/resources/org/jenkinsci/plugins/example/Messages.properties
(basically, in the same package).
Create that file if it doesn’t exist.
Now, let’s add entries for the localizable strings identified above to that file:
HelloWorldBuilder.NoName=Please set a name (1)
HelloWorldBuilder.ShortName=\(2)
Isn''t the name too short? (3)
# Unicode variant of the line above: (4)
# Isn\u2019t the name too short? (5)
HelloWorldBuilder.DisplayName=Say hello world
1 | This sets the value for the key HelloWorldBuilder.NoName .
While the key can be freely chosen, it’s typically a good idea to indicate where it’s used, as multiple files may share the same Messages.properties file.
This is also the format generated by the Stapler Plugins for IntelliJ IDEA and NetBeans. |
2 | Line breaks, mostly useful with very long values, e.g. usage instructions, can be escaped with a back slash. Make sure to not add whitespace after it. |
3 | In properties files, single quotes need to be escaped with another single quote. Alternatively, a Unicode apostrophe could be used here as well. |
4 | Lines starting with the # character are comments. |
5 | The file encoding for .properties files is ISO-8859-1 (Latin 1), so characters not in that set need to be specified using their Unicode code point, e.g. \u2019 for the apostrophe. |
Step 3: Build the project once
After adding new entries to any Messages.properties
file (or renaming existing ones), the project needs to be rebuilt so the localizer can generate source code from it.
While we can refer to them in source code without that, we only get autocompletion once the Messages
class has been generated.
Step 4: Reference Messages
strings
After code generation has run, we can add references to the generated class to the source code. Example:
public FormValidation doCheckName(@QueryParameter String value)
throws IOException, ServletException {
if (value.length() == 0)
return FormValidation.error(Messages.HelloWorldBuilder_NoName());
if (value.length() < 4)
return FormValidation.warning(Messages.HelloWorldBuilder_ShortName());
return FormValidation.ok();
}
If your IDE doesn’t offer autocompletion even after building the project once, make sure the output folder of the localizer, target/generated-sources/localizer
, is configured and recognized as a directory containing generated source code.