Unverified Commit 173322dc authored by Shi-Hao Hong's avatar Shi-Hao Hong Committed by GitHub

Support preferred locales for gen_l10n (#47845)

* Add preferred-supported-locales option to gen_l10n.dart executable
parent 659dc812
...@@ -46,6 +46,15 @@ Future<void> main(List<String> arguments) async { ...@@ -46,6 +46,15 @@ Future<void> main(List<String> arguments) async {
help: 'The Dart class name to use for the output localization and ' help: 'The Dart class name to use for the output localization and '
'localizations delegate classes.', 'localizations delegate classes.',
); );
parser.addOption(
'preferred-supported-locales',
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.',
);
final argslib.ArgResults results = parser.parse(arguments); final argslib.ArgResults results = parser.parse(arguments);
if (results['help'] == true) { if (results['help'] == true) {
...@@ -57,6 +66,7 @@ Future<void> main(List<String> arguments) async { ...@@ -57,6 +66,7 @@ Future<void> main(List<String> arguments) async {
final String outputFileString = results['output-localization-file'] as String; final String outputFileString = results['output-localization-file'] as String;
final String templateArbFileName = results['template-arb-file'] as String; final String templateArbFileName = results['template-arb-file'] as String;
final String classNameString = results['output-class'] as String; final String classNameString = results['output-class'] as String;
final String preferredSupportedLocaleString = results['preferred-supported-locales'] as String;
const local.LocalFileSystem fs = local.LocalFileSystem(); const local.LocalFileSystem fs = local.LocalFileSystem();
final LocalizationsGenerator localizationsGenerator = LocalizationsGenerator(fs); final LocalizationsGenerator localizationsGenerator = LocalizationsGenerator(fs);
...@@ -67,6 +77,7 @@ Future<void> main(List<String> arguments) async { ...@@ -67,6 +77,7 @@ Future<void> main(List<String> arguments) async {
templateArbFileName: templateArbFileName, templateArbFileName: templateArbFileName,
outputFileString: outputFileString, outputFileString: outputFileString,
classNameString: classNameString, classNameString: classNameString,
preferredSupportedLocaleString: preferredSupportedLocaleString,
) )
..parseArbFiles() ..parseArbFiles()
..generateClassMethods() ..generateClassMethods()
......
...@@ -534,8 +534,21 @@ class LocalizationsGenerator { ...@@ -534,8 +534,21 @@ class LocalizationsGenerator {
/// The class name is specified with the [initialize] method. /// The class name is specified with the [initialize] method.
String get className => _className; String get className => _className;
String _className; String _className;
/// Sets the [className] for the localizations and localizations delegate
/// classes. /// The list of preferred supported locales.
///
/// By default, the list of supported locales in the localizations class
/// will be sorted in alphabetical order. However, this option
/// allows for a set of preferred locales to appear at the top of the
/// list.
///
/// The order of locales in this list will also be the order of locale
/// priority. For example, if a device supports 'en' and 'es' and
/// ['es', 'en'] is passed in, the 'es' locale will take priority over 'en'.
///
/// The list of preferred locales is specified with the [initialize] method.
List<LocaleInfo> get preferredSupportedLocales => _preferredSupportedLocales;
List<LocaleInfo> _preferredSupportedLocales;
/// The list of all arb path strings in [l10nDirectory]. /// The list of all arb path strings in [l10nDirectory].
final List<String> arbPathStrings = <String>[]; final List<String> arbPathStrings = <String>[];
...@@ -564,10 +577,12 @@ class LocalizationsGenerator { ...@@ -564,10 +577,12 @@ class LocalizationsGenerator {
String templateArbFileName, String templateArbFileName,
String outputFileString, String outputFileString,
String classNameString, String classNameString,
String preferredSupportedLocaleString,
}) { }) {
setL10nDirectory(l10nDirectoryPath); setL10nDirectory(l10nDirectoryPath);
setTemplateArbFile(templateArbFileName); setTemplateArbFile(templateArbFileName);
setOutputFile(outputFileString); setOutputFile(outputFileString);
setPreferredSupportedLocales(preferredSupportedLocaleString);
className = classNameString; className = classNameString;
} }
...@@ -616,6 +631,8 @@ class LocalizationsGenerator { ...@@ -616,6 +631,8 @@ class LocalizationsGenerator {
outputFile = _fs.file(path.join(l10nDirectory.path, outputFileString)); outputFile = _fs.file(path.join(l10nDirectory.path, outputFileString));
} }
/// Sets the [className] for the localizations and localizations delegate
/// classes.
@visibleForTesting @visibleForTesting
set className(String classNameString) { set className(String classNameString) {
if (classNameString == null) if (classNameString == null)
...@@ -627,6 +644,21 @@ class LocalizationsGenerator { ...@@ -627,6 +644,21 @@ class LocalizationsGenerator {
_className = classNameString; _className = classNameString;
} }
/// Sets [preferredSupportedLocales] so that this particular list of locales
/// will take priority over the other locales.
@visibleForTesting
void setPreferredSupportedLocales(String inputLocales) {
if (inputLocales != null) {
final List<dynamic> preferredLocalesStringList = json.decode(inputLocales) as List<dynamic>;
_preferredSupportedLocales = preferredLocalesStringList.map((dynamic localeString) {
if (localeString.runtimeType != String) {
throw L10nException('Incorrect runtime type for $localeString');
}
return LocaleInfo.fromString(localeString.toString());
}).toList();
}
}
/// Scans [l10nDirectory] for arb files and parses them for language and locale /// Scans [l10nDirectory] for arb files and parses them for language and locale
/// information. /// information.
void parseArbFiles() { void parseArbFiles() {
...@@ -668,10 +700,27 @@ class LocalizationsGenerator { ...@@ -668,10 +700,27 @@ class LocalizationsGenerator {
arbPathStrings.sort(); arbPathStrings.sort();
localeInfoList.sort(); localeInfoList.sort();
supportedLocales.addAll(localeInfoList);
supportedLanguageCodes.addAll(localeInfoList.map((LocaleInfo localeInfo) { supportedLanguageCodes.addAll(localeInfoList.map((LocaleInfo localeInfo) {
return '\'${localeInfo.languageCode}\''; return '\'${localeInfo.languageCode}\'';
})); }));
if (preferredSupportedLocales != null) {
for (LocaleInfo preferredLocale in preferredSupportedLocales) {
if (!localeInfoList.contains(preferredLocale)) {
throw L10nException(
'The preferred supported locale, \'$preferredLocale\', cannot be '
'added. Please make sure that there is a corresponding arb file '
'with translations for the locale, or remove the locale from the '
'preferred supported locale list if there is no intent to support '
'it.'
);
}
localeInfoList.removeWhere((LocaleInfo localeInfo) => localeInfo == preferredLocale);
}
localeInfoList.insertAll(0, preferredSupportedLocales);
}
supportedLocales.addAll(localeInfoList);
} }
/// Generates the methods for the localizations class. /// Generates the methods for the localizations class.
......
...@@ -294,6 +294,118 @@ void main() { ...@@ -294,6 +294,118 @@ void main() {
expect(generator.supportedLocales.elementAt(2), LocaleInfo.fromString('zh')); expect(generator.supportedLocales.elementAt(2), LocaleInfo.fromString('zh'));
}); });
test('adds preferred locales to the top of supportedLocales and supportedLanguageCodes', () {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile('app_en_US.arb')
.writeAsStringSync(singleMessageArbFileString);
l10nDirectory.childFile('app_es.arb')
.writeAsStringSync(singleEsMessageArbFileString);
l10nDirectory.childFile('app_zh.arb')
.writeAsStringSync(singleZhMessageArbFileString);
const String preferredSupportedLocaleString = '["zh", "es"]';
LocalizationsGenerator generator;
try {
generator = LocalizationsGenerator(fs);
generator.initialize(
l10nDirectoryPath: defaultArbPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
preferredSupportedLocaleString: preferredSupportedLocaleString,
);
generator.parseArbFiles();
} on L10nException catch (e) {
fail('Setting language and locales should not fail: \n$e');
}
expect(generator.supportedLocales.first, LocaleInfo.fromString('zh'));
expect(generator.supportedLocales.elementAt(1), LocaleInfo.fromString('es'));
expect(generator.supportedLocales.elementAt(2), LocaleInfo.fromString('en_US'));
});
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_US.arb')
.writeAsStringSync(singleMessageArbFileString);
l10nDirectory.childFile('app_es.arb')
.writeAsStringSync(singleEsMessageArbFileString);
l10nDirectory.childFile('app_zh.arb')
.writeAsStringSync(singleZhMessageArbFileString);
const String preferredSupportedLocaleString = '[44, "en_US"]';
LocalizationsGenerator generator;
try {
generator = LocalizationsGenerator(fs);
generator.initialize(
l10nDirectoryPath: defaultArbPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
preferredSupportedLocaleString: preferredSupportedLocaleString,
);
generator.parseArbFiles();
} 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 '
'locale',
() {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile('app_en_US.arb')
.writeAsStringSync(singleMessageArbFileString);
l10nDirectory.childFile('app_es.arb')
.writeAsStringSync(singleEsMessageArbFileString);
l10nDirectory.childFile('app_zh.arb')
.writeAsStringSync(singleZhMessageArbFileString);
const String preferredSupportedLocaleString = '["am", "es"]';
LocalizationsGenerator generator;
try {
generator = LocalizationsGenerator(fs);
generator.initialize(
l10nDirectoryPath: defaultArbPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
preferredSupportedLocaleString: preferredSupportedLocaleString,
);
generator.parseArbFiles();
} on L10nException catch (e) {
expect(
e.message,
contains("The preferred supported locale, 'am', cannot be added."),
);
return;
}
fail(
'Should fail since an unsupported locale was added '
'to the preferredSupportedLocales list.'
);
},
);
test('correctly sorts arbPathString alphabetically', () { test('correctly sorts arbPathString alphabetically', () {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n') final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true); ..createSync(recursive: true);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment