Skip to main content

Потпун водич за локализацију Android апликације

Од strings.xml до Play Store метаподатака: локализујте Android апликацију помоћу Kotlin, Jetpack Compose, Fastlane и аутоматизованог AI превођења.

1

Подесите Android пројекат за локализацију

Android користи правило фасцикли за локализацију. Подразумевани текстови су у res/values/strings.xml, а преведени у фасциклама локала као што су res/values-de/ и res/values-ja/.

Android Project Structure
// Android project structure for localization:
// res/
// ├── values/              ← Default (fallback) locale
// │   └── strings.xml
// ├── values-de/           ← German
// │   └── strings.xml
// ├── values-ja/           ← Japanese
// │   └── strings.xml
// └── values-es/           ← Spanish
//     └── strings.xml
//
// Folder naming: values-{language} or values-{language}-r{Region}
// Examples: values-pt-rBR, values-zh-rCN, values-zh-rTW
Фасцикла res/values/ је резервни локал. Ако текст недостаје у фасцикли локала, Android га учитава из подразумеване. Али ако текст недостаје у подразумеваној фасцикли, апликација се руши на неподржаним локалима.
2

Направите strings.xml

Android ресурси текста користе XML са елементима '<string>' у корену '<resources>'. Користите %s за текстуална места, %d за целе бројеве и %1$s/%2$s за позиционе аргументе које преводиоци могу да преместе.

res/values/strings.xml
<!-- res/values/strings.xml -->
<resources>
    <string name="welcome_title">Welcome to MyApp</string>
    <string name="login_button">Sign In</string>
    <string name="settings_label">Settings</string>
    <string name="greeting">Hello, %s!</string>        <!-- %s = string -->
    <string name="item_count">%d items</string>          <!-- %d = integer -->
    <string name="app_name" translatable="false">MyApp</string>
</resources>
Апострофи без излаза неприметно руше XML анализатор. Користите \' или ставите вредност под двоструке наводнике. Такође, недостајући текст у подразумеваној values/strings.xml датотеци изазива рушење, а не неприметан резервни избор као iOS.
Common strings.xml Mistakes
<!-- ❌ Common mistakes in strings.xml: -->

<!-- Unescaped apostrophe — crashes XML parser silently -->
<string name="message">It's a great day</string>

<!-- Missing from default values/strings.xml — app crashes -->
<!-- (only exists in values-de/strings.xml) -->

<!-- ✅ Correct versions: -->
<string name="message">It\'s a great day</string>
<!-- Or wrap in double quotes: -->
<string name="message">"It's a great day"</string>
3

Обрадите множину

Android користи елементе '&lt;plurals&gt;' са атрибутима quantity: zero, one, two, few, many, other. Сваком циљном језику могу бити потребне друге категорије — арапски користи свих шест, руском требају few/many, а јапански само other.

res/values/strings.xml
<!-- res/values/strings.xml -->
<resources>
    <plurals name="items_count">
        <item quantity="zero">No items</item>
        <item quantity="one">%d item</item>
        <item quantity="other">%d items</item>
    </plurals>
</resources>

<!-- Usage in Kotlin: -->
<!-- val text = resources.getQuantityString(
    R.plurals.items_count,
    count,    // selects plural form
    count     // format argument
) -->
Атрибут quantity бира облик множине према CLDR правилима локала уређаја. Увек укључите „other" као резервну вредност — то је једина категорија која постоји у сваком језику.
4

Користите у коду: Kotlin и Jetpack Compose

Традиционални Android користи getString(R.string.key) и resources.getQuantityString(). Jetpack Compose користи stringResource(R.string.key) и pluralStringResource(). Оба при извршавању проналазе исправан превод према локалу уређаја.

WelcomeScreen.kt
// Traditional Android (Activity/Fragment)
val title = getString(R.string.welcome_title)
val greeting = getString(R.string.greeting, userName)
val items = resources.getQuantityString(
    R.plurals.items_count, count, count
)

// Jetpack Compose
@Composable
fun WelcomeScreen(userName: String, itemCount: Int) {
    // ✅ stringResource — Compose-aware, triggers recomposition
    Text(text = stringResource(R.string.welcome_title))

    // ✅ With format arguments
    Text(text = stringResource(R.string.greeting, userName))

    // ✅ Plurals — count passed TWICE
    Text(text = pluralStringResource(
        R.plurals.items_count,
        itemCount,    // selects plural form
        itemCount     // format argument
    ))
}
pluralStringResource(R.plurals.items, count, count) — параметар count се прослеђује два пута. Први бира облик множине, други је аргумент формата. Изостављање другог count параметра је најчешћа грешка Compose множине.
5

