Flutter之國際化多語言

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

1.引入依賴

引入后,保存會自動加入安裝此依賴

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

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

我們新建一個和"/lib"同級別的文件夾"/locale",然后在這個文件夾中新建兩個文件,分別為"i18n_en.json" 和" i18n_zh.json"。再在"/lib"文件夾下創(chuàng)建和"main.dart"同級的"translation.dart"和"application.dart"。
??文件夾樹現(xiàn)在是這個樣子的:
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 
  //圖片也是需要手動加入到assets中的
  - images/lake.jpg
  - images/number.png
3.main.dart中加入配置
//導入flutter的包
import 'package:flutter_localizations/flutter_localizations.dart';
import 'translation.dart';
import 'application.dart';

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

class _MyAppState extends State<MyApp> {
  SpecificLocalizationDelegate _localeOverrideDelegate;
   
  @override
  void initState(){
    super.initState();
    /// 初始化一個新的Localization Delegate,有了它,當用戶選擇一種新的工作語言時,可以強制初始化一個新的Translations
    _localeOverrideDelegate = new SpecificLocalizationDelegate(null);

    /// 保存這個方法的指針,當用戶改變語言時,我們可以調用applic.onLocaleChanged(new Locale('en',''));,通過SetState()我們可以強制App整個刷新
    applic.onLocaleChanged = onLocaleChange;
  }

/// 改變語言時的應用刷新核心,每次選擇一種新的語言時,都會創(chuàng)造一個新的SpecificLocalizationDelegate實例,強制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,  // 注冊一個新的delegate
        const TranslationsDelegate(), // 指向默認的處理翻譯邏輯的庫
        // 本地化的代理類
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: applic.supportedLocales(), 
   
      title: 'Flutter  Router',
      debugShowCheckedModeBanner: false, //關掉模擬器右上角debug圖標
      theme: ThemeData(
        primarySwatch: Colors.orange,
      ),
      home: Homes(),
      //路由表設置
      routes: <String, WidgetBuilder>{
        '/Second':(BuildContext context) => new SecondPage(),
        '/Http':(BuildContext context) => new HttpPage(),
      },
    );
  }
}
......
//Homes()省略了
4.給translation.dart和application.dart添加內容
//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();

/// 改這里是為了不硬編碼支持的語言
  @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類的實現(xiàn),每次選擇一種新的語言時,強制初始化一個新的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')) //這里
          ],
        )
      ),......

補充:如果需要強制轉換的話(小編自己沒有用到)

//為了強制切換另一種工作語言,只需要一行代碼,可以在App的任何地方調用:
applic.onLocaleChanged(new Locale('fr',''));
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容