migrate localization to null safety (#84064)
migrate localization to null safety
This commit is contained in:
parent
4265acd6fe
commit
4705e0cc19
@ -13,8 +13,6 @@
|
||||
// This utility is run by `gen_localizations.dart` if --overwrite is passed
|
||||
// in as an option.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
/// This program extracts localized date symbols and patterns from the intl
|
||||
/// package for the subset of locales supported by the flutter_localizations
|
||||
/// package.
|
||||
@ -42,7 +40,7 @@ const String _kCommandName = 'gen_date_localizations.dart';
|
||||
// Date symbols for the Kannada locale ('kn') are handled specially because
|
||||
// some of the strings contain characters that can crash Emacs on Linux.
|
||||
// See packages/flutter_localizations/lib/src/l10n/README for more information.
|
||||
String currentLocale;
|
||||
String? currentLocale;
|
||||
|
||||
Future<void> main(List<String> rawArgs) async {
|
||||
checkCwdIsRepoRoot(_kCommandName);
|
||||
@ -66,7 +64,7 @@ Future<void> main(List<String> rawArgs) async {
|
||||
(String line) => line.startsWith('intl:'),
|
||||
orElse: () {
|
||||
exitWithError('intl dependency not found in ${dotPackagesFile.path}');
|
||||
return null; // unreachable
|
||||
return ''; // unreachable
|
||||
},
|
||||
)
|
||||
.split(':')
|
||||
@ -143,7 +141,7 @@ String _jsonToMap(dynamic json) {
|
||||
return '$json';
|
||||
|
||||
if (json is String)
|
||||
return generateEncodedString(currentLocale, json);
|
||||
return generateEncodedString(currentLocale!, json);
|
||||
|
||||
if (json is Iterable) {
|
||||
final StringBuffer buffer = StringBuffer('<dynamic>[');
|
||||
@ -180,7 +178,7 @@ Set<String> _supportedLocales() {
|
||||
for (final FileSystemEntity entity in supportedLocalesDirectory.listSync()) {
|
||||
final String filePath = entity.path;
|
||||
if (FileSystemEntity.isFileSync(filePath) && filenameRE.hasMatch(filePath)) {
|
||||
supportedLocales.add(filenameRE.firstMatch(filePath)[1]);
|
||||
supportedLocales.add(filenameRE.firstMatch(filePath)![1]!);
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,5 +198,5 @@ Map<String, File> _listIntlData(Directory directory) {
|
||||
|
||||
final List<String> locales = localeFiles.keys.toList(growable: false);
|
||||
locales.sort();
|
||||
return Map<String, File>.fromIterable(locales, value: (dynamic locale) => localeFiles[locale]);
|
||||
return Map<String, File>.fromIterable(locales, value: (dynamic locale) => localeFiles[locale]!);
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
// This program updates the language locale arb files with any missing resource
|
||||
// entries that are included in the English arb files. This is useful when
|
||||
// adding new resources for localization. You can just add the appropriate
|
||||
@ -68,10 +66,10 @@ bool intentionallyOmitted(String key, Map<String, dynamic> bundle) {
|
||||
/// Whether `key` corresponds to one of the plural variations of a key with
|
||||
/// the same prefix and suffix "Other".
|
||||
bool isPluralVariation(String key, Map<String, dynamic> bundle) {
|
||||
final Match pluralMatch = kPluralRegexp.firstMatch(key);
|
||||
final Match? pluralMatch = kPluralRegexp.firstMatch(key);
|
||||
if (pluralMatch == null)
|
||||
return false;
|
||||
final String prefix = pluralMatch[1];
|
||||
final String prefix = pluralMatch[1]!;
|
||||
return bundle.containsKey('${prefix}Other');
|
||||
}
|
||||
|
||||
@ -85,7 +83,7 @@ void updateMissingResources(String localizationPath, String groupPrefix) {
|
||||
for (final FileSystemEntity entity in localizationDir.listSync().toList()..sort(sortFilesByPath)) {
|
||||
final String entityPath = entity.path;
|
||||
if (FileSystemEntity.isFileSync(entityPath) && filenamePattern.hasMatch(entityPath)) {
|
||||
final String localeString = filenamePattern.firstMatch(entityPath)[1];
|
||||
final String localeString = filenamePattern.firstMatch(entityPath)![1]!;
|
||||
final LocaleInfo locale = LocaleInfo.fromString(localeString);
|
||||
|
||||
// Only look at top-level language locales
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'localizations_utils.dart';
|
||||
|
||||
String generateCupertinoHeader(String regenerateInstructions) {
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'localizations_utils.dart';
|
||||
|
||||
String generateMaterialHeader(String regenerateInstructions) {
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
@ -23,11 +21,11 @@ int sortFilesByPath (FileSystemEntity a, FileSystemEntity b) {
|
||||
@immutable
|
||||
class LocaleInfo implements Comparable<LocaleInfo> {
|
||||
const LocaleInfo({
|
||||
this.languageCode,
|
||||
required this.languageCode,
|
||||
this.scriptCode,
|
||||
this.countryCode,
|
||||
this.length,
|
||||
this.originalString,
|
||||
required this.length,
|
||||
required this.originalString,
|
||||
});
|
||||
|
||||
/// Simple parser. Expects the locale string to be in the form of 'language_script_COUNTRY'
|
||||
@ -42,8 +40,8 @@ class LocaleInfo implements Comparable<LocaleInfo> {
|
||||
final List<String> codes = locale.split('_'); // [language, script, country]
|
||||
assert(codes.isNotEmpty && codes.length < 4);
|
||||
final String languageCode = codes[0];
|
||||
String scriptCode;
|
||||
String countryCode;
|
||||
String? scriptCode;
|
||||
String? countryCode;
|
||||
int length = codes.length;
|
||||
String originalString = locale;
|
||||
if (codes.length == 2) {
|
||||
@ -111,8 +109,8 @@ class LocaleInfo implements Comparable<LocaleInfo> {
|
||||
}
|
||||
|
||||
final String languageCode;
|
||||
final String scriptCode;
|
||||
final String countryCode;
|
||||
final String? scriptCode;
|
||||
final String? countryCode;
|
||||
final int length; // The number of fields. Ranges from 1-3.
|
||||
final String originalString; // Original un-parsed locale string.
|
||||
|
||||
@ -148,10 +146,10 @@ 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,
|
||||
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);
|
||||
@ -169,13 +167,13 @@ void loadMatchingArbsIntoBundleMaps({
|
||||
for (final FileSystemEntity entity in directory.listSync().toList()..sort(sortFilesByPath)) {
|
||||
final String entityPath = entity.path;
|
||||
if (FileSystemEntity.isFileSync(entityPath) && filenamePattern.hasMatch(entityPath)) {
|
||||
final String localeString = filenamePattern.firstMatch(entityPath)[1];
|
||||
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, String> resources = localeToResources[locale]!;
|
||||
final Map<String, dynamic> attributes = localeToResourceAttributes[locale]!;
|
||||
final Map<String, dynamic> bundle = json.decode(file.readAsStringSync()) as Map<String, dynamic>;
|
||||
for (final String key in bundle.keys) {
|
||||
// The ARB file resource "attributes" for foo are called @foo.
|
||||
@ -258,9 +256,9 @@ GeneratorOptions parseArgs(List<String> rawArgs) {
|
||||
|
||||
class GeneratorOptions {
|
||||
GeneratorOptions({
|
||||
@required this.writeToFile,
|
||||
@required this.materialOnly,
|
||||
@required this.cupertinoOnly,
|
||||
required this.writeToFile,
|
||||
required this.materialOnly,
|
||||
required this.cupertinoOnly,
|
||||
});
|
||||
|
||||
final bool writeToFile;
|
||||
@ -271,7 +269,7 @@ class GeneratorOptions {
|
||||
// See also //master/tools/gen_locale.dart in the engine repo.
|
||||
Map<String, List<String>> _parseSection(String section) {
|
||||
final Map<String, List<String>> result = <String, List<String>>{};
|
||||
List<String> lastHeading;
|
||||
late List<String> lastHeading;
|
||||
for (final String line in section.split('\n')) {
|
||||
if (line == '')
|
||||
continue;
|
||||
@ -285,7 +283,7 @@ Map<String, List<String>> _parseSection(String section) {
|
||||
final String name = line.substring(0, colon);
|
||||
final String value = line.substring(colon + 2);
|
||||
lastHeading = result.putIfAbsent(name, () => <String>[]);
|
||||
result[name].add(value);
|
||||
result[name]!.add(value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -304,11 +302,11 @@ void precacheLanguageAndRegionTags() {
|
||||
languageSubtagRegistry.split('%%').skip(1).map<Map<String, List<String>>>(_parseSection).toList();
|
||||
for (final Map<String, List<String>> section in sections) {
|
||||
assert(section.containsKey('Type'), section.toString());
|
||||
final String type = section['Type'].single;
|
||||
final String type = section['Type']!.single;
|
||||
if (type == 'language' || type == 'region' || type == 'script') {
|
||||
assert(section.containsKey('Subtag') && section.containsKey('Description'), section.toString());
|
||||
final String subtag = section['Subtag'].single;
|
||||
String description = section['Description'].join(' ');
|
||||
final String subtag = section['Subtag']!.single;
|
||||
String description = section['Description']!.join(' ');
|
||||
if (description.startsWith('United '))
|
||||
description = 'the $description';
|
||||
if (description.contains(kParentheticalPrefix))
|
||||
@ -336,10 +334,10 @@ String describeLocale(String tag) {
|
||||
final List<String> subtags = tag.split('_');
|
||||
assert(subtags.isNotEmpty);
|
||||
assert(_languages.containsKey(subtags[0]));
|
||||
final String language = _languages[subtags[0]];
|
||||
final String language = _languages[subtags[0]]!;
|
||||
String output = language;
|
||||
String region;
|
||||
String script;
|
||||
String? region;
|
||||
String? script;
|
||||
if (subtags.length == 2) {
|
||||
region = _regions[subtags[1]];
|
||||
script = _scripts[subtags[1]];
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:convert' show json;
|
||||
import 'dart:io';
|
||||
|
||||
@ -62,7 +60,7 @@ void validateEnglishLocalizations(File file) {
|
||||
continue;
|
||||
|
||||
final dynamic atResourceValue = bundle[atResourceId];
|
||||
final Map<String, dynamic> atResource =
|
||||
final Map<String, dynamic>? atResource =
|
||||
atResourceValue is Map<String, dynamic> ? atResourceValue : null;
|
||||
if (atResource == null) {
|
||||
errorMessages.writeln('A map value was not specified for $atResourceId');
|
||||
@ -103,12 +101,12 @@ void validateLocalizations(
|
||||
Map<LocaleInfo, Map<String, String>> localeToResources,
|
||||
Map<LocaleInfo, Map<String, dynamic>> localeToAttributes,
|
||||
) {
|
||||
final Map<String, String> canonicalLocalizations = localeToResources[LocaleInfo.fromString('en')];
|
||||
final Map<String, String> canonicalLocalizations = localeToResources[LocaleInfo.fromString('en')]!;
|
||||
final Set<String> canonicalKeys = Set<String>.from(canonicalLocalizations.keys);
|
||||
final StringBuffer errorMessages = StringBuffer();
|
||||
bool explainMissingKeys = false;
|
||||
for (final LocaleInfo locale in localeToResources.keys) {
|
||||
final Map<String, String> resources = localeToResources[locale];
|
||||
final Map<String, String> resources = localeToResources[locale]!;
|
||||
|
||||
// Whether `key` corresponds to one of the plural variations of a key with
|
||||
// the same prefix and suffix "Other".
|
||||
@ -116,10 +114,10 @@ void validateLocalizations(
|
||||
// Many languages require only a subset of these variations, so we do not
|
||||
// require them so long as the "Other" variation exists.
|
||||
bool isPluralVariation(String key) {
|
||||
final Match pluralMatch = kPluralRegexp.firstMatch(key);
|
||||
final Match? pluralMatch = kPluralRegexp.firstMatch(key);
|
||||
if (pluralMatch == null)
|
||||
return false;
|
||||
final String prefix = pluralMatch[1];
|
||||
final String? prefix = pluralMatch[1];
|
||||
return resources.containsKey('${prefix}Other');
|
||||
}
|
||||
|
||||
@ -135,10 +133,10 @@ void validateLocalizations(
|
||||
// For language-level locales only, check that they have a complete list of
|
||||
// keys, or opted out of using certain ones.
|
||||
if (locale.length == 1) {
|
||||
final Map<String, dynamic> attributes = localeToAttributes[locale];
|
||||
final List<String> missingKeys = <String>[];
|
||||
final Map<String, dynamic>? attributes = localeToAttributes[locale];
|
||||
final List<String?> missingKeys = <String?>[];
|
||||
for (final String missingKey in canonicalKeys.difference(keys)) {
|
||||
final dynamic attribute = attributes[missingKey];
|
||||
final dynamic attribute = attributes?[missingKey];
|
||||
final bool intentionallyOmitted = attribute is Map && attribute.containsKey('notUsed');
|
||||
if (!intentionallyOmitted && !isPluralVariation(missingKey))
|
||||
missingKeys.add(missingKey);
|
||||
|
Loading…
x
Reference in New Issue
Block a user