Internationalization of Kotlin Applications: How Not to Get Confused in Languages

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why Your Application Needs Internationalization Today

\n\n

Imagine: you've written a cool Kotlin application — convenient, fast, with a beautiful UI. But all the labels are in Russian. A user from Berlin or Tokyo opens your product and... closes it after 10 seconds. Why? Because they don't understand a word. Internationalization (i18n) is not just "translating buttons," but a bridge between your code and millions of users worldwide.

\n\n

In this article, we'll break down how to properly implement Kotlin internationalization in projects of any scale: from Android applications to server-side services on Ktor. You'll learn how to avoid common mistakes, how to use Kotlin Multiplatform for shared logic, and why "magic strings" are evil.

\n\n

i18n Basics in Kotlin: From Simple to Complex

\n\n

Resource Files: The Foundation of Localization

\n\n

The most reliable way to organize Kotlin application localization is to extract all string literals into separate resource files. In Android Studio, these are standard strings.xml, but for pure Kotlin (backend, desktop), we can use .properties or JSON.

\n\n

Example for Android:

\n\n
// res/values/strings.xml (Russian — default)\n<resources>\n    <string name="app_name">My Application</string>\n    <string name="welcome_message">Welcome, %s!</string>\n    <string name="points">You have %d points</string>\n</resources>\n\n// res/values-en/strings.xml (English)\n<resources>\n    <string name="app_name">My App</string>\n    <string name="welcome_message">Welcome, %s!</string>\n    <string name="points">You have %d points</string>\n</resources>
\n\n

In code, we access via context.getString():

\n\n
val userName = "Alexey"\nval message = context.getString(R.string.welcome_message, userName)\n// Result: "Welcome, Alexey!" (or "Добро пожаловать, Алексей!" in Russian)
\n\n

Note: we use %s for strings and %d for numbers. Never concatenate strings manually — in Japanese or Arabic, word order may differ.

\n\n

Working with Plural Forms

\n\n

The Russian language is famous for complex declension rules: 1 балл, 2 балла, 5 баллов. In English, it's simpler: 1 point, 2 points. Kotlin internationalization must account for this.

\n\n

In Android, there is <plurals> for this:

\n\n
// strings.xml\n<plurals name="points_count">\n    <item quantity="one">%d point</item>\n    <item quantity="other">%d points</item>\n</plurals>\n\n// In code\nval points = 3\nval text = resources.getQuantityString(R.plurals.points_count, points, points)\n// "3 points"
\n\n

For server-side Kotlin, you can use the icu4j library or write your own simple resolver. The main rule: never hardcode texts with numbers.

\n\n

Internationalization in Kotlin Multiplatform (KMP)

\n\n

If you're writing a cross-platform application in Kotlin Multiplatform, the task becomes more complex. Shared code does not have access to Android resources. The solution is to use a common interface and platform-specific implementations.

\n\n

Architecture for KMP

\n\n

Create an expect class in the common module:

\n\n
// commonMain\nexpect class StringProvider {\n    fun getString(key: String, vararg args: Any): String\n}\n\n// Usage in shared code\nclass Greeting(private val strings: StringProvider) {\n    fun greet(name: String): String {\n        return strings.getString("welcome", name)\n    }\n}
\n\n

Implementation for Android:

\n\n

Blogs

Book Recommendations