The i18n addon provides backend services and a Web UI to manage your application’s locales and translations.

Dependencies

If you only need to internationalize at server-side, add the following dependency:

<dependency>
    <groupId>org.seedstack.addons.i18n</groupId>
    <artifactId>i18n-core</artifactId>
</dependency>
Show version
dependencies {
    compile("org.seedstack.addons.i18n:i18n-core:3.0.0")
}

If you need to expose internationalization REST APIs for your frontend, use the following dependency instead:

<dependency>
    <groupId>org.seedstack.addons.i18n</groupId>
    <artifactId>i18n-rest</artifactId>
</dependency>
Show version
dependencies {
    compile("org.seedstack.addons.i18n:i18n-rest:3.0.0")
}

If you also need the W20 UI, use the following dependency instead:

<dependency>
    <groupId>org.seedstack.addons.i18n</groupId>
    <artifactId>i18n-web</artifactId>
</dependency>
Show version
dependencies {
    compile("org.seedstack.addons.i18n:i18n-web:3.0.0")
}

Persistence

The i18n add-on uses JPA to store its data in a relational database. You need to configure its JPA unit named seed-i18n-domain. See the (http://seedstack.org/addons/jpa/) for details about how to configure JPA units. An example could be:

jdbc:
  datasources:
    myDataSource:
        provider: org.seedstack.jdbc.internal.datasource.HikariDataSourceProvider
        url: jdbc:hsqldb:mem:testdb1
jpa:
  units:
    seed-i18n-domain:
      datasource: myDataSource

Security

All the REST APIs are secured with permissions. These permissions are bound to two default roles:

  • seed-i18n.reader for read access
  • seed-i18n.translator for read/write/delete access

You can map those i18n roles to your own realm roles. Consider the following users:

  • john having the role MYPROJECT.DEVELOPER,
  • admin having the role MYPROJECT.ADMIN.

You can map the i18n roles like this:

security:
  roles:
    seed-i18n.reader: [ MYPROJECT.DEVELOPER, MYPROJECT.ADMIN ]
    seed-i18n.translator: [ MYPROJECT.ADMIN ]

It is possible to create more fine grained security roles using the provided permissions. Below is the list of available permissions:

seed:i18n:locale:read
seed:i18n:locale:write
seed:i18n:locale:delete

seed:i18n:key:read
seed:i18n:key:write
seed:i18n:key:delete

seed:i18n:translation:read
seed:i18n:translation:write
seed:i18n:translation:delete

Cache (Optional)

The add-on uses cache to improve i18n performances. By default, this cache does not need configuration, but it is possible to change the configuration as follow:

i18n:
  cache:
    initialSize: 2048
    maxSize: 8192
    concurrencyLevel: 32

Backup/Restore

The «Manage Keys» interface provides CSV import/export functionality. The exported CSV file is in UTF-8 in order to support all the possible languages.

Usage

Locales

The i18n add-on stores application available locales and default locale. Available locales are the locales in which the application is translated, i.e. available to users. The default locale is the «native language» of the application. This locale will be used as starting locale for translations.

Locales can be managed with i18n administration interface or programmatically with the LocaleService.

public class SomeClass {
    @Inject
    private LocaleService localeService;
}

Localization

Localization is provided by the LocalizationService which allows to localize date, number, string and currency.

public class SomeClass {
    @Inject
    private LocalizationService localizationService;
}

The LocalizationService allows to translate i18n keys in different locales using the localize(String, String) method. This method will fallback on the parent locale if the required locale is not present.

public class SomeClass {
    @Inject
    private LocalizationService localizationService;

    public void someMethod() {
        // Case 1: fr-BE translation is present
        localizationService.localize("fr-BE", "key1"); // -> "translation fr-BE"
        
        // Case 2: fr-BE translation is NOT present, but fr translation is present
        localizationService.localize("fr-BE", "key1"); // -> "translation fr"
        
        // Case 2: no translation present
        localizationService.localize("fr-BE", "key1"); // -> "[key]"
    }
}