Skip to main content

Išsamus Android programų lokalizavimo vadovas

Nuo strings.xml iki Play Store metaduomenų: lokalizuokite Android programą naudodami Kotlin, Jetpack Compose, Fastlane ir automatizuotą DI vertimą.

1

Paruošti Android projektą lokalizavimui

Android lokalizavimui naudoja aplankais pagrįstą susitarimą. Numatytosios eilutės yra res/values/strings.xml, o išverstos – konkrečioms lokalėms skirtuose aplankuose, pavyzdžiui, res/values-de/ ir 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
Aplankas res/values/ yra atsarginė lokalė. Jei konkrečios lokalės aplanke trūksta eilutės, Android įkelia ją iš numatytojo aplanko. Tačiau jei eilutės trūksta numatytajame aplanke, nepalaikomose lokalėse programa nulūžta.
2

Sukurti strings.xml

Android eilučių ištekliuose naudojamas XML su '<string>' elementais '<resources>' šakniniame elemente. Eilučių vietos rezervavimo ženklams naudokite %s, sveikiesiems skaičiams – %d, o poziciniams argumentams, kuriuos vertėjai gali pertvarkyti, – %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>
Dėl neekranizuotų apostrofų XML analizatorius tyliai nulūžta. Naudokite \' arba apgaubkite reikšmę dvigubomis kabutėmis. Taip pat jei numatytajame values/strings.xml trūksta eilutės, programa ne sklandžiai grįžta prie atsarginio varianto kaip iOS, o visiškai nulūžta.
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

Apdoroti daugiskaitą

Android naudoja '&lt;plurals&gt;' elementus su quantity atributais: zero, one, two, few, many, other. Kiekvienai tikslinei kalbai gali reikėti skirtingų kategorijų – arabų kalba naudoja visas 6, rusų reikia few ir many, o japonų naudoja tik 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 atributas daugiskaitos formą parenka pagal įrenginio lokalės CLDR taisykles. Visada įtraukite other kaip atsarginį variantą – tai vienintelė kategorija, kuri garantuotai egzistuoja kiekvienoje kalboje.
4

Naudoti kode: Kotlin ir Jetpack Compose

Tradicinis Android naudoja getString(R.string.key) ir resources.getQuantityString(). Jetpack Compose naudoja stringResource(R.string.key) ir pluralStringResource(). Vykdymo metu abi priemonės pagal įrenginio lokalę parenka tinkamą vertimą.

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 parametras perduodamas du kartus. Pirmasis parenka daugiskaitos formą, antrasis yra formato argumentas. Antrojo count praleidimas – dažniausia Compose daugiskaitos klaida.
5

Eilučių masyvai ir suformatuotos eilutės

Sutvarkytiems sąrašams (pvz., išskleidžiamojo meniu parinktims ar pirminio supažindinimo veiksmams) naudokite '&lt;string-array&gt;'. Suformatuotose eilutėse naudokite pozicinius formato argumentus (%1$s, %2$d), kad vertėjai galėtų pertvarkyti žodžius nesugadindami sakinio struktūros.

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>
Tokie poziciniai argumentai kaip %1$s leidžia vertėjams laisvai pertvarkyti parametrus. „Sveiki, %1$s, turite %2$d elementų“ kitokią žodžių tvarką turinčiose kalbose gali virsti į „%2$d elementų naudotojui %1$s“ be jokių kodo pakeitimų.
6

Lokalizuoti Google Play metaduomenis naudojant Fastlane

Naudodami Fastlane komandą supply tvarkykite Play Store metaduomenis – pavadinimą, trumpąjį ir visą aprašus bei pakeitimų žurnalus – savo saugykloje kaip pagal lokales sutvarkytus paprasto teksto failus.

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
Lokalizavus Play Store puslapį ne anglakalbėse rinkose atsisiuntimų skaičius padidėja daugiau nei 30 %. Pavadinimas, trumpasis ir visas aprašai indeksuojami paieškoje, todėl jų vertimas yra didžiausią grąžą teikiantis lokalizavimo darbas.
Google Play

Automatizuokite Play Store puslapio lokalizavimą

Atsisakykite rankinio kopijavimo. Išverskite Play Store pavadinimą, aprašą ir leidimo pastabas į 175+ lokalių atsižvelgdami į simbolių limitus.

Susipažinti su Google Play integracija
7

