Flutter+GetX国际化异常:设置localizationsDelegates触发UnsupportedError
问题原因分析
- 添加
localizationsDelegates时报错:GlobalMaterialLocalizations.delegates是Flutter提供的不可修改列表,GetMaterialApp内部会尝试扩展传入的代理集合,直接赋值这个不可变列表会触发"修改不可修改集合"的错误。 - 移除
localizationsDelegates后TabBar报错:TabBar依赖MaterialLocalizations提供的本地化文本(如标签切换提示语),未配置正确代理时,Flutter无法找到对应的实例,从而抛出异常。 - 硬编码
en_US能运行:Flutter默认内置英文的MaterialLocalizations实现,无需额外代理即可工作,但印尼语没有默认实现,必须通过正确配置加载。
解决方案
1. 正确配置GetMaterialApp的本地化代理
不要直接赋值GlobalMaterialLocalizations.delegates,而是合并GetX代理与原生代理,同时启用GetX国际化功能:
修改main.dart中的GetMaterialApp配置:
return GetMaterialApp( title: "MyApp", initialRoute: AppPages.INITIAL, getPages: AppPages.routes, themeMode: ThemeMode.dark, theme: MyAppTheme.light, darkTheme: MyAppTheme.dark, debugShowCheckedModeBanner: false, translations: AppTranslations(), // 取消注释,启用GetX国际化 locale: EnvService.instance.defaultLocale, // 从EnvService获取默认Locale,替代硬编码 fallbackLocale: const Locale('en', 'US'), supportedLocales: const [ Locale('en', 'US'), Locale('id', 'ID'), ], // 合并原生代理与GetX代理 localizationsDelegates: [ ...GlobalMaterialLocalizations.delegates, GetLocalizations.delegate, ], );
2. 修复IntlService的初始化逻辑
当前IntlService.init()在runApp前执行,此时Get.locale尚未初始化,且initializeDateFormatting需传入语言代码而非国家代码,修改如下:
class IntlService extends GetxService { static IntlService get instance => Get.find(); final _currentLocale = Rx<Locale>(EnvService.instance.defaultLocale); @override void onInit() { super.onInit(); // 监听GetX的Locale变化,动态更新格式化器 ever(Get.locale, (Locale? newLocale) { if (newLocale != null) { _currentLocale.value = newLocale; _initDateFormatting(newLocale.languageCode); } }); // 初始化默认格式 _initDateFormatting(_currentLocale.value.languageCode); } Future<void> _initDateFormatting(String languageCode) async { await initializeDateFormatting(languageCode); } String formatCurrency(double number) { final formatter = NumberFormat.simpleCurrency( decimalDigits: 0, locale: _currentLocale.value.toLanguageTag(), ); return formatter.format(number); } String formatDate(DateTime? dateTime, [String? format = 'yyyy-MM-dd']) { if (dateTime == null) { return ''; } return DateFormat(format, _currentLocale.value.languageCode).format(dateTime); } }
同时调整main.dart的初始化顺序,确保App启动后再初始化IntlService:
void main() async { WidgetsFlutterBinding.ensureInitialized(); await Get.putAsync(() => EnvService().init()); runApp(const MyApp()); await Get.putAsync(() => IntlService().init()); }
3. 实现GetX国际化翻译类
确保AppTranslations正确继承Translations,提供印尼语与英文的映射:
class AppTranslations extends Translations { @override Map<String, Map<String, String>> get keys => { 'en_US': { 'tab_home': 'Home', // 补充其他英文翻译项 }, 'id_ID': { 'tab_home': 'Beranda', // 补充其他印尼语翻译项 }, }; }
4. 验证默认Locale配置
确认EnvService中defaultLocale的逻辑正确:当.env文件中DEFAULT_LOCALE为id时,返回Locale('id', 'ID'),否则返回英文Locale。
内容的提问来源于stack exchange,提问作者Yura
相关产品推荐
相关产品推荐

