From 3fabbc5c5e31d1e480465354ab701dc1761b5716 Mon Sep 17 00:00:00 2001 From: Blazebrain Date: Thu, 3 Sep 2026 13:40:26 +0100 Subject: [PATCH] fix: brazillian localle bug that makes app unresponsive --- lib/entities/language_service.dart | 13 +++++++++++++ lib/main.dart | 2 +- tool/generate_localization.dart | 16 ++++++++++++---- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/entities/language_service.dart b/lib/entities/language_service.dart index 11c892df3..5331b1e83 100644 --- a/lib/entities/language_service.dart +++ b/lib/entities/language_service.dart @@ -1,7 +1,20 @@ import 'package:cake_wallet/generated/locales.dart'; import 'package:devicelocale/devicelocale.dart'; +import "package:flutter/widgets.dart"; import 'package:intl/intl.dart'; +// This will turn stored language code into Flutter Locale. +// Some of our language codes uses an underscore (like "pt_BR") and this must be split into language +// and country subtags, if we pass the whole string as the languageCode, GlobalMaterialLocalizations +// would reject it as an invalid ISO 639-1 code and crash the app on locale switch +Locale localeFromLanguageCode(String code) { + final parts = code.split("_"); + if (parts.length == 2 && parts[0].isNotEmpty && parts[1].isNotEmpty) { + return Locale(parts[0], parts[1]); + } + return Locale(code); +} + class LanguageService { static const Map supportedLocales = { 'en': 'English', diff --git a/lib/main.dart b/lib/main.dart index 02229c80a..eeb9e0394 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -426,7 +426,7 @@ class AppState extends State with SingleTickerProviderStateMixin { themeMode: themeMode, localizationsDelegates: localizationDelegates, supportedLocales: S.delegate.supportedLocales, - locale: Locale(appStore.settingsStore.languageCode), + locale: localeFromLanguageCode(appStore.settingsStore.languageCode), onGenerateRoute: (settings) => Router.createRoute(settings), initialRoute: initialRoute, scrollBehavior: AppScrollBehavior(), diff --git a/tool/generate_localization.dart b/tool/generate_localization.dart index 719cf4c5c..5bbf016a4 100644 --- a/tool/generate_localization.dart +++ b/tool/generate_localization.dart @@ -1,6 +1,5 @@ import 'dart:io'; import 'dart:convert'; -import './print_verbose_dummy.dart'; import 'localization/localization_constants.dart'; import 'utils/utils.dart'; @@ -49,7 +48,7 @@ Future main(List args) async { return; } - final localePath = {}; + final arbFiles = {}; await dir.list(recursive: false).forEach((element) { // Parse the locale from the file name (e.g. strings_pt_br.arb -> pt_BR), // normalizing the case so keys match LanguageService.supportedLocales. @@ -63,9 +62,12 @@ Future main(List args) async { final locale = parts.length > 1 ? '${parts.first.toLowerCase()}_${parts.sublist(1).join('_').toUpperCase()}' : parts.first.toLowerCase(); - localePath[locale] = element.path; + arbFiles[locale] = element.path; }); + final sortedLocales = arbFiles.keys.toList()..sort(); + final localePath = {for (final key in sortedLocales) key: arbFiles[key]}; + if (!localePath.keys.contains(defaultLocale)) { print("Locale list doesn't contain $defaultLocale"); return; @@ -103,8 +105,14 @@ Future main(List args) async { output += classDeclaration; + // for handling keys like pt_BR so entry becomes Locale("pt", "BR") and doesn't crash app localePath.keys.forEach((key) { - output += ' Locale("$key", ""),' + '\n'; + final parts = key.split("_"); + if (parts.length == 2) { + output += " Locale(\"${parts[0]}\", \"${parts[1]}\"),\n"; + } else { + output += " Locale(\"$key\", \"\"),\n"; + } }); output += part2;