Skip to main content

De complete handleiding voor lokalisatie van Android-apps

Van strings.xml tot Play Store-metadata: lokaliseer je Android-app met Kotlin, Jetpack Compose, Fastlane en geautomatiseerde AI-vertalingen.

1

Je Android-project instellen voor lokalisatie

Android gebruikt een op mappen gebaseerde conventie voor lokalisatie. Je standaardtekenreeksen staan in res/values/strings.xml en vertaalde tekenreeksen in localespecifieke mappen zoals res/values-de/, res/values-ja/ enz.

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
De map res/values/ bevat je terugvallocale. Als een tekenreeks ontbreekt in een localespecifieke map, laadt Android deze uit de standaardmap. Maar als een tekenreeks in de standaardmap ontbreekt, crasht je app bij niet-ondersteunde locales.
2

strings.xml maken

Android-tekenreeksresources gebruiken XML met '<string>'-elementen binnen het hoofdelement '<resources>'. Gebruik %s als plaatsaanduiding voor tekenreeksen, %d voor gehele getallen en %1$s/%2$s voor positionele argumenten waarvan vertalers de volgorde kunnen wijzigen.

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>
Apostroffen zonder escape laten de XML-parser stilzwijgend crashen. Gebruik \' of zet de waarde tussen dubbele aanhalingstekens. Let ook op: als een tekenreeks in het standaardbestand values/strings.xml ontbreekt, volgt er een harde crash en geen probleemloze terugval zoals bij 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

Meervoudsvormen verwerken

Android gebruikt '&lt;plurals&gt;'-elementen met de quantity-kenmerken zero, one, two, few, many en other. Elke doeltaal kan andere categorieën nodig hebben: Arabisch gebruikt ze alle 6, Russisch heeft few/many nodig en Japans alleen 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
) -->
Het kenmerk quantity selecteert de meervoudsvorm op basis van de CLDR-regels voor de apparaatlocale. Neem altijd other op als reserve: dit is de enige categorie die gegarandeerd in elke taal bestaat.
4

Gebruiken in code: Kotlin en Jetpack Compose

Traditioneel Android gebruikt getString(R.string.key) en resources.getQuantityString(). Jetpack Compose gebruikt stringResource(R.string.key) en pluralStringResource(). Beide bepalen tijdens de uitvoering de juiste vertaling op basis van de apparaatlocale.

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): de parameter count wordt tweemaal doorgegeven. De eerste keer selecteert deze de meervoudsvorm en de tweede keer is deze het opmaakargument. Het ontbreken van de tweede count is de meest voorkomende fout bij meervoudsvormen in Compose.
5

Tekenreeksarrays en opgemaakte tekenreeksen

Gebruik '&lt;string-array&gt;' voor geordende lijsten (bijv. opties in keuzelijsten en onboardingstappen). Gebruik positionele opmaakargumenten (%1$s, %2$d) in opgemaakte tekenreeksen, zodat vertalers de woordvolgorde kunnen wijzigen zonder de zinsstructuur te beschadigen.

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>
Met positionele argumenten zoals %1$s kunnen vertalers parameters vrij herschikken. 'Hello %1$s, you have %2$d items' kan in talen met een andere woordvolgorde '%2$d items for %1$s' worden, zonder wijzigingen in de code.
6

Google Play-metadata lokaliseren met Fastlane

Gebruik het commando supply van Fastlane om Play Store-metadata, zoals de titel, korte en volledige beschrijving en wijzigingslogboeken, als platte tekstbestanden per locale in je repository te beheren.

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
Door je Play Store-vermelding te lokaliseren, stijgt het aantal downloads in niet-Engelstalige markten met meer dan 30%. De titel, korte beschrijving en volledige beschrijving worden voor zoekopdrachten geïndexeerd; de vertaling ervan levert het hoogste rendement op van alle lokalisatiewerkzaamheden.
Google Play

De lokalisatie van je Play Store-vermelding automatiseren

Sla handmatig kopiëren en plakken over. Vertaal de titel, beschrijving en releaseopmerkingen van je Play Store-vermelding naar meer dan 175 locales, met inachtneming van tekenlimieten.

Google Play-integratie bekijken
7

Je lokalisatie testen

