Flutter Localization (i18n): Çok Dilli Uygulama Geliştirme

12 dakika okuma9 Şubat 2026Güncellendi: 9 Mar 2026
Flutter localizationFlutter i18nFlutter multi languageFlutter intlFlutter ARBFlutter localeFlutter translationFlutter internationalization

# Flutter Localization (i18n): Cok Dilli Uygulama Gelistirme

Kuresel kullaniciya hitap eden bir uygulamada dil destegi artik opsiyon degil, temel bir gereksinim. 10'dan fazla pazara uygulama gonderdigim projelerde, i18n altyapisini ilk gunden dogru kurmanin sonradan haftalarca surecek refactoring'den kurtardigini defalarca gordum. Bu rehber, Flutter'da sifirdan lokalizasyon kurulumundan RTL destegi ve ekip ceviri is akislarina kadar tum surecleri kapsiyor.

Sifirdan Lokalizasyon Kurulumu

Adim 1: Bagimliliklari Ekleyin

dart
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: ^class="code-number">0.19.class="code-number">0

flutter:
  generate: true

`generate: true` bayragi, Flutter'a ARB dosyalarinizdan otomatik olarak lokalizasyon kodu uretmesini soyler.

Adim 2: l10n Yapilandirma Dosyasi

Proje kok dizininde `l10n.yaml` dosyasi olusturun:

dart
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: AppLocalizations
nullable-getter: false

Adim 3: ARB Dosyalarini Olusturun

ARB dosyalari JSON tabanlidir ve cevirileriniz icin tek dogru kaynaktir. `lib/l10n/app_en.arb`:

dart
{
  class="code-string">"@@locale": class="code-string">"en",
  class="code-string">"appTitle": class="code-string">"My Application",
  class="code-string">"@appTitle": { class="code-string">"description": class="code-string">"The title of the application" },
  class="code-string">"welcomeMessage": class="code-string">"Welcome, {userName}!",
  class="code-string">"@welcomeMessage": {
    class="code-string">"placeholders": { class="code-string">"userName": { class="code-string">"type": class="code-string">"String", class="code-string">"example": class="code-string">"John" } }
  },
  class="code-string">"itemCount": class="code-string">"{count, plural, =class="code-number">0{No items} =class="code-number">1{class="code-number">1 item} other{{count} items}}",
  class="code-string">"@itemCount": {
    class="code-string">"placeholders": { class="code-string">"count": { class="code-string">"type": class="code-string">"num", class="code-string">"format": class="code-string">"compact" } }
  },
  class="code-string">"lastLogin": class="code-string">"Last login: {date}",
  class="code-string">"@lastLogin": {
    class="code-string">"placeholders": { class="code-string">"date": { class="code-string">"type": class="code-string">"DateTime", class="code-string">"format": class="code-string">"yMMMd" } }
  }
}

Turkce icin `lib/l10n/app_tr.arb`:

dart
{
  class="code-string">"@@locale": class="code-string">"tr",
  class="code-string">"appTitle": class="code-string">"Uygulamam",
  class="code-string">"welcomeMessage": class="code-string">"Hos geldin, {userName}!",
  class="code-string">"itemCount": class="code-string">"{count, plural, =class="code-number">0{Oge yok} =class="code-number">1{class="code-number">1 oge} other{{count} oge}}",
  class="code-string">"lastLogin": class="code-string">"Son giris: {date}"
}

Adim 4: MaterialApp Yapilandirmasi

dart
import class="code-string">'package:flutter_localizations/flutter_localizations.dart';
import class="code-string">'package:flutter_gen/gen_l10n/app_localizations.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: const [Locale(class="code-string">'en'), Locale(class="code-string">'tr'), Locale(class="code-string">'de')],
      locale: const Locale(class="code-string">'tr'),
      home: const HomeScreen(),
    );
  }
}

Adim 5: Widget'larda Cevirilere Erisim

dart
class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context);
    return Scaffold(
      appBar: AppBar(title: Text(l10n.appTitle)),
      body: Column(children: [
        Text(l10n.welcomeMessage(class="code-string">'Utku')),
        Text(l10n.itemCount(class="code-number">5)),
        Text(l10n.lastLogin(DateTime.now())),
      ]),
    );
  }
}

Dinamik Dil Degistirme

Kullanicilar uygulamayi yeniden baslatmadan dil degistirebilmeli. Temiz bir `ChangeNotifier` yapisi:

dart
class LocaleProvider extends ChangeNotifier {
  Locale _locale = const Locale(class="code-string">'tr');
  Locale get locale => _locale;
  void setLocale(Locale locale) {
    _locale = locale;
    notifyListeners();
  }
}

