Skip to main content

Guida completa alla localizzazione delle applicazioni Android

Da strings.xml ai metadati Play Store: localizzare un'app Android con Kotlin, Jetpack Compose, Fastlane e traduzione IA automatizzata.

1

Preparare il progetto Android per la localizzazione

Android usa cartelle specifiche: le stringhe predefinite risiedono in res/values/strings.xml e quelle tradotte in cartelle come res/values-de/ o 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/ è la lingua di fallback. Se una stringa manca in una cartella specifica, Android usa quella predefinita. Se manca anche da quest'ultima, l'applicazione si blocca nelle lingue non supportate.
2

Creare strings.xml

Le risorse stringa Android usano XML con elementi '<string>' in una radice '<resources>'. Usare %s per stringhe, %d per interi e %1$s/%2$s per argomenti posizionali riordinabili dai traduttori.

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>
Gli apostrofi senza escape bloccano il parser XML senza segnalazioni. Usare \' oppure racchiudere il valore tra virgolette doppie. Inoltre, una stringa mancante in values/strings.xml causa un arresto, non un fallback controllato come in 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

Gestire i plurali

Android usa elementi '&lt;plurals&gt;' con attributi quantity: zero, one, two, few, many, other. Ogni lingua può richiedere categorie diverse: l'arabo tutte e 6, il russo few/many, il giapponese soltanto 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
) -->
L'attributo quantity seleziona la forma secondo le regole CLDR della lingua del dispositivo. Includere sempre 'other' come fallback: è l'unica categoria presente in ogni lingua.
4

Uso nel codice: Kotlin e Jetpack Compose

Android tradizionale usa getString(R.string.key) e resources.getQuantityString(). Jetpack Compose usa stringResource(R.string.key) e pluralStringResource(). Entrambi risolvono la traduzione in base alla lingua del dispositivo.

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 viene passato due volte. Il primo seleziona la forma, il secondo è l'argomento di formato. Omettere il secondo è il principale errore dei plurali in Compose.
5

Array di stringhe e stringhe formattate

Usare '&lt;string-array&gt;' per elenchi ordinati, ad esempio opzioni e passaggi di onboarding. Usare argomenti posizionali (%1$s, %2$d) affinché i traduttori possano riordinare le parole senza rompere la frase.

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>
Gli argomenti come %1$s consentono di riordinare liberamente i parametri. 'Hello %1$s, you have %2$d items' può diventare '%2$d items for %1$s' in lingue con ordine diverso, senza modifiche al codice.
6

Localizzare i metadati Google Play con Fastlane

Usare supply di Fastlane per gestire titolo, descrizione breve e completa e changelog come file di testo organizzati per lingua nel 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
Localizzare la scheda Play Store aumenta i download di oltre il 30% nei mercati non anglofoni. Titolo e descrizioni sono indicizzati: tradurli offre il massimo ritorno sull'investimento.
Google Play

Automatizzare la localizzazione della scheda Play Store

Evitare il copia e incolla manuale. Tradurre titolo, descrizione e note di rilascio in oltre 175 lingue rispettando i limiti di caratteri.

Esplorare l'integrazione Google Play
7

Testare la localizzazione

Testare cambiando lingua nell'emulatore, con anteprime Compose e LocaleList personalizzato e con pseudolingue nelle Opzioni sviluppatore. Usare resConfigs in Gradle per rimuovere risorse indesiderate delle biblioteche.

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
Testare con tedesco, che espande il testo di circa il 30%, e giapponese, che lo riduce di circa il 50%. Abilitare en-XA e ar-XB nelle Opzioni sviluppatore per prove di stress senza traduzioni reali.

Automatizzare la qualità

Rilevare chiavi mancanti, segnaposto danneggiati e problemi di plurali con i18n-validate. Testare l'interfaccia con pseudotraduzioni tramite i18n-pseudo prima che arrivino quelle reali.
8

Automatizzare le traduzioni

Tradurre strings.xml, plurals, array di stringhe e metadati Fastlane Supply con l'IA. Automatizzare stringhe dell'applicazione e metadati Play Store per una presenza completamente localizzata.

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 gestisce gli escape XML Android, conserva i marcatori translatable="false", rispetta le categorie CLDR e mantiene intatti gli argomenti posizionali.
JetBrains

Plugin Android Studio disponibile

Tradurre le risorse XML Android direttamente dall'IDE con il plugin i18n Agent per IntelliJ/Android Studio.

Install
+

Extra: fallback intelligente con LocaleChain

Il fallback delle risorse di Android è controllato dal sistema operativo. Quando mancano le traduzioni pt-BR, Android ignora completamente pt-PT e mostra l'inglese. LocaleChain intercetta le ricerche delle stringhe e percorre una catena di fallback configurabile, così gli utenti regionali vedono la traduzione disponibile più vicina.

LocaleChain per Android è una biblioteca Kotlin open source. Visualizzare su 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"))
)

Problemi comuni

L'assenza delle stringhe predefinite causa arresti anomali

A differenza di iOS, che mostra la chiave non elaborata, Android genera un arresto anomalo con ResourceNotFoundException se manca una stringa nel file predefinito res/values/strings.xml. Verificare sempre che ogni chiave esista nel file predefinito.

La suddivisione per lingua degli App Bundle impedisce il cambio di lingua nell'app

Gli App Bundle di Google Play suddividono gli APK per lingua: gli utenti ricevono solo le stringhe della lingua del proprio dispositivo. Se offre il cambio di lingua nell'app, aggiunga bundle '{ language { enableSplit = false } }' al file build.gradle.kts.

Layout RTL non funzionanti

L'uso di left/right anziché start/end nei layout o l'assenza di android:supportsRtl="true" in AndroidManifest.xml. Utilizzi Refactor > Add RTL Support di Android Studio per convertire automaticamente i layout esistenti.

Contaminazione delle risorse delle biblioteche

Le biblioteche di terze parti includono i propri file values-XX/strings.xml, facendo credere ad Android che l'app supporti lingue in realtà non disponibili. Usi resConfigs in build.gradle.kts per limitare le lingue incluse a quelle che traduce effettivamente.

Struttura dei file consigliata

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

Provi subito i18n Agent

Trascinare qui il file di traduzione

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

oppure fare clic per selezionarlo

Lingue di destinazione

Nessuna registrazione richiestaPreventivo immediato

Fallback della lingua con locale-chain-android

Quando manca una chiave di traduzione in una lingua regionale come pt-BR, Android passa direttamente alla cartella delle risorse predefinite anziché controllare prima la lingua principale 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"),
    )
)

Consultare la Guida al fallback delle lingue per l'elenco completo dei framework supportati e delle 75 catene integrate. Learn more →

Domande frequenti sulla localizzazione Android