
الدليل الشامل لتوطين Flutter
من ملفات ARB إلى دعم RTL: وطّن تطبيق Flutter باستخدام easy_localization، وتعامل مع صيغ الجمع لكل لغة، وأتمت الترجمات بالذكاء الاصطناعي.
تثبيت easy_localization
أضِف حزمة easy_localization إلى pubspec.yaml. هذه هي الحزمة الأكثر شيوعاً لتوطين Flutter، مع دعم ملفات ARB/JSON وصيغ الجمع وامتدادات السياق. وأضِف أيضاً flutter_localizations من SDK لتنسيق التواريخ والأرقام واتجاه النص اعتماداً على locale.
dependencies:
easy_localization: ^3.0.7
flutter_localizations:
sdk: flutterإنشاء ملفات ترجمة ARB
تُعد ملفات ARB (Application Resource Bundle) صيغة التوطين القياسية في Flutter. يحتوي كل ملف أزواج مفتاح/قيمة مع بيانات وصفية اختيارية تصف العناصر النائبة وقواعد الجمع وسياق المترجم. أنشئ ملفاً واحداً لكل locale ضمن المجلد assets/translations.
{
"@@locale": "en",
"appTitle": "My App",
"@appTitle": {
"description": "The title of the application"
},
"greeting": "Hello, {name}!",
"@greeting": {
"description": "Greeting with user name",
"placeholders": {
"name": {
"type": "String",
"example": "Alice"
}
}
},
"itemCount": "{count, plural, =0{No items} =1{1 item} other{{count} items}}",
"@itemCount": {
"description": "Number of items in the cart",
"placeholders": {
"count": {
"type": "num",
"format": "compact"
}
}
}
}تهيئة التطبيق
غلّف تطبيقك بالـ widget EasyLocalization. يدير حالة locale، ويحمّل الترجمات من ملفات الأصول لديك، ويوفر delegates المحلية التي يحتاجها MaterialApp. خصائص delegate الثلاث المطلوبة هي: localizationsDelegates وsupportedLocales وlocale؛ وجميعها متاحة عبر امتدادات السياق.
import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
runApp(
EasyLocalization(
supportedLocales: [
Locale('en'),
Locale('ar'),
Locale('ja'),
Locale('de'),
],
path: 'assets/translations', // Path to your ARB/JSON files
fallbackLocale: Locale('en'),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
home: HomePage(),
);
}
}ترجمة Widgets
استخدم طريقة الامتداد .tr() على مفاتيح السلاسل للحصول على النص المترجم في أي Widget. ولصيغ الجمع، استخدم .plural() مع قيمة العدد. توفر easy_localization كلاً من صيغة امتداد السلسلة ('key'.tr()) وصيغة طريقة السياق (context.tr('key')).
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('appTitle'.tr()), // Simple key
),
body: Column(
children: [
// String with variable interpolation
Text('greeting'.tr(args: ['Alice'])),
// Named arguments
Text('greeting'.tr(namedArgs: {'name': 'Alice'})),
// Plural form
Text('itemCount'.plural(3)),
],
),
);
}
}التعامل مع صيغ الجمع والمتغيرات
يستخدم Flutter معيار ICU MessageFormat لصيغ الجمع؛ وهو المعيار نفسه المستخدم في iOS وAndroid والويب. عرّف صيغ الجمع باستخدام صيغة {count, plural, ...} ضمن ملفات ARB. تحتاج كل لغة إلى مجموعة صيغ خاصة بها وفق قواعد الجمع في CLDR. لدى العربية 6 صيغ، ولدى الروسية 4، ولدى اليابانية 1.
// English: 3 useful forms (=0, =1, other)
"itemCount": "{count, plural, =0{No items} =1{1 item} other{{count} items}}"
// Arabic: 6 forms (=0, =1, =2, few, many, other)
"itemCount": "{count, plural, =0{لا عناصر} =1{عنصر واحد} =2{عنصران} few{{count} عناصر} many{{count} عنصرًا} other{{count} عنصر}}"
// Japanese: 1 form (other)
"itemCount": "{count, plural, other{{count}個のアイテム}}"
// German: 2 forms (=1, other)
"itemCount": "{count, plural, =1{1 Artikel} other{{count} Artikel}}"
// Russian: 3 forms (one, few, many)
"itemCount": "{count, plural, =0{Нет товаров} one{{count} товар} few{{count} товара} many{{count} товаров} other{{count} товаров}}"// Simple variable
"welcome": "Welcome, {name}!"
// Multiple variables
"orderStatus": "Order #{orderId} — {status}"
// Variable in plural context
"unreadMessages": "{count, plural, =0{No unread messages} =1{1 unread message from {sender}} other{{count} unread messages}}"
// In widgets:
Text('welcome'.tr(namedArgs: {'name': userName}));
Text('orderStatus'.tr(namedArgs: {'orderId': '1234', 'status': 'Shipped'}));
Text('unreadMessages'.plural(count, namedArgs: {'sender': senderName}));دعم لغات RTL
يعكس Flutter التخطيط بالكامل تلقائياً عندما تكون locale لغة تُكتب من اليمين إلى اليسار (العربية، العبرية، الفارسية، الأردية). لكن يجب أن يستخدم كودك widgets وخصائص مدركة للاتجاه كي يعمل الانعكاس بشكل صحيح. استبدل left/right الثابتة بمكافئات start/end.
import 'package:flutter/material.dart';
class AdaptiveLayout extends StatelessWidget {
@override
Widget build(BuildContext context) {
final isRtl = Directionality.of(context) == TextDirection.rtl;
return Scaffold(
body: Row(
children: [
// Use start/end instead of left/right
Expanded(
child: Padding(
padding: EdgeInsetsDirectional.only(
start: 16.0, // Leading edge (left in LTR, right in RTL)
end: 8.0, // Trailing edge
),
child: Text('content'.tr()),
),
),
// Flip icons for RTL
Icon(
isRtl ? Icons.arrow_back : Icons.arrow_forward,
),
],
),
);
}
}// Use Directional widgets for RTL-aware layouts
EdgeInsetsDirectional.only(start: 16, end: 8) // Not EdgeInsets.only(left: 16, right: 8)
AlignmentDirectional.centerStart // Not Alignment.centerLeft
BorderRadiusDirectional.only(topStart: Radius.circular(8))
// Automatically mirrors when locale changes to Arabic, Hebrew, etc.
// No conditional logic needed — Flutter handles text direction from localeسلاسل تراجع locale الذكية
افتراضياً، عندما تكون ترجمة pt-BR مفقودة، يتراجع Flutter مباشرةً إلى الإنجليزية، متجاوزاً ترجمات pt-PT المتاحة. تعالج حزمة locale_chain ذلك عبر سلاسل تراجع قابلة للتهيئة. سطر إعداد واحد، دون أي ترحيل؛ وستستمر استدعاءات .tr() الحالية بالعمل كما هي.
import 'package:locale_chain/locale_chain.dart';
import 'package:locale_chain/easy_localization.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
LocaleChain.configure(); // Enable smart fallback chains
runApp(
EasyLocalization(
supportedLocales: [
Locale('en'),
Locale('pt', 'BR'),
Locale('pt', 'PT'),
Locale('es'),
Locale('es', 'MX'),
],
path: 'assets/translations',
assetLoader: LocaleChainAssetLoader( // Swap in the chain loader
baseLoader: RootBundleAssetLoader(),
),
fallbackLocale: Locale('en'),
child: MyApp(),
),
);
}
// Result: pt-BR user sees pt-PT translations when pt-BR keys are missing,
// instead of falling back directly to English.// Override specific chains while keeping built-in defaults
LocaleChain.configure(
fallbacks: {
'pt-BR': ['pt-PT', 'pt'], // pt-BR → pt-PT → pt → en
'es-MX': ['es-419', 'es'], // es-MX → es-419 → es → en
'fr-CA': ['fr'], // fr-CA → fr → en
},
);
// Or replace all defaults with your own chains
LocaleChain.configure(
fallbacks: {
'zh-Hant-HK': ['zh-Hant-TW', 'zh-Hans'],
'pt-BR': ['pt-PT', 'pt'],
},
mergeDefaults: false, // Only your chains, no built-in defaults
);أتمتة الترجمات
بعد اكتمال إعداد التوطين، ترجم ملفات ARB باستخدام الذكاء الاصطناعي. في IDE، اطلب من مساعدك بالذكاء الاصطناعي ترجمة ملف ARB المصدر، أو استخدم i18n Agent CLI ضمن مسار CI/CD لديك. توفر بيانات ARB الوصفية (العناصر النائبة، الأوصاف) سياقاً يحسّن جودة الترجمة.
# In your IDE, ask your AI assistant:
> Translate assets/translations/en.arb to Arabic, Japanese, and German
✓ ar.arb created (1.4s)
✓ ja.arb created (1.2s)
✓ de.arb created (1.1s)
# Or use the CLI in CI/CD:
npx i18n-agent translate assets/translations/en.arb --lang ar,ja,deأتمتة جودة الترجمة
أخطاء شائعة
تعذّر العثور على ملفات الترجمة أثناء التشغيل
صياغة ملف ARB غير صالحة
لا تظهر تغييرات الترجمة عند Hot Reload
تثبيت اتجاه Left/Right برمجياً يكسر دعم RTL
بنية الملفات الموصى بها
my_flutter_app/
├── assets/
│ └── translations/
│ ├── en.arb # Source language (English)
│ ├── ar.arb # Arabic (with 6 plural forms)
│ ├── de.arb # German
│ ├── ja.arb # Japanese
│ ├── pt-BR.arb # Brazilian Portuguese
│ └── pt-PT.arb # European Portuguese
├── lib/
│ ├── main.dart # App entry with EasyLocalization
│ ├── app.dart # MaterialApp with locale delegates
│ └── widgets/
│ └── language_switcher.dart
├── pubspec.yaml # Dependencies
└── analysis_options.yamlجرّب i18n Agent الآن
أفلت ملف الترجمة هنا
JSON, YAML, PO, XML, CSV, Markdown, Properties
أو انقر للاستعراض
اللغات المستهدفة
التراجع عن الإعداد المحلي باستخدام locale_chain
عندما يكون مفتاح ترجمة مفقوداً في إعداد محلي إقليمي مثل pt-BR، يقفز Flutter مباشرةً إلى لغة القالب بدلاً من التحقق أولاً من الإعداد المحلي الأب pt.
flutter pub add locale_chainimport 'package:locale_chain/locale_chain.dart';
LocaleChain.configure(fallbacks: {
'pt-BR': ['pt', 'en'],
'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
});
LocaleChainAssetLoader(baseLoader: RootBundleAssetLoader());اطّلع على دليل Locale Fallback لدينا للحصول على القائمة الكاملة للأُطر المدعومة و75 سلسلة مدمجة. Learn more →