Flutter之國(guó)際化多語(yǔ)言

在說flutter國(guó)際化前检号,不得不提到蛙酪,在uni-app中支持的Vue-i18n齐苛,兩者有相似之處,也有差異的地方桂塞。
本篇借鑒了三篇熱門帖子
Flutter中的國(guó)際化:如何寫一個(gè)多語(yǔ)言的App
Flutter國(guó)際化完整例子
Internationalization - Make an Flutter application multi-lingual
只記錄根據(jù)手機(jī)系統(tǒng)語(yǔ)言自動(dòng)轉(zhuǎn)換app語(yǔ)言

1.引入依賴

引入后,保存會(huì)自動(dòng)加入安裝此依賴

//pubspec.yaml
dependencies:
  flutter:
    sdk: flutter

  flutter_localizations: #多語(yǔ)言
    sdk: flutter
//這里是Http網(wǎng)絡(luò)請(qǐng)求需要加入的
  dio: ^2.1.13  #Http 請(qǐng)求Dio
  http: ^0.12.0 #http
  json_serializable: ^3.1.0 #json 序列化
  json_annotation: ^2.4.0 #json 注釋
2.創(chuàng)建翻譯json文件和添加配置

我們新建一個(gè)和"/lib"同級(jí)別的文件夾"/locale"狂打,然后在這個(gè)文件夾中新建兩個(gè)文件擂煞,分別為"i18n_en.json" 和" i18n_zh.json"。再在"/lib"文件夾下創(chuàng)建和"main.dart"同級(jí)的"translation.dart"和"application.dart"趴乡。
??文件夾樹現(xiàn)在是這個(gè)樣子的:
MyApplication
? |
? +- android
? +- build
? +- images
? +- ios
? +- lib
?? |
?? +-main.dart
?? +-translation.dart
?? +-application.dart
? +- locale
?? |
?? +- i18n_en.json
?? +- i18n_zh.json
? +- test

//i18n_zh.json      or  i18n_en.json
{ "hello" : "你好对省!" , "hello" : "Hello~" }

在pubspec.yaml繼續(xù)加入json蝗拿,引入靜態(tài)資源

 assets:
  - locale/i18n_zh.json
  - locale/i18n_en.json 
  //圖片也是需要手動(dòng)加入到assets中的
  - images/lake.jpg
  - images/number.png
3.main.dart中加入配置
//導(dǎo)入flutter的包
import 'package:flutter_localizations/flutter_localizations.dart';
import 'translation.dart';
import 'application.dart';

void main(){
  debugPaintSizeEnabled = !true;
  runApp(MyApp());  
}
/// 將App設(shè)置為Stateful,這讓它可以響應(yīng)刷新事件蒿涎,調(diào)用應(yīng)用的SetState()
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  SpecificLocalizationDelegate _localeOverrideDelegate;
   
  @override
  void initState(){
    super.initState();
    /// 初始化一個(gè)新的Localization Delegate蛹磺,有了它,當(dāng)用戶選擇一種新的工作語(yǔ)言時(shí)同仆,可以強(qiáng)制初始化一個(gè)新的Translations
    _localeOverrideDelegate = new SpecificLocalizationDelegate(null);

    /// 保存這個(gè)方法的指針萤捆,當(dāng)用戶改變語(yǔ)言時(shí),我們可以調(diào)用applic.onLocaleChanged(new Locale('en',''));俗批,通過SetState()我們可以強(qiáng)制App整個(gè)刷新
    applic.onLocaleChanged = onLocaleChange;
  }

/// 改變語(yǔ)言時(shí)的應(yīng)用刷新核心俗或,每次選擇一種新的語(yǔ)言時(shí),都會(huì)創(chuàng)造一個(gè)新的SpecificLocalizationDelegate實(shí)例岁忘,強(qiáng)制Translations類刷新辛慰。
  onLocaleChange(Locale locale){
    setState((){
      _localeOverrideDelegate = new SpecificLocalizationDelegate(locale);
    });
  }


  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [
        _localeOverrideDelegate,  // 注冊(cè)一個(gè)新的delegate
        const TranslationsDelegate(), // 指向默認(rèn)的處理翻譯邏輯的庫(kù)
        // 本地化的代理類
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: applic.supportedLocales(), 
   
      title: 'Flutter  Router',
      debugShowCheckedModeBanner: false, //關(guān)掉模擬器右上角debug圖標(biāo)
      theme: ThemeData(
        primarySwatch: Colors.orange,
      ),
      home: Homes(),
      //路由表設(shè)置
      routes: <String, WidgetBuilder>{
        '/Second':(BuildContext context) => new SecondPage(),
        '/Http':(BuildContext context) => new HttpPage(),
      },
    );
  }
}
......
//Homes()省略了
4.給translation.dart和application.dart添加內(nèi)容
//application.dart
import 'package:flutter/material.dart';
typedef void LocaleChangeCallback(Locale locale);
class APPLIC {
    // List of supported languages
    final List<String> supportedLanguages = ['en','zh'];
    // Returns the list of supported Locales
    Iterable<Locale> supportedLocales() => supportedLanguages.map<Locale>((lang) => new Locale(lang, ''));
    // Function to be invoked when changing the working language
    LocaleChangeCallback onLocaleChanged;
    ///
    /// Internals
    ///
    static final APPLIC _applic = new APPLIC._internal();
    factory APPLIC(){
        return _applic;
    }
    APPLIC._internal();
}
APPLIC applic = new APPLIC();
//translation.dart
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show  rootBundle;
import 'application.dart';

