Skip to content

edwardsCam/i18nliner-kt

Repository files navigation

I18nliner-kt

I18n made simple - for Kotlin!


Key Features

  • (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).

Usage

  1. Call I18nliner.setPath("path/to/your/language/files"), so that I18nliner knows where to find your translations.
  2. Call I18nliner.setLocale() with the language tag you want your app to display (if using en_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 call setLocale() with the new locale, so that all subsequent calls to t() will reflect the correct language.
  3. 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 signature I18nliner.t("My string", locale = "pt_BR"). This will ignore the locale you set via setLocale() for that call only.

Pluralization

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!"
)

Gender

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."
)

Guidelines and Gotchas

Only pass literal strings to t()

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")

Interpolation over concatenation

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"))
)

Example

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"
      )
    )
  )
}

Development setup

Intellij

  1. Import Project
  2. Check Import project from external model and select Gradle

Testing

gradle test

About

I18n made simple - for Kotlin! (still in beta)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages