TornadoFX makes it very easy to support multiple languages in your app.
Each Component
has access to a property called messages
of type ResourceBundle
. This can be used to look messages in the current locale and assign them to controls programmatically:
class MyView: View() {
init {
val helloLabel = Label(messages["hello"])
}
}
A label is programmatically configured to get it's text from a resource bundle
As well of the shorthand syntax messages["key"]
, all other functions of the ResourceBundle
class is available as well.
The bundle is automatically loaded by looking up a base name equal to the fully qualified class name of the Component
. For a Component named views.CustomerList
, the corresponding resource bundle in /views/CustomerList.properties
will be used. All normal variants of the resource bundle name is supported, see ResourceBundle Javadocs for more information.
When an FXML
file is loaded via the fxml
delegate function, the corresponding messages
property of the component will be used in exactly the same way.
<HBox>
<Label text="%hello"/>
</HBox>
The message with key
hello
will be injected into the label.
You can add a global set of messages with the base name Messages
(for example Messages_en.properties
) at the root of the class path.
When a key is not found in the component bundle, or when there is no bundle for the currrent component, the global resource bundle is consulted. As such, you might use the global bundle for all resources, and place overrides in the per component bundle.
In stead of throwing an exception when a key is not available in your bundle, the value will simply be [key]
. This makes it easy to spot your errors, and your UI is still fully functional while you add the missing keys.
The default locale is the one retrieved from Locale.getDefault()
. You can configure a different locale by issuing:
FX.locale = Locale("my-locale")
The global bundle will automatically be changed to the bundle corresponding to the new locale, and all subsequently loaded components will get their bundle in the new locale as well.
If you want to change the bundle for a component after it's been initialized, or if you simply want to load a specific bundle without relying on the conventions, simply assign the new bundle to the messages
property of the component.
If you want to use the overriden resource bundle to load FXML
, make sure you change the bundle before you load the root view:
class MyView: View() {
init { messages = ResourceBundle.getBundle("MyCustomBundle") }
override val root = HBox by fxml()
}
A manually overriden resource bundle is used by the
FXML
file corresponding to the View
The same technique can be used to override the global bundle by assigning to FX.messages
.
You can override the default locale as early as the App
class init
function by assigning to FX.locale
.
The same conventions are valid for Controllers
and Fragments
, since the functionality is made available to their common super class, Component
.