forked from firka/flutter
@@ -69,18 +69,23 @@ void _rewriteBundle(File file, Map<String, dynamic> bundle) {
|
||||
}
|
||||
|
||||
void encodeKnArbFiles(Directory directory) {
|
||||
final File widgetsArbFile = File(path.join(directory.path, 'widgets_kn.arb'));
|
||||
final File materialArbFile = File(path.join(directory.path, 'material_kn.arb'));
|
||||
final File cupertinoArbFile = File(path.join(directory.path, 'cupertino_kn.arb'));
|
||||
|
||||
final Map<String, dynamic> widgetsBundle = _loadBundle(widgetsArbFile);
|
||||
final Map<String, dynamic> materialBundle = _loadBundle(materialArbFile);
|
||||
final Map<String, dynamic> cupertinoBundle = _loadBundle(cupertinoArbFile);
|
||||
|
||||
_encodeBundleTranslations(widgetsBundle);
|
||||
_encodeBundleTranslations(materialBundle);
|
||||
_encodeBundleTranslations(cupertinoBundle);
|
||||
|
||||
_checkEncodedTranslations(widgetsBundle, _loadBundle(widgetsArbFile));
|
||||
_checkEncodedTranslations(materialBundle, _loadBundle(materialArbFile));
|
||||
_checkEncodedTranslations(cupertinoBundle, _loadBundle(cupertinoArbFile));
|
||||
|
||||
_rewriteBundle(widgetsArbFile, widgetsBundle);
|
||||
_rewriteBundle(materialArbFile, materialBundle);
|
||||
_rewriteBundle(cupertinoArbFile, cupertinoBundle);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import 'package:path/path.dart' as path;
|
||||
|
||||
import '../gen_cupertino_localizations.dart';
|
||||
import '../gen_material_localizations.dart';
|
||||
import '../gen_widgets_localizations.dart';
|
||||
import '../localizations_utils.dart';
|
||||
import '../localizations_validator.dart';
|
||||
import 'encode_kn_arb_files.dart';
|
||||
@@ -65,8 +66,10 @@ String generateArbBasedLocalizationSubclasses({
|
||||
required String baseClass,
|
||||
required HeaderGenerator generateHeader,
|
||||
required ConstructorGenerator generateConstructor,
|
||||
ConstructorGenerator? generateConstructorForCountrySubClass,
|
||||
required String factoryName,
|
||||
required String factoryDeclaration,
|
||||
required bool callsFactoryWithConst,
|
||||
required String factoryArguments,
|
||||
required String supportedLanguagesConstant,
|
||||
required String supportedLanguagesDocMacro,
|
||||
@@ -78,7 +81,7 @@ String generateArbBasedLocalizationSubclasses({
|
||||
assert(factoryArguments.isNotEmpty);
|
||||
assert(supportedLanguagesConstant.isNotEmpty);
|
||||
assert(supportedLanguagesDocMacro.isNotEmpty);
|
||||
|
||||
generateConstructorForCountrySubClass ??= generateConstructor;
|
||||
final StringBuffer output = StringBuffer();
|
||||
output.writeln(generateHeader('dart dev/tools/localization/bin/gen_localizations.dart --overwrite'));
|
||||
|
||||
@@ -133,7 +136,6 @@ String generateArbBasedLocalizationSubclasses({
|
||||
final LocaleInfo canonicalLocale = LocaleInfo.fromString('en');
|
||||
for (final String languageName in languageCodes) {
|
||||
final LocaleInfo languageLocale = LocaleInfo.fromString(languageName);
|
||||
|
||||
output.writeln(generateClassDeclaration(languageLocale, generatedClassPrefix, baseClass));
|
||||
output.writeln(generateConstructor(languageLocale));
|
||||
|
||||
@@ -156,7 +158,7 @@ String generateArbBasedLocalizationSubclasses({
|
||||
generatedClassPrefix,
|
||||
'$generatedClassPrefix${languageLocale.camelCase()}',
|
||||
));
|
||||
output.writeln(generateConstructor(scriptBaseLocale));
|
||||
output.writeln(generateConstructorForCountrySubClass(scriptBaseLocale));
|
||||
final Map<String, String> scriptResources = localeToResources[scriptBaseLocale]!;
|
||||
for (final String key in scriptResources.keys.toList()..sort()) {
|
||||
if (languageResources[key] == scriptResources[key]) {
|
||||
@@ -184,7 +186,7 @@ String generateArbBasedLocalizationSubclasses({
|
||||
generatedClassPrefix,
|
||||
'$generatedClassPrefix${scriptBaseLocale.camelCase()}',
|
||||
));
|
||||
output.writeln(generateConstructor(locale));
|
||||
output.writeln(generateConstructorForCountrySubClass(locale));
|
||||
final Map<String, String> localeResources = localeToResources[locale]!;
|
||||
for (final String key in localeResources.keys) {
|
||||
// When script fallback contains the key, we compare to it instead of language fallback.
|
||||
@@ -212,7 +214,7 @@ String generateArbBasedLocalizationSubclasses({
|
||||
generatedClassPrefix,
|
||||
'$generatedClassPrefix${languageLocale.camelCase()}',
|
||||
));
|
||||
output.writeln(generateConstructor(locale));
|
||||
output.writeln(generateConstructorForCountrySubClass(locale));
|
||||
for (final String key in localeResources.keys) {
|
||||
if (languageResources[key] == localeResources[key]) {
|
||||
continue;
|
||||
@@ -279,7 +281,7 @@ $factoryDeclaration
|
||||
if (languageToLocales[language]!.length == 1) {
|
||||
output.writeln('''
|
||||
case '$language':
|
||||
return $generatedClassPrefix${languageToLocales[language]![0].camelCase()}($factoryArguments);''');
|
||||
return ${callsFactoryWithConst ? 'const ': ''}$generatedClassPrefix${languageToLocales[language]![0].camelCase()}($factoryArguments);''');
|
||||
} else if (!languageToScriptCodes.containsKey(language)) { // Does not distinguish between scripts. Switch on countryCode directly.
|
||||
output.writeln('''
|
||||
case '$language': {
|
||||
@@ -292,11 +294,11 @@ $factoryDeclaration
|
||||
final String countryCode = locale.countryCode!;
|
||||
output.writeln('''
|
||||
case '$countryCode':
|
||||
return $generatedClassPrefix${locale.camelCase()}($factoryArguments);''');
|
||||
return ${callsFactoryWithConst ? 'const ': ''}$generatedClassPrefix${locale.camelCase()}($factoryArguments);''');
|
||||
}
|
||||
output.writeln('''
|
||||
}
|
||||
return $generatedClassPrefix${LocaleInfo.fromString(language).camelCase()}($factoryArguments);
|
||||
return ${callsFactoryWithConst ? 'const ': ''}$generatedClassPrefix${LocaleInfo.fromString(language).camelCase()}($factoryArguments);
|
||||
}''');
|
||||
} else { // Language has scriptCode, add additional switch logic.
|
||||
bool hasCountryCode = false;
|
||||
@@ -325,7 +327,7 @@ $factoryDeclaration
|
||||
final String countryCode = locale.countryCode!;
|
||||
output.writeln('''
|
||||
case '$countryCode':
|
||||
return $generatedClassPrefix${locale.camelCase()}($factoryArguments);''');
|
||||
return ${callsFactoryWithConst ? 'const ': ''}$generatedClassPrefix${locale.camelCase()}($factoryArguments);''');
|
||||
}
|
||||
}
|
||||
// Return a fallback locale that matches scriptCode, but not countryCode.
|
||||
@@ -337,7 +339,7 @@ $factoryDeclaration
|
||||
}''');
|
||||
}
|
||||
output.writeln('''
|
||||
return $generatedClassPrefix${scriptLocale.camelCase()}($factoryArguments);
|
||||
return ${callsFactoryWithConst ? 'const ': ''}$generatedClassPrefix${scriptLocale.camelCase()}($factoryArguments);
|
||||
}''');
|
||||
} else {
|
||||
// Not Explicitly defined, fallback to first locale with the same language and
|
||||
@@ -351,7 +353,7 @@ $factoryDeclaration
|
||||
}''');
|
||||
}
|
||||
output.writeln('''
|
||||
return $generatedClassPrefix${scriptLocale.camelCase()}($factoryArguments);
|
||||
return ${callsFactoryWithConst ? 'const ': ''}$generatedClassPrefix${scriptLocale.camelCase()}($factoryArguments);
|
||||
}''');
|
||||
break;
|
||||
}
|
||||
@@ -373,13 +375,13 @@ $factoryDeclaration
|
||||
final String countryCode = locale.countryCode!;
|
||||
output.writeln('''
|
||||
case '$countryCode':
|
||||
return $generatedClassPrefix${locale.camelCase()}($factoryArguments);''');
|
||||
return ${callsFactoryWithConst ? 'const ': ''}$generatedClassPrefix${locale.camelCase()}($factoryArguments);''');
|
||||
}
|
||||
output.writeln('''
|
||||
}''');
|
||||
}
|
||||
output.writeln('''
|
||||
return $generatedClassPrefix${LocaleInfo.fromString(language).camelCase()}($factoryArguments);
|
||||
return ${callsFactoryWithConst ? 'const ': ''}$generatedClassPrefix${LocaleInfo.fromString(language).camelCase()}($factoryArguments);
|
||||
}''');
|
||||
}
|
||||
}
|
||||
@@ -515,10 +517,12 @@ void main(List<String> rawArgs) {
|
||||
// code. In most cases both codes are just two characters.
|
||||
|
||||
final Directory directory = Directory(path.join('packages', 'flutter_localizations', 'lib', 'src', 'l10n'));
|
||||
final RegExp widgetsFilenameRE = RegExp(r'widgets_(\w+)\.arb$');
|
||||
final RegExp materialFilenameRE = RegExp(r'material_(\w+)\.arb$');
|
||||
final RegExp cupertinoFilenameRE = RegExp(r'cupertino_(\w+)\.arb$');
|
||||
|
||||
try {
|
||||
validateEnglishLocalizations(File(path.join(directory.path, 'widgets_en.arb')));
|
||||
validateEnglishLocalizations(File(path.join(directory.path, 'material_en.arb')));
|
||||
validateEnglishLocalizations(File(path.join(directory.path, 'cupertino_en.arb')));
|
||||
} on ValidationError catch (exception) {
|
||||
@@ -537,17 +541,30 @@ void main(List<String> rawArgs) {
|
||||
|
||||
precacheLanguageAndRegionTags();
|
||||
|
||||
// Maps of locales to resource key/value pairs for Widgets ARBs.
|
||||
final Map<LocaleInfo, Map<String, String>> widgetsLocaleToResources = <LocaleInfo, Map<String, String>>{};
|
||||
// Maps of locales to resource key/attributes pairs for Widgets ARBs..
|
||||
// https://github.com/googlei18n/app-resource-bundle/wiki/ApplicationResourceBundleSpecification#resource-attributes
|
||||
final Map<LocaleInfo, Map<String, dynamic>> widgetsLocaleToResourceAttributes = <LocaleInfo, Map<String, dynamic>>{};
|
||||
|
||||
// Maps of locales to resource key/value pairs for Material ARBs.
|
||||
final Map<LocaleInfo, Map<String, String>> materialLocaleToResources = <LocaleInfo, Map<String, String>>{};
|
||||
// Maps of locales to resource key/attributes pairs for Material ARBs..
|
||||
// https://github.com/googlei18n/app-resource-bundle/wiki/ApplicationResourceBundleSpecification#resource-attributes
|
||||
final Map<LocaleInfo, Map<String, dynamic>> materialLocaleToResourceAttributes = <LocaleInfo, Map<String, dynamic>>{};
|
||||
|
||||
// Maps of locales to resource key/value pairs for Cupertino ARBs.
|
||||
final Map<LocaleInfo, Map<String, String>> cupertinoLocaleToResources = <LocaleInfo, Map<String, String>>{};
|
||||
// Maps of locales to resource key/attributes pairs for Cupertino ARBs..
|
||||
// https://github.com/googlei18n/app-resource-bundle/wiki/ApplicationResourceBundleSpecification#resource-attributes
|
||||
final Map<LocaleInfo, Map<String, dynamic>> cupertinoLocaleToResourceAttributes = <LocaleInfo, Map<String, dynamic>>{};
|
||||
|
||||
loadMatchingArbsIntoBundleMaps(
|
||||
directory: directory,
|
||||
filenamePattern: widgetsFilenameRE,
|
||||
localeToResources: widgetsLocaleToResources,
|
||||
localeToResourceAttributes: widgetsLocaleToResourceAttributes,
|
||||
);
|
||||
loadMatchingArbsIntoBundleMaps(
|
||||
directory: directory,
|
||||
filenamePattern: materialFilenameRE,
|
||||
@@ -562,17 +579,35 @@ void main(List<String> rawArgs) {
|
||||
);
|
||||
|
||||
try {
|
||||
validateLocalizations(widgetsLocaleToResources, widgetsLocaleToResourceAttributes, removeUndefined: options.removeUndefined);
|
||||
validateLocalizations(materialLocaleToResources, materialLocaleToResourceAttributes, removeUndefined: options.removeUndefined);
|
||||
validateLocalizations(cupertinoLocaleToResources, cupertinoLocaleToResourceAttributes, removeUndefined: options.removeUndefined);
|
||||
} on ValidationError catch (exception) {
|
||||
exitWithError('$exception');
|
||||
}
|
||||
|
||||
if (options.removeUndefined) {
|
||||
removeUndefinedLocalizations(widgetsLocaleToResources);
|
||||
removeUndefinedLocalizations(materialLocaleToResources);
|
||||
removeUndefinedLocalizations(cupertinoLocaleToResources);
|
||||
}
|
||||
|
||||
final String? widgetsLocalizations = options.writeToFile || !options.cupertinoOnly
|
||||
? generateArbBasedLocalizationSubclasses(
|
||||
localeToResources: widgetsLocaleToResources,
|
||||
localeToResourceAttributes: widgetsLocaleToResourceAttributes,
|
||||
generatedClassPrefix: 'WidgetsLocalization',
|
||||
baseClass: 'GlobalWidgetsLocalizations',
|
||||
generateHeader: generateWidgetsHeader,
|
||||
generateConstructor: generateWidgetsConstructor,
|
||||
generateConstructorForCountrySubClass: generateWidgetsConstructorForCountrySubclass,
|
||||
factoryName: widgetsFactoryName,
|
||||
factoryDeclaration: widgetsFactoryDeclaration,
|
||||
callsFactoryWithConst: true,
|
||||
factoryArguments: widgetsFactoryArguments,
|
||||
supportedLanguagesConstant: widgetsSupportedLanguagesConstant,
|
||||
supportedLanguagesDocMacro: widgetsSupportedLanguagesDocMacro,
|
||||
)
|
||||
: null;
|
||||
final String? materialLocalizations = options.writeToFile || !options.cupertinoOnly
|
||||
? generateArbBasedLocalizationSubclasses(
|
||||
localeToResources: materialLocaleToResources,
|
||||
@@ -583,6 +618,7 @@ void main(List<String> rawArgs) {
|
||||
generateConstructor: generateMaterialConstructor,
|
||||
factoryName: materialFactoryName,
|
||||
factoryDeclaration: materialFactoryDeclaration,
|
||||
callsFactoryWithConst: false,
|
||||
factoryArguments: materialFactoryArguments,
|
||||
supportedLanguagesConstant: materialSupportedLanguagesConstant,
|
||||
supportedLanguagesDocMacro: materialSupportedLanguagesDocMacro,
|
||||
@@ -598,6 +634,7 @@ void main(List<String> rawArgs) {
|
||||
generateConstructor: generateCupertinoConstructor,
|
||||
factoryName: cupertinoFactoryName,
|
||||
factoryDeclaration: cupertinoFactoryDeclaration,
|
||||
callsFactoryWithConst: false,
|
||||
factoryArguments: cupertinoFactoryArguments,
|
||||
supportedLanguagesConstant: cupertinoSupportedLanguagesConstant,
|
||||
supportedLanguagesDocMacro: cupertinoSupportedLanguagesDocMacro,
|
||||
@@ -605,15 +642,22 @@ void main(List<String> rawArgs) {
|
||||
: null;
|
||||
|
||||
if (options.writeToFile) {
|
||||
final File widgetsLocalizationsFile = File(path.join(directory.path, 'generated_widgets_localizations.dart'));
|
||||
widgetsLocalizationsFile.writeAsStringSync(widgetsLocalizations!, flush: true);
|
||||
final File materialLocalizationsFile = File(path.join(directory.path, 'generated_material_localizations.dart'));
|
||||
materialLocalizationsFile.writeAsStringSync(materialLocalizations!, flush: true);
|
||||
final File cupertinoLocalizationsFile = File(path.join(directory.path, 'generated_cupertino_localizations.dart'));
|
||||
cupertinoLocalizationsFile.writeAsStringSync(cupertinoLocalizations!, flush: true);
|
||||
} else {
|
||||
if (!options.cupertinoOnly) {
|
||||
if (options.cupertinoOnly) {
|
||||
stdout.write(cupertinoLocalizations);
|
||||
} else if (options.materialOnly) {
|
||||
stdout.write(materialLocalizations);
|
||||
} else if (options.widgetsOnly) {
|
||||
stdout.write(widgetsLocalizations);
|
||||
} else {
|
||||
stdout.write(widgetsLocalizations);
|
||||
stdout.write(materialLocalizations);
|
||||
}
|
||||
if (!options.materialOnly) {
|
||||
stdout.write(cupertinoLocalizations);
|
||||
}
|
||||
}
|
||||
|
||||
74
dev/tools/localization/gen_widgets_localizations.dart
Normal file
74
dev/tools/localization/gen_widgets_localizations.dart
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'localizations_utils.dart';
|
||||
|
||||
// See http://en.wikipedia.org/wiki/Right-to-left
|
||||
const List<String> _rtlLanguages = <String>[
|
||||
'ar', // Arabic
|
||||
'fa', // Farsi
|
||||
'he', // Hebrew
|
||||
'ps', // Pashto
|
||||
'ur', // Urdu
|
||||
];
|
||||
|
||||
String generateWidgetsHeader(String regenerateInstructions) {
|
||||
return '''
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// This file has been automatically generated. Please do not edit it manually.
|
||||
// To regenerate the file, use:
|
||||
// $regenerateInstructions
|
||||
|
||||
import 'dart:collection';
|
||||
import 'dart:ui';
|
||||
|
||||
import '../widgets_localizations.dart';
|
||||
|
||||
// The classes defined here encode all of the translations found in the
|
||||
// `flutter_localizations/lib/src/l10n/*.arb` files.
|
||||
//
|
||||
// These classes are constructed by the [getWidgetsTranslation] method at the
|
||||
// bottom of this file, and used by the [_WidgetsLocalizationsDelegate.load]
|
||||
// method defined in `flutter_localizations/lib/src/widgets_localizations.dart`.''';
|
||||
}
|
||||
|
||||
/// Returns the source of the constructor for a GlobalWidgetsLocalizations
|
||||
/// subclass.
|
||||
String generateWidgetsConstructor(LocaleInfo locale) {
|
||||
final String localeName = locale.originalString;
|
||||
final String language = locale.languageCode.toLowerCase();
|
||||
final String textDirection = _rtlLanguages.contains(language) ? 'TextDirection.rtl' : 'TextDirection.ltr';
|
||||
return '''
|
||||
/// Create an instance of the translation bundle for ${describeLocale(localeName)}.
|
||||
///
|
||||
/// For details on the meaning of the arguments, see [GlobalWidgetsLocalizations].
|
||||
const WidgetsLocalization${locale.camelCase()}() : super($textDirection);''';
|
||||
}
|
||||
|
||||
/// Returns the source of the constructor for a GlobalWidgetsLocalizations
|
||||
/// subclass.
|
||||
String generateWidgetsConstructorForCountrySubclass(LocaleInfo locale) {
|
||||
final String localeName = locale.originalString;
|
||||
return '''
|
||||
/// Create an instance of the translation bundle for ${describeLocale(localeName)}.
|
||||
///
|
||||
/// For details on the meaning of the arguments, see [GlobalWidgetsLocalizations].
|
||||
const WidgetsLocalization${locale.camelCase()}();''';
|
||||
}
|
||||
|
||||
const String widgetsFactoryName = 'getWidgetsTranslation';
|
||||
|
||||
const String widgetsFactoryDeclaration = '''
|
||||
GlobalWidgetsLocalizations? getWidgetsTranslation(
|
||||
Locale locale,
|
||||
) {''';
|
||||
|
||||
const String widgetsFactoryArguments = '';
|
||||
|
||||
const String widgetsSupportedLanguagesConstant = 'kWidgetsSupportedLanguages';
|
||||
|
||||
const String widgetsSupportedLanguagesDocMacro = 'flutter.localizations.widgets.languages';
|
||||
@@ -239,6 +239,10 @@ GeneratorOptions parseArgs(List<String> rawArgs) {
|
||||
'remove-undefined',
|
||||
help: 'Remove any localizations that are not defined in the canonical locale.',
|
||||
)
|
||||
..addFlag(
|
||||
'widgets',
|
||||
help: 'Whether to print the generated classes for the Widgets package only. Ignored when --overwrite is passed.',
|
||||
)
|
||||
..addFlag(
|
||||
'material',
|
||||
help: 'Whether to print the generated classes for the Material package only. Ignored when --overwrite is passed.',
|
||||
@@ -254,6 +258,7 @@ GeneratorOptions parseArgs(List<String> rawArgs) {
|
||||
}
|
||||
final bool writeToFile = args['overwrite'] as bool;
|
||||
final bool removeUndefined = args['remove-undefined'] as bool;
|
||||
final bool widgetsOnly = args['widgets'] as bool;
|
||||
final bool materialOnly = args['material'] as bool;
|
||||
final bool cupertinoOnly = args['cupertino'] as bool;
|
||||
|
||||
@@ -261,6 +266,7 @@ GeneratorOptions parseArgs(List<String> rawArgs) {
|
||||
writeToFile: writeToFile,
|
||||
materialOnly: materialOnly,
|
||||
cupertinoOnly: cupertinoOnly,
|
||||
widgetsOnly: widgetsOnly,
|
||||
removeUndefined: removeUndefined,
|
||||
);
|
||||
}
|
||||
@@ -271,12 +277,14 @@ class GeneratorOptions {
|
||||
required this.removeUndefined,
|
||||
required this.materialOnly,
|
||||
required this.cupertinoOnly,
|
||||
required this.widgetsOnly,
|
||||
});
|
||||
|
||||
final bool writeToFile;
|
||||
final bool removeUndefined;
|
||||
final bool materialOnly;
|
||||
final bool cupertinoOnly;
|
||||
final bool widgetsOnly;
|
||||
}
|
||||
|
||||
// See also //master/tools/gen_locale.dart in the engine repo.
|
||||
|
||||
Reference in New Issue
Block a user