class Translations {
  Translations(Locale locale) {
    this.locale = locale;
    _localizedValues = null;
  }

  Locale locale;
  static Map<dynamic, dynamic> _localizedValues;
  
  static Translations of(BuildContext context){
    return Localizations.of<Translations>(context, Translations);
  }

    String text(String key) {
    try {
      String value = _localizedValues[key];
      if(value == null || value.isEmpty) {
        return englishText(key);
      } else {
        return value;
      }
    } catch (e) {
      return englishText(key);
    }
  }

  String englishText(String key) {
    return _localizedValues[key] ?? '** $key not found';
  }

  static Future<Translations> load(Locale locale) async {
    Translations translations = new Translations(locale);
    String jsonContent = await rootBundle.loadString("locale/i18n_${locale.languageCode}.json");
    _localizedValues = json.decode(jsonContent);
    return translations;
  }

  get currentLanguage => locale.languageCode;
}

class TranslationsDelegate extends LocalizationsDelegate<Translations> {
  const TranslationsDelegate();

/// 改這里是為了不硬編碼支持的語(yǔ)言
  @override
  bool isSupported(Locale locale) => applic.supportedLanguages.contains(locale.languageCode);

  @override
  Future<Translations> load(Locale locale) => Translations.load(locale);

  @override
  bool shouldReload(TranslationsDelegate old) => false;
}

/// Delegate類的實(shí)現(xiàn),每次選擇一種新的語(yǔ)言時(shí)干像,強(qiáng)制初始化一個(gè)新的Translations類
class SpecificLocalizationDelegate extends LocalizationsDelegate<Translations> {
  final Locale overriddenLocale;

  const SpecificLocalizationDelegate(this.overriddenLocale);

  @override
  bool isSupported(Locale locale) => overriddenLocale != null;

  @override
  Future<Translations> load(Locale locale) => Translations.load(overriddenLocale);

  @override
  bool shouldReload(LocalizationsDelegate<Translations> old) => true;
}
5.獲取翻譯
......
 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("JSON"),
      ), 
      body:Center(
        child: Column(
          children: <Widget>[
            Text(Translations.of(context).text('hello')) //這里
          ],
        )
      ),......

補(bǔ)充:如果需要強(qiáng)制轉(zhuǎn)換的話(小編自己沒有用到)

//為了強(qiáng)制切換另一種工作語(yǔ)言帅腌,只需要一行代碼,可以在App的任何地方調(diào)用:
applic.onLocaleChanged(new Locale('fr',''));
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末麻汰,一起剝皮案震驚了整個(gè)濱河市速客,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌五鲫,老刑警劉巖溺职,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異位喂,居然都是意外死亡浪耘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門塑崖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來七冲,“玉大人,你說我怎么就攤上這事规婆±教桑” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵聋呢,是天一觀的道長(zhǎng)苗踪。 經(jīng)常有香客問我,道長(zhǎng)削锰,這世上最難降的妖魔是什么通铲? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮器贩,結(jié)果婚禮上颅夺,老公的妹妹穿的比我還像新娘朋截。我一直安慰自己,他們只是感情好吧黄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布部服。 她就那樣靜靜地躺著,像睡著了一般拗慨。 火紅的嫁衣襯著肌膚如雪廓八。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天赵抢,我揣著相機(jī)與錄音剧蹂,去河邊找鬼。 笑死烦却,一個(gè)胖子當(dāng)著我的面吹牛宠叼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播其爵,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冒冬,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了摩渺?” 一聲冷哼從身側(cè)響起简烤,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎证逻,沒想到半個(gè)月后乐埠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡囚企,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瑞眼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片龙宏。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖伤疙,靈堂內(nèi)的尸體忽然破棺而出银酗,到底是詐尸還是另有隱情,我是刑警寧澤徒像,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布黍特,位于F島的核電站,受9級(jí)特大地震影響锯蛀,放射性物質(zhì)發(fā)生泄漏灭衷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一旁涤、第九天 我趴在偏房一處隱蔽的房頂上張望翔曲。 院中可真熱鬧迫像,春花似錦、人聲如沸瞳遍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)掠械。三九已至由缆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間猾蒂,已是汗流浹背均唉。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留婚夫,地道東北人浸卦。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像案糙,于是被迫代替她去往敵國(guó)和親限嫌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355