Issue
I'm using Flutter i18n plugin for Android Studio following the official documentation.
I added the few configuration line needed to a minimal app that displays a String:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [S.delegate],
supportedLocales: S.delegate.supportedLocales,
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text("Hard-coded English string"),
// ),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(S.of(context).string_that_should_be_internationalized),
],
),
),
);
}
}
This is working (the string is actually translated to my phone system language). But a warning is thrown at every call to build:
Warning: This application's locale, it_, is not supported by all of its
localization delegates.
> A MaterialLocalizations delegate that supports the it_ locale was not found.
Despite S.delegate.supportedLocales
being [en_, it_]
and all arb file being correctly configured.
I can make the Scaffold
body arbitrarily complicated and the behavior remains the same (i18n works with warning). But if I add a simple AppBar
(even if the widged does not require translation) to the Scaffold
the whole application crashes. (E.g. uncommenting in the snippet above)
Abstract of the error:
I/flutter (11411): No MaterialLocalizations found.
I/flutter (11411): AppBar widgets require MaterialLocalizations to be provided by a Localizations widget ancestor.
I/flutter (11411): Localizations are used to generate many different messages, labels,and abbreviations which are used
I/flutter (11411): by the material library.
I/flutter (11411): To introduce a MaterialLocalizations, either use a MaterialApp at the root of your application to
I/flutter (11411): include them automatically, or add a Localization widget with a MaterialLocalizations delegate.
I/flutter (11411): The specific widget that could not find a MaterialLocalizations ancestor was:
I/flutter (11411): AppBar
The framework is complaining about my AppBar
not having a Localizations widget ancestor. But it actually have because it's inside a MaterialApp
. No clue on how to solve this mystery.
EDIT
Another weird thing i just discovered: running the same exact app in --release
mode gets rid of all the errors and warnings; everything is correctly translated including the AppBar
.
Still wondering why it crashes in --debug
mode.
Solution
The problem is not about the boilerplate code or configuration.
The meaning of the error is that there is no support for the language "it_" for the "default system strings". (In particular it crashes due to some default tooltip of the AppBar -> that's why it is crashing if an AppBar
is displayed).
As reported in this Q&A you can solve the issue by implementing your own LocalizationsDelegate
.
Full fix
class MaterialLocalizationItDelegate extends LocalizationsDelegate<MaterialLocalizations> {
/// Here list supported country and language codes
@override
bool isSupported(Locale locale) => locale.languageCode == "it";
/// Here create an instance of your [MaterialLocalizations] subclass
@override
Future<MaterialLocalizations> load(Locale locale) async => MaterialLocalizationIt();
@override
bool shouldReload(_) => false;
}
class MaterialLocalizationIt extends MaterialLocalizations {
// alt-enter on intellij and implement many overrides (somthing like 57)
}
And then append your delegate to the list of delegates:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [S.delegate, MaterialLocalizationItDelegate()], // <- append here
supportedLocales: S.delegate.supportedLocales,
home: MyHomePage(),
);
}
}
Quick fix
An hasty way to check if this will work for you before implementing the 57 overrides.
Copy exactly this code:
class FallbackLocalizationDelegate extends LocalizationsDelegate<MaterialLocalizations> {
@override
bool isSupported(Locale locale) => true;
@override
Future<MaterialLocalizations> load(Locale locale) async => DefaultMaterialLocalizations();
@override
bool shouldReload(_) => false;
}
The above class claim to support all locales (isSupported(Locale locale) => true
) and simply returns the default en_US locale.
Finally add this to your list of delegates.
localizationsDelegates: [S.delegate, FallbackLocalizationDelegate()], // <- append here
This quick fix will set all the default system strings to English, but your "custom" localization should work.
Answered By - Pado
Answer Checked By - Timothy Miller (JavaFixing Admin)