class=class="code-string">"code-comment">// MaterialApp icinde:
Consumer<LocaleProvider>(
  builder: (context, provider, _) => MaterialApp(
    locale: provider.locale,
    localizationsDelegates: AppLocalizations.localizationsDelegates,
    supportedLocales: AppLocalizations.supportedLocales,
    home: const HomeScreen(),
  ),
)

Cogullastirma ve Cinsiyet

ICU mesaj formati, cogullastirmayi zarif bir sekilde ele alir. Flutter ARB dosyalarinda dogrudan `plural`, `select` ve `gender` formlarini destekler:

dart
{
  class="code-string">"notificationCount": class="code-string">"{count, plural, =class="code-number">0{Bildirim yok} =class="code-number">1{class="code-number">1 bildiriminiz var} other{{count} bildiriminiz var}}",
  class="code-string">"@notificationCount": { class="code-string">"placeholders": { class="code-string">"count": { class="code-string">"type": class="code-string">"num" } } },
  class="code-string">"genderGreeting": class="code-string">"{gender, select, male{Sayin Bay {name}} female{Sayin Bayan {name}} other{Sayin {name}}}",
  class="code-string">"@genderGreeting": {
    class="code-string">"placeholders": { class="code-string">"gender": { class="code-string">"type": class="code-string">"String" }, class="code-string">"name": { class="code-string">"type": class="code-string">"String" } }
  }
}

Lehce, Arapca ve Rusca gibi dillerde tekil/cogul otesinde karmasik cogul kurallari vardir. ICU formati, yerel ayara gore `zero`, `one`, `two`, `few`, `many` ve `other` kategorilerini otomatik olarak yonetir.

Tarih ve Sayi Bicimlendirme

Tarih ve sayilari asla elle bicimlendirmeyin. Her zaman `intl` paketini kullanin:

dart
import class="code-string">'package:intl/intl.dart';

final dateFormatter = DateFormat.yMMMd(class="code-string">'tr');
print(dateFormatter.format(DateTime.now())); class=class="code-string">"code-comment">// "class="code-number">9 Mar class="code-number">2026"

final currencyFormatter = NumberFormat.currency(locale: class="code-string">'tr', symbol: class="code-string">'TL');
print(currencyFormatter.format(class="code-number">1234.56)); class=class="code-string">"code-comment">// "class="code-number">1.234,class="code-number">56 TL"

final compactFormatter = NumberFormat.compact(locale: class="code-string">'tr');
print(compactFormatter.format(class="code-number">1500000)); class=class="code-string">"code-comment">// "class="code-number">1,class="code-number">5 Mn"

RTL (Sagdan Sola) Dil Destegi

Arapca, Ibranice ve Farsca gibi sagdan sola yazilan dilleri desteklemek, yerlesim konusunda dikkatli olmayi gerektirir.

Flutter, `flutter_localizations` ile metin yonunu otomatik olarak yonetir. Temel kural: sabit kodlanmis `left`/`right` degerlerini `start`/`end` ile degistirin:

dart
class=class="code-string">"code-comment">// Yanlis - RTL'de bozulur
Padding(padding: EdgeInsets.only(left: class="code-number">16.0))

class=class="code-string">"code-comment">// Dogru - metin yonune saygi duyar
Padding(padding: EdgeInsetsDirectional.only(start: class="code-number">16.0))

Bazi ikonlarin RTL duzenlerinde aynalanmasi gerekir:

dart
Widget buildArrowIcon(BuildContext context) {
  final isRtl = Directionality.of(context) == TextDirection.rtl;
  return Transform.flip(flipX: isRtl, child: const Icon(Icons.arrow_forward));
}

10'dan fazla pazara uygulama gonderdigim projelerde, uygulama resmi olarak Arapca desteklemese bile yon bagimli yerlesim hatalarini yakalamak icin Arapca'yi her zaman test dili olarak kullaniyorum.

Ekipler icin Ceviri Is Akisi

ARB Dosyalarini Duzenleme

Projeler buyudukce yonetilebilirligi korumak icin domain bazli anahtar isimlendirmesi oneriyorum:

dart
{
  class="code-string">"auth_loginButton": class="code-string">"Giris Yap",
  class="code-string">"auth_signupButton": class="code-string">"Kayit Ol",
  class="code-string">"profile_editTitle": class="code-string">"Profili Duzenle",
  class="code-string">"settings_languageLabel": class="code-string">"Dil",
  class="code-string">"error_networkTimeout": class="code-string">"Baglanti zaman asimina ugradi. Lutfen tekrar deneyin."
}

Ceviri Servisleriyle Entegrasyon

