Skip to main content

Panduan Lengkap Penyetempatan Aplikasi Android

Daripada strings.xml hingga metadata Play Store: setempatkan aplikasi Android dengan Kotlin, Jetpack Compose, Fastlane, dan terjemahan AI automatik.

1

Sediakan Projek Android untuk Penyetempatan

Android menggunakan konvensyen berasaskan folder untuk penyetempatan. Rentetan lalai berada dalam res/values/strings.xml dan rentetan terjemahan ditempatkan dalam folder khusus bahasa seperti res/values-de/, res/values-ja/, dan seterusnya.

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
Folder res/values/ ialah bahasa sandaran. Jika rentetan tiada dalam folder khusus bahasa, Android memuatkannya daripada folder lalai. Namun, jika rentetan tiada dalam folder lalai, aplikasi akan terhenti dalam bahasa yang tidak disokong.
2

Cipta strings.xml

Sumber rentetan Android menggunakan XML dengan elemen '<string>' dalam akar '<resources>'. Gunakan %s untuk ruang letak rentetan, %d untuk integer, serta %1$s/%2$s untuk argumen kedudukan yang boleh disusun semula oleh penterjemah.

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>
Apostrof yang tidak dilepaskan menyebabkan penghurai XML terhenti tanpa mesej. Gunakan \' atau balut nilai dengan tanda petik berganda. Selain itu, rentetan yang tiada dalam values/strings.xml lalai menyebabkan aplikasi terus terhenti—bukan sandaran yang lancar seperti 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

Kendalikan Bentuk Jamak

Android menggunakan elemen '&lt;plurals&gt;' dengan atribut quantity: zero, one, two, few, many, other. Setiap bahasa sasaran mungkin memerlukan kategori berbeza—bahasa Arab menggunakan kesemua enam kategori, Rusia memerlukan few/many, dan Jepun hanya menggunakan 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
) -->
Atribut quantity memilih bentuk jamak berdasarkan peraturan CLDR untuk bahasa peranti. Sentiasa sertakan 'other' sebagai sandaran—ini satu-satunya kategori yang dijamin wujud dalam setiap bahasa.
4

Gunakan dalam Kod: Kotlin dan Jetpack Compose

Android tradisional menggunakan getString(R.string.key) dan resources.getQuantityString(). Jetpack Compose menggunakan stringResource(R.string.key) dan pluralStringResource(). Kedua-duanya memilih terjemahan yang betul berdasarkan bahasa peranti semasa masa jalan.

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)—parameter count diteruskan dua kali. Yang pertama memilih bentuk jamak dan yang kedua menjadi argumen format. Menghilangkan count kedua ialah pepijat bentuk jamak Compose yang paling biasa.
5

Tatasusunan Rentetan dan Rentetan Berformat

Gunakan '&lt;string-array&gt;' untuk senarai berurutan (contohnya pilihan lungsur turun, langkah pengenalan). Gunakan argumen format kedudukan (%1$s, %2$d) dalam rentetan berformat supaya penterjemah boleh menyusun semula perkataan tanpa merosakkan struktur ayat.

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>
Argumen kedudukan seperti %1$s membolehkan penterjemah menyusun semula parameter dengan bebas. 'Hello %1$s, you have %2$d items' boleh menjadi '%2$d items for %1$s' dalam bahasa dengan susunan perkataan berbeza—tanpa mengubah kod.
6

Setempatkan Metadata Google Play dengan Fastlane

Gunakan perintah supply Fastlane untuk mengurus metadata Play Store—tajuk, penerangan ringkas, penerangan penuh, dan log perubahan—sebagai fail teks biasa yang disusun mengikut bahasa dalam repositori.

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
Menyetempatkan penyenaraian Play Store meningkatkan muat turun lebih daripada 30% dalam pasaran bukan bahasa Inggeris. Tajuk, penerangan ringkas, dan penerangan penuh diindeks untuk carian—menterjemahnya ialah penyetempatan dengan ROI tertinggi yang boleh anda lakukan.
Google Play

Automatikkan Penyetempatan Penyenaraian Play Store

Langkau salin-tampal manual. Terjemah tajuk, penerangan, dan nota keluaran Play Store kepada lebih daripada 175 bahasa dengan mengambil kira had aksara.

Terokai Penyepaduan Google Play
7

Uji Penyetempatan anda

