Skip to main content

Den kompletta guiden till lokalisering av Android-appar

Från strings.xml till Play Store-metadata: lokalisera din Android-app med Kotlin, Jetpack Compose, Fastlane och automatiserad AI-översättning.

1

Konfigurera Android-projektet för lokalisering

Android använder en mappbaserad konvention för lokalisering. Dina standardsträngar finns i res/values/strings.xml och översatta strängar placeras i språkspecifika mappar som res/values-de/, res/values-ja/ och så vidare.

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/ är din reservspråkvariant. Om en sträng saknas i en språkspecifik mapp läser Android in den från standardmappen. Om en sträng däremot saknas i standardmappen kraschar appen för språkvarianter som inte stöds.
2

Skapa strings.xml

Androids strängresurser använder XML med '<string>'-element inuti ett '<resources>'-rotelement. Använd %s som platshållare för strängar, %d för heltal och %1$s/%2$s för positionsargument som översättare kan ordna om.

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>
Apostrofer som inte har undantagits får XML-parsern att krascha utan felmeddelande. Använd \' eller omslut värdet med dubbla citattecken. Dessutom orsakar en saknad sträng i standardfilen values/strings.xml en direkt krasch, inte en smidig reservlösning 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

Hantera pluralformer

Android använder '&lt;plurals&gt;'-element med mängdattributen zero, one, two, few, many, other. Varje målspråk kan behöva olika kategorier – arabiska använder alla 6, ryska behöver few/many och japanska använder endast 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
) -->
Attributet quantity väljer pluralform utifrån CLDR-reglerna för enhetens språkvariant. Inkludera alltid 'other' som reserv – det är den enda kategorin som garanterat finns på alla språk.
4

Använd i kod: Kotlin och Jetpack Compose

Traditionell Android-kod använder getString(R.string.key) och resources.getQuantityString(). Jetpack Compose använder stringResource(R.string.key) och pluralStringResource(). Båda hämtar rätt översättning vid körning utifrån enhetens språkvariant.

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) – parametern count skickas två gånger. Den första väljer pluralformen och den andra är formatargumentet. Att utelämna den andra count är det vanligaste pluraliseringsfelet i Compose.
5

Strängmatriser och formaterade strängar

Använd '&lt;string-array&gt;' för ordnade listor (t.ex. alternativ i listrutor och introduktionssteg). Använd positionsbaserade formatargument (%1$s, %2$d) i formaterade strängar så att översättare kan ändra ordföljden utan att meningsstrukturen går sönder.

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>
Med positionsargument som %1$s kan översättare fritt ordna om parametrarna. 'Hello %1$s, you have %2$d items' kan bli '%2$d items for %1$s' på språk med en annan ordföljd utan några kodändringar.
6

Lokalisera Google Play-metadata med Fastlane

Använd kommandot supply i Fastlane för att hantera Play Store-metadata – titel, kort beskrivning, fullständig beskrivning och ändringsloggar – som textfiler ordnade efter språkvariant i ditt 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
En lokaliserad Play Store-sida kan öka antalet nedladdningar med över 30 % på marknader där engelska inte är huvudspråk. Titel, kort beskrivning och fullständig beskrivning indexeras för sökning – att översätta dem är ofta den lokalisering som ger bäst avkastning.
Google Play

Automatisera lokaliseringen av din Play Store-sida

Slipp manuell kopiering. Översätt din Play Store-titel, beskrivning och versionsinformation till fler än 175 språkvarianter med hänsyn till teckenbegränsningar.

Utforska Google Play-integreringen
7

Testa lokaliseringen

Testa genom att byta språkvariant i emulatorn, använda Compose-förhandsvisningar med en anpassad LocaleList och aktivera pseudolokaler i utvecklaralternativen. Använd resConfigs i Gradle för att ta bort oönskade språkresurser från tredjepartsbibliotek.

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
Testa med tyska (texten blir cirka 30 % längre) och japanska (cirka 50 % kortare) för att upptäcka layoutproblem. Aktivera pseudolokaler (en-XA för accentuerad text och ar-XB för RTL) i utvecklaralternativen för att stresstesta layouter utan riktiga översättningar.

Automatisera översättningskvaliteten

Upptäck saknade nycklar, trasiga platshållare och problem med pluralformer före lansering med i18n-validate. Testa gränssnittet med pseudoöversättningar via i18n-pseudo innan de riktiga översättningarna är klara.
8

Automatisera översättningar

Översätt strings.xml, pluralformer, strängmatriser och Fastlane Supply-metadata med AI. Automatisera översättningen av både strängar i appen och Play Store-metadata för en helt lokaliserad närvaro.

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 hanterar undantagstecken i Android-XML, bevarar markörer av typen translatable="false", följer CLDR-kategorierna för varje målspråk och lämnar positionsbaserade formatargument intakta.
JetBrains

Insticksprogram för Android Studio finns tillgängligt

Översätt Androids XML-resurser direkt från din IDE med insticksprogrammet i18n Agent för IntelliJ/Android Studio.

Install
+

Bonus: smart reservspråk med LocaleChain

Androids reservresurser styrs av operativsystemet. När översättningar för pt-BR saknas hoppar Android helt över pt-PT och visar engelska. LocaleChain fångar upp stränguppslagningar och går igenom en konfigurerbar reservkedja så att regionala användare ser den närmast tillgängliga översättningen.

LocaleChain för Android är ett Kotlin-bibliotek med öppen källkod. Visa 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"))
)

Vanliga fallgropar

Saknade standardsträngar orsakar krascher

Till skillnad från iOS, som visar den råa nyckeln, kraschar Android med ResourceNotFoundException om en sträng saknas i standardfilen res/values/strings.xml. Kontrollera alltid att varje nyckel finns i standardfilen.

Språkuppdelning i App Bundles stoppar språkbyte i appen

Google Play App Bundles delar upp APK-filer efter språk, så användarna får endast strängarna för enhetens språk. Om du erbjuder språkbyte i appen lägger du till bundle '{ language { enableSplit = false } }' i build.gradle.kts.

RTL-layouter fungerar inte

Orsaken är ofta att left/right används i stället för start/end i layouter eller att android:supportsRtl="true" saknas i AndroidManifest.xml. Använd Refactor > Add RTL Support i Android Studio för att automatiskt konvertera befintliga layouter.

Språkresurser från bibliotek skapar felaktigt stöd

Tredjepartsbibliotek paketerar egna values-XX/strings.xml-filer, vilket får Android att tro att appen stöder språk som den inte stöder. Använd resConfigs i build.gradle.kts för att begränsa de inkluderade språkvarianterna till dem som du faktiskt översätter.

Rekommenderad 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

Prova i18n Agent nu

Släpp din översättningsfil här

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

eller klicka för att välja en fil

Målspråk

Ingen registrering krävsPrisuppskattning direkt

Reservspråk med locale-chain-android

När en översättningsnyckel saknas i en regional språkvariant som pt-BR går Android direkt över till standardmappen för resurser i stället för att först kontrollera det överordnade språket 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 vår guide till reservspråk för en fullständig lista över ramverk som stöds och 75 inbyggda kedjor. Learn more →

Vanliga frågor om Android-lokalisering