123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- import 'package:fis_i18n/i18n.dart';
- import 'package:fis_i18n/types.dart';
- import 'package:flutter/cupertino.dart';
- import 'package:flutter/services.dart';
- import 'package:flyinsonolite/localization/fis_keybook.dart';
- typedef FTrKeybookBuilder = Future<FISTrKeybook> Function();
- typedef FI18nLocaleUpdater = void Function(Locale locale);
- AssetBundle _assetBundle = rootBundle;
- /// 翻译字典选项
- ///
- /// [locale] 语言
- ///
- /// [builder] 字典建造器
- class FISTrKeybookOption {
- const FISTrKeybookOption(this.locale, this.builder);
- final Locale locale;
- final FTrKeybookBuilder builder;
- /// 中文字典建造器
- static final FISTrKeybookOption ChineseOption = FISTrKeybookOption(
- CHINESE_LOCALE,
- () => _buildInnerBoook(CHINESE_LOCALE),
- );
- /// 英文字典建造器
- static final FISTrKeybookOption EnglishOption = FISTrKeybookOption(
- ENGLISH_LOCALE,
- () => _buildInnerBoook(ENGLISH_LOCALE),
- );
- }
- /// 国际化翻译字典
- FISTrKeybook get fisI18nBook => FISI18n.ins.currentBook;
- /// 国际化
- class FISI18n {
- FISI18n._();
- static FISI18n? _singleton;
- /// 单例
- static FISI18n get ins {
- if (_singleton == null) {
- throw Exception("There aren't any instance of FI18n.");
- }
- return _singleton!;
- }
- late FISTrKeybook _currentBook;
- late FI18nLocaleUpdater _localeUpdater;
- final Map<Locale, FTrKeybookBuilder> _bookMap = {};
- /// 当前语言字典
- FISTrKeybook get currentBook => _currentBook;
- /// 当前是否中文
- bool get isCurrentChinese => currentBook.isCurrentChinese;
- /// 支持的语言
- List<Locale> get supportedLocales => _bookMap.keys.toList();
- /// 设置内置资源包
- static void setAssetBundle(AssetBundle bundle) {
- _assetBundle = bundle;
- }
- /// 初始化
- static Future<void> init(
- FI18nLocaleUpdater localeUpdater,
- List<FISTrKeybookOption> bookOptions,
- ) async {
- if (_singleton != null) {
- throw Exception("FI18n has been init.");
- }
- _singleton = FISI18n._();
- _singleton!._localeUpdater = localeUpdater;
- await _singleton!._buildInstance(bookOptions);
- }
- Future<void> _buildInstance(List<FISTrKeybookOption> bookOptions) async {
- for (var option in bookOptions) {
- if (_bookMap.containsKey(option.locale)) {
- throw Exception("FI18n init: The same locale value already exists.");
- }
- setKeyBook(option.locale, option.builder);
- }
- }
- /// 加载(初始语言,init之后)
- static Future<void> load(Locale locale) async {
- // 语言+国家 精准匹配
- var bookBuilder = _singleton!._bookMap[locale];
- // 语言匹配
- if (bookBuilder == null) {
- final matchKey = _singleton!._bookMap.keys.firstWhere(
- (x) => x.languageCode == locale.languageCode,
- orElse: () => ENGLISH_LOCALE,
- );
- bookBuilder = _singleton!._bookMap[matchKey];
- }
- if (bookBuilder == null) {
- throw Exception(
- "FISI18n load error: No book-builder match the target locale.");
- }
- _singleton!._currentBook = await bookBuilder();
- }
- /// 切换语言
- Future<Locale> switchLanguage([Locale? locale]) async {
- Locale matchLocale;
- if (locale == null) {
- // 顺序找下一个字典
- final keys = _bookMap.keys.toList();
- final curIdx = keys.indexOf(currentBook.locale);
- int nextIdx = curIdx + 1;
- if (nextIdx >= keys.length) nextIdx = 0;
- matchLocale = keys[nextIdx];
- } else {
- // 优先语言Code和国家Code双匹配,否则选语言Code匹配
- final langCodeMatchList =
- _bookMap.keys.where((x) => x.languageCode == locale.languageCode);
- if (langCodeMatchList.isEmpty) {
- // 无匹配
- throw Exception(
- "FI18n switchLanguage: No keybook found for the target locale.");
- }
- if (langCodeMatchList.length > 1) {
- // 查找双匹配
- matchLocale = langCodeMatchList.firstWhere(
- (x) => x.countryCode == locale.languageCode,
- orElse: () => langCodeMatchList.first,
- );
- } else {
- // 单匹配
- matchLocale = langCodeMatchList.first;
- }
- }
- FTrKeybookBuilder builder = _bookMap[matchLocale]!;
- _currentBook = await builder();
- _localeUpdater(matchLocale);
- return matchLocale;
- }
- /// 设置翻译字典(相同语言会覆盖)
- void setKeyBook(Locale locale, FTrKeybookBuilder bookBuilder) {
- _bookMap[locale] = bookBuilder;
- }
- /// 根据字典树翻译
- ///
- /// [keyTree] 字典树,以.分隔,例:common.loading
- String translate(String keyTree) {
- final tiers = keyTree.split('.');
- dynamic curr = currentBook;
- for (var key in tiers) {
- if (curr is IPropQueryable) {
- curr = curr.getProp(key);
- } else {
- return keyTree;
- }
- }
- return curr;
- }
- }
- Future<FISTrKeybook> _buildInnerBoook(Locale locale) async {
- final code = locale.toCodeString();
- final assetKey = "assets/languages/$code.json";
- final text = await _assetBundle.loadString(assetKey, cache: false);
- final book = FISTrKeybook.createFromJson(text);
- return book;
- }
|