forked from firka/flutter
Add support for the Kannada (kn) locale (#37026)
This commit is contained in:
95
dev/tools/localization/encode_kn_arb_files.dart
Normal file
95
dev/tools/localization/encode_kn_arb_files.dart
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright 2019 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 program replaces the material_kn.arb and cupertino_kn.arb
|
||||
// files in flutter_localizations/packages/lib/src/l10n with versions
|
||||
// where the contents of the localized strings have been replaced by JSON
|
||||
// escapes. This is done because some of those strings contain characters
|
||||
// that can crash Emacs on Linux. There is more information
|
||||
// here: https://github.com/flutter/flutter/issues/36704 and in the README
|
||||
// in flutter_localizations/packages/lib/src/l10n.
|
||||
//
|
||||
// This app needs to be run by hand when material_kn.arb or cupertino_kn.arb
|
||||
// have been updated.
|
||||
//
|
||||
// ## Usage
|
||||
//
|
||||
// Run this program from the root of the git repository.
|
||||
//
|
||||
// ```
|
||||
// dart dev/tools/localization/encode_kn_arb_files.dart
|
||||
// ```
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import 'localizations_utils.dart';
|
||||
|
||||
Map<String, dynamic> loadBundle(File file) {
|
||||
if (!FileSystemEntity.isFileSync(file.path))
|
||||
exitWithError('Unable to find input file: ${file.path}');
|
||||
return json.decode(file.readAsStringSync());
|
||||
}
|
||||
|
||||
void encodeBundleTranslations(Map<String, dynamic> bundle) {
|
||||
for (String key in bundle.keys) {
|
||||
// The ARB file resource "attributes" for foo are called @foo. Don't need
|
||||
// to encode them.
|
||||
if (key.startsWith('@'))
|
||||
continue;
|
||||
final String translation = bundle[key];
|
||||
// Rewrite the string as a series of unicode characters in JSON format.
|
||||
// Like "\u0012\u0123\u1234".
|
||||
bundle[key] = translation.runes.map((int code) {
|
||||
final String codeString = '00${code.toRadixString(16)}';
|
||||
return '\\u${codeString.substring(codeString.length - 4)}';
|
||||
}).join();
|
||||
}
|
||||
}
|
||||
|
||||
void checkEncodedTranslations(Map<String, dynamic> encodedBundle, Map<String, dynamic> bundle) {
|
||||
bool errorFound = false;
|
||||
const JsonDecoder decoder = JsonDecoder();
|
||||
for (String key in bundle.keys) {
|
||||
if (decoder.convert('"${encodedBundle[key]}"') != bundle[key]) {
|
||||
stderr.writeln(' encodedTranslation for $key does not match original value "${bundle[key]}"');
|
||||
errorFound = true;
|
||||
}
|
||||
}
|
||||
if (errorFound)
|
||||
exitWithError('JSON unicode translation encoding failed');
|
||||
}
|
||||
|
||||
void rewriteBundle(File file, Map<String, dynamic> bundle) {
|
||||
final StringBuffer contents = StringBuffer();
|
||||
contents.writeln('{');
|
||||
for (String key in bundle.keys) {
|
||||
contents.writeln(' "$key": "${bundle[key]}"${key == bundle.keys.last ? '' : ','}');
|
||||
}
|
||||
contents.writeln('}');
|
||||
file.writeAsStringSync(contents.toString());
|
||||
}
|
||||
|
||||
Future<void> main(List<String> rawArgs) async {
|
||||
checkCwdIsRepoRoot('encode_kn_arb_files');
|
||||
|
||||
final String l10nPath = path.join('packages', 'flutter_localizations', 'lib', 'src', 'l10n');
|
||||
final File materialArbFile = File(path.join(l10nPath, 'material_kn.arb'));
|
||||
final File cupertinoArbFile = File(path.join(l10nPath, 'cupertino_kn.arb'));
|
||||
|
||||
final Map<String, dynamic> materialBundle = loadBundle(materialArbFile);
|
||||
final Map<String, dynamic> cupertinoBundle = loadBundle(cupertinoArbFile);
|
||||
|
||||
encodeBundleTranslations(materialBundle);
|
||||
encodeBundleTranslations(cupertinoBundle);
|
||||
|
||||
checkEncodedTranslations(materialBundle, loadBundle(materialArbFile));
|
||||
checkEncodedTranslations(cupertinoBundle, loadBundle(cupertinoArbFile));
|
||||
|
||||
rewriteBundle(materialArbFile, materialBundle);
|
||||
rewriteBundle(cupertinoArbFile, cupertinoBundle);
|
||||
}
|
||||
@@ -36,6 +36,12 @@ import 'localizations_utils.dart';
|
||||
|
||||
const String _kCommandName = 'gen_date_localizations.dart';
|
||||
|
||||
// Used to let _jsonToMap know what locale it's date symbols converting for.
|
||||
// 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;
|
||||
|
||||
Future<void> main(List<String> rawArgs) async {
|
||||
checkCwdIsRepoRoot(_kCommandName);
|
||||
|
||||
@@ -87,9 +93,11 @@ Future<void> main(List<String> rawArgs) async {
|
||||
/// supported by flutter_localizations.''');
|
||||
buffer.writeln('const Map<String, dynamic> dateSymbols = <String, dynamic> {');
|
||||
symbolFiles.forEach((String locale, File data) {
|
||||
currentLocale = locale;
|
||||
if (_supportedLocales().contains(locale))
|
||||
buffer.writeln(_jsonToMapEntry(locale, json.decode(data.readAsStringSync())));
|
||||
});
|
||||
currentLocale = null;
|
||||
buffer.writeln('};');
|
||||
|
||||
// Code that uses datePatterns expects it to contain values of type
|
||||
@@ -132,7 +140,9 @@ String _jsonToMap(dynamic json) {
|
||||
return '$json';
|
||||
|
||||
if (json is String) {
|
||||
if (json.contains("'"))
|
||||
if (currentLocale == 'kn')
|
||||
return generateEncodedString(json);
|
||||
else if (json.contains("'"))
|
||||
return 'r"""$json"""';
|
||||
else
|
||||
return "r'''$json'''";
|
||||
|
||||
@@ -137,7 +137,7 @@ String generateArbBasedLocalizationSubclasses({
|
||||
final Map<String, String> languageResources = localeToResources[languageLocale];
|
||||
for (String key in allKeys) {
|
||||
final Map<String, dynamic> attributes = localeToResourceAttributes[canonicalLocale][key];
|
||||
output.writeln(generateGetter(key, languageResources[key], attributes));
|
||||
output.writeln(generateGetter(key, languageResources[key], attributes, languageLocale));
|
||||
}
|
||||
output.writeln('}');
|
||||
int countryCodeCount = 0;
|
||||
@@ -159,7 +159,7 @@ String generateArbBasedLocalizationSubclasses({
|
||||
if (languageResources[key] == scriptResources[key])
|
||||
continue;
|
||||
final Map<String, dynamic> attributes = localeToResourceAttributes[canonicalLocale][key];
|
||||
output.writeln(generateGetter(key, scriptResources[key], attributes));
|
||||
output.writeln(generateGetter(key, scriptResources[key], attributes, languageLocale));
|
||||
}
|
||||
output.writeln('}');
|
||||
|
||||
@@ -184,7 +184,7 @@ String generateArbBasedLocalizationSubclasses({
|
||||
if (scriptResources.containsKey(key) ? scriptResources[key] == localeResources[key] : languageResources[key] == localeResources[key])
|
||||
continue;
|
||||
final Map<String, dynamic> attributes = localeToResourceAttributes[canonicalLocale][key];
|
||||
output.writeln(generateGetter(key, localeResources[key], attributes));
|
||||
output.writeln(generateGetter(key, localeResources[key], attributes, languageLocale));
|
||||
}
|
||||
output.writeln('}');
|
||||
}
|
||||
@@ -208,7 +208,7 @@ String generateArbBasedLocalizationSubclasses({
|
||||
if (languageResources[key] == localeResources[key])
|
||||
continue;
|
||||
final Map<String, dynamic> attributes = localeToResourceAttributes[canonicalLocale][key];
|
||||
output.writeln(generateGetter(key, localeResources[key], attributes));
|
||||
output.writeln(generateGetter(key, localeResources[key], attributes, languageLocale));
|
||||
}
|
||||
output.writeln('}');
|
||||
}
|
||||
@@ -438,7 +438,7 @@ const Map<String, String> _scriptCategoryToEnum = <String, String>{
|
||||
/// it.
|
||||
///
|
||||
/// Used by [generateGetter] below.
|
||||
String generateValue(String value, Map<String, dynamic> attributes) {
|
||||
String generateValue(String value, Map<String, dynamic> attributes, LocaleInfo locale) {
|
||||
if (value == null)
|
||||
return null;
|
||||
// cupertino_en.arb doesn't use x-flutter-type.
|
||||
@@ -464,15 +464,19 @@ String generateValue(String value, Map<String, dynamic> attributes) {
|
||||
return _scriptCategoryToEnum[value];
|
||||
}
|
||||
}
|
||||
return generateString(value);
|
||||
// Localization strings for the Kannada locale ('kn') are encoded because
|
||||
// some of the localized strings contain characters that can crash Emacs on Linux.
|
||||
// See packages/flutter_localizations/lib/src/l10n/README for more information.
|
||||
return locale.languageCode == 'kn' ? generateEncodedString(value) : generateString(value);
|
||||
}
|
||||
|
||||
/// Combines [generateType], [generateKey], and [generateValue] to return
|
||||
/// the source of getters for the GlobalMaterialLocalizations subclass.
|
||||
String generateGetter(String key, String value, Map<String, dynamic> attributes) {
|
||||
/// The locale is the locale for which the getter is being generated.
|
||||
String generateGetter(String key, String value, Map<String, dynamic> attributes, LocaleInfo locale) {
|
||||
final String type = generateType(attributes);
|
||||
key = generateKey(key, attributes);
|
||||
value = generateValue(value, attributes);
|
||||
value = generateValue(value, attributes, locale);
|
||||
return '''
|
||||
|
||||
@override
|
||||
|
||||
@@ -401,3 +401,14 @@ String generateString(String s) {
|
||||
output.write("'");
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
/// Only used to generate localization strings for the Kannada locale ('kn') because
|
||||
/// some of the localized strings contain characters that can crash Emacs on Linux.
|
||||
/// See packages/flutter_localizations/lib/src/l10n/README for more information.
|
||||
String generateEncodedString(String s) {
|
||||
if (s.runes.every((int code) => code <= 0xFF))
|
||||
return generateString(s);
|
||||
|
||||
final String unicodeEscapes = s.runes.map((int code) => '\\u{${code.toRadixString(16)}}').join();
|
||||
return "'$unicodeEscapes'";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user