Patois

Type-safe internationalization (i18n) library and Gradle plugin for Kotlin Multiplatform projects.
Features
- Type-safe translations: Generates Kotlin classes from YAML translation files
- Compile-time safety: Missing translations and typos caught at compile time
- Kotlin Multiplatform: Supports JVM, iOS (arm64, x64, simulator), and JS (browser, Node.js)
- Parameter interpolation:
{param} style arguments become function parameters
- Nested keys: Organize translations hierarchically with nested YAML maps
- Ktor integration: Optional server-side locale resolution from HTTP headers
Installation
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("io.github.erabti.patois") version "0.1.0"
}
dependencies {
implementation("io.github.erabti.patois:patois-core:0.1.0")
implementation("io.github.erabti.patois:patois-extension-ktor:0.1.0")
}
Quick Start
1. Create translation files
Create YAML files in src/main/resources/translations/:
greeting: Hello
welcome: "Welcome, {name}!"
errors:
notFound: Page not found
unauthorized: Access denied
greeting: Hallo
welcome: "Willkommen, {name}!"
errors:
notFound: Seite nicht gefunden
unauthorized: Zugriff verweigert
2. Configure the plugin (optional)
patois {
className = "AppStrings"
packageName = "com.example.i18n"
baseLocale = "en"
}
3. Use generated code
After running ./gradlew generateTranslations (or any compile task):
import com.example.i18n.AppStrings
import com.example.i18n.AppStringsEn
import com.example.i18n.AppStringsDe
import com.example.i18n.AppLocale
val strings: AppStrings = AppStringsEn()
println(strings.greeting)
println(strings.welcome("World"))
println(strings.errors.notFound)
locale = AppLocale.EN
localizedStrings = locale.toStrings()
resolved = AppLocale.resolver()
Configuration Options
Ktor Integration
For Ktor server applications, add the extension dependency and install the plugin:
import io.github.erabti.patois.ktor.installPatoisPlugin
import com.example.i18n.AppLocale
fun Application.module() {
installPatoisPlugin(AppLocale.resolver)
installPatoisPlugin(AppLocale.resolver) {
localeExtractor = PatoisLocaleExtractor { call ->
call.request.cookies["locale"]
?: call.request.headers["Accept-Language"]
}
}
}
In route handlers, use the generated strings extension property:
import com.example.i18n.strings
routing {
get("/hello") {
call.respondText(strings.greeting)
}
get("/welcome/{name}") {
val name = call.parameters["name"] ?: "Guest"
call.respondText(strings.welcome(name))
}
}
Generated Code Structure
For translation files en.yaml and de.yaml, the plugin generates:
Modules
Requirements
- Kotlin 2.0+
- Gradle 8.0+
- JVM 21+ (for the Gradle plugin)
License
Copyright 2024 Ahmed Erabti
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance the License.
You may obtain a copy of the License at
http:
Unless applicable law agreed to writing, software
distributed under the License distributed an BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
See the License the specific language governing permissions
limitations under the License.