I18n made simple - for Kotlin!
- (Coming soon!) Auto-generation of your default translation file (en_US by default). No more manual management of your english translation file (or whatever your team's lingua franca is).
- Use human language strings in your code - no more referencing internationalized strings by their key in the translation file.
- Support for pluralization constructs.
- Support for gender constructs.
- (Coming soon!) Support for variable formats (date, number, currency, etc).
- Call
I18nliner.setPath("path/to/your/language/files")
, so that I18nliner knows where to find your translations. - Call
I18nliner.setLocale()
with the language tag you want your app to display (if usingen_US
you can skip this step, that's the default).- Whenever the displayed locale changes (e.g. UserA logs out, UserB who has
their profile set to
pt_BR
logs in), you will need to callsetLocale()
with the new locale, so that all subsequent calls tot()
will reflect the correct language.
- Whenever the displayed locale changes (e.g. UserA logs out, UserB who has
their profile set to
- When developing, call
I18nliner.t("A string to be translated!")
. This will pull from the current locale and return the translated string. (Note: You can also define an override locale on each call, via the signatureI18nliner.t("My string", locale = "pt_BR")
. This will ignore the locale you set viasetLocale()
for that call only.
There is a method tPlural()
, which accepts a required count
number,
and strings for zero
, one
, and other
.
If count == 0
, it will translate the zero
string,
if 1
the one
string, otherwise it will translate the other
string.
This allows you to translate sentences that have completely different structures
based on pluralization. Here's an example:
I18nliner.tPlural(
count = lights.count(),
zero = "There aren't any lights!",
one = "There is one light!",
other = "There are { count } lights!"
)
I18nliner allows you to specify different sentences for gendered constructs via
tGender()
, which accepts a required gender
string, and strings for male
,
female
, and other
.
gender
can be "male"
/"m"
, or "female"
/"f"
. Anything else and it will hit
the other
string.
I18nliner.tGender(
user.getGender(),
male = "This is his towel.",
female = "This is her towel.",
other = "This is their towel."
)
Do not pass variables, or condition which argument you pass.
This is because we do static code analysis to find all calls to t()
and generate the default translation file, and every sentence needs to be a
literal string for that to happen.
If you need to condition on which string to translate, just repeat the call:
// bad, static analysis can't figure out what strings need to be translated
I18nliner.t(
if (someCondition) "That condition was true" else "No way man"
)
// correct, static analysis can easily parse both branches
if (someCondition)
I18nliner.t("That condition was true")
else
I18nliner.t("No way man")
Do not concatenate strings together. Instead, write one string for your whole sentence. If you need to include variables, just stick them inline and I18nliner will interpolate them. Again, this enables static analysis, but it also makes it easier on your translators and ensures better translations. Many languages have entirely different structures that makes it impossible to translate ( A ) + ( B ) + ( C ) as one sentence. It's generally better to translate ( A + B + C ).
// bad, static analysis has a hard time making a sentence out of this
I18nliner.t("Your essay is due on " + I18nliner.t("Tuesday"))
// correct, one sentence with interpolated variables.
// your translators can see the entire logic of the sentence.
I18nliner.t(
"Your essay is due on { dueDate }",
hashMapOf("dueDate" to I18nliner.t("Tuesday"))
)
in resources/translations/messages_en_US.properties
:
inertia_is_a_property_of_matter=Inertia is a property of matter!
the_name_is_lastname_firstname_lastname=The name is { lastName }. { firstName } { lastName }
in resources/translations/messages_pt_BR.properties
:
inertia_is_a_property_of_matter=A inércia é uma propriedade da matéria!
the_name_is_lastname_firstname_lastname=Meu nome é { lastName }. { firstName } { lastName }.
in main.kt
:
fun main(args: Array<String>) {
I18nliner.setPath("resources/translations/") // or wherever your translation files live
println(
I18nliner.t("Inertia is a property of matter!") // Inertia is a property of matter!
)
// upon changing locale, calls to t() will produce different results
I18nliner.setLocale("pt_BR")
println(
I18nliner.t("Inertia is a property of matter!") // A inércia é uma propriedade da matéria!
)
// variable interpolation
println(
I18nliner.t(
"The name is { lastName }. { firstName } { lastName }.", // Meu nome é Bond. James Bond.
hashMapOf(
"firstName" to "James",
"lastName" to "Bond"
)
)
)
}
- Import Project
- Check
Import project from external model
and select Gradle
gradle test