
Type-safe, code-generated localization: write JSON translations, compile-time generated accessors, plural-form handling with extendable rules, per-module sources, runtime language switching and graceful fallbacks.
"Divide et impera" — translations divided by module, ruled by type safety.
A Gradle plugin that turns i18n/<lang>.json files into a Kotlin object with one function per key, and a small
multiplatform runtime that the generated code calls. You write Tr.Legion.Orders.march() rather than
t("Legion.Orders.march"): a key that no file has is a compile error, and a key that one language lacks stops
the build, so neither turns up untranslated in production.
The translations are compiled in. Nothing is read at runtime and there are no resource files to find, so the same generated code runs on every target the runtime is built for.
| Artifact | What it is |
|---|---|
i18n-plugin — the scribe
|
The Gradle plugin io.github.octavius-framework.i18n. Reads every i18n/<lang>.json of a project and its subprojects, generates the accessor object, and adds it to compilation. |
i18n-core — the tablet
|
The runtime the generated code calls: the current language, the plural rules, placeholders. Kotlin Multiplatform: JVM, JS, Wasm (JS and WASI), Linux, Windows, macOS, iOS. |
The scribe copies the text out once, at build time; the tablet is what gets read afterwards, in whichever language is current.
Both are released together on the same version:
plugins {
id("io.github.octavius-framework.i18n") version "1.2.0"
}
dependencies {
implementation("io.github.octavius-framework:i18n-core:1.2.0")
}The plugin does not add the runtime by itself, and the generated code does not compile without it. In a Kotlin
Multiplatform project the runtime goes into commonMain instead — see the Quickstart.
src/main/i18n/pl.json:
{
"Legion": {
"Orders": {
"march": "Marsz!"
},
"Units": {
"cohort": {
"_one": "{0} kohorta",
"_few": "{0} kohorty",
"_many": "{0} kohort",
"_other": "{0} kohorty"
}
}
}
}OctaviusI18n.currentLanguage = "pl"
Tr.Legion.Orders.march() // "Marsz!"
Tr.Legion.Units.cohort(3) // "3 kohorty"
Tr.Legion.Units.cohort(17) // "17 kohort"main or commonMain; with any other setup the generation task still exists, but nothing
compiles what it writes.The guides start from the documentation index; the Quickstart is where to begin from an empty project. Every change is recorded in the CHANGELOG.
Licensed under the Apache License, Version 2.0.
"Divide et impera" — translations divided by module, ruled by type safety.
A Gradle plugin that turns i18n/<lang>.json files into a Kotlin object with one function per key, and a small
multiplatform runtime that the generated code calls. You write Tr.Legion.Orders.march() rather than
t("Legion.Orders.march"): a key that no file has is a compile error, and a key that one language lacks stops
the build, so neither turns up untranslated in production.
The translations are compiled in. Nothing is read at runtime and there are no resource files to find, so the same generated code runs on every target the runtime is built for.
| Artifact | What it is |
|---|---|
i18n-plugin — the scribe
|
The Gradle plugin io.github.octavius-framework.i18n. Reads every i18n/<lang>.json of a project and its subprojects, generates the accessor object, and adds it to compilation. |
i18n-core — the tablet
|
The runtime the generated code calls: the current language, the plural rules, placeholders. Kotlin Multiplatform: JVM, JS, Wasm (JS and WASI), Linux, Windows, macOS, iOS. |
The scribe copies the text out once, at build time; the tablet is what gets read afterwards, in whichever language is current.
Both are released together on the same version:
plugins {
id("io.github.octavius-framework.i18n") version "1.2.0"
}
dependencies {
implementation("io.github.octavius-framework:i18n-core:1.2.0")
}The plugin does not add the runtime by itself, and the generated code does not compile without it. In a Kotlin
Multiplatform project the runtime goes into commonMain instead — see the Quickstart.
src/main/i18n/pl.json:
{
"Legion": {
"Orders": {
"march": "Marsz!"
},
"Units": {
"cohort": {
"_one": "{0} kohorta",
"_few": "{0} kohorty",
"_many": "{0} kohort",
"_other": "{0} kohorty"
}
}
}
}OctaviusI18n.currentLanguage = "pl"
Tr.Legion.Orders.march() // "Marsz!"
Tr.Legion.Units.cohort(3) // "3 kohorty"
Tr.Legion.Units.cohort(17) // "17 kohort"main or commonMain; with any other setup the generation task still exists, but nothing
compiles what it writes.The guides start from the documentation index; the Quickstart is where to begin from an empty project. Every change is recorded in the CHANGELOG.
Licensed under the Apache License, Version 2.0.