Skip to main content

Den komplette guide til lokalisering af Android-apps

Fra strings.xml til metadata i Play Store: Lokaliser din Android-app med Kotlin, Jetpack Compose, Fastlane og automatiseret AI-oversættelse.

1

Konfigurer dit Android-projekt til lokalisering

Android bruger en mappebaseret struktur til lokalisering. Dine standardstrenge ligger i res/values/strings.xml og oversatte strenge placeres i landestandardspecifikke mapper som res/values-de/, res/values-ja/ osv.

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
Mappen res/values/ er din reservelandestandard. Hvis en streng mangler i en landestandardspecifik mappe, indlæser Android den fra standardmappen. Men hvis en streng mangler i standardmappen, går din app ned på landestandarder, der ikke understøttes.
2

Opret strings.xml

Android-strengressourcer bruger XML med '<string>'-elementer i et '<resources>'-rodelement. Brug %s som pladsholder for strenge, %d for heltal og %1$s/%2$s for positionsargumenter, som oversættere kan ændre rækkefølgen på.

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>
Apostroffer uden escape-tegn får XML-parseren til at gå ned uden en fejlmeddelelse. Brug \' eller omslut værdien med dobbelte anførselstegn. Bemærk også: En manglende streng i standardfilen values/strings.xml medfører et nedbrud – ikke et kontrolleret fallback som i 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

Håndter flertalsformer

Android bruger '&lt;plurals&gt;'-elementer med quantity-attributterne zero, one, two, few, many og other. Hvert målsprog kan kræve forskellige kategorier – arabisk bruger alle 6, russisk kræver few/many og japansk bruger kun 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
) -->
Attributten quantity vælger flertalsformen ud fra CLDR-reglerne for enhedens landestandard. Medtag altid 'other' som fallback – det er den eneste kategori, der med sikkerhed findes på alle sprog.
4

Brug i kode: Kotlin og Jetpack Compose

Traditionel Android-kode bruger getString(R.string.key) og resources.getQuantityString(). Jetpack Compose bruger stringResource(R.string.key) og pluralStringResource(). Begge finder den korrekte oversættelse ved kørsel ud fra enhedens landestandard.

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) – parameteren count angives to gange. Den første vælger flertalsformen og den anden er formateringsargumentet. En manglende anden count er den mest almindelige fejl ved flertalsformer i Compose.
5

Strengarrays og formaterede strenge

Brug '&lt;string-array&gt;' til sorterede lister (f.eks. valgmuligheder i rullemenuer og introduktionstrin). Brug positionsbaserede formateringsargumenter (%1$s, %2$d) i formaterede strenge, så oversættere kan ændre ordenes rækkefølge uden at ødelægge sætningsstrukturen.

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>
Positionsargumenter som %1$s giver oversættere mulighed for frit at ændre parametrenes rækkefølge. 'Hello %1$s, you have %2$d items' kan blive til '%2$d items for %1$s' på sprog med en anden ordstilling – uden kodeændringer.
6

Lokaliser Google Play-metadata med Fastlane

Brug Fastlanes supply-kommando til at administrere metadata i Play Store – titel, kort beskrivelse, fuld beskrivelse og ændringslogge – som almindelige tekstfiler, der er organiseret efter landestandard i dit repository.

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
Lokalisering af din side i Play Store øger antallet af downloads med mindst 30 % på ikke-engelsksprogede markeder. Titel, kort beskrivelse og fuld beskrivelse indekseres til søgning – oversættelse af dem er den lokaliseringsindsats, der giver det højeste afkast.
Google Play

Automatiser lokaliseringen af din side i Play Store

Spring manuel kopiering og indsættelse over. Oversæt din titel, beskrivelse og dine produktbemærkninger i Play Store til mere end 175 landestandarder under hensyntagen til tegngrænsen.

Udforsk Google Play-integrationen
7

Test din lokalisering