Uretim uygulamalarinda su is akislarindan birini kullaniyorum:

  • **Manuel ceviri**: ARB dosyalarini disa aktarin, cevirmenlere gonderin, geri alin. 100'den az metin iceren kucuk projeler icin uygundur.
  • **Localizely / Crowdin / Phrase**: Sablon ARB'nizi yukleyin, cevirmenler web arayuzunde calissin, tamamlanan ARB'leri indirin. Bu araclar cogul kurallarini yonetir ve eksik cevirileri isaretler.
  • **CI/CD entegrasyonu**: Her PR'da eksik ceviri anahtarlarini kontrol eden bir GitHub Action kurun.
  • Eksik Ceviri Tespiti

    Basit bir Dart scripti tum ARB dosyalarini parse edip anahtarlari sablonla karsilastirabilir ve eksik ceviri varsa CI'i basarisiz yapabilir. Her projemde `scripts/check_translations.dart` dosyasi bulundururum — `app_en.arb`'yi referans alip diger tum ARB dosyalarini buna karsi kontrol eder.

    Sik Yapilan i18n Hatalari

    Hata 1: Sabit Kodlanmis Metinler

    Hata mesajlari, buton etiketleri ve erisilebirlik etiketleri dahil her kullaniciya donuk metin lokalizasyon sisteminden gecmeli.

    dart
    class=class="code-string">"code-comment">// Yanlis
    Text(class="code-string">'Tekrar hos geldiniz!')
    class=class="code-string">"code-comment">// Dogru
    Text(AppLocalizations.of(context).welcomeBack)

    Hata 2: Metin Birlestirme

    Cevrilmis parcalari birlestirerek cumle kurmayin. Kelime sirasi diller arasinda farklilik gosterir.

    dart
    class=class="code-string">"code-comment">// Yanlis - kelime sirasi diger dillerde bozulur
    Text(l10n.sizin + class="code-string">' ' + count.toString() + class="code-string">' ' + l10n.mesajiniz)
    class=class="code-string">"code-comment">// Dogru - tek bir parametreli metin kullanin
    Text(l10n.messageCount(count))

    Hata 3: Yedek Dil Tanimlamamak

    Bir ceviri eksikse ve yedek dil yoksa uygulamaniz cokebilir veya ham anahtarlari gosterebilir. Flutter otomatik olarak `supportedLocales` listesindeki ilk dile geri doner, bu yuzden birincil dilinizi her zaman basa koyun.

    Hata 4: Metin Genislemesini Goz Ardi Etmek

    Almanca metinler tipik olarak Ingilizce'den %30 daha uzundur. Arapca daha da genis olabilir. Arayuzunuzu uzun cevirilerle mutlaka test edin. Gelistirme sirasinda genislemeyi simule etmek icin sozde lokalizasyon kullaniyorum.

    Hata 5: Sabit Kodlanmis Tarih ve Sayi Formatlari

    dart
    class=class="code-string">"code-comment">// Yanlis - sadece belirli bir format
    Text(class="code-string">'${date.day}/${date.month}/${date.year}')
    class=class="code-string">"code-comment">// Dogru - yerel ayara duyarli
    Text(DateFormat.yMd(Localizations.localeOf(context).toString()).format(date))

    Hata 6: Erisilebilirligi Unutmak

    Ekran okuyucular lokalize edilmis `Semantics` etiketlerine ihtiyac duyar. Sadece gorunur metni lokalize ederseniz, diger dillerdeki gorme engelli kullanicilar bozuk bir deneyim yasar:

    dart
    Semantics(
      label: AppLocalizations.of(context).closeButtonLabel,
      child: IconButton(icon: const Icon(Icons.close), onPressed: () => Navigator.pop(context)),
    )

    Lokalizasyon Testi

    dart
    testWidgets(class="code-string">'Turkce hos geldin mesajini gosterir', (tester) async {
      await tester.pumpWidget(MaterialApp(
        locale: const Locale(class="code-string">'tr'),
        localizationsDelegates: AppLocalizations.localizationsDelegates,
        supportedLocales: AppLocalizations.supportedLocales,
        home: const HomeScreen(),
      ));
      expect(find.text(class="code-string">'Hos geldin, Utku!'), findsOneWidget);
    });

    Sonuc

    Dogru kurulmus bir i18n altyapisi, yeni pazarlara acilirken surtunmeyi ciddi oranda azaltir. ARB yapisi, yerel ayara duyarli bicimlendirme ve temiz bir ceviri is akisina erken yapilan yatirim, kendini defalarca geri oder. 10'dan fazla pazara uygulama gonderdigim projelerde, lokalizasyonu birinci sinif bir mimari kaygi olarak ele alan ekipler, acil duzeltmelere gerek kalmadan yeni bolgelere sorunsuzca olceklenen ekiplerdi.

    Isterseniz mevcut uygulamaniza olceklenebilir bir lokalizasyon altyapisi ekleyebilirim -- ARB kurulumundan CI entegreli ceviri is akislarina kadar.

    İlgili Makaleler

    Flutter Projeniz mi Var?

    iOS, Android ve web için yüksek performanslı Flutter uygulamaları geliştiriyorum.

    İletişime Geç