Language-specific LocalizationDelegates (#12645)
This commit is contained in:
parent
a554401e79
commit
796c5439f6
@ -26,6 +26,9 @@ class _StocksLocalizationsDelegate extends LocalizationsDelegate<StockStrings> {
|
||||
@override
|
||||
Future<StockStrings> load(Locale locale) => StockStrings.load(locale);
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => locale.languageCode == 'es' || locale.languageCode == 'en';
|
||||
|
||||
@override
|
||||
bool shouldReload(_StocksLocalizationsDelegate old) => false;
|
||||
}
|
||||
|
@ -187,6 +187,9 @@ abstract class MaterialLocalizations {
|
||||
class _MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
|
||||
const _MaterialLocalizationsDelegate();
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => locale.languageCode == 'en';
|
||||
|
||||
@override
|
||||
Future<MaterialLocalizations> load(Locale locale) => DefaultMaterialLocalizations.load(locale);
|
||||
|
||||
|
@ -42,11 +42,12 @@ Future<Map<Type, dynamic>> _loadAll(Locale locale, Iterable<LocalizationsDelegat
|
||||
final Map<Type, dynamic> output = <Type, dynamic>{};
|
||||
List<_Pending> pendingList;
|
||||
|
||||
// Only load the first delegate for each delgate type.
|
||||
// Only load the first delegate for each delegate type that supports
|
||||
// locale.languageCode.
|
||||
final Set<Type> types = new Set<Type>();
|
||||
final List<LocalizationsDelegate<dynamic>> delegates = <LocalizationsDelegate<dynamic>>[];
|
||||
for (LocalizationsDelegate<dynamic> delegate in allDelegates) {
|
||||
if (!types.contains(delegate.type)) {
|
||||
if (!types.contains(delegate.type) && delegate.isSupported(locale)) {
|
||||
types.add(delegate.type);
|
||||
delegates.add(delegate);
|
||||
}
|
||||
@ -97,6 +98,12 @@ abstract class LocalizationsDelegate<T> {
|
||||
/// const constructors so that they can be used in const expressions.
|
||||
const LocalizationsDelegate();
|
||||
|
||||
/// Whether resources for the given locale can be loaded by this delegate.
|
||||
///
|
||||
/// Return true if the instance of `T` loaded by this delegate's [load]
|
||||
/// method supports the given `locale`'s language.
|
||||
bool isSupported(Locale locale);
|
||||
|
||||
/// Start loading the resources for `locale`. The returned future completes
|
||||
/// when the resources have finished loading.
|
||||
///
|
||||
@ -164,6 +171,11 @@ abstract class WidgetsLocalizations {
|
||||
class _WidgetsLocalizationsDelegate extends LocalizationsDelegate<WidgetsLocalizations> {
|
||||
const _WidgetsLocalizationsDelegate();
|
||||
|
||||
// This is convenient simplification. It would be more correct test if the locale's
|
||||
// text-direction is LTR.
|
||||
@override
|
||||
bool isSupported(Locale locale) => true;
|
||||
|
||||
@override
|
||||
Future<WidgetsLocalizations> load(Locale locale) => DefaultWidgetsLocalizations.load(locale);
|
||||
|
||||
|
@ -28,6 +28,9 @@ class MockClipboard {
|
||||
}
|
||||
|
||||
class MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
|
||||
@override
|
||||
bool isSupported(Locale locale) => true;
|
||||
|
||||
@override
|
||||
Future<MaterialLocalizations> load(Locale locale) => DefaultMaterialLocalizations.load(locale);
|
||||
|
||||
@ -36,6 +39,9 @@ class MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocali
|
||||
}
|
||||
|
||||
class WidgetsLocalizationsDelegate extends LocalizationsDelegate<WidgetsLocalizations> {
|
||||
@override
|
||||
bool isSupported(Locale locale) => true;
|
||||
|
||||
@override
|
||||
Future<WidgetsLocalizations> load(Locale locale) => DefaultWidgetsLocalizations.load(locale);
|
||||
|
||||
|
@ -423,6 +423,27 @@ void _loadDateIntlDataIfNotLoaded() {
|
||||
class _MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
|
||||
const _MaterialLocalizationsDelegate();
|
||||
|
||||
static const List<String> _supportedLanguages = const <String>[
|
||||
'ar', // Arabic
|
||||
'de', // German
|
||||
'en', // English
|
||||
'es', // Spanish
|
||||
'fa', // Farsi
|
||||
'fr', // French
|
||||
'he', // Hebrew
|
||||
'it', // Italian
|
||||
'ja', // Japanese
|
||||
'ps', // Pashto
|
||||
'pt', // Portugese
|
||||
'ru', // Russian
|
||||
'sd', // Sindhi
|
||||
'ur', // Urdu
|
||||
'zh', // Simplified Chinese
|
||||
];
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => _supportedLanguages.contains(locale.languageCode);
|
||||
|
||||
@override
|
||||
Future<MaterialLocalizations> load(Locale locale) => GlobalMaterialLocalizations.load(locale);
|
||||
|
||||
|
@ -67,6 +67,9 @@ class GlobalWidgetsLocalizations implements WidgetsLocalizations {
|
||||
class _WidgetsLocalizationsDelegate extends LocalizationsDelegate<WidgetsLocalizations> {
|
||||
const _WidgetsLocalizationsDelegate();
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => true;
|
||||
|
||||
@override
|
||||
Future<WidgetsLocalizations> load(Locale locale) => GlobalWidgetsLocalizations.load(locale);
|
||||
|
||||
|
@ -55,6 +55,9 @@ class _DummyLocalizationsDelegate extends LocalizationsDelegate<DummyLocalizatio
|
||||
@override
|
||||
Future<DummyLocalizations> load(Locale locale) async => new DummyLocalizations();
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => true;
|
||||
|
||||
@override
|
||||
bool shouldReload(_DummyLocalizationsDelegate old) => true;
|
||||
}
|
||||
|
@ -8,18 +8,29 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
class FooMaterialLocalizations extends GlobalMaterialLocalizations {
|
||||
FooMaterialLocalizations(Locale locale) : super(locale);
|
||||
FooMaterialLocalizations(Locale locale, this.backButtonTooltip) : super(locale);
|
||||
|
||||
@override
|
||||
String get backButtonTooltip => 'foo';
|
||||
final String backButtonTooltip;
|
||||
}
|
||||
|
||||
class FooMaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
|
||||
const FooMaterialLocalizationsDelegate();
|
||||
const FooMaterialLocalizationsDelegate({
|
||||
this.supportedLanguage: 'en',
|
||||
this.backButtonTooltip: 'foo'
|
||||
});
|
||||
|
||||
final String supportedLanguage;
|
||||
final String backButtonTooltip;
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) {
|
||||
return supportedLanguage == 'allLanguages' ? true : locale.languageCode == supportedLanguage;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<FooMaterialLocalizations> load(Locale locale) {
|
||||
return new SynchronousFuture<FooMaterialLocalizations>(new FooMaterialLocalizations(locale));
|
||||
return new SynchronousFuture<FooMaterialLocalizations>(new FooMaterialLocalizations(locale, backButtonTooltip));
|
||||
}
|
||||
|
||||
@override
|
||||
@ -143,7 +154,42 @@ void main() {
|
||||
expect(find.text('Back'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('MaterialApp overrides MaterialLocalizations', (WidgetTester tester) async {
|
||||
testWidgets('MaterialApp adds MaterialLocalizations for additional languages', (WidgetTester tester) async {
|
||||
final Key textKey = new UniqueKey();
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildFrame(
|
||||
delegates: <FooMaterialLocalizationsDelegate>[
|
||||
const FooMaterialLocalizationsDelegate(supportedLanguage: 'fr', backButtonTooltip: 'FR'),
|
||||
const FooMaterialLocalizationsDelegate(supportedLanguage: 'de', backButtonTooltip: 'DE'),
|
||||
],
|
||||
supportedLocales: const <Locale>[
|
||||
const Locale('en', ''),
|
||||
const Locale('fr', ''),
|
||||
const Locale('de', ''),
|
||||
],
|
||||
buildContent: (BuildContext context) {
|
||||
// Should always be 'foo', no matter what the locale is
|
||||
return new Text(
|
||||
MaterialLocalizations.of(context).backButtonTooltip,
|
||||
key: textKey,
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
expect(tester.widget<Text>(find.byKey(textKey)).data, 'Back');
|
||||
|
||||
await tester.binding.setLocale('fr', 'CA');
|
||||
await tester.pump();
|
||||
expect(find.text('FR'), findsOneWidget);
|
||||
|
||||
await tester.binding.setLocale('de', 'DE');
|
||||
await tester.pump();
|
||||
expect(find.text('DE'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('MaterialApp overrides MaterialLocalizations for all locales', (WidgetTester tester) async {
|
||||
final Key textKey = new UniqueKey();
|
||||
|
||||
await tester.pumpWidget(
|
||||
@ -151,7 +197,7 @@ void main() {
|
||||
// Accept whatever locale we're given
|
||||
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) => locale,
|
||||
delegates: <FooMaterialLocalizationsDelegate>[
|
||||
const FooMaterialLocalizationsDelegate(),
|
||||
const FooMaterialLocalizationsDelegate(supportedLanguage: 'allLanguages'),
|
||||
],
|
||||
buildContent: (BuildContext context) {
|
||||
// Should always be 'foo', no matter what the locale is
|
||||
@ -174,6 +220,38 @@ void main() {
|
||||
expect(find.text('foo'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('MaterialApp overrides MaterialLocalizations for default locale', (WidgetTester tester) async {
|
||||
final Key textKey = new UniqueKey();
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildFrame(
|
||||
delegates: <FooMaterialLocalizationsDelegate>[
|
||||
const FooMaterialLocalizationsDelegate(supportedLanguage: 'en'),
|
||||
],
|
||||
// supportedLocales not specified, so all locales resolve to 'en'
|
||||
buildContent: (BuildContext context) {
|
||||
return new Text(
|
||||
MaterialLocalizations.of(context).backButtonTooltip,
|
||||
key: textKey,
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Unsupported locale '_' (the widget tester's default) resolves to 'en'.
|
||||
expect(tester.widget<Text>(find.byKey(textKey)).data, 'foo');
|
||||
|
||||
// Unsupported locale 'zh' resolves to 'en'.
|
||||
await tester.binding.setLocale('zh', 'CN');
|
||||
await tester.pump();
|
||||
expect(find.text('foo'), findsOneWidget);
|
||||
|
||||
// Unsupported locale 'de' resolves to 'en'.
|
||||
await tester.binding.setLocale('de', 'DE');
|
||||
await tester.pump();
|
||||
expect(find.text('foo'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('deprecated Android/Java locales are modernized', (WidgetTester tester) async {
|
||||
final Key textKey = new UniqueKey();
|
||||
|
||||
|
@ -35,6 +35,9 @@ class SyncTestLocalizationsDelegate extends LocalizationsDelegate<TestLocalizati
|
||||
final String prefix; // Changing this value triggers a rebuild
|
||||
final List<bool> shouldReloadValues = <bool>[];
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => true;
|
||||
|
||||
@override
|
||||
Future<TestLocalizations> load(Locale locale) => TestLocalizations.loadSync(locale, prefix);
|
||||
|
||||
@ -54,6 +57,9 @@ class AsyncTestLocalizationsDelegate extends LocalizationsDelegate<TestLocalizat
|
||||
final String prefix; // Changing this value triggers a rebuild
|
||||
final List<bool> shouldReloadValues = <bool>[];
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => true;
|
||||
|
||||
@override
|
||||
Future<TestLocalizations> load(Locale locale) => TestLocalizations.loadAsync(locale, prefix);
|
||||
|
||||
@ -92,6 +98,9 @@ class SyncMoreLocalizationsDelegate extends LocalizationsDelegate<MoreLocalizati
|
||||
@override
|
||||
Future<MoreLocalizations> load(Locale locale) => MoreLocalizations.loadSync(locale);
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => true;
|
||||
|
||||
@override
|
||||
bool shouldReload(SyncMoreLocalizationsDelegate old) => false;
|
||||
}
|
||||
@ -100,6 +109,9 @@ class AsyncMoreLocalizationsDelegate extends LocalizationsDelegate<MoreLocalizat
|
||||
@override
|
||||
Future<MoreLocalizations> load(Locale locale) => MoreLocalizations.loadAsync(locale);
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => true;
|
||||
|
||||
@override
|
||||
bool shouldReload(AsyncMoreLocalizationsDelegate old) => false;
|
||||
}
|
||||
@ -112,6 +124,9 @@ class OnlyRTLDefaultWidgetsLocalizations extends DefaultWidgetsLocalizations {
|
||||
class OnlyRTLDefaultWidgetsLocalizationsDelegate extends LocalizationsDelegate<WidgetsLocalizations> {
|
||||
const OnlyRTLDefaultWidgetsLocalizationsDelegate();
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => true;
|
||||
|
||||
@override
|
||||
Future<WidgetsLocalizations> load(Locale locale) {
|
||||
return new SynchronousFuture<WidgetsLocalizations>(new OnlyRTLDefaultWidgetsLocalizations());
|
||||
|
Loading…
x
Reference in New Issue
Block a user