Internationalization for Kotlin
Home: github.com/comahe-de/i18n4k
Lastest release version: 0.9.0
Table of contents
- About
- Supported platforms
- Artefact repository
- Gradle dependencies
- Gradle plugin
- Code generation
- Runtime configuration
- Hints for Android
- Message format
- Further dokumentation
- Example
- Example projects
- Contribute
- Status
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 languageLocalizedString
class that stores the reference to the translatable message. ThetoString()
will return the message string in the currently selected language/locale.- Parameter support via
LocalizedStringFatory*
that creates aLocalizedString
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
- Java (JVM) & Android
- JS (IR backend)
- Native:
- iosArm64
- iosX64
- iosSimulatorArm64
- macosX64
- macosArm64
- mingwX64
- linuxX64
- tvosArm64
- tvosX64
- tvosSimulatorArm64
- watchosArm64
- watchosX86
- watchosX64
- watchosSimulatorArm64
Ensure that you have Maven-Central (mavenCentral()
) in your repository list
repositories {
mavenCentral()
}
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:0.9.0")
}
}
For Kotlin/JS: add de.comahe.i18n4k:i18n4k-core-js:<VERSION>
to the dependencies
dependencies {
implementation("de.comahe.i18n4k:i18n4k-core-js:0.9.0")
}
For Kotlin/Jvm: add de.comahe.i18n4k:i18n4k-core-jvm:<VERSION>
to the dependencies
dependencies {
implementation("de.comahe.i18n4k:i18n4k-core-jvm:0.9.0")
}
Apply the plugin "de.comahe.i18n4k", e.g:
plugins {
id("de.comahe.i18n4k") version "0.9.0"
}
The configuration is done via the i18n4k
object, e.g.:
i18n4k {
sourceCodeLocales = listOf("en", "de")
}
For the full list of parameters, see I18n4kExtension
The Gradle plugin can generate code to access the message via constants instead of string keys or similar.
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.
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.
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
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.
Generated resource files are not added to the "Java resource", but as "raw Android resources". As Android does not allow sub-folders or uppercase letters, the resource name is adapted: packages names are prefixed to the resource name and concatenated by "_". Also, camel case names are converted to sneak-case, e.g. "/x/y/MyMessages_fr.i18n4k.txt" will be changed to "x_y_my_messages_fr_i18n4k".
Generated raw resources can be loaded in the following way:
MyMessages.registerTranslation(
MessagesProviderViaText(
text = String(
context.resources.openRawResource(
R.raw.x_y_my_messages_fr_i18n4k
).readBytes()
)
)
)
The default message format is similar to the Java-MessageFormat. E.g. the text "Hello, {0}" has one parameter. Any string can be used as parameter name.
The parameter values can also be formatted, e.g. "{0,number, %.2}" formats parameter 0 as number with max. 2 fraction digits. See Formatters for more information.
For messages with parameters, the generator plugin creates special LocalizedStringFactories where the parameters must be supplied as arguments to get the resulting string.
Other message formatters can be implemented and be configured in
I18n4kConfig.messageFormatter
For more advanced features, have a look at the documenation files
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("MyMessages", "x.y") {
/**
* Hello, {0}!
*/
public val sayHello: LocalizedStringFactory1 = getLocalizedStringFactory1("sayHello", 0)
/**
* Internationalisation example 🇬🇧
*/
public val title: LocalizedString = getLocalizedString0("title", 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!
Please also check the examples projects in the examples folder!
- Create an issue on github.
- Open a Pull requests on github.
- Trello board
The library is under development. So the API is not stable. Enhancements and feature request are very welcome.