/i18n4k

Internationalization for Kotlin

Primary LanguageKotlinApache License 2.0Apache-2.0

i18n4k

Version Kotlin Kotlin Kotlin License

Kotlin/Multiplatform Kotlin/JVN Kotlin/JS Kotlin/Native

i18n4k

Internationalization for Kotlin

Home: github.com/comahe-de/i18n4k

Lastest release version: 0.3.0

Table of contents

About

i18n4k is a multiplatform (JVM, JS, native) library and code generator for Kotlin to handle internationalisation (i18n) in your program.

It provides

  • Locale class to store the selected language
  • LocalizedString class that stores the reference to the translatable message. The toString() will return the message string in the currently selected language/locale.
  • Parameter support via LocalizedStringFatory* that creates a LocalizedString with the supplied parameters using a parameter format like "Hello, {0}!"
  • Code generators that creates...
    • ... access objects with a constant per message key
    • ... objects for inline storing of messages of specified locales (no need of loading resources at runtime)
    • ... optimized message files for loading message resources at runtime
  • The code generators currently can load Java Properties files (but can be extended for additional formats).
  • Gradle plugin to start the code generator

Supported platforms

  • Java (JVM)
  • JS (legacy and IR backend)
  • Native:
    • iosArm32
    • iosArm64
    • iosX64
    • macosX64
    • mingwX64
    • linuxX64

Artefact repository

Ensure that you have Maven-Central (mavenCentral()) in your repository list

repositories {
    mavenCentral()
}

Gradle dependencies

For multiplatform projects: add de.comahe.i18n4k:i18n4k-core:<VERSION> to commonMain source set.

val commonMain by getting {
    dependencies {
        implementation("de.comahe.i18n4k:i18n4k-core:<VERSION>")
    }
}

For Kotlin/JS: add de.comahe.i18n4k:i18n4k-core-js:<VERSION> to the dependencies

dependencies {
    implementation("de.comahe.i18n4k:i18n4k-core-js:0.3.0")
}

For Kotlin/Jvm: add de.comahe.i18n4k:i18n4k-core-jvm:<VERSION> to the dependencies

dependencies {
    implementation("de.comahe.i18n4k:i18n4k-core-jvm:0.3.0")
}

Gradle plugin

Apply the plugin "de.comahe.i18n4k", e.g:

plugins {
    id("de.comahe.i18n4k") version "<VERSION>"
}

The configuration is done via the i18n4k object, e.g.:

i18n4k {
    sourceCodeLocales = listOf("en", "de")
}

For the full list of parameters, see I18n4kExtension

Code generation

The Gradle plugin can generate code to access the message via constants instead of string keys or similar.

Adding message bundles

By default, the language files of the message bundles are searched in the path src/main/i18n (normal projects) respectively src/commonMain/i18 (for multiplatform projects). See configuration for other folder locations.

Any sub folder in this directory will be converted to a package in the Kotlin code.

Inline storing of translations

To avoid loading of translations at runtime, there is also the possibility to include the messages in the source code. So the translations are always available and no need for platform-specific loading of resources is needed. Drawback is that the messages are hold in memory all the time. So only the most important translations should be stored in the source code.

Optimized message files

i18n4k has an internal format to store message files to be loaded at runtime. It is index-based instead of key-bases as e.g. Java-Property files. This has the advantage that no memory is wasted for storing the key in each language.

More details are described here MessagesProviderViaLoadingText

Runtime configuration

The current locale and other parameters are stored in the global variable i184k of type I18n4kConfig

Predefined implementations of I18n4kConfig are:

The configuration can be changed by assigning (and editing) one of these implementation to the i184k variable.

Example

Source files are the following message bundle as Java-Properties files located in the src/main/i18n/x/y/ folder

MyMessages_en.properties

sayHello=Hello, {0}!
title=Internationalisation example \uD83C\uDDEC\uD83C\uDDE7

MyMessages_de.properties

sayHello=Hallo, {0}!
title=Internationalisierung Beispiel \uD83C\uDDE9\uD83C\uDDEA

In the Gradle script, "en" is defined as source code locale (to be stored in source code)

i18n4k {
    sourceCodeLocaleCodes = listOf("en")
}

This results in the following generate Kotlin code

package x.y

import de.comahe.i18n4k.Locale
import de.comahe.i18n4k.messages.MessageBundle
import de.comahe.i18n4k.messages.providers.MessagesProvider
import de.comahe.i18n4k.strings.LocalizedString
import de.comahe.i18n4k.strings.LocalizedStringFactory1
import kotlin.Array
import kotlin.Int
import kotlin.String

/**
 * Massage constants for bundle 'MyMessages'. Generated by i18n4k.
 */
public object MyMessages : MessageBundle() {
    /**
     * Hello, {0}!
     */
    public val sayHello: LocalizedStringFactory1 = getLocalizedStringFactory1(0)

    /**
     * Internationalisation example 🇬🇧
     */
    public val title: LocalizedString = getLocalizedString0(1)

    init {
        registerTranslation(MyMessages_en)
    }
}

/**
 * Translation of message bundle 'MyMessages' for locale 'en'. Generated by i18n4k.
 */
private object MyMessages_en : MessagesProvider {
    private val _data: Array<String?> = arrayOf(
        "Hello, {0}!",
        "Internationalisation example 🇬🇧"
    )

    public override val locale: Locale = Locale("en")

    public override val size: Int = _data.size

    public override fun `get`(index: Int): String? = _data[index]
}

And the following message file:

MyMessages_de.i18n4k.txt

de
^
Hallo, {0}!
^
Internationalisierung Beispiel 🇩🇪
^

The messages can than be accessed like this

println(MyMessages.sayHello("i18n4k"))

which prints

Hello, i18n4k!

The German message file can be loaded at runtime, e.g. like this (for JVM plattform)

MyMessages.registerTranslation(MessagesProviderViaResource(pathToResource = "/x/y/MyMessages_de.i18n4k.txt"))

Changing the locale can be done like this:

val i18n4kConfig = I18n4kConfigDefault()
i18n4k = i18n4kConfig
i18n4kConfig.locale = Locale("de")

Afterwards the expression from above prints

Hallo, i18n4k!

Example projects

Please also check the examples projects in the examples folder!

Contribute

Status

The library is under development. So the API is not stable. Enhancements and feature request are very welcome.