
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ą.
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 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-rTWSukurti 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 -->
<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><!-- ❌ 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>Apdoroti daugiskaitą
Android naudoja '<plurals>' 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 -->
<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
) -->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ą.
// 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
))
}Eilučių masyvai ir suformatuotos eilutės
Sutvarkytiems sąrašams (pvz., išskleidžiamojo meniu parinktims ar pirminio supažindinimo veiksmams) naudokite '<string-array>'. 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 -->
<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>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.
# 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 supplyAutomatizuokite 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 integracijaIš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.
// 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 mirroringAutomatizuoti vertimo kokybę
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.
# 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.2sYra Android Studio papildinys
Verskite Android XML išteklius tiesiai iš IDE naudodami i18n Agent papildinį, skirtą IntelliJ / Android Studio.
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 (app module)
dependencies {
implementation("com.i18nagent:locale-chain-android:0.1.0")
}// 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
App Bundle kalbų skaidymas sugadina kalbos keitimą programoje
Sugenda RTL maketai
Bibliotekų išteklių tarša
Rekomenduojama failų struktūra
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.ktsTaip pat verskite:
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
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.
implementation("com.i18nagent:locale-chain-android:0.1.0")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 →