Test ved at skifte landestandard i emulatoren, bruge Compose-forhåndsvisninger med en tilpasset LocaleList og aktivere pseudolandestandarder i Udviklerindstillinger. Brug resConfigs i Gradle til at fjerne uønskede landestandardressourcer fra tredjepartsbiblioteker.

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 med tysk (teksten bliver ca. 30 % længere) og japansk (teksten bliver ca. 50 % kortere) for at opdage layoutproblemer. Aktivér pseudolandestandarder (en-XA med accenter og ar-XB til RTL) i Udviklerindstillinger for at stressteste layouts uden rigtige oversættelser.

Automatiser oversættelseskvaliteten

Find manglende nøgler, defekte pladsholdere og problemer med flertalsformer, før de udgives, med i18n-validate. Test din brugergrænseflade med pseudooversættelser ved hjælp af i18n-pseudo, før de rigtige oversættelser er klar.
8

Automatiser oversættelser

Oversæt din strings.xml, flertalsformer, strengarrays og Fastlane Supply-metadata med AI. Automatiser oversættelsen af både strenge i appen og metadata i Play Store for at opnå en fuldt lokaliseret tilstedeværelse.

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 håndterer escape-tegn i Android XML, bevarer translatable="false"-markører, overholder CLDR-flertalskategorierne for hvert målsprog og bevarer positionsbaserede formateringsargumenter.
JetBrains

Plugin til Android Studio er tilgængeligt

Oversæt Android XML-ressourcer direkte fra dit IDE med i18n Agent-pluginet til IntelliJ / Android Studio.

Install
+

Bonus: Intelligent fallback for landestandarder med LocaleChain

Androids ressourcefallback styres af operativsystemet. Når pt-BR-oversættelser mangler, springer Android pt-PT helt over og viser engelsk. LocaleChain opfanger strengopslag og gennemgår en konfigurerbar fallbackkæde, så regionale brugere ser den nærmeste tilgængelige oversættelse.

LocaleChain til Android er et Kotlin-bibliotek med åben kildekode. Se det på 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"))
)

Almindelige faldgruber

Manglende standardstrenge medfører nedbrud

I modsætning til iOS, som viser den rå nøgle, går Android ned med en ResourceNotFoundException, hvis en streng mangler i standardfilen res/values/strings.xml. Sørg altid for, at alle nøgler findes i standardfilen.

App Bundle-sprogopdeling ødelægger sprogskift i appen

Google Play App Bundles opdeler APK-filer efter sprog – brugerne modtager kun strengene til deres enheds sprog. Hvis du tilbyder sprogskift i appen, skal du føje bundle '{ language { enableSplit = false } }' til din build.gradle.kts.

RTL-layouts går i stykker

Det sker, når du bruger left/right i stedet for start/end i layouts eller når android:supportsRtl="true" mangler i AndroidManifest.xml. Brug Android Studios Refactor > Add RTL Support til automatisk at konvertere eksisterende layouts.

Forurening fra biblioteksressourcer

Tredjepartsbiblioteker indeholder deres egne values-XX/strings.xml-filer, hvilket får Android til at tro, at din app understøtter sprog, den ikke understøtter. Brug resConfigs i build.gradle.kts til at begrænse de medtagne landestandarder til dem, du faktisk oversætter.

Anbefalet filstruktur

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

Prøv i18n Agent nu

Slip din oversættelsesfil her

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

eller klik for at vælge en fil

Målsprog

Kræver ingen tilmeldingEstimat med det samme

Fallback for landestandarder med locale-chain-android

Når en oversættelsesnøgle mangler i en regional landestandard som pt-BR, går Android direkte til standardressourcemappen i stedet for først at kontrollere den overordnede landestandard 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"),
    )
)

Se vores guide til fallback for landestandarder for at få den komplette liste over understøttede frameworks og 75 indbyggede kæder. Learn more →

Ofte stillede spørgsmål om Android-lokalisering