
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.
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 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-rTWstrings.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 -->
<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>Meervoudsvormen verwerken
Android gebruikt '<plurals>'-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 -->
<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
) -->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.
// 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
))
}Tekenreeksarrays en opgemaakte tekenreeksen
Gebruik '<string-array>' 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 -->
<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>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.
# 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 supplyDe 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 bekijkenJe 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.
// 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 mirroringDe vertaalkwaliteit automatisch controleren
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.
# 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.2sAndroid Studio-plug-in beschikbaar
Vertaal Android-XML-resources rechtstreeks vanuit je IDE met de i18n Agent-plug-in voor IntelliJ / Android Studio.
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 (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"))
)Veelvoorkomende valkuilen
Ontbrekende standaardtekenreeksen veroorzaken crashes
Taalsplitsingen in App Bundles verstoren taalwissels in de app
RTL-indelingen werken niet goed
Onbedoelde localeresources uit bibliotheken
Aanbevolen bestandsstructuur
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.ktsProbeer i18n Agent nu
Zet je vertaalbestand hier neer
JSON, YAML, PO, XML, CSV, Markdown, Properties
of klik om een bestand te selecteren
Doeltalen
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.
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"),
)
)Bekijk onze handleiding over terugval voor locales voor de volledige lijst met ondersteunde frameworks en 75 ingebouwde ketens. Learn more →