颤振:多语言应用程序 - 如何覆盖区域设置



我遵循了官方 Flutter 页面(见这里(中给出的解释,使我的应用程序在不同的语言中工作。

根据文档,它检索用户的区域设置,这工作正常。

现在让我们假设我的应用程序支持不同的语言(例如 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;
}

在主飞镖中:

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(),
    );
  }
}

非常感谢您的帮助。

这可以通过

  1. 创建一个新的本地化委托,该委托转换为单个区域设置或完全延迟取决于参数
  2. 将基本应用程序 (MyApp( 转换为有状态小组件,并将上面的新委托插入到本地化委托列表中
  3. 使用基于某些事件针对特定区域设置的新委托管理基本应用 (MyApp( 状态

1( 的简单实现可能是:

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;
}

接下来是 2( 和 3(,将 MyApp 转换为有状态并包括新委托(最初只是延迟所有内容(,以及一些事件处理程序,以使用指定新区域设置的新委托更改状态。

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
  SpecifiedLocalizationDelegate _localeOverrideDelegate;
  @override
  void initState() {
    super.initState();
    _localeOverrideDelegate = new SpecifiedLocalizationDelegate(null);
  }
  onLocaleChange(Locale l) {
    setState(() {
      _localeOverrideDelegate = new SpecifiedLocalizationDelegate(l);
    });
  }
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      localizationsDelegates: [
        _localeOverrideDelegate,
        const TranslationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [
        const Locale('en', ''), // English
        const Locale('fr', ''), // French
      ],
      home: new LandingPage(onLocaleSwitch: onLocaleChange),
    );
  }
}

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

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

若要控制应用的区域设置,可以使用 MaterialApp 的区域设置属性:

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

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

使用其中一个提供者应该可以完成这项工作,我对提供者不是很熟悉,但这让我可以轻松工作

  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"));

提供程序中包装材料应用程序的好处是,您可以从应用程序的任何部分访问区域设置值

最简单的方法(奇怪的是国际化教程中没有提到(是使用 locale 属性。MaterialApp 类的此属性允许我们立即指定我们希望应用程序使用的区域设置

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

本教程更好地解释了它

它还解释了如何从共享首选项加载区域设置首选项

Material App 上使用 locale 参数来覆盖应用程序默认值。如果"区域设置"为空,则使用系统的区域设置值。 但请确保您传递的是可识别的区域设置,Locale.fromSubtags对我有用:

 return MaterialApp(
   locale: Locale.fromSubtags(languageCode: 'es'),
   localizationsDelegates: [
     ...
 );

如果您想稍后更改此值,请使用 Provider 并使用 Consumer 包装Material App以监视更改。

最新更新