Unverified Commit 5a6c140d authored by xster's avatar xster Committed by GitHub

Cupertino localization step 7: modularize material specific things out of...

Cupertino localization step 7: modularize material specific things out of gen_localizations.dart (#29822)
parent 421f16a6
import 'localizations_utils.dart';
HeaderGenerator generateMaterialHeader = (String regenerateInstructions) {
return '''
// Copyright 2017 The Chromium 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 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart' as intl;
import '../material_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 [getMaterialTranslation] method at the
// bottom of this file, and used by the [_MaterialLocalizationsDelegate.load]
// method defined in `flutter_localizations/lib/src/material_localizations.dart`.''';
};
/// Returns the source of the constructor for a GlobalMaterialLocalizations
/// subclass.
ConstructorGenerator generateMaterialConstructor = (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 [GlobalMaterialLocalizations].
const MaterialLocalization${camelCase(locale)}({
String localeName = '$localeName',
@required intl.DateFormat fullYearFormat,
@required intl.DateFormat mediumDateFormat,
@required intl.DateFormat longDateFormat,
@required intl.DateFormat yearMonthFormat,
@required intl.NumberFormat decimalFormat,
@required intl.NumberFormat twoDigitZeroPaddedFormat,
}) : super(
localeName: localeName,
fullYearFormat: fullYearFormat,
mediumDateFormat: mediumDateFormat,
longDateFormat: longDateFormat,
yearMonthFormat: yearMonthFormat,
decimalFormat: decimalFormat,
twoDigitZeroPaddedFormat: twoDigitZeroPaddedFormat,
);''';
};
const String materialFactoryDeclaration = '''
GlobalMaterialLocalizations getMaterialTranslation(
Locale locale,
intl.DateFormat fullYearFormat,
intl.DateFormat mediumDateFormat,
intl.DateFormat longDateFormat,
intl.DateFormat yearMonthFormat,
intl.NumberFormat decimalFormat,
intl.NumberFormat twoDigitZeroPaddedFormat,
) {''';
const String materialFactoryArguments =
'fullYearFormat: fullYearFormat, mediumDateFormat: mediumDateFormat, longDateFormat: longDateFormat, yearMonthFormat: yearMonthFormat, decimalFormat: decimalFormat, twoDigitZeroPaddedFormat: twoDigitZeroPaddedFormat';
......@@ -9,6 +9,9 @@ import 'dart:io';
import 'package:args/args.dart' as argslib;
import 'package:meta/meta.dart';
typedef HeaderGenerator = String Function(String regenerateInstructions);
typedef ConstructorGenerator = String Function(LocaleInfo locale);
/// Simple data class to hold parsed locale. Does not promise validity of any data.
class LocaleInfo implements Comparable<LocaleInfo> {
LocaleInfo({
......@@ -129,6 +132,75 @@ class LocaleInfo implements Comparable<LocaleInfo> {
}
}
/// Parse the data for a locale from a file, and store it in the [attributes]
/// and [resources] keys.
void loadMatchingArbsIntoBundleMaps({
@required Directory directory,
@required RegExp filenamePattern,
@required Map<LocaleInfo, Map<String, String>> localeToResources,
@required Map<LocaleInfo, Map<String, dynamic>> localeToResourceAttributes,
}) {
assert(directory != null);
assert(filenamePattern != null);
assert(localeToResources != null);
assert(localeToResourceAttributes != null);
/// Set that holds the locales that were assumed from the existing locales.
///
/// For example, when the data lacks data for zh_Hant, we will use the data of
/// the first Hant Chinese locale as a default by repeating the data. If an
/// explicit match is later found, we can reference this set to see if we should
/// overwrite the existing assumed data.
final Set<LocaleInfo> assumedLocales = <LocaleInfo>{};
for (FileSystemEntity entity in directory.listSync()) {
final String entityPath = entity.path;
if (FileSystemEntity.isFileSync(entityPath) && filenamePattern.hasMatch(entityPath)) {
final String localeString = filenamePattern.firstMatch(entityPath)[1];
final File arbFile = File(entityPath);
// Helper method to fill the maps with the correct data from file.
void populateResources(LocaleInfo locale, File file) {
final Map<String, String> resources = localeToResources[locale];
final Map<String, dynamic> attributes = localeToResourceAttributes[locale];
final Map<String, dynamic> bundle = json.decode(file.readAsStringSync());
for (String key in bundle.keys) {
// The ARB file resource "attributes" for foo are called @foo.
if (key.startsWith('@'))
attributes[key.substring(1)] = bundle[key];
else
resources[key] = bundle[key];
}
}
// Only pre-assume scriptCode if there is a country or script code to assume off of.
// When we assume scriptCode based on languageCode-only, we want this initial pass
// to use the un-assumed version as a base class.
LocaleInfo locale = LocaleInfo.fromString(localeString, deriveScriptCode: localeString.split('_').length > 1);
// Allow overwrite if the existing data is assumed.
if (assumedLocales.contains(locale)) {
localeToResources[locale] = <String, String>{};
localeToResourceAttributes[locale] = <String, dynamic>{};
assumedLocales.remove(locale);
} else {
localeToResources[locale] ??= <String, String>{};
localeToResourceAttributes[locale] ??= <String, dynamic>{};
}
populateResources(locale, arbFile);
// Add an assumed locale to default to when there is no info on scriptOnly locales.
locale = LocaleInfo.fromString(localeString, deriveScriptCode: true);
if (locale.scriptCode != null) {
final LocaleInfo scriptLocale = LocaleInfo.fromString(locale.languageCode + '_' + locale.scriptCode);
if (!localeToResources.containsKey(scriptLocale)) {
assumedLocales.add(scriptLocale);
localeToResources[scriptLocale] ??= <String, String>{};
localeToResourceAttributes[scriptLocale] ??= <String, dynamic>{};
populateResources(scriptLocale, arbFile);
}
}
}
}
}
void exitWithError(String errorMessage) {
assert(errorMessage != null);
stderr.writeln('fatal: $errorMessage');
......@@ -266,4 +338,50 @@ String describeLocale(String tag) {
if (script != null)
output += ', using the $script script';
return output;
}
\ No newline at end of file
}
/// Writes the header of each class which corresponds to a locale.
String generateClassDeclaration(
LocaleInfo locale,
String classNamePrefix,
String superClass,
) {
final String camelCaseName = camelCase(locale);
return '''
/// The translations for ${describeLocale(locale.originalString)} (`${locale.originalString}`).
class $classNamePrefix$camelCaseName extends $superClass {''';
}
/// Return `s` as a Dart-parseable raw string in single or double quotes.
///
/// Double quotes are expanded:
///
/// ```
/// foo => r'foo'
/// foo "bar" => r'foo "bar"'
/// foo 'bar' => r'foo ' "'" r'bar' "'"
/// ```
String generateString(String s) {
if (!s.contains("'"))
return "r'$s'";
final StringBuffer output = StringBuffer();
bool started = false; // Have we started writing a raw string.
for (int i = 0; i < s.length; i++) {
if (s[i] == "'") {
if (started)
output.write("'");
output.write(' "\'" ');
started = false;
} else if (!started) {
output.write("r'${s[i]}");
started = true;
} else {
output.write(s[i]);
}
}
if (started)
output.write("'");
return output.toString();
}
......@@ -13202,7 +13202,7 @@ final Set<String> kSupportedLanguages = HashSet<String>.from(const <String>[
/// Creates a [GlobalMaterialLocalizations] instance for the given `locale`.
///
/// All of the function's arguments except `locale` will be passed to the [new
/// All of the function's arguments except `locale` will be passed to the [
/// GlobalMaterialLocalizations] constructor. (The `localeName` argument of that
/// constructor is specified by the actual subclass constructor by this
/// function.)
......
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