Skip to main content

Cjelovit vodič za Flutter lokalizaciju

Od ARB datoteka do RTL podrške: lokalizirajte Flutter aplikaciju pomoću easy_localization, obradite množine za svaki jezik i automatizirajte prijevode pomoću AI-ja.

1

Instalirajte easy_localization

Dodajte paket easy_localization u pubspec.yaml. To je najpopularniji Flutter i18n paket, s podrškom za ARB/JSON datoteke, množinu i proširenja konteksta. Dodajte i flutter_localizations iz paketa Flutter SDK za formatiranje datuma, brojeva i smjera teksta u skladu s regionalnim postavkama.

easy_localization pruža proširenja konteksta kao što su context.tr() i 'key'.tr() za sažet pristup prijevodu. Učitava odabrani jezik, pamti ga i tijekom razvoja ponovno učitava datoteke prijevoda bez ponovnog pokretanja aplikacije.
pubspec.yaml
dependencies:
  easy_localization: ^3.0.7
  flutter_localizations:
    sdk: flutter
2

Izradite ARB datoteke prijevoda

Datoteke Application Resource Bundle (ARB) standardni su lokalizacijski format za Flutter. Svaka datoteka sadržava parove ključ–vrijednost s neobveznim metapodacima koji opisuju rezervirana mjesta, pravila množine i kontekst za prevoditelje. Izradite po jednu datoteku za svaku jezično-regionalnu oznaku u mapi assets/translations.

assets/translations/en.arb
{
  "@@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"
      }
    }
  }
}
Ključevi s prefiksom @ (kao što je @greeting) predstavljaju metapodatke — opisuju tekst iznad njih. Navedite vrste i primjere rezerviranih mjesta kako biste prevoditeljima pomogli izraditi točne prijevode. Ti se metapodatkovni ključevi uklanjaju tijekom izvođenja i ne stvaraju dodatno opterećenje.
3

Konfigurirajte aplikaciju

Obuhvatite aplikaciju widgetom EasyLocalization. On upravlja stanjem jezika, učitava prijevode iz datoteka resursa i pruža lokalizacijske delegate potrebne komponenti MaterialApp. Tri obvezna svojstva delegata jesu localizationsDelegates, supportedLocales i locale — sva su dostupna putem proširenja konteksta.

lib/main.dart
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(),
    );
  }
}
"Easy Localization not initialized" — ova pogreška znači da ste zaboravili pozvati EasyLocalization.ensureInitialized() prije runApp(). Potrebno je pričekati završetak te funkcije nakon WidgetsFlutterBinding.ensureInitialized(), a prije runApp().
4

Prevedite widgete

Upotrijebite metodu proširenja .tr() na tekstnim ključevima kako biste dohvatili prevedeni tekst u bilo kojem widgetu. Za množinu upotrijebite .plural() s brojčanom vrijednošću. easy_localization pruža i sintaksu proširenja tekstnog niza ('key'.tr()) i sintaksu metode konteksta (context.tr('key')).

lib/widgets/home_page.dart
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)),
        ],
      ),
    );
  }
}
Ako prijevodi vraćaju neobrađene ključeve umjesto prevedenog teksta, provjerite: 1) widget EasyLocalization obuhvaća MaterialApp, a ne obrnuto; 2) datoteke prijevoda navedene su u pubspec.yaml pod assets; 3) putanja datoteke u EasyLocalization odgovara stvarnoj strukturi mapa.
5

Obradite množinu i varijable

Flutter koristi ICU MessageFormat za množinu — isti standard koji upotrebljavaju iOS, Android i web. Definirajte oblike množine sintaksom {count, plural, ...} u ARB datotekama. Svakom je jeziku potreban vlastiti skup oblika prema CLDR pravilima množine. Arapski ima 6 oblika, ruski 4, a japanski 1.

Plural forms by language
// 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} товаров}}"
Variables and named arguments
// 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}));
Nikada ne upisujte izravno logiku jednine i množine pomoću if (count == 1). Jezici poput francuskog tretiraju 0 kao jedninu. Ruski, poljski i arapski imaju oblike množine koji u engleskom uopće ne postoje. Uvijek koristite ICU sintaksu množine i prepustite radnom okviru izbor ispravnog oblika.
6

Podržite RTL jezike

Flutter automatski preslikava cijeli raspored kada je aktivan jezik koji se piše zdesna nalijevo (arapski, hebrejski, perzijski ili urdu). Međutim, Vaš kod mora upotrebljavati widgete i svojstva prilagođena smjeru kako bi preslikavanje ispravno radilo. Izravno zadane vrijednosti left/right zamijenite odgovarajućim vrijednostima start/end.

