颤动:多语言应用程序 - 如何覆盖语言环境?

时间:2018-03-23 01:52:56

标签: flutter

我按照官方Flutter页面中的解释(参见here),使我的应用程序以不同的语言工作。

根据文档,它检索用户的语言环境,这很好。

现在假设我的应用程序支持不同的语言(例如EN,FR,ES,...),并且用户可以选择其中一种语言来使用该应用程序(所选语言将与该语言不同)在手机的设置中定义),我该如何实现?

我如何强制应用程序区域设置并动态“重新加载”所有翻译?

Flutter页面没有解释这一点,我在文档中没有看到任何可以帮助我的内容......

以下是当前的实施:

class Translations {
  Translations(this.locale);

  final Locale locale;

  static Translations of(BuildContext context){
    return Localizations.of<Translations>(context, Translations);
  }

  static Map<String, Map<String, String>> _localizedValues = {
    'en': {
      'title': 'Hello',
    },
    'fr': {
      'title': 'Bonjour',
    },
    'es': {
      'title': 'Hola',
    }
  };

  String text(String key){
    return _localizedValues[locale.languageCode][key] ?? '** ${key} not found';
  }
}

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

  @override
  bool isSupported(Locale locale) => ['en', 'fr','es'].contains(locale.languageCode);

  @override
  Future<Translations> load(Locale locale) {
    return new SynchronousFuture<Translations>(new Translations(locale));
  }

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

在main.dart中:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: Translations.of(context).text('title'),
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      localizationsDelegates: [
        const TranslationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [
        const Locale('en', ''), // English
        const Locale('fr', ''), // French
        const Locale('fr', ''), // French
      ],
        home: new LandingPage(),
    );
  }
}

非常感谢你的帮助。

4 个答案:

答案 0 :(得分:10)

这可以通过

来完成
  1. 创建一个新的LocalizationsDelegate,转换为 单个区域设置或完全取决于参数
  2. 将基础应用(MyApp)转换为有状态小部件,并将上面的新代理插入localizationsDelegates列表
  3. 使用基于某个事件定位特定区域设置的新代理来管理基本应用(MyApp)状态
  4. 1)的简单实现可能是:

      SELECT c.ID, c.DateEnd 
      FROM conference c 
      INNER  JOIN (
      SELECT a.ID, a.IDConf 
      FROM application a 
      GROUP BY a.IDConf 
      HAVING COUNT(a.IDConf) >= 2 
      ) t ON c.ID=t.IDConf  
       WHERE c.DateEnd = DATE_ADD(CURDATE(),INTERVAL 1 DAY)
    

    接下来针对2)和3),将MyApp转换为有状态并包含新委托(最初只是推迟所有内容),以及一些事件处理程序,以使用指定新Locale的新委托来更改状态。

    class SpecifiedLocalizationDelegate
        extends LocalizationsDelegate<Translations> {
      final Locale overriddenLocale;
    
      const SpecifiedLocalizationDelegate(this.overriddenLocale);
    
      @override
      bool isSupported(Locale locale) => overriddenLocale != null;
    
      @override
      Future<Translations> load(Locale locale) =>
          Translations.load(overriddenLocale);
    
      @override
      bool shouldReload(SpecifiedLocalizationDelegate old) => true;
    }
    

    通过这些更改,您可以在子窗口小部件中使用Translations.of(context).myLocalizedString来检索翻译。

    更完整的要点:https://gist.github.com/ilikerobots/474b414138f3f99150dbb3d0cc4cc721

答案 1 :(得分:5)

要控制应用的语言环境,可以使用MaterialApp的locale属性:

return MaterialApp(
  ...
  locale: _myLocal,
  ...
);

这与@ilikerobots StatefulWidget方法相结合,将为您提供所需的内容。

答案 2 :(得分:0)

使用Providers之一应该可以完成这项工作,我对供应商并不十分熟悉,但这使我轻松工作了

  1. 使用ChangeNotifierProvider包装您的重要应用
    return ChangeNotifierProvider(
        create: (_) => new LocaleModel(),
        child: Consumer<LocaleModel>(
            builder: (context, provider, child) => MaterialApp(
                title: 'myapp',
                locale: Provider.of<LocaleModel>(context).locale
                 ...
                 ...
                 ...

  1. 使用getter和setter创建模型类,以获取和设置语言环境为 \
import 'package:iborganic/const/page_exports.dart';

class LocaleModel with ChangeNotifier {
  Locale locale = Locale('en');
  Locale get getlocale => locale;
  void changelocale(Locale l) {
    locale = l;
    notifyListeners();
  }
}

  1. 将某些事件的区域设置(单击按钮)更改为
Provider.of<LocaleModel>(context).changelocale(Locale("kn"));

将实质性应用程序包装在Provider中的好处是您可以从应用程序的任何部分访问区域设置值

答案 3 :(得分:0)

国际化教程中没有提到的最简单的方法是使用locale属性。 MaterialApp类的此属性使我们可以立即指定我们希望我们的应用使用的语言环境

 return MaterialApp(
  locale: Locale('ar', ''),
  localizationsDelegates: [
    MyLocalizationsDelegate,
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
  ],
  supportedLocales: [
    const Locale('en', ''), // English
    const Locale('ar', ''), // Arabic
  ],
  home: HomeScreen()
);

This tutorial explained it better

它还解释了如何从sharedPreferences加载语言环境首选项