Uji dengan penukaran bahasa emulator, pratonton Compose menggunakan LocaleList tersuai, dan bahasa pseudo dalam Developer Options. Gunakan resConfigs dalam Gradle untuk membuang sumber bahasa yang tidak diingini daripada pustaka pihak ketiga.

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
Uji dengan bahasa Jerman (teks memanjang kira-kira 30%) dan Jepun (memendek kira-kira 50%) untuk mengesan masalah susun atur. Aktifkan bahasa pseudo (en-XA untuk aksen, ar-XB untuk RTL) dalam Developer Options untuk menguji susun atur secara ekstrem tanpa terjemahan sebenar.

Automatikkan Kualiti Terjemahan

Kesan kekunci hilang, ruang letak rosak, dan masalah bentuk jamak sebelum dikeluarkan dengan i18n-validate. Uji UI dengan terjemahan pseudo menggunakan i18n-pseudo sebelum terjemahan sebenar tersedia.
8

Automatikkan Terjemahan

Terjemah strings.xml, bentuk jamak, tatasusunan rentetan, dan metadata Fastlane Supply dengan AI. Automatikkan terjemahan rentetan dalam aplikasi dan metadata Play Store untuk menyediakan pengalaman yang disetempatkan sepenuhnya.

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 mengendalikan pelepasan XML Android, mengekalkan penanda translatable="false", mematuhi kategori bentuk jamak CLDR untuk setiap bahasa sasaran, dan memastikan argumen format kedudukan kekal utuh.
JetBrains

Pemalam Android Studio Tersedia

Terjemah sumber XML Android terus daripada IDE dengan pemalam i18n Agent untuk IntelliJ / Android Studio.

Install
+

Bonus: Sandaran Bahasa Pintar dengan LocaleChain

Sandaran sumber Android dikawal oleh OS. Apabila terjemahan pt-BR tiada, Android melangkau pt-PT sepenuhnya dan memaparkan bahasa Inggeris. LocaleChain memintas carian rentetan dan menelusuri rantaian sandaran yang boleh dikonfigurasi—supaya pengguna serantau melihat terjemahan tersedia yang paling hampir.

LocaleChain untuk Android ialah pustaka Kotlin sumber terbuka. Lihat di 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"))
)

Kesilapan Umum

Rentetan Lalai yang Hilang Menyebabkan Aplikasi Terhenti

Tidak seperti iOS yang memaparkan kekunci mentah, Android terhenti dengan ResourceNotFoundException jika rentetan tiada dalam res/values/strings.xml lalai. Sentiasa pastikan setiap kekunci wujud dalam fail lalai.

Pemisahan Bahasa App Bundle Merosakkan Penukaran dalam Aplikasi

Google Play App Bundle memisahkan APK mengikut bahasa—pengguna hanya menerima rentetan bahasa peranti mereka. Jika anda menawarkan penukaran bahasa dalam aplikasi, tambahkan bundle '{ language { enableSplit = false } }' pada build.gradle.kts.

Susun Atur RTL Rosak

Menggunakan left/right dan bukannya start/end dalam susun atur atau tidak menyertakan android:supportsRtl="true" dalam AndroidManifest.xml. Gunakan Refactor > Add RTL Support dalam Android Studio untuk menukar susun atur sedia ada secara automatik.

Pencemaran Sumber Pustaka

Pustaka pihak ketiga menyertakan fail values-XX/strings.xml sendiri sehingga Android menganggap aplikasi menyokong bahasa yang sebenarnya tidak disokong. Gunakan resConfigs dalam build.gradle.kts untuk mengehadkan bahasa yang disertakan hanya kepada bahasa yang benar-benar anda terjemah.

Struktur Fail yang Disyorkan

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

Cuba i18n Agent Sekarang

Lepaskan fail terjemahan anda di sini

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

atau klik untuk semak imbas

Bahasa sasaran

Tidak perlu mendaftarAnggaran serta-merta

Sandaran Bahasa dengan locale-chain-android

Apabila kekunci terjemahan tiada dalam bahasa serantau seperti pt-BR, Android terus beralih kepada folder sumber lalai dan bukannya memeriksa bahasa induk pt terlebih dahulu.

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

Lihat Panduan Sandaran Bahasa kami untuk senarai lengkap rangka kerja yang disokong dan 75 rantaian terbina dalam. Learn more →

Soalan Lazim Penyetempatan Android