Entegrasyonlar Serisi gitHub adresi : https://github.com/XPersPective/flutterdersleri.com
Entegrasyonlar Serisi Video Anlatım : https://www.youtube.com/watch?v=CeQrIzCb8D4&list=PLXBVQ2h2yVru3Xu9ae64DhGenKQ5BmY49
Önce localization’dan ne anllıyoruz. Localization’ türkçe anlamına baktığımızda yerelleştirme olduğunu görüyoruz. googleda bir arama yaptığımda Burak Selim Şenyurt’un yazmış olduğu https://www.buraksenyurt.com/post/Localization-(Yerellestirme)-1-bsenyurt-com-dan adlı bir makale karşıma çıktı bu makalenenin ilk paragrafı oldukça açıklayıcı. Kısacası her ülkenin konuştuğu dil vss farklı yani bir yerelsellik söz konusu. Her ülkenin hatta her bölgenin dilleri lehçeleri örneğin çince geleneksel çince, basit çince gibi farklılıklar gösterbiliyor. Yani uygulamanın yerele göre tasarlanması ihtiyacı doğuyor.Bu yerelleştirmeyi olabileçek her yerele/dile göre gerçekleştirdiğimizde uygulama altık global hale tüm dünyanın her yereline(ülkeye, dile..vs) uygun hale geliyor. Buna globalizasyon deniyor. Kısacası amerikadan giren biri uygulamayı ingilizce kullanırken Türkiye deki türkçe olarak kullanabiliyor. Uygulamayı yerel bir dile uyarlayarak localization yapmış yerelleştirmiş oluyoruz, bir den çok dile uyarlayarak globalization/ulustararası hale getirmiş oluyoruz.
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
name: localizationornek
description: A new Flutter project.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
#flutter_localizations paketimizi dahil ettik
flutter_localizations:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
Gelelim flutterda localization işlemine. flutter localizasyon işlerini materialapp sınıfı yoluyla gerçekleştiriyor. MaterialApp locale(local/yerel), localizationsDelegates(yerelleri temsil edenler), supportedLocale(uygulamanın desteklediği diller) parametrelerini kullanarak uygulamanın başlangıç diline karar veriyor ve yönetiyor. locale türü bir Locale türü. Locale sınıfıyla tanımlanıyor.Locale(‘dil kodu’, ‘Ülke Kodu’). Örneğin türkçe local, Locale(‘tr’,’TR’). locali temsil eden şey Locale sınıfının nesnesi yani amaç materialapp içerindeki locale hangi dilin atanacağına karar vermek. Bir flutter uygulaması başlatıldığında materialapp içerisindeki locale parametresine bir değer atanmışmı önce ona bakıyor. Materapp in locale parametresine bir değer atanmışsa supportedLocales/uygulamanın destekleği dillere bakıyor eğer locale atanmış dil desteklenen dillerde varsa onu kullanıyor. locale bir değer atanmamışsa sisteme soruyor cihazın işletim sisteminden/android yada ios tan gelen dili yani sistemin dilini alıyor ve desteklenen dillerde(supported locale) bu dil varmı bakıyor ve varsa dili uygulamanın dili olarak ayarlıyor, yani materialapp ın locale paremetresine geçiyor eğer yoksa flutter ın varsayılan dili olan ingilizceyi uygulama dili olarak geçiyor.
şöyle bir senaryo düşünelim;
Biz bir çinliyiz ve çince android yada ios telefonumuz var.
telefonumuzda yüklü herhangi bir flutter uygulamasına tıkladık.
uygulama açılıyor ve materialappın locale : parametresine bakıyor bir değer atanmış mı?
bir değer atanmamış o halde sisteme hangi dili kullandığını soruyor . sistem telefonun dil ayarının çince olduğunu bildiriyor.
daha sonra flutter materyalapp içerisinde suppotedlocale: parametresinde uygulamanın hangi dilleri desteklediğini soruyor . supportedLocales te çince destek yok.
flutter telefonun çince kullanılmış olduğunu ama uygulamanın çinceyi desteklemediğini öğrendiği için flutterın varsayılan dili olan ingiliceyi uygulamanın varsayılan dili olarak kabul ediyor.
MaterialApp(
locale: //Başlangıç yerel ayarı.Eğer 'yerel' boşsa o zaman sistemin yerel dili kullanılır.
localizationsDelegates: [
// bizim localization nesnemizi temsil eden temisilci/delegete sınıfımız
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
//uygulamanın desteklediği diller
supportedLocales: [
const Locale('en'), // English
const Locale('tr'), //türkçe
],
.....
)
Buraya kadar ne biliyoruz:
flutter yerelleştirme işlerini materyalapp yürütüyor.
materialapp içerisinde locale parametresi ilk bakılan yer,
eğer uygulamaya bir yerel destek ekleyeceksek yani bir dil ekleyeceksek, mutlaka supportedLocale içerisine temsil ettiği dili Locale(‘dilkodu’,”) türünden eklememiz gerekecek.,
peki ya localizationsDelegates te neyin nesi?
Delege : bir şeyi temsil eden şey
localizationsDelegates uygulamanın tüm yerellerini temsil edenlerin bir listesi.
bunu bir tarafa not edip konumuza geri dönelim. biz uygulamamızın çok dilli olmasını istiyoruz bir dil ekleyelim.
Materialapp içerisinde locale’e arapça localini atayalım ve desteklediği dillere arapça ekleyelim.
şimdi uygulama açıldığında varsayılan dil arapça oldu. Flutter uygulamanın arapça olduğunu varsayıyor. Uygulamadaki bir tetxtfield e tıklayıp yazmaya başladığımızda sağdan sola doğru yazmaya başladığını göreceğiz.
Bu şekilde sadece tek bir dile/yerele sahip uygulamamız oldu. Sadece arapça kullanıcılarına hitap ediyor bunu globalleştirmemiz gerekecek.
MaterialApp(
locale: Locale('ar',''), //uygulamanın varsayılan dili arapça localizationsDelegates: [
// bu kısma daha sonra geleceğiz
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
//uygulamanın desteklediği dillere arapça ekliyoruz
supportedLocales: [
const Locale('tr'), //arapça
],
.....
)
Önce ideal bir senaryo hayal edelim:
bir localization/yerelleştirme sınıfımız olsun.
Localization sınıfımızın bir cevir metodu olsun o anda uygulamamız handi dilde ise o dilde çevrilmiş metinleri getirsin.
(örneğin uygulama ingilizce kullanılıyor ise butonumuz
RaisedButton(child: Text(“Ok”),onpressd:..)
//Türkçe ise
RaisedButton(child: Text(“Tamam”),onpressd:..)
şunu gibi..
//ingilizce
RaisedButton(child: Text(localization.cevir('tamambutonu'),onpressd:..)
//artık uygulama türkçe ise Text içerisinnde Tamam yazacak, ingilizce ise Ok yazacak.
tabii ki bu kadar basit değil ama böyle bişey istiyoruz.
Ayrıca uygulamamızın bir sürü bölümleri var: hakkında kısmı, faklı test içerene butonlar,nasıl kullanılır metinler vss yani bir sürü çevrilmesi gereken metin var. bunları bir map formatında ve ayrı dosyalarda saklayabiliriz.
şöye olabilir,
// assets/localization/en.json
Map<String, String> en={'tamam': 'OK',
'iptal': 'Cancel'}
//diğer dosya
// assets/localization/tr.json
tr={'tamam': 'Tamam',
'iptal': 'İptal'}
şimdi materialapp içerisinde supportedLocales e en ve tr yide ekleyeceğiz. ayrıca uygulamanın herhangi biryerinden çevirmek istediğimiz metni anahar olarak verip çevrilmiş halini alabileceğiz.
Artık ihtiyaçlarımızın bir listesini yapma vakti:
Gerekli olanlar:
1.metinler için LangKey sınıfı : çevrilecek metinleri getirmek için kullanacağımız anahtarlar(map te ki değerler ulaşmak için) Bunlar oldukça uzun olabilir, ayrı bir sınıfta tutmak daha derli toplu ve ulaşılabilir olabilir.
2.desteklediğimiz dilleri tutacağımız LangSupported sınıfımız. Destekledğimiz diller listesi de oldukça uzun olabilir ayrı bir sınıfta tutmakta fayda var.
3.ve nihayet olmazsa olmaz Localizaton sınıfımız.işleri bu sınıfla yapacağız.
//LangKey sınıfı, keyleri içinde tutan abstract sınıf
//çevrilecek anahtar/key metinlerini her yerden ulaşılır olamasını ve değiştilmemesini istiyoruz.static const
//ayrıca sınıfımızın kurulmasına ihtiyaç duymadığımız için soyut sanal bir abstract sınıfı olarak tanımladık
abstract class LangKey {
static const button_geri = "button_geri";
static const button_iptal = "button_iptal";
}
...
//LangSupported sınıfımız, uygulamanın desteklediği dilleri ve bunların farklı küçük bir kaç sunumunu içerir.
abstract class LangSupported {
//desteklenen dillerin dil kodlarının listesini verir: ['en','tr'..] gibi
static List<String> get languageCodeList => languagesMap.entries.map((e) => e.key).toList(growable: false);
//desteklenen dillerin locale türünden listesini verir: [Locale('en',''),Locale('tr',''),..] gibi materialapp ta supportedLocales için ..
static List<Locale> get locales => languagesMap.entries.map((e) => Locale(e.key, '')).toList(growable: false);
// static List<String> get languageNamesList =>languagesMap.entries.map((e) => e.value).toList(growable: false);
static final Map<String, String> languagesMap = <String, String>{
"en": "English",
"tr": "Türkçe",
"ar": "Arapça"
};
}
Şimdi sıra Localization sınıfımıza geldi fakat;
yukarıda flutter uygulaması ilk açıldığında locali nasıl belirlediğini hayal etmeye çalıştığımız senaryoya dönersek,
Bir flutter uygulaması başlatıldığında materialapp içerisindeki locale parametresine bir değer atanmışmı önce ona bakıyor.
Materapp in locale özelliğinebir değer atanmışsa supportedLocales/uygulamanın destekleği dillere bakıyor eğer locale atanmış dil desteklenen dillerde varsa onu kullanıyor.
nasıl kullanıyor ?
işte burda bizim Localization nesnemizi temsil eden delegate miz/ temsilci sınıfımız yoluyla.
localizationsDelegates: [
BizimLocalizationSınıfımızıTemsiledenDelegateSınıfı(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
Senaryoya devam edersek.
Materapp in locale özelliğine bir değer atanmışsa supportedLocales/uygulamanın destekleği dillere bakıyor eğer locale atanmış dil desteklenen dillerde varsa onu kullanıyor.
Biz de uygulama içerinden desteklediğimiz dillerin çevrilmiş metinlerine ihtiyacımız olduğunda localization sınıfımıza erişip kuallanabilecek duruma gelmiş oluyoruz. Burada kendi localization sınıfımızı bir yerden başlatmamız gerekiyor.(sınıfımızın bir örneğini yani nesnesini elde etmemiz gerekiyor) Bu işi flutter localizationsDelegates içerinde kendi sağlıyor.Bunun için kendi localization sınıfımızı temsil edecek bir Mylocalizationtemsilci/ MyLocalizationDelegate sınıfı tanımlamamız ve localizationsDelegates listesine nesne olarak eklememiz yeterli.
Flutter buradaki delegates/temsilci neslerini alıyor ve onların load(Locale locale) metodunu çalıştırıp temsil ettikleri sınıfın nesnesini(yani MyLocalization nesnesini) oluşturup bunları bir Type : nesne olacak şekilde bir map e aktarıyor görünüyor. final Map<Type, dynamic> output = <Type, dynamic>{}; . Peki uyguma içerinden kendi Localization nesnemize nasıl ulaşacağız.
Örneğin kendi tanımladığımız localization sınıfımız MyLocalization olsun,
Şunu gibi bir map olmalı;
key bir Type, değeri bu tipteki nesne
final Map<Type, dynamic> tumlocalizasyonlar={MyLocalization :MyLocalization()};
o halde uygulamanın bir yerinden bu map e ulaşıp bir Tpye verirsek bize kendi MyLocalization nesnemizi verecek.
Flutterda tanımlanmış olan Localization sınıfının static of metodu bunu bize sağlıyor.
Localizations.of<MyLocalization >(context, MyLocalization); verirsek bu metod bize yukarıdaki tumlocalizasyonlar mapinden MyLocalization nesnesini o contexteki widgete vereceini kabul edersek. O halde bunu daha kolay hale getirmek için kendi MyLocalization snıfımıza bir static metod yazalım. Bu metoda sadece bir Type ve contex verelim bize bunu sağlasın şunun gibi;
class MyLocalizations {
static MyLocalizations of(BuildContext context) {
return Localizations.of<DemoLocalizations>(context, MyLocalizations );
}
Map<String,String> ceviriler;
Strin cevir(String langKey) => cevriler['langKey'] ?? 'key bulunamadı!';
}
Sıra geldi kendi MyLocalization sınıfımız temsil edecek delegate/temsilci sınıfımızı yazmaya. Bunun adın ada MyLocalizationDelegate diyelim yani MyLocalization sınıfını temsil edecek olan temsilci sınıfı. Flutter MyLocalization sınıfımızın nesnesini oluşturacağı zaman MyLocalizationDelegate sınıfının load yöntemini çaşıtıracak. O halde load metodu bir MyLocalization nesnesi döndürmeli(MyLocalization() ). Flutter kendi temsilci sınıfımızı tanımlarken LocalizationsDelegate<KendiTemsilciSınıfımız> ten miras almamızı şart koşuyor. Bu sayede bunun bir temsilci sınıfı olduğunu bilecek ve bizim temsilci sınıfımızda bizi bir şeyleri yapmaya zorlayacak en nihayetinde de yukarıdaki o Map i ve bir takım ihtiyacı olan şeyleri gerçekleştirebilecek.
O halde MyLocalization sınıfımız temsil edecek MyLocalizationDelegate temsilci sınıfımız yazalım;
class MyLocalizations {
static MyLocalizations of(BuildContext context) {
return Localizations.of<DemoLocalizations>(context, MyLocalizations );
}
Map<String,String> ceviriler;
Strin cevir(String langKey) => cevriler['langKey'] ?? 'key bulunamadı!';
}
class MyLocalizationDelegate extends LocalizationsDelegate<MyLocalization> {
const MyLocalizationDelegate();
@override
bool isSupported(Locale locale);
@override
Future<MyLocalization> load(Locale locale) {
return SynchronousFuture<MyLocalization>(MyLocalization());
});
}
@override
bool shouldReload(MyLocalizationDelegate old) => false;
}
Görüldüğü gibi LocalizationsDelegate bizi bir şeyleri yapmaya zorladı.
@override
bool isSupported(Locale locale) =>bu kısmı tamamlamamızı söylüyor. uygulama dili destekliyorsa true desteklemiyorsa false vermeli diyor. bunu sorgulayabilmemiz için desteklediğimiz dillerin bir listeine ihtiyacımız var.
//bu kısmıda doldurmamızı ve geriye MyLocalization nesnemizi döndürmemizi istiyor. SynchronousFuture : nesnemizin üretilmesi bir future döndürmez hemen gerçekleşir ama sanırım future gibi davranmasını fakat asencron olmamasını istiyor.sanırım delegelerin temsil ettiği sınıflardan nesne üretirken bazıları future döndürüyor o yuzden bunu hemen gerçekleştirip diğerlerini sonraya bıraksın istemiyor.herneyse aynene yazalım
@override
Future<MyLocalization> load(Locale locale) {
return SynchronousFuture<MyLocalization>(MyLocalization(locale));
}
//bu kısımı aynen bırakıyorum
@override
bool shouldReload(MyLocalizationDelegate old) => false;
}
Artık bir MyLocalization sınıfımız ve onu temsil eden MyLocalizationDelegate sınıfımız var. Ve uygulamanın herhangi bir widgetinden MyLocalization.of(context) dediğimizde MyLocalization ulaşabileceğiz ama hala çevrilmiş metinleri Map şeklinde tutan ceviriler değişkeni boş.sayfaları ve mapleri oluşturalım.
Neler gerekli?
1.assets altında bir localizations klasörü ve altında dil kolarıyla isimlendirilmiş içerinde map olarak çevirilerini içeren dosyalar. bu dosyaları yaml a tanıtalım
2.MyLocalizatation sınıfı ve MyLocalizationDelegate sınıfı
3.LangKey sınıfı :maplerdeki değerler ulamak için
4.LangSupported sınıfı:

//main.dart ----------------------
void main() {
runApp(RunApp());
}
//RunApp.dart ----------------------------------------------------
class RunApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
locale: Locale("en", ""),
supportedLocales: LangSupported.locales,
localizationsDelegates: [
MyLocalizationDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: Home(),
);
}
}
//Home.dart ---------------------------------------
class Home extends StatelessWidget {
const Home({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Uygulamanın Dili : ${MyLocalization.of(context).locale.languageCode} - Telefonun Dili: + ${window.locale.languageCode}"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField( decoration: InputDecoration(hintText: "uygulamanın dili arapça ise sağa yaslanır", helperText:'bir şeyler yazın' ),),
RaisedButton(child: Text(MyLocalization.of(context).cevir(LangKey.button_Ok)),onPressed:(){}),
RaisedButton(child: Text(MyLocalization.of(context).cevir(LangKey.button_Iptal)),onPressed:(){}),
Text("-----------------------------------------------------"),
RaisedButton(child: Text("Arapça Yap"),onPressed:(){}),
RaisedButton(child: Text("İngilizce Yap"),onPressed:(){}),
RaisedButton(child: Text("Türkçe Yap"),onPressed:(){}),
],
),
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
}
//------------------------------------------------------------------------
// assets/localizations/ar.json
{
"button_Ok": "حسنا",
"button_Iptal": "إلغاء"
}
// assets/localizations/en.json
{
"button_Ok": "Ok",
"button_Iptal": "Cancel"
}
// assets/localizations/tr.json
{
"button_Ok": "Tamam",
"button_Iptal": "İptal"
}
//LangKey.dart ----------------------------
class LangKey {
static const button_Ok = "button_Ok";
static const button_Iptal = "button_Iptal";
}
//LangSupported.dart --------------------------
class LangSupported {
static final Map<String, String> languagesMap = <String, String>{
"ar": "Arapça",
"en": "English",
"tr": "Türkçe"
};
static List<String> get languageCodeList => languagesMap.entries.map((e) => e.key).toList(growable: false);
static List<String> get languageNamesList =>languagesMap.entries.map((e) => e.value).toList(growable: false);
static List<Locale> get locales => languagesMap.entries.map((e) => Locale(e.key, '')).toList(growable: false);
}
//MyLocalization.dart --------------------------------------------------
class MyLocalization {
MyLocalization(this.locale);
final Locale locale;
Map<dynamic, dynamic> _cevrilmisMap;
String cevir(String langKey) =>_cevrilmisMap[langKey] ?? '** $langKey not found';
Future<void> load() async {
String jsonLang = await rootBundle.loadString("assets/localizations/${locale.languageCode}.json");
_cevrilmisMap = json.decode(jsonLang);
}
static MyLocalization of(BuildContext context) {
return Localizations.of<MyLocalization>(context, MyLocalization);
}
}
//MyLocalizationDelegate timiz-
class MyLocalizationDelegate extends LocalizationsDelegate<MyLocalization> {
const MyLocalizationDelegate();
@override
bool isSupported(Locale locale) =>
LangSupported.languageCodeList.contains(locale.languageCode);
@override
Future<MyLocalization> load(Locale locale) {
MyLocalization myLocalization =MyLocalization(locale);
return myLocalization.load().then((onValue)=>SynchronousFuture<MyLocalization>(myLocalization));
}
@override
bool shouldReload(MyLocalizationDelegate old) => false;
}
//pubspect.yaml ----------------------------------------------------
name: localizationornek
description: A new Flutter project.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
# localizations altındaki tüm dosyalar
assets:
- assets/localizations/
Ne yaptik:
class MyLocalization {
MyLocalization(this.locale);
Locale locale;
Map<dynamic, dynamic> _cevrilmisMap;
String cevir(String langKey) =>_cevrilmisMap[langKey] ?? '** $langKey not found';
Future<void> load() async {
String jsonLang = await rootBundle.loadString("assets/localizations/${locale.languageCode}.json");
_cevrilmisMap = json.decode(jsonLang);
}
Future<void> setLocale(Locale newlocale) async {
locale=newlocale;
String jsonLang = await rootBundle.loadString("assets/localizations/${locale.languageCode}.json");
_cevrilmisMap = json.decode(jsonLang);
}
static MyLocalization of(BuildContext context) {
return Localizations.of<MyLocalization>(context, MyLocalization);
}
}
Yukarıdakine benzer setLocale(Locale newlocale) metoduyla uygulamanın içerisinden dili değiştirebilme olanağına sahibiz fakat flutter hala locale atanan ilk değeri tanır,
Örneğin ugulama açıldığında materialapp içerinde locale bir değer ataması yapmadığımızı varsayalım ve telefonun dil ayarıda türkçe olsun,
flutter materyalapp içerisinde locale alanına türkçe localini atar,
daha sonra uygulma içerisinden MyLocalization.of(context). setLocale(Locale(‘ar’,”) yöntemiyle dili değiştirdiğimizde uygulamanın içerisindeki metinler arapça ya dönmesine karşın
hala sola yaslı olacaktır. ayrıca bir textfield alanlarımızda yazılar soldan yazılmaya başlanacaktır. Bunun nedeni flutter uygulamanızın local dilini hala türkçe zannediyor oluşu en asılı
materyalapp içindeli locale nin değimemiş olmasıdır.
Öyleyse materapp ın rebuildi gerekli,
ayrıca dilin uygulama içerinden değiştirildiğinde bunu bir yere kaydetmeli ve uygulama yeniden açıldığında hatırlamalıyız.
Yazıyı daha fazla uzatmamak adına…
Çözüm:

//yaml dosyamız
name: localizationornek
description: A new Flutter project.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
provider: ^4.0.4
shared_preferences: ^0.5.6+3
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
# localizations altındaki tüm dosyalar
assets:
- assets/localizations/
//main.dart------------------
import 'package:flutter/material.dart';
import 'RunApp.dart';
void main() {
runApp(RunApp());
}
//RunApp.dart------------
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'GsLocalization/GsLocalization.dart';
import 'GsLocalization/LangSupported.dart';
import 'Wp/WpSplash/WpSplash.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
class RunApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<GsLocalization>(create: (_) => GsLocalization(),lazy: false),
],
child: Consumer<GsLocalization>(
builder: (context, gsLocalization, child) {
return MaterialApp(
debugShowCheckedModeBanner: false,
locale: gsLocalization.locale,
supportedLocales: LangSupported.locales,
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: child,
);
},
child: WpSplash(),
),
);
}
}
//WpSplash.dart------------
import 'package:flutter/material.dart';
import 'package:localizationornek/GsLocalization/GsLocalization.dart';
import 'package:provider/provider.dart';
import '../WpHome.dart';
class WpSplash extends StatefulWidget {
@override
_WpSplashState createState() => _WpSplashState();
}
class _WpSplashState extends State<WpSplash> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
final _gsLocalization = Provider.of<GsLocalization>(context, listen: false);
await _gsLocalization.load();
Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (BuildContext context) => WpHome()));
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueAccent,
body: Center(
child: Padding(
padding: EdgeInsets.all(10),
child: Column(mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text( "Slash Ekranı" ,style: TextStyle(fontSize: 30,color: Colors.white,fontWeight: FontWeight.bold),),
Text( "Uygulamanın başlangıç ayarlarını yapmak için en doğru yer...",style: TextStyle(fontSize: 13,color: Colors.white ),),
],
),
),
),
);
}
}
//WpHome.dart------------
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:localizationornek/GsLocalization/GsLocalization.dart';
import 'package:localizationornek/GsLocalization/LangKey.dart';
import 'package:provider/provider.dart';
class WpHome extends StatelessWidget {
const WpHome({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
final gsLocalization = Provider.of<GsLocalization>(context, listen: false);
return Scaffold(
appBar: AppBar(
title: Text("Uygulamanın Dili : ${gsLocalization.locale.languageCode} - Telefonun Dili: ${window.locale.languageCode}"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField( decoration: InputDecoration(hintText: "uygulamanın dili arapça ise sağa yaslanır", helperText:'bir şeyler yazın' ),),
RaisedButton(child: Text(gsLocalization.getTranslated(LangKey.button_Ok)), onPressed:(){}),
RaisedButton(child: Text(gsLocalization.getTranslated(LangKey.button_Iptal)), onPressed:(){}),
Text("-----------------------------------------------------"),
RaisedButton(child: Text("Arapça Yap"),onPressed:()=>gsLocalization.setLocale('ar')),
RaisedButton(child: Text("İngilizce Yap"),onPressed:()=>gsLocalization.setLocale('en')),
RaisedButton(child: Text("Türkçe Yap"),onPressed:()=>gsLocalization.setLocale('tr')),
],
),
),
);
}
}
//GsLocalization.dart------------------
import 'dart:convert';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'LangSupported.dart';
class GsLocalization with ChangeNotifier {
Locale _locale = Locale(LangSupported.languageCodeList.contains(window.locale.languageCode) ? window.locale.languageCode : 'en','');
Locale get locale => _locale;
Map<dynamic, dynamic> _translated;
String getTranslated(String langKey) =>_translated[langKey] ?? '** $langKey not found';
Future<void> load() async {
final SharedPreferences mSharedPreferences = await SharedPreferences.getInstance();
String tempLanguageCode = mSharedPreferences.getString("languageCode") ?? "notfound";
if(_locale.languageCode == tempLanguageCode ){
String jsonLang = await rootBundle.loadString("assets/localizations/${_locale.languageCode}.json");
_translated = json.decode(jsonLang);
return;
}
if(tempLanguageCode == "notfound"){
await mSharedPreferences.setString("languageCode", _locale.languageCode);
String jsonLang = await rootBundle.loadString("assets/localizations/${_locale.languageCode}.json");
_translated = json.decode(jsonLang);
return;
}
_locale = Locale(tempLanguageCode, '');
String jsonLang = await rootBundle.loadString("assets/localizations/${_locale.languageCode}.json");
_translated = json.decode(jsonLang);
notifyListeners();
}
Future<void> setLocale(String languageCode) async {
if(_locale.languageCode == languageCode ) return;
final SharedPreferences mSharedPreferences = await SharedPreferences.getInstance();
await mSharedPreferences.setString("languageCode", languageCode);
_locale = Locale(languageCode, '');
String jsonLang = await rootBundle.loadString("assets/localizations/${_locale.languageCode}.json");
_translated = json.decode(jsonLang);
notifyListeners();
}
}
//LangKey.dart------------------
abstract class LangKey {
static const button_Ok = "button_Ok";
static const button_Iptal = "button_Iptal";
}
//LangSupported.dart------------------
import 'package:flutter/material.dart';
abstract class LangSupported {
static List<String> get languageCodeList => languagesMap.entries.map((e) => e.key).toList(growable: false);
static List<Locale> get locales => languagesMap.entries.map((e) => Locale(e.key, '')).toList(growable: false);
// static List<String> get languageNamesList =>languagesMap.entries.map((e) => e.value).toList(growable: false);
static final Map<String, String> languagesMap = <String, String>{
"ar": "Arapça",
"en": "English",
"tr": "Türkçe"
};
}
Kullanımı:
1. bir metnin çevrilmiş haline ulaşmak için:
final gsLocalization = Provider.of<GsLocalization>(context, listen: false);
gsLocalization.getTranslated(LangKey.button_Ok)
2. uygulamanın dilini değiştimek için:
final gsLocalization = Provider.of<GsLocalization>(context, listen: false);
gsLocalization.setLocale(‘en’);
Özelleştirmek için:
A.Yeni bir dil tanımlamak için:
örneğin fransızca dili ekleyelim:
1.
– assets/localizations/ altına yen bir fr.json dosyası ekleyelim ve fransızcaya çevrilmiş değerleri keylerin karşılıklarına girelim.
2. LangSupported sınıfında languagesMap map te “fr” : “français”, yı ekleyelim
static final Map<String, String> languagesMap = <String, String>{
“ar”: “Arapça”,
“en”: “English”,
“tr”: “Türkçe”,
“fr” : “Français”
};
}
bu kadar..
B.Yeni bir metin çevirisi girmek için:
örneğin oyla sözcüğünü girelim.
1.
LangKey sınıfımıza bir key girelim
abstract class LangKey {
static const button_Ok = “button_Ok”;
static const button_Iptal = “button_Iptal”;
static const oyla = “oyla”;
}
2. assets/localizations/ altındaki tüm json dosylarındaki her map e oyla key ini girip ilgili dildeki çevirisi atayalım
assets/localizations/tr.json
{
“button_Ok”: “Tamam”,
“button_Iptal”: “İptal”
“oyla” : “Oy ver”
}
assets/localizations/en.json
{
“button_Ok”: “Ok”,
“button_Iptal”: “Cancel”
“oyla” : “Rate”
}
…
bu kadar…
motivastonunuzu yüksek tutmanız dileğiyle….