android - 如何使用 Provider 实现 Flutter 本地化?
问题描述
我想让我的应用程序以 2 种不同的语言工作。我想问题是我无法在 multiprovider 中处理Cosumer,可以吗?
我正在使用flutter_localization 包和flutter 提供程序包;
这是我的代码:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
AppLanguage appLanguage = AppLanguage();
await appLanguage.fetchLocale();
SharedPreferences.getInstance().then((prefs) {
var darkModeOn = prefs.getBool('darkMode') ?? true;
runApp(
ChangeNotifierProvider<ThemeManager>(
builder: (_) => ThemeManager(lightTheme),
child: MyApp(appLanguage: appLanguage),
),
);
});
}
给我的应用上课
class MyApp extends StatelessWidget {
final AppLanguage appLanguage;
MyApp({this.appLanguage});
@override
Widget build(BuildContext context) {
final themeNotifier = Provider.of<ThemeManager>(context);
return MultiProvider(
providers: [
ChangeNotifierProvider.value(value: ApiService()),
ChangeNotifierProxyProvider<ApiService, StudentData>(
builder: (ctx, auth, _) => StudentData(auth.token, auth.school),
)
],
child: Consumer<ApiService>(
builder: (ctx, auth, _) => ChangeNotifierProvider<AppLanguage>(
builder: (_) => appLanguage,
child: Consumer<AppLanguage>(
builder: (context, model, child) => MaterialApp(
locale: appLanguage.appLocal,
supportedLocales: [Locale('ru', 'RU'), Locale('uz', 'UZ')],
localizationsDelegates: [
AppLocalization.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
debugShowCheckedModeBanner: false,
title: "Socratus |Mobile",
theme: themeNotifier.getTheme(),
home: auth.isAuth
? MainScreen()
: FutureBuilder(
future: auth.tryAutoLogin(),
builder: (ctx, authResultSnapshot) => LoginScreen()),
routes: {
MainScreen.routeName: (ctx) => MainScreen(),
ProfilePage.routeName: (ctx) => ProfilePage(),
SettingsPage.routeName: (ctx) => SettingsPage(
appLanguage: appLanguage,
),
ChangePassword.routeName: (ctx) => ChangePassword(),
HomeworkScreen.routeName: (ctx) => HomeworkScreen(),
HWDetails.routeName: (ctx) => HWDetails(),
NewsPage.routeName: (ctx) => NewsPage(),
QuestionAndAnswers.routeName: (ctx) => QuestionAndAnswers(),
MyDownloads.routeName: (ctx) => MyDownloads(),
},
),
),
),
),
);
}
}
这里我是如何尝试实现的
class AppLocalization {
final Locale locale;
AppLocalization(this.locale);
static AppLocalization of(BuildContext context) {
return Localizations.of<AppLocalization>(context, AppLocalization);
}
static const LocalizationsDelegate<AppLocalization> delegate =
_AppLocalizationDelegate();
Map<String, String> _localizedStrings;
Future<bool> load() async {
String jsonString = await rootBundle
.loadString('assets/translations/${locale.languageCode}.json');
Map<String, dynamic> jsonMap = json.decode(jsonString);
_localizedStrings = jsonMap.map((key, value) {
return MapEntry(key, value.toString());
});
return true;
}
String translate(String key) {
return _localizedStrings[key];
}
}
class _AppLocalizationDelegate extends LocalizationsDelegate<AppLocalization> {
// This delegate instance will never change (it doesn't even have fields!)
// It can provide a constant constructor.
const _AppLocalizationDelegate();
@override
bool isSupported(Locale locale) {
// Include all of your supported language codes here
return ['ru', 'uz'].contains(locale.languageCode);
}
@override
Future<AppLocalization> load(Locale locale) async {
AppLocalization localizations = new AppLocalization(locale);
await localizations.load();
return localizations;
}
@override
bool shouldReload(_AppLocalizationDelegate old) => false;
}
我的提供者:
class AppLanguage extends ChangeNotifier {
Locale _appLocale = Locale('ru');
Locale get appLocal => _appLocale ?? Locale("ru");
fetchLocale() async {
var prefs = await SharedPreferences.getInstance();
if (prefs.getString('language_code') == null) {
_appLocale = Locale('ru');
return Null;
}
_appLocale = Locale(prefs.getString('language_code'));
return Null;
}
void changeLanguage(Locale type) async {
var prefs = await SharedPreferences.getInstance();
if (_appLocale == type) {
return;
}
if (type == Locale("uz")) {
_appLocale = Locale("uz");
await prefs.setString('language_code', 'uz');
await prefs.setString('countryCode', 'UZ');
} else {
_appLocale = Locale("ru");
await prefs.setString('language_code', 'ru');
await prefs.setString('countryCode', 'RU');
}
notifyListeners();
}
}
如果这不是正确的方法,我该如何实现这个功能?
解决方案
本文解释了您尝试实现的方式,如果您想要一种不同的方法,我建议您从 pub.dev 中查看Easy Localization,它目前可以很好地处理所有Flutter 国际化功能。
推荐阅读
- google-sheets - Dynamic cell reference SUBSTITUTE formula
- binance - 如何以 EUR Node.js 获得加密货币的价格?
- python - 如果用户在 tkinter 的组合框中选择是,则显示的文本字段
- terraform - 厨房 terraform 错误 - 无法加载“terraform”驱动程序。错误:nil:NilClass 的未定义方法“大小”
- c - 使用逻辑运算符比较多个字符串在 C 编程中不能正常工作
- flutter - 颤振 - 小部件测试 - 为什么我的线路覆盖率没有反映在超级构造函数调用中?
- php - 如何只为一篇文章发表评论?php
- angular - 如何在加载应用程序时运行“microsoftTeams.media.scanBarCode”API
- r - R:如何填写 DF 中依赖于前一行的值
- java - 使用 Quartz 调度程序的 Spring Boot:集群不起作用