Skip to main content

Пълно ръководство за локализация на приложения за Android

От strings.xml до метаданните в Play Store: локализирайте Вашето приложение за Android с Kotlin, Jetpack Compose, Fastlane и автоматизиран превод с ИИ.

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. Всеки целеви език може да изисква различни категории — арабският използва всичките 6, руският изисква 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 е грешката #1 при обработката на множествено число в 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

Използвайте командата supply на Fastlane, за да управлявате метаданните в 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, преди да достигнат до потребителите. Тествайте интерфейса си с псевдопреводи чрез i18n-pseudo, преди да са готови истинските преводи.
8

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

Превеждайте с ИИ Вашите strings.xml, форми за множествено число, масиви от низове и метаданни на Fastlane Supply. Автоматизирайте превода както на низовете в приложението, така и на метаданните в 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

Превеждайте XML ресурсите на Android направо от Вашата 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. Използвайте Refactor > Add RTL Support в Android Studio, за да преобразувате автоматично съществуващите оформления.

Замърсяване с ресурси от библиотеки

Библиотеките на трети страни включват собствени файлове 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