diff --git a/packages/flutter_tools/lib/src/build_system/targets/localizations.dart b/packages/flutter_tools/lib/src/build_system/targets/localizations.dart index 40c1f9a8cb5..e173709a84a 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/localizations.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/localizations.dart @@ -56,7 +56,7 @@ void generateLocalizations({ templateArbFileName: templateArbFileName, outputFileString: outputFileString, classNameString: options.outputClass ?? 'AppLocalizations', - preferredSupportedLocaleString: options.preferredSupportedLocales, + preferredSupportedLocale: options.preferredSupportedLocales, headerString: options.header, headerFile: options?.headerFile?.toFilePath(), useDeferredLoading: options.deferredLoading ?? false, @@ -193,7 +193,7 @@ class LocalizationOptions { final String outputClass; /// The `--preferred-supported-locales` argument. - final String preferredSupportedLocales; + final List preferredSupportedLocales; /// The `--header-file` argument. /// @@ -240,7 +240,7 @@ LocalizationOptions parseLocalizationsOptions({ untranslatedMessagesFile: _tryReadUri(yamlMap, 'untranslated-messages-file', logger), header: _tryReadString(yamlMap, 'header', logger), outputClass: _tryReadString(yamlMap, 'output-class', logger), - preferredSupportedLocales: _tryReadString(yamlMap, 'preferred-supported-locales', logger), + preferredSupportedLocales: _tryReadStringList(yamlMap, 'preferred-supported-locales', logger), headerFile: _tryReadUri(yamlMap, 'header-file', logger), deferredLoading: _tryReadBool(yamlMap, 'use-deferred-loading', logger), useSyntheticPackage: _tryReadBool(yamlMap, 'synthetic-package', logger) ?? true, @@ -273,6 +273,21 @@ String _tryReadString(YamlMap yamlMap, String key, Logger logger) { return value as String; } +List _tryReadStringList(YamlMap yamlMap, String key, Logger logger) { + final Object value = yamlMap[key]; + if (value == null) { + return null; + } + if (value is String) { + return [value]; + } + if (value is Iterable) { + return value.map((dynamic e) => e.toString()).toList(); + } + logger.printError('"$value" must be String or List.'); + throw Exception(); +} + // Try to read a valid `Uri` or null from `yamlMap`, otherwise throw. Uri _tryReadUri(YamlMap yamlMap, String key, Logger logger) { final String value = _tryReadString(yamlMap, key, logger); diff --git a/packages/flutter_tools/lib/src/commands/generate_localizations.dart b/packages/flutter_tools/lib/src/commands/generate_localizations.dart index 73d7a451c9d..8224e766641 100644 --- a/packages/flutter_tools/lib/src/commands/generate_localizations.dart +++ b/packages/flutter_tools/lib/src/commands/generate_localizations.dart @@ -65,14 +65,16 @@ class GenerateLocalizationsCommand extends FlutterCommand { help: 'The Dart class name to use for the output localization and ' 'localizations delegate classes.', ); - argParser.addOption( + argParser.addMultiOption( 'preferred-supported-locales', + valueHelp: 'locale', help: 'The list of preferred supported locales for the application. ' 'By default, the tool will generate the supported locales list in ' 'alphabetical order. Use this flag if you would like to default to ' 'a different locale. \n\n' - "For example, pass in ['en_US'] if you would like your app to " - 'default to American English if a device supports it.', + 'For example, pass in `en_US` if you would like your app to ' + 'default to American English if a device supports it.' + '(Pass this option multiple times for defining multiple items', ); argParser.addOption( 'header', @@ -169,7 +171,7 @@ class GenerateLocalizationsCommand extends FlutterCommand { final String templateArbFileName = stringArg('template-arb-file'); final String untranslatedMessagesFile = stringArg('untranslated-messages-file'); final String classNameString = stringArg('output-class'); - final String preferredSupportedLocaleString = stringArg('preferred-supported-locales'); + final List preferredSupportedLocale = stringsArg('preferred-supported-locales'); final String headerString = stringArg('header'); final String headerFile = stringArg('header-file'); final bool useDeferredLoading = boolArg('use-deferred-loading'); @@ -187,7 +189,7 @@ class GenerateLocalizationsCommand extends FlutterCommand { templateArbFileName: templateArbFileName, outputFileString: outputFileString, classNameString: classNameString, - preferredSupportedLocaleString: preferredSupportedLocaleString, + preferredSupportedLocale: preferredSupportedLocale, headerString: headerString, headerFile: headerFile, useDeferredLoading: useDeferredLoading, diff --git a/packages/flutter_tools/lib/src/localizations/gen_l10n.dart b/packages/flutter_tools/lib/src/localizations/gen_l10n.dart index 6a36bb42448..a961b161dfd 100644 --- a/packages/flutter_tools/lib/src/localizations/gen_l10n.dart +++ b/packages/flutter_tools/lib/src/localizations/gen_l10n.dart @@ -530,7 +530,7 @@ class LocalizationsGenerator { String templateArbFileName, String outputFileString, String classNameString, - String preferredSupportedLocaleString, + List preferredSupportedLocale, String headerString, String headerFile, bool useDeferredLoading = false, @@ -546,7 +546,7 @@ class LocalizationsGenerator { ); setTemplateArbFile(templateArbFileName); setBaseOutputFile(outputFileString); - setPreferredSupportedLocales(preferredSupportedLocaleString); + setPreferredSupportedLocales(preferredSupportedLocale); _setHeader(headerString, headerFile); _setUseDeferredLoading(useDeferredLoading); className = classNameString; @@ -707,18 +707,12 @@ class LocalizationsGenerator { /// Sets [preferredSupportedLocales] so that this particular list of locales /// will take priority over the other locales. @visibleForTesting - void setPreferredSupportedLocales(String inputLocales) { - if (inputLocales == null || inputLocales.trim().isEmpty) { + void setPreferredSupportedLocales(List inputLocales) { + if (inputLocales == null || inputLocales.isEmpty) { _preferredSupportedLocales = const []; } else { - final List preferredLocalesStringList = json.decode(inputLocales) as List; - _preferredSupportedLocales = preferredLocalesStringList.map((dynamic localeString) { - if (localeString.runtimeType != String) { - throw L10nException('Incorrect runtime type for $localeString'); - } - return LocaleInfo.fromString( - localeString.toString(), - ); + _preferredSupportedLocales = inputLocales.map((String localeString) { + return LocaleInfo.fromString(localeString); }).toList(); } } diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/localizations_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/localizations_test.dart index 1381246ca33..e068ee76410 100644 --- a/packages/flutter_tools/test/general.shard/build_system/targets/localizations_test.dart +++ b/packages/flutter_tools/test/general.shard/build_system/targets/localizations_test.dart @@ -35,7 +35,7 @@ void main() { deferredLoading: true, outputClass: 'Foo', outputLocalizationsFile: Uri.file('bar'), - preferredSupportedLocales: 'en_US', + preferredSupportedLocales: ['en_US'], templateArbFile: Uri.file('example.arb'), untranslatedMessagesFile: Uri.file('untranslated'), useSyntheticPackage: false, @@ -57,7 +57,7 @@ void main() { templateArbFileName: 'example.arb', outputFileString: 'bar', classNameString: 'Foo', - preferredSupportedLocaleString: 'en_US', + preferredSupportedLocale: ['en_US'], headerString: 'HEADER', headerFile: 'header', useDeferredLoading: true, @@ -92,7 +92,7 @@ flutter: deferredLoading: true, outputClass: 'Foo', outputLocalizationsFile: Uri.file('bar'), - preferredSupportedLocales: 'en_US', + preferredSupportedLocales: ['en_US'], templateArbFile: Uri.file('example.arb'), untranslatedMessagesFile: Uri.file('untranslated'), // Set synthetic package to true. @@ -161,13 +161,28 @@ preferred-supported-locales: en_US expect(options.headerFile, Uri.parse('header')); expect(options.header, 'HEADER'); expect(options.deferredLoading, true); - expect(options.preferredSupportedLocales, 'en_US'); + expect(options.preferredSupportedLocales, ['en_US']); }); - testWithoutContext('parseLocalizationsOptions throws exception on invalid yaml configuration', () async { + testWithoutContext('parseLocalizationsOptions handles preferredSupportedLocales as list', () async { final FileSystem fileSystem = MemoryFileSystem.test(); - final File configFile = fileSystem.file('l10n.yaml') - ..writeAsStringSync(''' + final File configFile = fileSystem.file('l10n.yaml')..writeAsStringSync(''' +preferred-supported-locales: ['en_US', 'de'] +'''); + + final LocalizationOptions options = parseLocalizationsOptions( + file: configFile, + logger: BufferLogger.test(), + ); + + expect(options.preferredSupportedLocales, ['en_US', 'de']); + }); + + testWithoutContext( + 'parseLocalizationsOptions throws exception on invalid yaml configuration', + () async { + final FileSystem fileSystem = MemoryFileSystem.test(); + final File configFile = fileSystem.file('l10n.yaml')..writeAsStringSync(''' use-deferred-loading: string '''); diff --git a/packages/flutter_tools/test/general.shard/generate_localizations_test.dart b/packages/flutter_tools/test/general.shard/generate_localizations_test.dart index c19f852b0fe..125b45852c3 100644 --- a/packages/flutter_tools/test/general.shard/generate_localizations_test.dart +++ b/packages/flutter_tools/test/general.shard/generate_localizations_test.dart @@ -793,7 +793,7 @@ void main() { l10nDirectory.childFile('app_zh.arb') .writeAsStringSync(singleZhMessageArbFileString); - const String preferredSupportedLocaleString = '["zh", "es"]'; + const List preferredSupportedLocale = ['zh', 'es']; LocalizationsGenerator generator; try { generator = LocalizationsGenerator(fs); @@ -803,7 +803,7 @@ void main() { templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString, classNameString: defaultClassNameString, - preferredSupportedLocaleString: preferredSupportedLocaleString, + preferredSupportedLocale: preferredSupportedLocale, ); generator.loadResources(); } on L10nException catch (e) { @@ -815,47 +815,6 @@ void main() { expect(generator.supportedLocales.elementAt(2), LocaleInfo.fromString('en')); }); - test( - 'throws an error attempting to add preferred locales ' - 'with incorrect runtime type', - () { - final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n') - ..createSync(recursive: true); - l10nDirectory.childFile('app_en.arb') - .writeAsStringSync(singleMessageArbFileString); - l10nDirectory.childFile('app_es.arb') - .writeAsStringSync(singleEsMessageArbFileString); - l10nDirectory.childFile('app_zh.arb') - .writeAsStringSync(singleZhMessageArbFileString); - - const String preferredSupportedLocaleString = '[44, "en"]'; - LocalizationsGenerator generator; - try { - generator = LocalizationsGenerator(fs); - generator.initialize( - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - preferredSupportedLocaleString: preferredSupportedLocaleString, - ); - generator.loadResources(); - } on L10nException catch (e) { - expect( - e.message, - contains('Incorrect runtime type'), - ); - return; - } - - fail( - 'Should fail since an incorrect runtime type was used ' - 'in the preferredSupportedLocales list.' - ); - }, - ); - test( 'throws an error attempting to add preferred locales ' 'when there is no corresponding arb file for that ' @@ -870,7 +829,7 @@ void main() { l10nDirectory.childFile('app_zh.arb') .writeAsStringSync(singleZhMessageArbFileString); - const String preferredSupportedLocaleString = '["am", "es"]'; + const List preferredSupportedLocale = ['am', 'es']; LocalizationsGenerator generator; try { generator = LocalizationsGenerator(fs); @@ -880,7 +839,7 @@ void main() { templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString, classNameString: defaultClassNameString, - preferredSupportedLocaleString: preferredSupportedLocaleString, + preferredSupportedLocale: preferredSupportedLocale, ); generator.loadResources(); } on L10nException catch (e) { @@ -1152,7 +1111,7 @@ void main() { ..childFile('app_zh.arb').writeAsStringSync(singleZhMessageArbFileString) ..childFile('app_es.arb').writeAsStringSync(singleEsMessageArbFileString); - const String preferredSupportedLocaleString = '["zh"]'; + const List preferredSupportedLocale = ['zh']; final LocalizationsGenerator generator = LocalizationsGenerator(fs); try { generator.initialize( @@ -1161,7 +1120,7 @@ void main() { templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString, classNameString: defaultClassNameString, - preferredSupportedLocaleString: preferredSupportedLocaleString, + preferredSupportedLocale: preferredSupportedLocale, ); generator.loadResources(); generator.writeOutputFiles();