美文网首页Flutter
Flutter国际化的三种方式-->json

Flutter国际化的三种方式-->json

作者: 谢尔顿 | 来源:发表于2019-08-26 10:29 被阅读0次

关于Flutter的国际化有三种实现方式,本文主要讲述的是使用flutter_localizations的实现方式。
下面是我们最终实现的效果图:


  1. 项目结构


2.代码分析
assets/i18n下的两个json文件,是我们翻译中分别用到的源文件,en.json和zh.json的源码如下所示:

en.json:

{
  "hello": "Hello!",
  "greetTo": "Nice to meet you,{{name}}!",
  "app_title":"Flutter Internationalization",
  "jump_to_second_page": "Jump to the second page",
  "second_page": "Second page",
  "switch": "Switch"
}

zh.json

{
  "hello": "你好!",
  "greetTo": "{{name}},见到你很高兴!",
  "app_title":"Flutter国际化",
  "jump_to_second_page": "跳转到第二个界面",
  "second_page": "第二个界面",
  "switch": "切换"
}

翻译资源json准备完之后,在pubspec.yaml中添加所需要的依赖,如下图所示:


红框的部分就是我们项目所以需要的。

initialize_i18n.dart文件是用来加载assets/i18n下的json资源的:

import 'dart:convert';

import 'package:flutter/services.dart';

import 'constant.dart' show languages;

//加载json资源
Future<String> loadJsonFromAsset(language) async {
  return await rootBundle.loadString('assets/i18n/' + language + '.json');
}

Map<String, String> convertValueToString(obj) {
  Map<String, String> result = {};
  obj.forEach((key, value) {
    result[key] = value.toString();
  });
  return result;
}

Future<Map<String, Map<String, String>>> initializeI18n() async {
  Map<String, Map<String, String>> values = {};
  for (String language in languages) {
    Map<String, dynamic> translation =
        json.decode(await loadJsonFromAsset(language));
    values[language] = convertValueToString(translation);
  }

  return values;
}

localizations.dart文件:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'constant.dart';

//调用该类获取字符串内容
class MyLocalizations {
  final Map<String, Map<String, String>> localizedValues;
  final Locale locale;

  MyLocalizations(this.locale, this.localizedValues);
  static MyLocalizations of(BuildContext context) {
    return Localizations.of<MyLocalizations>(context, MyLocalizations);
  }

  String get hello {
    return localizedValues[locale.languageCode]['hello'];
  }

  greetTo(name) {
    return localizedValues[locale.languageCode]['greetTo']
        .replaceAll('{{name}}', name);
  }

  String get homeTitle {
    return localizedValues[locale.languageCode]['app_title'];
  }

  String get jumpToSecondPage {
    return localizedValues[locale.languageCode]['jump_to_second_page'];
  }

  String get secondPage {
    return localizedValues[locale.languageCode]['second_page'];
  }

  String get qh {
    return localizedValues[locale.languageCode]['switch'];
  }
}

class MyLocalizationsDelegate extends LocalizationsDelegate<MyLocalizations> {
  Map<String, Map<String, String>> localizedValues;
  MyLocalizationsDelegate(this.localizedValues);
  @override
  bool isSupported(Locale locale) => languages.contains(locale.languageCode);

  @override
  Future<MyLocalizations> load(Locale locale) {
    return SynchronousFuture<MyLocalizations>(
        MyLocalizations(locale, localizedValues));
  }

  @override
  bool shouldReload(LocalizationsDelegate<MyLocalizations> old) {
    return false;
  }
}

MyLocalizationsDelegate中的languges来自于constant.dart.

List<String> languages=['en','zh'];

最后,在main.dart中将上面的每个部分连接起来:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

import 'constant.dart';
import 'initialize_i18n.dart';
import 'localizations.dart';
import 'pages/second_page.dart';

//import 'package:url_launcher/url_launcher.dart';

void main() async {
  //加载中英文数据源
  Map<String, Map<String, String>> localizedValues = await initializeI18n();

  runApp(MyApp(localizedValues));
}

class MyApp extends StatefulWidget {
  final Map<String, Map<String, String>> localizedValues;
  MyApp(this.localizedValues);
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _locale = 'en';
  //切换语言
  onChangeLanguage() {
    if (_locale == 'en') {
      setState(() {
        _locale = 'zh';
      });
    } else {
      setState(() {
        _locale = 'en';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [
        MyLocalizationsDelegate(widget.localizedValues),//设置自己定义的代理
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,//用于兼容ios
      ],
      locale: Locale(_locale),//设置当前的语言
      supportedLocales: languages.map((language) => Locale(language, '')),
      home: MyHomePage(onChangeLanguage),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final VoidCallback onChangeLanguage;
  MyHomePage(this.onChangeLanguage);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: new Text(MyLocalizations.of(context).homeTitle),
      ),
      body: Container(
        width: MediaQuery.of(context).size.width,
        padding: EdgeInsets.only(top: 30),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: <Widget>[
            Text(MyLocalizations.of(context).greetTo('胡歌')),
            SizedBox(
              height: 20.0,
            ),
            Container(
              width: 200.0,
              height: 40.0,
              child: FlatButton(
                  color: Colors.lightBlue,
                  onPressed: () {
                    Navigator.of(context)
                        .push(MaterialPageRoute(builder: (cxt) {
                      return SecondPage();
                    }));
                  },
                  child: Text(
                    MyLocalizations.of(context).jumpToSecondPage,
                    style: TextStyle(color: Colors.white),
                  )),
            ),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
          child: Text(MyLocalizations.of(context).qh),
          onPressed: onChangeLanguage),
    );
  }
}

在main.dart中,我们可以直接利用MyLocalizations.of(context).homeTitle等给对应的字符串赋值。点击按钮切换时,只需要切换MaterialApp中locale的值即可。

相关文章

网友评论

    本文标题:Flutter国际化的三种方式-->json

    本文链接:https://www.haomeiwen.com/subject/oveosctx.html