我是新来的人。
我正在构建一个多语言应用程序。
在应用启动之前,它需要加载当前的语言环境文件。 然后,每次用户更改语言环境时,都需要加载新文件。
至少在理论上,我认为可以使用“ ChangeNotifierProvider”,ProxyProvider或类似的方法来完成。
所以我让AppLanguage类根据语言代码加载正确的语言环境文件
class AppLanguage extends ChangeNotifier {
String _appLocale = 'en';
Map<String, String> _localizedStrings;
Map<String, String> get localeData => this._localizedStrings;
Future<bool> getLocaleData() async {
var prefs = await SharedPreferences.getInstance();
if (prefs.getString('language_code') == null) {
_appLocale = 'en';
await prefs.setString('language_code', _appLocale);
} else {
_appLocale = prefs.getString('language_code');
}
String jsonString = await rootBundle.loadString('i18n/$_appLocale.json');
Map<String, dynamic> jsonMap = json.decode(jsonString);
_localizedStrings = jsonMap.map((key, value) {
return MapEntry(key, value.toString());
});
return true;
}
Future<void> changeLanguage(String locale) async {
var prefs = await SharedPreferences.getInstance();
_appLocale = locale;
await prefs.setString('language_code', locale);
notifyListeners();
}
}
getLocaleData()函数读取数据并使用changeLanguage更改当前语言环境并触发notifyListeners
class Translator {
final Map<String, String> localizedStrings;
Translator(this.localizedStrings);
String translate(String key) {
return localizedStrings[key];
}
}
小部件将使用翻译器类来获取正确的翻译。
我的问题是,如何将其连接到主电源。我被困在如何设置提供程序上。
void main() async {
WidgetsFlutterBinding.ensureInitialized();
AppLanguage appLanguage = AppLanguage();
await appLanguage.getLocaleData();
runApp(MyApp(appLanguage: appLanguage));
}
class MyApp extends StatelessWidget {
final AppLanguage appLanguage;
MyApp({this.appLanguage});
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ProxyProvider<AppLanguage, Translator>(
update: (context, appLanguage, trans) =>
Translator(appLanguage.localeData),
),
],
child: MaterialApp(
title: 'Language Demo',
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Hello'),
),
body: Container(),
);
}
}
有人可以帮忙吗? 还是提供一种更好的方法?
答案 0 :(得分:0)
有些事情,ProxyProvider(或任何类型的ProxyProvider,ChangeNotifierProxyProvider等)在提供程序也依赖于更改时也会更新其值,但是您在main中创建了AppLanguage,没有注入依赖,就像一个简单的类一样(在上下文中并未真正提供),因此在这种情况下仅使用ChangeNotifierProvider会更容易。
有一个名为window.locale的参数,该参数返回当时使用的设备的语言,在应用程序启动时,您可以使用它来了解设备的语言(如果没有)。第一次使用sharedPreference。这样做的好处是,在您的示例中,如果未保存首选项,它将使用默认的“ en”作为英语,但是您还支持japanase,因此,如果有人将其设备安装为日语并首次下载您的应用,从一开始就很好用日语。
Future<Locale> _getLocaleData() async {
var prefs = await SharedPreferences.getInstance();
String languageCode = prefs.getString('language_code');
if (languageCode == null) {
return window.locale;
} else {
return Locale(languageCode);
}
}
void main() async {
Locale locale = await _getLocaleData();
runApp(MyApp(
appLanguage: locale,
));
}
class MyApp extends StatelessWidget {
final Locale language;
MyApp({this.language});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<AppLanguage>(
builder: (_) => AppLanguage(language),
child: Consumer<AppLanguage>(builder: (context, model, _) {
return MaterialApp(
locale: model.appLocal,
supportedLocales: [
Locale('en', 'US'),
Locale('ja', ''),
],
localizationsDelegates: [
AppLocalizations.delegate, //create your AppLocalizations just like the article you shared
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: MyWidget(),
);
}),
);
}
}
class AppLanguage extends ChangeNotifier {
AppLanguage(Locale locale) : _appLocale = locale;
Locale _appLocale;
Locale get appLocal => _appLocale;
Future<void> changeLanguage(String locale) async {
var prefs = await SharedPreferences.getInstance();
_appLocale = Locale(locale);
await prefs.setString('language_code', locale);
notifyListeners();
}
}