Išbandyti lokalizavimą

Testuokite keisdami emuliatoriaus lokalę, naudodami Compose peržiūras su pasirinktiniu LocaleList ir pseudolokales kūrėjo parinktyse. Naudodami Gradle resConfigs pašalinkite nereikalingus trečiųjų šalių bibliotekų lokalių išteklius.

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
Išbandykite vokiečių (tekstas maždaug 30 % ilgesnis) ir japonų (maždaug 50 % trumpesnis) kalbas, kad aptiktumėte maketo problemas. Kūrėjo parinktyse įjunkite pseudolokales (en-XA diakritiniams ženklams, ar-XB RTL), kad atliktumėte maketų apkrovos bandymą be tikrų vertimų.

Automatizuoti vertimo kokybę

Naudodami i18n-validate prieš išleidimą aptikite trūkstamus raktus, sugadintus vietos rezervavimo ženklus ir daugiskaitos problemas. Kol dar nėra tikrų vertimų, patikrinkite UI su i18n-pseudo pseudoverstimais.
8

Automatizuoti vertimus

Išverskite strings.xml, daugiskaitą, eilučių masyvus ir Fastlane Supply metaduomenis naudodami DI. Automatizuokite ir programos eilučių, ir Play Store metaduomenų vertimą, kad viskas būtų visiškai lokalizuota.

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 tinkamai apdoroja Android XML ekranizavimą, išsaugo translatable="false" žymeklius, paiso kiekvienos tikslinės kalbos CLDR daugiskaitos kategorijų ir nekeičia pozicinių formato argumentų.
JetBrains

Yra Android Studio papildinys

Verskite Android XML išteklius tiesiai iš IDE naudodami i18n Agent papildinį, skirtą IntelliJ / Android Studio.

Install
+

Papildomai: išmani atsarginė lokalė su LocaleChain

Android išteklių atsarginę tvarką valdo operacinė sistema. Kai nėra pt-BR vertimų, Android visiškai praleidžia pt-PT ir rodo anglų kalbą. LocaleChain perima eilučių paiešką ir pereina konfigūruojamą atsarginę grandinę, todėl regionų naudotojai mato artimiausią esamą vertimą.

LocaleChain for Android yra atvirojo kodo Kotlin biblioteka. Peržiūrėti 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"))
)

Dažnos klaidos

Dėl trūkstamų numatytųjų eilučių programa nulūžta

Kitaip nei iOS, kuri rodo neapdorotą raktą, Android pateikia ResourceNotFoundException ir nulūžta, jei numatytajame res/values/strings.xml faile nėra eilutės. Visada užtikrinkite, kad numatytajame faile būtų kiekvienas raktas.

App Bundle kalbų skaidymas sugadina kalbos keitimą programoje

Google Play App Bundle suskaido APK pagal kalbą, todėl naudotojai gauna tik įrenginio kalbos eilutes. Jei programoje galima keisti kalbą, pridėkite bundle '{ language { enableSplit = false } }' prie build.gradle.kts.

Sugenda RTL maketai

Maketuose naudojama left/right vietoje start/end arba AndroidManifest.xml faile trūksta android:supportsRtl="true". Norėdami automatiškai konvertuoti esamus maketus, naudokite Android Studio Refactor > Add RTL Support.

Bibliotekų išteklių tarša

Trečiųjų šalių bibliotekos įtraukia savo values-XX/strings.xml failus, todėl Android mano, kad programa palaiko kalbas, kurių iš tiesų nepalaiko. Naudodami resConfigs faile build.gradle.kts apribokite įtraukiamas lokales tik iki tų, kurias iš tikrųjų verčiate.

Rekomenduojama failų struktūra

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

Išbandykite i18n Agent dabar

Nuvilkite vertimo failą čia

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

arba spustelėkite norėdami pasirinkti

Tikslinės kalbos

Registruotis nereikiaMomentinis įvertis

Atsarginė lokalė su locale-chain-android

Kai regioninėje lokalėje, pavyzdžiui, pt-BR, nėra vertimo rakto, Android iškart pereina prie numatytojo išteklių aplanko, užuot pirmiausia patikrinęs pirminę lokalę 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"),
    )
)

Visą palaikomų sistemų sąrašą ir 75 integruotas grandines rasite mūsų atsarginių lokalių vadove. Learn more →

DUK apie Android lokalizavimą