
الدليل الشامل لتوطين تطبيقات Android
من strings.xml إلى بيانات Play Store الوصفية: وطّن تطبيق Android باستخدام Kotlin وJetpack Compose وFastlane والترجمة الآلية بالذكاء الاصطناعي.
إعداد مشروع Android لديك للتوطين
يعتمد Android اصطلاحاً قائماً على المجلدات للتوطين. توجد سلاسك الافتراضية في res/values/strings.xml، وتوضع السلاسل المترجمة في مجلدات خاصة بالإعدادات المحلية مثل res/values-de/ وres/values-ja/، إلخ.
// 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إنشاء strings.xml
تستخدم موارد السلاسل في Android تنسيق XML مع عناصر '<string>' داخل الجذر '<resources>'. استخدم %s للعناصر النائبة النصية، و%d للأعداد الصحيحة، و%1$s/%2$s للوسائط الموضعية التي يمكن للمترجمين إعادة ترتيبها.
<!-- 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>التعامل مع صيغ الجمع
يستخدم Android عناصر '<plurals>' مع سمات quantity: zero وone وtwo وfew وmany وother. قد تحتاج كل لغة مستهدفة فئات مختلفة؛ العربية تستخدم الفئات الست كلها، والروسية تحتاج few/many، واليابانية تستخدم 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
) -->الاستخدام في الشيفرة: Kotlin وJetpack Compose
يستخدم Android التقليدي getString(R.string.key) وresources.getQuantityString(). ويستخدم Jetpack Compose الدالتين stringResource(R.string.key) وpluralStringResource(). كلاهما يحل الترجمة الصحيحة وفق إعدادات الجهاز المحلية أثناء وقت التشغيل.
// 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
))
}مصفوفات السلاسل والسلاسل المنسّقة
استخدم '<string-array>' للقوائم المرتبة (مثل خيارات القوائم المنسدلة وخطوات الإعداد). استخدم وسائط تنسيق موضعية (%1$s، %2$d) في السلاسل المنسّقة كي يتمكن المترجمون من إعادة ترتيب الكلمات من دون كسر بنية الجملة.
<!-- 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 الوصفية باستخدام Fastlane
استخدم أمر supply في Fastlane لإدارة بيانات Play Store الوصفية؛ العنوان، والوصف القصير، والوصف الكامل، وسجلات التغيير؛ على هيئة ملفات نصية عادية منظمة حسب الإعدادات المحلية داخل مستودعك.
# 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أتمتة توطين صفحة تطبيقك في Play Store
تخطَّ النسخ واللصق اليدوي. ترجم عنوان Play Store والوصف وملاحظات الإصدار عبر أكثر من 175 إعداداً محلياً مع مراعاة حدود عدد الأحرف.
استكشف تكامل Google Playاختبار التوطين لديك
اختبر عبر تبديل الإعدادات المحلية في المحاكي، ومعاينات Compose باستخدام LocaleList مخصصة، وpseudolocales ضمن Developer Options. استخدم resConfigs في Gradle لإزالة موارد الإعدادات المحلية غير المرغوب فيها من مكتبات الطرف الثالث.
// 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أتمتة جودة الترجمة
أتمتة الترجمات
ترجم strings.xml وصيغ الجمع ومصفوفات السلاسل وبيانات Fastlane Supply الوصفية باستخدام الذكاء الاصطناعي. أتمت ترجمة سلاسل داخل التطبيق وبيانات Play Store الوصفية معاً للحصول على حضور محلي كامل.
# 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يتوفر ملحق لـ Android Studio
ترجم موارد Android XML مباشرة من بيئة التطوير المتكاملة لديك باستخدام ملحق i18n Agent لـ IntelliJ / Android Studio.
مكافأة: رجوع ذكي للإعدادات المحلية باستخدام LocaleChain
يتحكم نظام التشغيل في رجوع موارد Android. عند غياب ترجمات pt-BR، يتجاوز Android pt-PT بالكامل ويعرض الإنجليزية. يعترض LocaleChain عمليات البحث عن السلاسل ويتتبع سلسلة رجوع قابلة للتهيئة، بحيث يرى المستخدمون الإقليميون أقرب ترجمة متاحة.
LocaleChain for Android مكتبة Kotlin مفتوحة المصدر. عرض على 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"))
)مواطن الخلل الشائعة
غياب السلاسل الافتراضية يسبب أعطالاً
تقسيمات لغة App Bundle تكسر تبديل اللغة داخل التطبيق
تعطل تخطيطات RTL
تلوث موارد المكتبات
هيكل الملفات الموصى به
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جرّب i18n Agent الآن
أفلت ملف الترجمة هنا
JSON, YAML, PO, XML, CSV, Markdown, Properties
أو انقر للاستعراض
اللغات المستهدفة
الرجوع إلى إعدادات محلية بديلة باستخدام locale-chain-android
عندما يكون مفتاح الترجمة مفقوداً في إعدادات محلية إقليمية مثل pt-BR، ينتقل Android مباشرة إلى مجلد الموارد الافتراضي بدلاً من التحقق أولاً من الإعدادات المحلية الأصلية pt.
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"),
)
)اطّلع على دليل الرجوع إلى إعدادات محلية بديلة للاطّلاع على القائمة الكاملة للأطر المدعومة و75 سلسلة مدمجة. Learn more →