lib/widgets/adaptive_layout.dart
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,
          ),
        ],
      ),
    );
  }
}
RTL-aware widget patterns
// 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
Testirajte RTL tako da privremeno postavite jezik aplikacije na arapski (Locale('ar')). Flutter preslikava cijelo korisničko sučelje — navigacijske ladice otvaraju se zdesna, strelice za povratak okreću se, a tekst se poravnava udesno. Upotrijebite EdgeInsetsDirectional, AlignmentDirectional i BorderRadiusDirectional kako biste osigurali ispravno preslikavanje prilagođenih rasporeda.
7

Pametni lanci pričuvnog odabira jezika

Kada prijevod za pt-BR nedostaje, Flutter zadano odmah prelazi na engleski i preskače dostupne prijevode za pt-PT. Paket locale_chain to ispravlja prilagodljivim pričuvnim lancima. Dovoljan je jedan redak za postavljanje, bez migracije — postojeći pozivi .tr() nastavljaju raditi.

lib/main.dart with LocaleChain
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.
Custom fallback configuration
// 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
);
locale_chain sadržava ugrađene lance pričuvnog odabira za regionalne inačice portugalskog, španjolskog, francuskog, njemačkog, talijanskog, nizozemskog, norveškog i malajskog. Korisnik s oznakom pt-BR vidjet će sadržaj za pt-PT prije engleskog. Korisnik s oznakom es-MX vidjet će es-419, a zatim es, prije zadanog jezika.
8

Automatizirajte prijevode

Kada postavite lokalizaciju, prevedite ARB datoteke pomoću AI-ja. U IDE-u zatražite od AI pomoćnika da prevede izvornu ARB datoteku ili upotrijebite i18n Agent CLI u CI/CD procesu. ARB metapodaci (rezervirana mjesta, opisi) pružaju kontekst koji poboljšava kvalitetu prijevoda.

Terminal
# 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
Prevodite postupno — kada dodate nove ključeve u izvornu ARB datoteku, prevedite samo razliku umjesto ponovnog generiranja svih datoteka. Time se čuvaju prijevodi koje su ljudi pregledali, a ARB metapodaci ostaju netaknuti.

Automatizirajte provjeru kvalitete prijevoda

Alatom i18n-validate otkrijte ključeve koji nedostaju i neispravna rezervirana mjesta prije isporuke. Korisničko sučelje testirajte pseudoprijevodima iz alata i18n-pseudo prije nego što stignu stvarni prijevodi.

Uobičajene zamke

Datoteke prijevoda nisu pronađene tijekom izvršavanja

ARB/JSON datoteke moraju biti navedene u pubspec.yaml u odjeljku assets. Ako preskočite taj korak, Flutter ne može pronaći datoteke tijekom izvođenja iako postoje na disku. Dodajte: assets: - assets/translations/

Neispravna sintaksa ARB datoteke

ARB datoteke strogo su oblikovan JSON — bez završnih zareza, jednostrukih navodnika i komentara. Jedna sintaksna pogreška neprimjetno sprječava učitavanje cijele datoteke. Provjerite ARB datoteke alatom za provjeru JSON-a prije otklanjanja problema s prijevodom.

Izmjene prijevoda se ne pojavljuju nakon hot reload postupka

easy_localization predmemorira prijevode. Dodavanje novih ključeva ili izmjena postojećih prijevoda može zahtijevati potpuno ponovno pokretanje (hot restart, a ne hot reload) kako bi promjene stupile na snagu. Tijekom razvoja provedite hot restart (Shift+R) nakon uređivanja datoteka prijevoda.

Izravno upisano lijevo/desno narušava RTL

Upotreba EdgeInsets.only(left: 16) umjesto EdgeInsetsDirectional.only(start: 16) sprječava Flutter da preslika raspored za RTL jezike. U bazi izvornog koda potražite EdgeInsets, Alignment i BorderRadius bez nastavka Directional.

Preporučena struktura datoteka

Project Structure
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

Isprobajte i18n Agent odmah

Povucite datoteku za prijevod ovdje

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

ili kliknite za odabir

Ciljni jezici

Registracija nije potrebnaProcjena odmah

Pričuvni odabir jezika uz locale_chain

Kada ključ prijevoda nedostaje u regionalnoj jezičnoj inačici kao što je pt-BR, Flutter odmah prelazi na jezik predloška umjesto da prvo provjeri nadređenu jezičnu oznaku pt.

Terminal
flutter pub add locale_chain
Configuration
import 'package:locale_chain/locale_chain.dart';

LocaleChain.configure(fallbacks: {
  'pt-BR': ['pt', 'en'],
  'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
});

LocaleChainAssetLoader(baseLoader: RootBundleAssetLoader());

U našem vodiču za pričuvni odabir jezika pogledajte cjelovit popis podržanih radnih okvira i 75 ugrađenih lanaca. Learn more →

Česta pitanja