Internationalization
The bot you are developing is likely to be used by people which primary language is not English. To support these users, Botrino encourages the externalization of strings so they can be translated more conveniently.
The Translator interface
The Translator interface has one abstract method Locale getLocale() which defines what is the target locale of the
translator, and a default method String translate(String, String, Object...) which effectively does the translation.
By default, the translate method does the following:
default String translate(String bundle, String key, Object... args) {
return MessageFormat.format(ResourceBundle.getBundle(bundle, getLocale()).getString(key), args);
}
- Strings are located in a
ResourceBundlewhich name is given. Typically, that's the name of a.propertiesfile located at the root of the resources folder. - Strings are parameterized using
MessageFormat, which aims at being a language-independent way to put variables in a string, unlikeString.format().
Externalizing strings
If let's say you have a file named AppStrings.properties in src/main/resources with the following contents:
hello=Hello {0}!
You can use a translator like this:
var tr = Translator.to(Locale.ENGLISH);
System.out.println(tr.translate("AppStrings", "hello", "Alex"));
Which gives the output:
Hello Alex!
What happened here?
- The first argument of
tr.translateisAppStrings, so it will look for aResourceBundlenamedAppStrings. It will find theAppStrings.propertiesand will load its content. - The second argument says to find the string with key
hello, which is what we defined earlier. - The third argument will substitute the
{0}of our string with the value at runtime, hereAlex.
To learn more about resource bundles and string argument formatting, check out the Javadoc
for ResourceBundle
and MessageFormat. Note
that since Translator.translate is a default interface method and thus can be overriden, you may customize the way
translations are retrieved, but this section will only document the default behavior.
Using translated strings
Once a string is properly externalized, it is possible to add a translation for it by duplicating the resource file and
naming it with the locale suffix. For example, if you have src/main/resources/AppStrings.properties and want to
translate it in French, you will duplicate the file and name the copy src/main/resources/AppStrings_fr.properties. The
way to name the translated files is documented in
the ResourceBundle javadoc.
In your AppStrings_fr.properties, you will translate the value of the hello string:
hello=Bonjour {0} !
In your Java code, you can now specify either English or French locale and the string will adapt automatically:
var tr1 = Translator.to(Locale.ENGLISH);
var tr2 = Translator.to(Locale.FRENCH);
System.out.println(tr1.translate("AppStrings", "hello", "Alex"));
System.out.println(tr2.translate("AppStrings", "hello", "Alex")); // notice we use exact same arguments
Which gives the output you want:
Hello Alex!
Bonjour Alex !