
Ο πλήρης οδηγός τοπικοποίησης Flutter
Από τα αρχεία ARB έως την υποστήριξη RTL: τοπικοποιήστε την εφαρμογή Flutter με το easy_localization, χειριστείτε σωστά τους πληθυντικούς κάθε γλώσσας και αυτοματοποιήστε τις μεταφράσεις με AI.
Εγκαταστήστε το easy_localization
Προσθέστε το πακέτο easy_localization στο pubspec.yaml. Είναι το δημοφιλέστερο πακέτο i18n για Flutter και υποστηρίζει αρχεία ARB/JSON, πληθυντικούς αριθμούς και επεκτάσεις context. Προσθέστε επίσης το flutter_localizations από το SDK, ώστε οι ημερομηνίες, οι αριθμοί και η κατεύθυνση του κειμένου να μορφοποιούνται ανάλογα με το locale.
dependencies:
easy_localization: ^3.0.7
flutter_localizations:
sdk: flutterΔημιουργήστε αρχεία μετάφρασης ARB
Τα αρχεία Application Resource Bundle (ARB) αποτελούν την τυπική μορφή τοπικοποίησης για το Flutter. Κάθε αρχείο περιέχει ζεύγη κλειδιών-τιμών και προαιρετικά μεταδεδομένα που περιγράφουν placeholders, κανόνες πληθυντικού και πληροφορίες περιβάλλοντος για τους μεταφραστές. Δημιουργήστε ένα αρχείο ανά 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 — όλες διαθέσιμες μέσω επεκτάσεων context.
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() με την τιμή count. Το easy_localization παρέχει τόσο τη σύνταξη επέκτασης συμβολοσειράς ('key'.tr()) όσο και τη σύνταξη μεθόδου context (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 και Web. Ορίστε τις μορφές πληθυντικού με τη σύνταξη {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 και ιδιότητες που λαμβάνουν υπόψη την κατεύθυνση. Αντικαταστήστε τις σταθερές αναφορές σε αριστερά και δεξιά με τα αντίστοιχα 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 διορθώνει το πρόβλημα με διαμορφώσιμες αλυσίδες εναλλακτικών locale. Μία γραμμή ρύθμισης, χωρίς καμία μετεγκατάσταση — οι υπάρχουσες κλήσεις .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 με AI. Στο IDE σας, ζητήστε από τον βοηθό AI να μεταφράσει το αρχείο ARB προέλευσης ή χρησιμοποιήστε το i18n Agent CLI στο pipeline CI/CD. Τα μεταδεδομένα ARB, όπως τα placeholders και οι περιγραφές, παρέχουν πληροφορίες περιβάλλοντος που βελτιώνουν την ποιότητα της μετάφρασης.
# 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
Οι σταθερές αναφορές σε αριστερά και δεξιά διαταράσσουν το 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 με το locale_chain
Όταν λείπει ένα κλειδί μετάφρασης από ένα τοπικό locale όπως το pt-BR, το Flutter μεταβαίνει απευθείας στη γλώσσα προτύπου αντί να ελέγξει πρώτα το γονικό locale 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, με την πλήρη λίστα των υποστηριζόμενων frameworks και 75 ενσωματωμένων αλυσίδων. Learn more →