Низови текстова и форматирани текстови

Користите '&lt;string-array&gt;' за уређене листе (нпр. опције падајућег менија и кораке увођења). У форматираним текстовима користите позиционе аргументе (%1$s, %2$d) како би преводиоци могли да промене редослед речи без кварења реченице.

res/values/strings.xml
<!-- res/values/strings.xml -->
<resources>
    <!-- String array for dropdown/list -->
    <string-array name="sort_options">
        <item>Most Recent</item>
        <item>Most Popular</item>
        <item>Price: Low to High</item>
        <item>Price: High to Low</item>
    </string-array>

    <!-- Positional format args for reordering -->
    <string name="welcome_message">
        Hello %1$s, you have %2$d new messages
    </string>
    <!-- Translators can reorder: -->
    <!-- %2$d neue Nachrichten für %1$s -->
</resources>
Позициони аргументи као %1$s омогућавају преводиоцима да слободно преместе параметре. „Hello %1$s, you have %2$d items" може постати „%2$d items for %1$s" у језику са другим редоследом речи, без измене кода.
6

Локализујте Google Play метаподатке помоћу Fastlane

Користите Fastlane команду supply да управљате Play Store метаподацима — насловом, кратким и пуним описом и евиденцијом измена — као обичним текстуалним датотекама организованим по локалу у репозиторијуму.

Terminal
# Install Fastlane
$ gem install fastlane

# Initialize supply for Play Store metadata
$ fastlane supply init

# Directory structure created:
# fastlane/metadata/android/
# ├── en-US/
# │   ├── title.txt              # App name (50 chars)
# │   ├── short_description.txt  # Short desc (80 chars)
# │   ├── full_description.txt   # Full desc (4000 chars)
# │   └── changelogs/
# │       └── default.txt        # What's New
# ├── de-DE/
# │   └── ...
# └── ja-JP/
#     └── ...

# Push metadata to Play Store:
$ fastlane supply
Локализација Play Store странице повећава преузимања за више од 30% на тржиштима ван енглеског говорног подручја. Наслов, кратак и пун опис индексирају се у претрази — њихово превођење има највећи повраћај улагања.
Google Play

Аутоматизујте локализацију Play Store странице

Прескочите ручно копирање. Преведите Play Store наслов, опис и напомене о издању на више од 175 локала уз поштовање ограничења знакова.

Истражите Google Play интеграцију
7

Тестирајте локализацију

Тестирајте променом локала емулатора, Compose прегледима са прилагођеним LocaleList и псеудолокалима у Developer Options. Користите resConfigs у Gradle да уклоните нежељене ресурсе локала из независних библиотека.

Testing Localization
// 1. Emulator: Settings > System > Language > Add language

// 2. Compose Preview with locale:
@Preview
@Composable
fun WelcomePreview() {
    val config = Configuration(resources.configuration).apply {
        setLocale(Locale("de"))
    }
    val localContext = LocalContext.current
    val localizedContext = localContext.createConfigurationContext(config)
    CompositionLocalProvider(
        LocalContext provides localizedContext
    ) {
        WelcomeScreen()
    }
}

// 3. Restrict library locales in build.gradle.kts:
android {
    defaultConfig {
        // Only include locales you actually translate
        resourceConfigurations += listOf("en", "de", "ja", "es", "fr")
    }
}

// 4. Enable pseudolocales in Developer Options:
// en-XA (accented) — detects hardcoded strings
// ar-XB (RTL) — tests layout mirroring
Тестирајте на немачком (текст је око 30% дужи) и јапанском (око 50% краћи) да откријете проблеме распореда. Укључите псеудолокале (en-XA за акцентовани текст, ar-XB за RTL) у Developer Options ради тестирања без правих превода.

Аутоматизујте квалитет превода

Откријте недостајуће кључеве, неисправна места за променљиве и проблеме множине помоћу i18n-validate пре објављивања. Тестирајте UI псеудопреводима помоћу i18n-pseudo пре него што стигну прави преводи.
8

Аутоматизујте преводе

Преведите strings.xml, множину, низове текстова и Fastlane Supply метаподатке помоћу AI. Аутоматизујте превод текстова у апликацији и Play Store метаподатака ради потпуно локализованог присуства.

Terminal
# Translate strings.xml files
> Translate res/values/strings.xml
  to Japanese, German, and Spanish

# Translate Play Store metadata too
> Translate fastlane/metadata/android/en-US/
  to de-DE, ja-JP, es-ES

