Description
Hi to all,
on a my Flutter app I use the flutter i18n plugin for texts localizations, with two supported languages: Italian and English (the English is also the fallback language). This localizations until a few days ago worked properly, but after the upgrade of the i18n plugin to the latest version 0.1.1 it stopped working, and all the app's texts are now always displayed in English (the fallback language ) even if on my Android device the language is set to Italian ('it'), and before this upgrade the texts were correctly localized in Italian.
I did not change anything in the code, but I realized that now, if I call (for test) Localizations.localeOf (context), it always returns the 'en_' Locale, even if on the device I set the French language or Italian language, or any other language other than English.
This is clearly a mistake. I'm not sure, but I think this error came out after upgrading to version 0.1.1 of the flutter i18n plugin in my Android Studio (version 3.2.1) development environment.
Steps to Reproduce
This is the interestings code:
@override
Widget build(BuildContext context) {
Locale currentLocale = Localizations.localeOf(context);
String localizationLanguageCode = S.delegate.isSupported(currentLocale) ? currentLocale.languageCode : Config.defaultLanguageCode;
print('currentLocale is: ${currentLocale.toString()}, currentLocale.languageCode is: ${currentLocale.languageCode}, localizationLanguageCode is: $localizationLanguageCode');
return MaterialApp(
localizationsDelegates: [
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: S.delegate.supportedLocales,
localeResolutionCallback: S.delegate.resolution(fallback: new Locale('${Config.defaultLanguageCode}', '')),
home: Scaffold(
appBar: _makeAppBar(context),
body: FutureBuilder<List<Lesson>>(
future: fetchLessons(http.Client(), selectedCourse, localizationLanguageCode),
//future: listLessons,
builder: (context, snapshot) {
this.numBuild++;
print('number of build of LessonsRoute: ${this.numBuild}...');
if (snapshot.hasError) {
print('Snaphot has the following error: ${snapshot.error}');
return Center(
child: Text('Snaphot has the following error: ${snapshot.error}')
);
} else {
if (snapshot.hasData) {
if (snapshot.data != null && courses != null) {
return ListViewLessons(lessons: snapshot.data, courses: courses);
} else {
return Center(child: Text('snapshot.data is null or/and courses is null!'));
}
} else {
return Center(child: CircularProgressIndicator());
}
}
},
),
),
);
}
In the above code, the following test instructions:
Locale currentLocale = Localizations.localeOf(context);
String localizationLanguageCode = S.delegate.isSupported(currentLocale) ? currentLocale.languageCode : Config.defaultLanguageCode;
print('currentLocale is: ${currentLocale.toString()}, currentLocale.languageCode is: ${currentLocale.languageCode}, localizationLanguageCode is: $localizationLanguageCode');
Produces the following result:
`I/flutter ( 4432): currentLocale is: en_, currentLocale.languageCode is: en, localizationLanguageCode is: en
But, on my device (Samsung Galaxy S5 with Android 6.0.1) the language is set to Italian, not to English! See attached screenshots. Even with the ADVs emulators, I now have the same problem.
So, it seems that some internal i18n call to Localizations.localeOf (context) or similar, returns now a wrong result (always English Locale), which prevents localizations in other languages.
What happened? How can I make the localizations of texts on my app work again?
Also, referring to (flutter/flutter#24747) might help which probably explains what broke flutter_i18n?
Thanks in advance for the help you want to give me.
Flutter Doctor
[v] Flutter (Channel beta, v0.11.9, on Microsoft Windows [Versione 10.0.17134.407], locale it-IT)
• Flutter version 0.11.9 at c:\src\flutter
• Framework revision d48e6e433c (2 days ago), 2018-11-20 22:05:23 -0500
• Engine revision 5c8147450d
• Dart version 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297)
[v] Android toolchain - develop for Android devices (Android SDK 28.0.3)
• Android SDK at C:\Users\lucio\AppData\Local\Android\sdk
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-28, build-tools 28.0.3
• Java binary at: C:\Program Files\Android\Android Studio1\jre\bin\java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06)
• All Android licenses accepted.
[v] Android Studio (version 3.2)
• Android Studio at C:\Program Files\Android\Android Studio1
• Flutter plugin version 30.0.1
• Dart plugin version 181.5656
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06)
[v] Connected device (1 available)
• SM G900F • 5fe4af7d • android-arm • Android 6.0.1 (API 23)
• No issues found!
Activity
sandrokl commentedon Nov 29, 2018
Following... I have this problem too.
noordawod commentedon Dec 2, 2018
Check: flutter/flutter#24481
Did you upgrade to the latest Flutter and are you checking for
null
value in your locale resolve callback?It's also important to note that Flutter may call your callback a couple of times, one time when it starts and one time when the system locale has been resolved.
LucioD commentedon Dec 4, 2018
No, I again analyzed everything and done a bit 'of debugging.
In my case, the problem lies in the isSupported() method of the GeneratedLocalizationsDelegate class, which is automatically generated in the Android Studio IDE (and made unmodifiable in that environment) by the Flutter i18n plugin (https://plugins.jetbrains.com/plugin/10128-flutter-i18n).
This isSupported() method, which is called by the localResolutionCallback method, now returns false if the device locale contains both the languageCode and the countryCode (example 'it_IT') and the supportedLocales locale contains only the languageCode (example 'it'), whereas before the last upgrade, it returned true!
I believe that this is the reason why now the localization does not work anymore!
This is the GeneratedLocalizationsDelegate class, automatically generated in the Android Studio IDE by the Flutter i18n plugin (I have removed the methods that are not important for this explanation):
I think that in this class the isSupported() method should be changed like this:
So that it returns true not only when the supportedLocale matches both language and country code, but also when it matches only the language code. In fact, before the last upgrade, the GeneratedLocalizationsDelegate class worked like this!
But I CAN NOT make this change, because the GeneratedLocalizationsDelegate class, is automatically generated in the Android Studio IDE (and unchangeable in that environment) by the Flutter i18n plugin.
So, I believe that a new version of the Flutter i18N plugin, that includes this change, is needed.
What do you think of this?
noordawod commentedon Dec 5, 2018
@LucioD
I suppose you have your source ARB files named as
strings_it.arb
,strings_en.arb
, right?Here's a quick way how to fix the problem you're facing: name your ARB files to include the country as well, for example:
strings_it_IT.arb
What I would suggest to do instead is to allow the user to provide a comparator function that returns whether a locale is supported or not. It should be an easy pr.
LucioD commentedon Dec 6, 2018
@noordawod
strings_it.arb
andstrings_en.arb
.That is, the current isSupported () function of the plugin should be changed, with a function like this:
In order to restore the previous functionality that has failed with the last upgrade.
Then, giving the user the possibility to override this method with its own function, everything would be perfect!
It's right?
noordawod commentedon Dec 7, 2018
Yeah, I mostly agree with you. My proposition was for a quick fix, not a long term one.
I would reformat the suggested method like this:
The reason for dropping the first check (
contains()
) is because we're already looping through the locales so your implementation is actually doing double the work in worst-case scenario.If you send a pr, maybe the maintainer @long1eu can merge it in?
LucioD commentedon Dec 7, 2018
@noordawod
No please! The reformatted method you suggested causes exactly the same problem I've reported!
So, the new method according to your reformatting, must be like this:
Or like this, if you want to use my previous method without the first check (contains()...:
noordawod commentedon Dec 7, 2018
@LucioD
Ahh, I think you're right about which variable holds the country code. So in this case, the method becomes much simpler:
A PR is shortcut for Pull Request. Google it :)
LucioD commentedon Dec 10, 2018
Ok, your last method is correct and works perfectly!
Can you make it the default isSupported() method in the GeneratedLocalizationsDelegate class of the Flutter i18n plugin, and /or allow the user to override it by an appropriate new parameter in the MaterialApp() constructor?
Thanks in advance.
noordawod commentedon Dec 11, 2018
I can provide a pr to the maintainer, but I cannot merge the changes. Based on the maintainer's last engagement, I would say that it'll take few weeks for these changes to find their way into the code.
@long1eu feel free to give me
merge
privilege so I can help out with maintaining this plugin.LucioD commentedon Dec 11, 2018
Ok, I will wait for these changes.
Thanks for now.
long1eu commentedon Dec 14, 2018
@noordawod thanks. Let me know if the latest release solves this. https://github.com/long1eu/flutter_i18n/releases
19 remaining items