In many languages there are country or region specific words. You wonder if you should provide resource bundles for each country while only a small subset of words is different. For this scenario you can use property inheritance which is nicely explained here.
So let's say I want to provide translations for english and Dutch. Because we want to provide Dutch translations for both Netherlands and Belgium we want to use the following locales: nl_NL(dutch) and nl_BE (flemish). Instead of duplicating the nl_NL resource file myResource_nl_NL
.properties to myResource_nl_BE.properties
we can create a general myResource_nl.properties
file and specify a myResource_nl_BE.properties
file which only differs for a few keys. If we retrieve a resource with getResource(resource = "some.key", locale="nl_BE) it will try to lookup this key in the following order
myResource_nl_BE.(properties|json)
myResource_nl.(properties|json)
myResource.(properties|json)
As you can see this lookup order does not stop at myResource.nl.(properties|json). It even goes up to a resource file without language indication. This can be especially useful if you create your app in one language, and only have incomplete translations for other languages. So let's say you create an english language app, you could just create a myResource.(properties|json)
file and assume your main language is english. If you want to provide French as a second language but don't have the full translation yet (because it is a community effort for example) you can add myResource.fr.(properties|json)
as a resource file, so you can provide a growing number of translated resource keys.
It is even possible to be more specific by adding country variants, e.g myResource.en_GB_someVariant.properties
Now that you have completed the initialization of the i18n settings in the configuration file, you are ready to code for them. There are several methods that are available to all handlers, interceptors, layouts and views that deal with i18n via runtime mixins. You can use these methods directly or go to the services directly if you inject them.
This module registers the following models in WireBox:
i18n@cbi18n
: Helper with all kinds of methods for localization
resourceService@cbi18n
: Service to interact with language resource bundles
The module registers the following methods for handlers/layouts/views/interceptors:
You can leverage the getResource() or $r()
method to retrieve resources from specific bundles by using the bundle
argument or the @bundle
convention.
We do like our @bundle
convention as it looks prettier and you type a lot less.
all bundles, including the default one, have names (aliases). If you want you can specify a resource in your default bundle as
Here are some examples of usage
INFO Please note that the i18N services are singleton objects and lives throughout your entire application span.
You can place the i18n@cbi18n
service in the prc
scope and then use this utility for i18n specific methods anywhere in your layouts and views, below is a simple example:
INFO There are tons of great utility methods in the i18n service that will allow you to work with localization and internationalization. Please view them via the API Docs for the latest methods and arguments.
If you elect not to use property files for your resource bundles, or need to expand your i18n implementation to include content pulled from other sources, the module allows for the specification of a customResourceService
in the configuration.
To begin, create a custom resource service which extends the core i18n resource service:
To override the resource bundle used, you would declare a new loadResourceBundle
method. To override the implementation of the getResource( i18nResourceLabel )
you would declare a new getResource
method. An example, using your database to retrieve an i18n resource bundle:
Lets say we want to account for a more complex metadata structure in our resource bundles. For example, allow a draft
value to allow for administrators to see which items in our bundle are pending review but display the default value to the public. We might also want to add any new resource requests containing a default value as drafts in the system (which we won't cover here). For special circumstances, such as these, we would need to change the implementation of the getResource
method to account for this draft functionality:
The ability to extend and implement custom resource services provides you with a great deal of flexibility in your internationalization efforts. Use cases might include database-driven i18n resources, distributed caching implementations, and variable bundle formats used in third-party tools and plugins.
For existing projects you probably have existing resource files, probably JSON files or java resources. For new projects you can ask yourself if you would choose JSON or java properties. Here are some pros and cons
JSON is a simple file format, supported by many editors.
Many frontend Javascript frameworks also support JSON
If you use many different locales it can become complex to make sure all keys are entered in all resource bundles. You might need specialized editors to keep track of all translated keys.
It is not hard to generate your own JSON resource files from a database.
if you already used cbi18n v1 you probably have java properties files.
there are very capable (free) resource editors available for java properties.
Several web based translation facilities provide export to java properties and/or json resources
A very basic list of resource editors will be discussed in the next paragraph.
most code editors can be used for JSON editing, but if you have large resource files or many locales you can probably better use a specialized tool, which keeps track of missing translations
BabelEdit is a very capable and affordable resource editor, for both JSON and java properties. It can edit JSON flavours for vue and angular libraries and also has support for other resource bundle formats. However it can not convert between formats. Only conversion between flat and nested JSON files is supported.
the Eclipse Resource Bundle Editor plugin is a FANTASTIC editor for eclipse: More info here https://essiembre.github.io/eclipse-rbe/
Attesoro is another free resource editor, a bit more limited and dated, but still usable.
BabelEdit is a very capable and affordable resource editor, for both JSON and java properties.
Below you can see some screenshots of the eclipse resource bundle editor plugin. I really recommend this tool.
INFO Make sure your files are all utf-8 encoding. It's also good i18n practice to liberally use cfprocessingdirective