Flutterの使用Provider进行简单的国际化

2,736 阅读3分钟
provider: ^3.1.0
shared_preferences: ^0.5.2

参考: www.imooc.com/article/293…

Main.js

顶端注册provider,初始化

主要代码

  Widget build(BuildContext context) {
  //获取本地语言(我这里是zh_CN)
    String locale=WidgetsBinding.instance.window.locale.toString();
    print('loacle:'+locale);
    //本地存储SharedPreferences.get
    String value = LocalStorage.get('language'); //获取本地存储
    String language;
    if (value == null) {
      if (locale == 'zh_CN' || locale == 'zh_TW' || locale == 'zh_HK') {
        language = 'Chinese';
      } else
        language = "English";
    } else
      language = value; //有就改
    return MultiProvider(//注册provider
      providers: [
        ChangeNotifierProvider(builder: (_) => LanguageModel(language)),
        //在这提供provider
      ],
      child: child, //孩子
    );
  }

主要思想:

if 有没有用SharedPreferences preferences存储
    用本地存的
else
    看系统语言设置
    if 是中国
      用中文
    else
        英文

全代码:

import 'package:flutter/material.dart';
import 'package:jieda/Page/A_login/LoginPage.dart';
import 'package:jieda/common/CommonInsert.dart';


void main() => realRunApp();

void realRunApp() async {
  WidgetsFlutterBinding.ensureInitialized();
  //将LocalStorage 异步转为同步
  bool success = await LocalStorage.getInstance();
  ///初始化屏幕适配器
  Adapt.init();
  assert(success);
  LocalImageSelecter.init();
//  runApp(ChangeNotifierProvider.value(
////    value: LanguageModel(),
////    child:
////    MyApp(),
////  ),);这种也行,不过要有带build的class才能执行方法
  runApp(Wrapper(child:MyApp()));
}

class Wrapper extends StatelessWidget {
  final Widget child;
  Wrapper({this.child});
  @override
  Widget build(BuildContext context) {
  //获取本地语言(我这里是zh_CN)
    String locale=WidgetsBinding.instance.window.locale.toString();
    print('loacle:'+locale);
    //本地存储SharedPreferences.get
    String value = LocalStorage.get('language'); //获取本地存储
    String language;
    if (value == null) {
      if (locale == 'zh_CN' || locale == 'zh_TW' || locale == 'zh_HK') {
        language = 'Chinese';
      } else
        language = "English";
    } else
      language = value; //有就改
    return MultiProvider(//注册provider
      providers: [
        ChangeNotifierProvider(builder: (_) => LanguageModel(language)),
        //在这提供provider
      ],
      child: child, //孩子
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '用provider进行国际化',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LoginPage(),//登录页
    );
  }
}

Language.dart

import 'package:flutter/material.dart';
import 'package:jieda/common/local/LocalStorage.dart';
class LanguageModel with ChangeNotifier {
  String _language = "Chinese";

//获取当前语言
  String get value => _language;
  LanguageModel(this._language);
  void initValue(){//无用,不如构造函数啊
    String getvalue=LocalStorage.get('language');
    if(getvalue!=null) setLanguage(getvalue);
  }

  //切换语言
  void switchLanguage() {
    if(_language=="Chinese") {
      _language = "English";
      LocalStorage.save('language','English');
    }
    else if(_language=="English") {
      _language="Chinese";
      LocalStorage.save('language','Chinese');
    }
    notifyListeners();
  }

  //设置语言,加这个是怕以后不只两个语言
  void setLanguage(value) {
      _language = value;
      LocalStorage.save('language',value);
    notifyListeners();
  }

  Map get test => contains[_language];

  Map<String, Map<String, String>> contains={
    'Chinese': {
      'modifyPasswordtitle': '验证原密码',
      'welecome':"欢迎回来,请登录",
         },
     'English': {
      'modifyPasswordtitle': 'Verify the original password',
      'welecome': "Welecome back,please log in",
      'phone': "Phone",
      }
  };

在该用的页面的引用

class Setting extends StatefulWidget {
  @override
  _SettingState createState() => _SettingState();
}

class _SettingState extends State<Setting> {
  var test;
  @override
  Widget build(BuildContext context) {
    test = Provider.of<LanguageModel>(context).test;//获取文本
    return Scaffold(
      resizeToAvoidBottomInset: false,
      backgroundColor: MyColors.bg,
      appBar: MyAppBar(title: test['modifyPasswordtitle'],),//直接用

切换语言的页面代码

import 'package:jieda/common/CommonInsert.dart';
class SelectLanguage extends StatefulWidget {
  @override
  _SelectLanguageState createState() => _SelectLanguageState();
}

class _SelectLanguageState extends State<SelectLanguage> {
  @override
  Widget build(BuildContext context) {
    String _language = Provider.of<LanguageModel>(context).value;
    Map test = Provider.of<LanguageModel>(context).test;//两种写法供君选择
    String english=_language=="English"?'English':"英文";
    String chinese=_language=="English"?'Chinese':"中文";
    String title=_language=="English"?'Switch Language':"切换语言";

    return Scaffold(
      backgroundColor: MyColors.bg,
      appBar: MyAppBar(
        title:title,
      ),
      body: Column(
        children: <Widget>[
          SizedBox(height: Adapt.dp(10),),
          Consumer<LanguageModel>(
            builder: (context, LanguageModel language, child) =>GestureDetector(  behavior: HitTestBehavior.translucent,onTap: _language!="English"?(){language.setLanguage('English');}:null,
              child: child,),
            child: Container(height: Adapt.dp(50),color: Colors.white,padding: EdgeInsets.only(left: 16,right: 13),
              child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Text(english,style: TextStyle(fontSize: 12),),Icon(_language=="English"?Icons.check_circle:Icons.panorama_fish_eye,color: _language=="English"?MyColors.ls:Colors.black26,)
                ],),),
          ),
          SizedBox(height:1 ,),
          Consumer<LanguageModel>(
            builder: (context, LanguageModel language, child) =>GestureDetector(  behavior: HitTestBehavior.translucent,onTap: _language=="English"?language.switchLanguage:null,
              child: child,),
            child: Container(height: Adapt.dp(50),color: Colors.white,padding: EdgeInsets.only(left: 16,right: 13),
              child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Text(chinese,style: TextStyle(fontSize: 12),),Icon(_language!="English"?Icons.check_circle:Icons.panorama_fish_eye,color: _language!="English"?MyColors.ls:Colors.black26,)
                ],),),
          ),
        ],
      ),
    );
  }
}

后记:

我研究了一下

flutter_localizations

好像有bug,

这个插件也是provider写的呀,那我直接用Provider,应该也可以。

参考:

flutter_localizations: book.flutterchina.club/chapter15/e…

init18好像不错

犯过的错:

之前在Main中是没搞这个Warapper的

尝试

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
   Provider.of<LanguageModel>(context).initValue();
      //报错,说是有方法during SetState。。
    return MaterialApp(
      title: '捷达智能电器',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LoginPage(),
    );
  }
}