Flutter
Flutter Localization (i18n): Çok Dilli Uygulama Geliştirme
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
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.19.0
flutter:
generate: truegenerate: true bayragi, Flutter'a ARB dosyalarinizdan otomatik olarak lokalizasyon kodu uretmesini soyler.
Adim 2: l10n Yapilandirma Dosyasi
Proje kok dizininde l10n.yaml dosyasi olusturun:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: AppLocalizations
nullable-getter: falseAdim 3: ARB Dosyalarini Olusturun
ARB dosyalari JSON tabanlidir ve cevirileriniz icin tek dogru kaynaktir. lib/l10n/app_en.arb:
{
"@@locale": "en",
"appTitle": "My Application",
"@appTitle": { "description": "The title of the application" },
"welcomeMessage": "Welcome, {userName}!",
"@welcomeMessage": {
"placeholders": { "userName": { "type": "String", "example": "John" } }
},
"itemCount": "{count, plural, =0{No items} =1{1 item} other{{count} items}}",
"@itemCount": {
"placeholders": { "count": { "type": "num", "format": "compact" } }
},
"lastLogin": "Last login: {date}",
"@lastLogin": {
"placeholders": { "date": { "type": "DateTime", "format": "yMMMd" } }
}
}Turkce icin lib/l10n/app_tr.arb:
{
"@@locale": "tr",
"appTitle": "Uygulamam",
"welcomeMessage": "Hos geldin, {userName}!",
"itemCount": "{count, plural, =0{Oge yok} =1{1 oge} other{{count} oge}}",
"lastLogin": "Son giris: {date}"
}Adim 4: MaterialApp Yapilandirmasi
import 'package:flutter_localizations/flutter_localizations.dart';
import '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('en'), Locale('tr'), Locale('de')],
locale: const Locale('tr'),
home: const HomeScreen(),
);
}
}Adim 5: Widget'larda Cevirilere Erisim
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('Utku')),
Text(l10n.itemCount(5)),
Text(l10n.lastLogin(DateTime.now())),
]),
);
}
}Dinamik Dil Degistirme
Kullanicilar uygulamayi yeniden baslatmadan dil degistirebilmeli. Temiz bir ChangeNotifier yapisi:
class LocaleProvider extends ChangeNotifier {
Locale _locale = const Locale('tr');
Locale get locale => _locale;
void setLocale(Locale locale) {
_locale = locale;
notifyListeners();
}
}
// 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:
{
"notificationCount": "{count, plural, =0{Bildirim yok} =1{1 bildiriminiz var} other{{count} bildiriminiz var}}",
"@notificationCount": { "placeholders": { "count": { "type": "num" } } },
"genderGreeting": "{gender, select, male{Sayin Bay {name}} female{Sayin Bayan {name}} other{Sayin {name}}}",
"@genderGreeting": {
"placeholders": { "gender": { "type": "String" }, "name": { "type": "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:
import 'package:intl/intl.dart';
final dateFormatter = DateFormat.yMMMd('tr');
print(dateFormatter.format(DateTime.now())); // "9 Mar 2026"
final currencyFormatter = NumberFormat.currency(locale: 'tr', symbol: 'TL');
print(currencyFormatter.format(1234.56)); // "1.234,56 TL"
final compactFormatter = NumberFormat.compact(locale: 'tr');
print(compactFormatter.format(1500000)); // "1,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:
// Yanlis - RTL'de bozulur
Padding(padding: EdgeInsets.only(left: 16.0))
// Dogru - metin yonune saygi duyar
Padding(padding: EdgeInsetsDirectional.only(start: 16.0))Bazi ikonlarin RTL duzenlerinde aynalanmasi gerekir:
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:
{
"auth_loginButton": "Giris Yap",
"auth_signupButton": "Kayit Ol",
"profile_editTitle": "Profili Duzenle",
"settings_languageLabel": "Dil",
"error_networkTimeout": "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.
// Yanlis
Text('Tekrar hos geldiniz!')
// Dogru
Text(AppLocalizations.of(context).welcomeBack)Hata 2: Metin Birlestirme
Cevrilmis parcalari birlestirerek cumle kurmayin. Kelime sirasi diller arasinda farklilik gosterir.
// Yanlis - kelime sirasi diger dillerde bozulur
Text(l10n.sizin + ' ' + count.toString() + ' ' + l10n.mesajiniz)
// 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
// Yanlis - sadece belirli bir format
Text('${date.day}/${date.month}/${date.year}')
// 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:
Semantics(
label: AppLocalizations.of(context).closeButtonLabel,
child: IconButton(icon: const Icon(Icons.close), onPressed: () => Navigator.pop(context)),
)Lokalizasyon Testi
testWidgets('Turkce hos geldin mesajini gosterir', (tester) async {
await tester.pumpWidget(MaterialApp(
locale: const Locale('tr'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const HomeScreen(),
));
expect(find.text('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 Nedir? Kapsamlı Başlangıç Rehberi
Flutter'ın ne olduğunu, nasıl çalıştığını ve neden modern ürün ekiplerinin tercih ettiğini öğrenin. Dart, widget yapısı ve çoklu platform geliştirme sürecini keşfedin.
Flutter Navigation: go_router ile Ölçeklenebilir Yönlendirme
go_router ile modern Flutter yönlendirme yapısını kurun. Nested route, redirect ve deep link senaryolarını yönetin.
Flutter Accessibility (a11y): Herkes İçin Kullanılabilir Uygulamalar
Flutter'da erişilebilirlik standartlarını uygulayın. Semantics, kontrast, yazı ölçekleme ve klavye erişimini doğru yönetin.
Flutter Projeniz mi Var?
iOS, Android ve web için yüksek performanslı Flutter uygulamaları geliştiriyorum.
İletişime Geç