Test door de locale van de emulator te wijzigen, Compose-previews met een aangepaste LocaleList te gebruiken en pseudolocales in Developer Options in te schakelen. Gebruik resConfigs in Gradle om ongewenste localeresources uit bibliotheken van derden te verwijderen.

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
Test met Duits (tekst wordt circa 30% langer) en Japans (tekst wordt circa 50% korter) om indelingsproblemen op te sporen. Schakel pseudolocales (en-XA voor accenten, ar-XB voor RTL) in Developer Options in om indelingen zonder echte vertalingen grondig te testen.

De vertaalkwaliteit automatisch controleren

Spoor met i18n-validate ontbrekende sleutels, defecte plaatsaanduidingen en problemen met meervoudsvormen op voordat ze in een release terechtkomen. Test je gebruikersinterface met pseudovertalingen uit i18n-pseudo voordat de echte vertalingen klaar zijn.
8

Vertalingen automatiseren

Vertaal je strings.xml, meervoudsvormen, tekenreeksarrays en Fastlane Supply-metadata met AI. Automatiseer zowel de vertaling van tekenreeksen in de app als die van Play Store-metadata voor een volledig gelokaliseerde aanwezigheid.

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 verwerkt Android-XML-escapes, behoudt translatable="false"-markeringen en positionele opmaakargumenten en respecteert per doeltaal de CLDR-meervoudscategorieën.
JetBrains

Android Studio-plug-in beschikbaar

Vertaal Android-XML-resources rechtstreeks vanuit je IDE met de i18n Agent-plug-in voor IntelliJ / Android Studio.

Install
+

Bonus: slimme terugval voor locales met LocaleChain

Het terugvalmechanisme voor Android-resources wordt door het besturingssysteem beheerd. Wanneer pt-BR-vertalingen ontbreken, slaat Android pt-PT volledig over en toont het Engels. LocaleChain onderschept het opzoeken van tekenreeksen en doorloopt een configureerbare terugvalketen, zodat gebruikers in een bepaalde regio de meest verwante beschikbare vertaling zien.

LocaleChain voor Android is een opensource-Kotlin-bibliotheek. Bekijken op 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"))
)

Veelvoorkomende valkuilen

Ontbrekende standaardtekenreeksen veroorzaken crashes

Anders dan iOS, dat de onbewerkte sleutel toont, crasht Android met een ResourceNotFoundException als een tekenreeks ontbreekt in het standaardbestand res/values/strings.xml. Zorg er altijd voor dat elke sleutel in het standaardbestand staat.

Taalsplitsingen in App Bundles verstoren taalwissels in de app

Google Play App Bundles splitsen APK's op taal, waardoor gebruikers alleen de tekenreeksen voor hun apparaattaal ontvangen. Als je taalwissels in de app aanbiedt, voeg je bundle '{ language { enableSplit = false } }' toe aan je build.gradle.kts.

RTL-indelingen werken niet goed

Dit gebeurt wanneer indelingen left/right in plaats van start/end gebruiken of wanneer android:supportsRtl="true" in AndroidManifest.xml ontbreekt. Gebruik Refactor > Add RTL Support in Android Studio om bestaande indelingen automatisch om te zetten.

Onbedoelde localeresources uit bibliotheken

Bibliotheken van derden leveren hun eigen bestanden mee, zoals values-XX/strings.xml, waardoor Android denkt dat je app talen ondersteunt die je niet aanbiedt. Gebruik resConfigs in build.gradle.kts om de opgenomen locales te beperken tot de talen die je daadwerkelijk vertaalt.

Aanbevolen bestandsstructuur

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

Probeer i18n Agent nu

Zet je vertaalbestand hier neer

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

of klik om een bestand te selecteren

Doeltalen

Geen registratie nodigDirecte prijsindicatie

Terugval voor locales met locale-chain-android

Wanneer een vertaalsleutel ontbreekt in een regionale locale zoals pt-BR, springt Android rechtstreeks naar de standaardresourcemap in plaats van eerst de bovenliggende locale pt te controleren.

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"),
    )
)

Bekijk onze handleiding over terugval voor locales voor de volledige lijst met ondersteunde frameworks en 75 ingebouwde ketens. Learn more →

Veelgestelde vragen over Android-lokalisatie