在Flutter中获取BuildContext进行本地化

Dan*_*ens 6 dart flutter

我尝试使用本地化包将Flutter中的字符串本地化。问题是需要翻译的位置。它与UI无关,而是在模型的深处,我无法访问BuildContext。还有其他可能性可以继续使用翻译功能吗?

// I don't have a context variable here
MyLocalizations.of(context).trans("foo")
Run Code Online (Sandbox Code Playgroud)

kin*_*ine 7

就在这里。您不需要BuildContext来访问字符串。这是我的解决方案:

class Strings {
  Strings._(Locale locale) : _localeName = locale.toString() {
    current = this;
  }

  final String _localeName;

  static Strings current;

  static Future<Strings> load(Locale locale) async {
    await initializeMessages(locale.toString());
    final result = Strings._(locale);
    return result;
  }

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

  String get title {
    return Intl.message(
      'Hello World',
      name: 'title',
      desc: 'Title for the Demo application',
    );
  }
}

Future<Null> main() async {
  final Locale myLocale = Locale(window.locale);
  await Strings.load(myLocale);
  runApp(MyApplication());
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以引用一个字符串,如下所示:

final title = Strings.current.title;
Run Code Online (Sandbox Code Playgroud)

  • @Martyns如果您想通过再次调用“Strings.load”在运行时更改当前语言,则需要重新加载存储的任何字符串,例如到类成员数据中。如果您将字符串存储到静态最终变量中,则需要重新启动应用程序。到目前为止没有遇到其他问题。 (3认同)

mab*_*abg 7

AppLocalizations 需要上下文。

您可以创建一个类(例如,Localization)来封装 AppLocalizations 初始化,并使用其上下文从主页小部件中对其进行初始化。之后,可以与 mixin 一起使用:

import 'package:flutter/widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class Localization {
  static AppLocalizations _loc;

  AppLocalizations get loc => Localization._loc;

  static void init(BuildContext context) => _loc = AppLocalizations.of(context);
}
Run Code Online (Sandbox Code Playgroud)

在主页小部件中:

...
    @override
    Widget build(BuildContext context) {
       Localization.init(context);
       return Scaffold(
...
Run Code Online (Sandbox Code Playgroud)

使用 mixins 访问某个类中的 loc(不一定是 Widget):

class XXXWidget extends StatelessWidget with Localization {
    ...
    Text(loc.xxxx)
    ...
}

class _XXXXWidgetState extends State<XXXWidget> with Localization {
    ...
    Text(loc.xxxx)
    ...
}

class XXXXController with Localization {
    ...
    cardNumberValidator = RequiredValidator(errorText: loc.commons_Required);
    ...
}
Run Code Online (Sandbox Code Playgroud)

空安全版本:

class Localization {
  static AppLocalizations? _l;    
  AppLocalizations get loc => Localization._l!;

  static void init(BuildContext context) => _l = AppLocalizations.of(context)!;
}
Run Code Online (Sandbox Code Playgroud)


cre*_*not 5

不,没有其他方法,因为它是使用 an 存储的InheritedWidget,它是构建树的一部分,因此只能通过对它的引用 (the BuildContext)来访问。
您需要将您的信息传递context到模型深处的某个地方。


thi*_*yen 5

我知道这个问题已经过时了。但是我在实现我的应用程序时遇到了这个问题,我没有看到任何“好”的方法来处理它。所以这是我的方法

class LanguageService {
  static String defaultLanguage = 'en';

  static Map<String, Map<String, String>> _localizedValues = {
    'en': {
      'title': 'Storefront',
      'language': 'Language',
      'googleLogin': 'Login with Google'
    },
    'vn': {
      'title': 'C?a hàng',
      'language': 'Ngôn ng?',
      'googleLogin': '??ng Nh?p v?i Google'
    }
  };

  static set language(String lang) {
    defaultLanguage = lang;
  }

  static String get title {
    return _localizedValues[defaultLanguage]['title'];
  }

  static String get language {
    return _localizedValues[defaultLanguage]['language'];
  }

  static String get googleLogin {
    return _localizedValues[defaultLanguage]['googleLogin'];
  }

}
Run Code Online (Sandbox Code Playgroud)

现在您可以按如下方式引用字符串:

String title = LanguageService.title;
Run Code Online (Sandbox Code Playgroud)

你可以在这里找到详细的教程