✓ 6 files translated in 3.2s
i18n Agent обрађује Android XML излаз, чува ознаке translatable="false", поштује CLDR категорије множине за сваки циљни језик и не мења позиционе аргументе формата.
JetBrains

Доступан је Android Studio додатак

Преводите Android XML ресурсе директно из IDE окружења помоћу i18n Agent додатка за IntelliJ / Android Studio.

Install
+

Додатно: паметни резервни локал са LocaleChain

Резервни избор Android ресурса контролише оперативни систем. Када недостају pt-BR преводи, Android потпуно прескаче pt-PT и приказује енглески. LocaleChain пресреће претрагу текста и пролази подесиви резервни ланац, па регионални корисници виде најближи доступан превод.

LocaleChain за Android је Kotlin библиотека отвореног кода. Погледајте на GitHub-у

build.gradle.kts
// build.gradle.kts (app module)
dependencies {
    implementation("com.i18nagent:locale-chain-android:0.1.0")
}
MyApp.kt / BaseActivity.kt
// 1. Application.onCreate() — configure chains once
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        LocaleChain.configure()
    }
}

// 2. BaseActivity — wrap context per Activity
open class BaseActivity : AppCompatActivity() {
    override fun attachBaseContext(newBase: Context) {
        super.attachBaseContext(LocaleChain.wrap(newBase))
    }
}

// pt-BR user with only pt-PT translations?
// → Shows Portuguese instead of falling back to English

// Custom overrides for your specific locales:
LocaleChain.configure(
    overrides = mapOf("es-MX" to listOf("es-419", "es"))
)

Уобичајене замке

Недостајући подразумевани текстови изазивају рушење

За разлику од iOS система који приказује необрађени кључ, Android се руши са ResourceNotFoundException ако текст недостаје у подразумеваној res/values/strings.xml датотеци. Увек обезбедите да сваки кључ постоји у подразумеваној датотеци.

Језичке поделе App Bundle пакета кваре промену језика у апликацији

Google Play App Bundles деле APK по језику, па корисници добијају само текстове језика уређаја. Ако нудите промену језика у апликацији, додајте bundle '{ language { enableSplit = false } }' у build.gradle.kts.

RTL распореди се кваре

Узрок је коришћење left/right уместо start/end у распоредима или недостатак android:supportsRtl="true" у AndroidManifest.xml. Користите Android Studio Refactor > Add RTL Support да аутоматски претворите постојеће распореде.

Контаминација ресурсима библиотеке

Независне библиотеке садрже сопствене values-XX/strings.xml датотеке, па Android мисли да апликација подржава језике које не подржава. Користите resConfigs у build.gradle.kts да ограничите укључене локале само на оне које заиста преводите.

Препоручена структура датотека

Project Structure
MyApp/
├── app/
│   └── src/main/
│       ├── res/
│       │   ├── values/
│       │   │   ├── strings.xml          # Default (source) strings
│       │   │   └── plurals.xml          # Plural rules
│       │   ├── values-de/
│       │   │   └── strings.xml
│       │   ├── values-ja/
│       │   │   └── strings.xml
│       │   └── values-es/
│       │       └── strings.xml
│       ├── java/com/example/myapp/
│       └── AndroidManifest.xml
├── fastlane/
│   └── metadata/android/
│       ├── en-US/
│       │   ├── title.txt
│       │   ├── short_description.txt
│       │   ├── full_description.txt
│       │   └── changelogs/default.txt
│       ├── de-DE/
│       └── ja-JP/
├── build.gradle.kts
└── settings.gradle.kts

Испробајте i18n Agent сада

Пустите датотеку за превођење овде

JSON, YAML, PO, XML, CSV, Markdown, Properties

или кликните за избор

Циљни језици

Регистрација није потребнаТренутна процена

Резервни локали са locale-chain-android

Када у регионалном локалу као што је pt-BR недостаје кључ превода, Android одмах прелази у подразумевану фасциклу ресурса уместо да најпре провери надређени локал pt.

Terminal
implementation("com.i18nagent:locale-chain-android:0.1.0")
Configuration
import com.i18nagent.localechain.LocaleChain

LocaleChain.configure(
    overrides = mapOf(
        "pt-BR" to listOf("pt", "en"),
        "zh-Hant-HK" to listOf("zh-Hant", "zh", "en"),
    )
)

Погледајте наш водич за резервне локале за целу листу подржаних система и 75 уграђених ланаца. Learn more →

Честа питања о Android локализацији