37

Flutter国际化完整例子

 5 years ago
source link: https://segmentfault.com/a/1190000018773751?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

请支持原文 http://tryenough.com/flutter-translation

flutter国际化实现方案

这里提供一份解决方案,和一份可以直接使用的demo。

1.添加依赖库

需要用到flutter_localizations包,在 pubspec.yaml 文件中添加如下依赖内容:

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter

添加完记得执行获取这个库:

在terminal中运行 flutter packages get, 或者在IntelliJ\Android Studio中点击’Packages get’

2.添加多种语言的文件

请支持原文 http://tryenough.com/flutter-translation

在项目的lib同级目录下创建locale文件夹,并创建几个json文件,用来存储不同语言的翻译文案。如下文件结构:

7vYVrmz.png!web

上图中创建了三种语言的json文件,你可以根据你的需要创建其他的语言json文件。添加翻译内容,如下:

i18n_en.json:

{
  "about_page_slogan":"Health starts here"
}

i18n_zh.json:

{
  "about_page_slogan":"健康从这里开始"
}

记得在 pubspec.yaml 文件中添加这几个资源文件:

Qv6nI3V.png!web

3.创建一个工具类,保存当前支持的语言等信息

请支持原文 http://tryenough.com/flutter-translation

locale_util.dart

import 'package:flutter/material.dart';

typedef void LocaleChangeCallback(Locale locale);
class LocaleUtil {

  // Support languages list
  final List<String> supportedLanguages = ['en','zh', 'ja'];

  // Support Locales list
  Iterable<Locale> supportedLocales() => supportedLanguages.map<Locale>((lang) => new Locale(lang, ''));

  // Callback for manual locale changed
  LocaleChangeCallback onLocaleChanged;

  Locale locale;
  String languageCode;

  static final LocaleUtil _localeUtil = new LocaleUtil._internal();

  factory LocaleUtil() {
    return _localeUtil;
  }

  LocaleUtil._internal();

  /// 获取当前系统语言
  String getLanguageCode() {
    if(languageCode == null) {
      return "en";
    }
    return languageCode;
  }
}

LocaleUtil localeUtil = new LocaleUtil();

3.添加翻译处理类文件

translations.dart

系统提供了LocalizationsDelegate类帮助我们监听系统语言的切换,所以我们可以继承LocalizationsDelegate类监听语言切换,并在切换时加载不同的json文件,来获取不同的语言文案。这里我们的translations工具类就是利用这样的原理来加载不同的语言文案:

import 'package:translation/locale_util.dart';

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show  rootBundle;

/// Class for Translate
///
/// For example:
///
/// import 'package:workout/translations.dart';
///
/// ```dart
/// For TextField content
/// Translations.of(context).text("home_page_title");
/// ```
///
/// ```dart
/// For speak string
/// Note: Tts will speak english if currentLanguage[# Tts's parameter] can't support
///
/// Translations.of(context).speakText("home_page_title");
/// ```
///
/// "home_page_title" is the key for text value
///
class Translations {
  Translations(Locale locale) {
    this.locale = locale;
    _localizedValues = null;
  }

  Locale locale;
  static Map<dynamic, dynamic> _localizedValues;
  static Map<dynamic, dynamic> _localizedValuesEn; // English map

  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 _localizedValuesEn[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);
    String enJsonContent = await rootBundle.loadString("locale/i18n_en.json");
    _localizedValuesEn = json.decode(enJsonContent);
    return translations;
  }

  get currentLanguage => locale.languageCode;
}

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

  // Support languages
  @override
  bool isSupported(Locale locale) {
    localeUtil.languageCode = locale.languageCode;
    return localeUtil.supportedLanguages.contains(locale.languageCode);
  }

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

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

// Delegate strong init a Translations instance when language was changed
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;
}

上面的代码我们看到有两个继承自LocalizationsDelegate类的代理类,SpecificLocalizationDelegate类是提供一种让我们强制指定一种位置的方式,通过改变传进来的local来达到从新load新json的方式。如果你没有这种需求,可以只关心TranslationsDelegate这种默认方式。

5.在main方法中将代理设置好

请支持原文 http://tryenough.com/flutter-translation

要想监听系统的代理,就需要设置系统位置代理。方法如下:

在main.dart方法中设置:

import 'package:translation/tanslations.dart';
import 'package:translation/locale_util.dart';

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'My Application',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      localizationsDelegates: [
        const TranslationsDelegate(), 
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: localeUtil.supportedLocales(),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>{
  @override
  Widget build(BuildContext context){
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(Translations.of(context).text("about_page_slogan")),
      ),
      body: Center(
          child: Text(Translations.of(context).text("about_page_slogan")),
        ),
    );
  }
}

请支持原文 http://tryenough.com/flutter-translation

demo下载地址: http://tryenough.com/flutter-translation


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK