Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
aab92447
Unverified
Commit
aab92447
authored
Nov 08, 2018
by
Gary Qian
Committed by
GitHub
Nov 08, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
scriptCode support in gen_localizations and strip scriptCodes for date l10n. (#23853)
parent
b21fe0aa
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
832 additions
and
240 deletions
+832
-240
gen_localizations.dart
dev/tools/gen_localizations.dart
+247
-62
localizations_utils.dart
dev/tools/localizations_utils.dart
+134
-10
localizations_validator.dart
dev/tools/localizations_validator.dart
+8
-8
date_localizations.dart
...lutter_localizations/lib/src/l10n/date_localizations.dart
+5
-5
localizations.dart
...ges/flutter_localizations/lib/src/l10n/localizations.dart
+110
-155
material_localizations.dart
...flutter_localizations/lib/src/material_localizations.dart
+20
-0
translations_test.dart
packages/flutter_localizations/test/translations_test.dart
+308
-0
No files found.
dev/tools/gen_localizations.dart
View file @
aab92447
...
...
@@ -67,12 +67,20 @@ import '../material_localizations.dart';
'''
;
/// Maps locales to resource key/value pairs.
final
Map
<
String
,
Map
<
String
,
String
>>
localeToResources
=
<
String
,
Map
<
String
,
String
>>{};
final
Map
<
LocaleInfo
,
Map
<
String
,
String
>>
localeToResources
=
<
LocaleInfo
,
Map
<
String
,
String
>>{};
/// Maps locales to resource key/attributes pairs.
///
/// See also: <https://github.com/googlei18n/app-resource-bundle/wiki/ApplicationResourceBundleSpecification#resource-attributes>
final
Map
<
String
,
Map
<
String
,
dynamic
>>
localeToResourceAttributes
=
<
String
,
Map
<
String
,
dynamic
>>{};
final
Map
<
LocaleInfo
,
Map
<
String
,
dynamic
>>
localeToResourceAttributes
=
<
LocaleInfo
,
Map
<
String
,
dynamic
>>{};
/// 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
=
Set
<
LocaleInfo
>();
/// Return `s` as a Dart-parseable raw string in single or double quotes.
///
...
...
@@ -112,13 +120,23 @@ String generateTranslationBundles() {
final
StringBuffer
output
=
StringBuffer
();
final
StringBuffer
supportedLocales
=
StringBuffer
();
final
Map
<
String
,
List
<
String
>>
languageToLocales
=
<
String
,
List
<
String
>>{};
final
Map
<
String
,
List
<
LocaleInfo
>>
languageToLocales
=
<
String
,
List
<
LocaleInfo
>>{};
final
Map
<
String
,
Set
<
String
>>
languageToScriptCodes
=
<
String
,
Set
<
String
>>{};
// Used to calculate if there are any corresponding countries for a given language and script.
final
Map
<
LocaleInfo
,
Set
<
String
>>
languageAndScriptToCountryCodes
=
<
LocaleInfo
,
Set
<
String
>>{};
final
Set
<
String
>
allResourceIdentifiers
=
Set
<
String
>();
for
(
String
locale
in
localeToResources
.
keys
.
toList
()..
sort
())
{
final
List
<
String
>
codes
=
locale
.
split
(
'_'
);
// [language, country]
assert
(
codes
.
length
==
1
||
codes
.
length
==
2
);
languageToLocales
[
codes
[
0
]]
??=
<
String
>[];
languageToLocales
[
codes
[
0
]].
add
(
locale
);
for
(
LocaleInfo
locale
in
localeToResources
.
keys
.
toList
()..
sort
())
{
if
(
locale
.
scriptCode
!=
null
)
{
languageToScriptCodes
[
locale
.
languageCode
]
??=
Set
<
String
>();
languageToScriptCodes
[
locale
.
languageCode
].
add
(
locale
.
scriptCode
);
}
if
(
locale
.
countryCode
!=
null
&&
locale
.
scriptCode
!=
null
)
{
final
LocaleInfo
key
=
LocaleInfo
.
fromString
(
locale
.
languageCode
+
'_'
+
locale
.
scriptCode
);
languageAndScriptToCountryCodes
[
key
]
??=
Set
<
String
>();
languageAndScriptToCountryCodes
[
key
].
add
(
locale
.
countryCode
);
}
languageToLocales
[
locale
.
languageCode
]
??=
<
LocaleInfo
>[];
languageToLocales
[
locale
.
languageCode
].
add
(
locale
);
allResourceIdentifiers
.
addAll
(
localeToResources
[
locale
].
keys
);
}
...
...
@@ -134,56 +152,107 @@ String generateTranslationBundles() {
// `MaterialLocalizationEn`). These implement everything that is needed by
// GlobalMaterialLocalizations.
// We also generate one subclass for each locale with a script code (e.g.
// `MaterialLocalizationZhHant`). Their superclasses are the aforementioned
// language classes for the same locale but without a script code (e.g.
// `MaterialLocalizationZh`).
// We also generate one subclass for each locale with a country code (e.g.
// `MaterialLocalizationEnGb`). Their superclasses are the aforementioned
// language classes for the same locale but without a country code (e.g.
// `MaterialLocalizationEn`). These classes only override getters that return
// a different value than their superclass.
// `MaterialLocalizationEn`).
// If scriptCodes for a language are defined, we expect a scriptCode to be
// defined for locales that contain a countryCode. The superclass becomes
// the script sublcass (e.g. `MaterialLocalizationZhHant`) and the generated
// subclass will also contain the script code (e.g. `MaterialLocalizationZhHantTW`).
// When scriptCodes are not defined for languages that use scriptCodes to distinguish
// between significantly differing scripts, we assume the scriptCodes in the
// [LocaleInfo.fromString] factory and add it to the [LocaleInfo]. We then generate
// the script classes based on the first locale that we assume to use the script.
final
List
<
String
>
allKeys
=
allResourceIdentifiers
.
toList
()..
sort
();
final
List
<
String
>
languageCodes
=
languageToLocales
.
keys
.
toList
()..
sort
();
final
LocaleInfo
canonicalLocale
=
LocaleInfo
.
fromString
(
'en'
);
for
(
String
languageName
in
languageCodes
)
{
final
String
camelCaseLanguage
=
camelCase
(
languageName
);
final
Map
<
String
,
String
>
languageResources
=
localeToResources
[
languageName
];
final
String
languageClassName
=
'MaterialLocalization
$camelCaseLanguage
'
;
final
String
constructor
=
generateConstructor
(
languageClassName
,
languageName
);
output
.
writeln
(
''
);
output
.
writeln
(
'/// The translations for
${describeLocale(languageName)}
(`
$languageName
`).'
);
output
.
writeln
(
'class
$languageClassName
extends GlobalMaterialLocalizations {'
);
output
.
writeln
(
constructor
);
final
LocaleInfo
languageLocale
=
LocaleInfo
.
fromString
(
languageName
);
writeClassHeader
(
output
,
languageLocale
,
'GlobalMaterialLocalizations'
);
final
Map
<
String
,
String
>
languageResources
=
localeToResources
[
languageLocale
];
for
(
String
key
in
allKeys
)
{
final
Map
<
String
,
dynamic
>
attributes
=
localeToResourceAttributes
[
'en'
][
key
];
final
Map
<
String
,
dynamic
>
attributes
=
localeToResourceAttributes
[
canonicalLocale
][
key
];
output
.
writeln
(
generateGetter
(
key
,
languageResources
[
key
],
attributes
));
}
output
.
writeln
(
'}'
);
int
countryCodeCount
=
0
;
final
List
<
String
>
localeCodes
=
languageToLocales
[
languageName
]..
sort
();
for
(
String
localeName
in
localeCodes
)
{
if
(
localeName
==
languageName
)
continue
;
countryCodeCount
+=
1
;
final
String
camelCaseLocaleName
=
camelCase
(
localeName
);
final
Map
<
String
,
String
>
localeResources
=
localeToResources
[
localeName
];
final
String
localeClassName
=
'MaterialLocalization
$camelCaseLocaleName
'
;
final
String
constructor
=
generateConstructor
(
localeClassName
,
localeName
);
output
.
writeln
(
''
);
output
.
writeln
(
'/// The translations for
${describeLocale(localeName)}
(`
$localeName
`).'
);
output
.
writeln
(
'class
$localeClassName
extends
$languageClassName
{'
);
output
.
writeln
(
constructor
);
for
(
String
key
in
localeResources
.
keys
)
{
if
(
languageResources
[
key
]
==
localeResources
[
key
])
int
scriptCodeCount
=
0
;
if
(
languageToScriptCodes
.
containsKey
(
languageName
))
{
scriptCodeCount
=
languageToScriptCodes
[
languageName
].
length
;
// Language has scriptCodes, so we need to properly fallback countries to corresponding
// script default values before language default values.
for
(
String
scriptCode
in
languageToScriptCodes
[
languageName
])
{
final
LocaleInfo
scriptBaseLocale
=
LocaleInfo
.
fromString
(
languageName
+
'_'
+
scriptCode
);
writeClassHeader
(
output
,
scriptBaseLocale
,
'MaterialLocalization
${camelCase(languageLocale)}
'
);
final
Map
<
String
,
String
>
scriptResources
=
localeToResources
[
scriptBaseLocale
];
for
(
String
key
in
scriptResources
.
keys
)
{
if
(
languageResources
[
key
]
==
scriptResources
[
key
])
continue
;
final
Map
<
String
,
dynamic
>
attributes
=
localeToResourceAttributes
[
canonicalLocale
][
key
];
output
.
writeln
(
generateGetter
(
key
,
scriptResources
[
key
],
attributes
));
}
output
.
writeln
(
'}'
);
final
List
<
LocaleInfo
>
localeCodes
=
languageToLocales
[
languageName
]..
sort
();
for
(
LocaleInfo
locale
in
localeCodes
)
{
if
(
locale
.
originalString
==
languageName
)
continue
;
if
(
locale
.
originalString
==
languageName
+
'_'
+
scriptCode
)
continue
;
if
(
locale
.
scriptCode
!=
scriptCode
)
continue
;
countryCodeCount
+=
1
;
writeClassHeader
(
output
,
locale
,
'MaterialLocalization
${camelCase(scriptBaseLocale)}
'
);
final
Map
<
String
,
String
>
localeResources
=
localeToResources
[
locale
];
for
(
String
key
in
localeResources
.
keys
)
{
// When script fallback contains the key, we compare to it instead of language fallback.
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
(
'}'
);
}
}
}
else
{
// No scriptCode. Here, we do not compare against script default (because it
// doesn't exist).
final
List
<
LocaleInfo
>
localeCodes
=
languageToLocales
[
languageName
]..
sort
();
for
(
LocaleInfo
locale
in
localeCodes
)
{
if
(
locale
.
originalString
==
languageName
)
continue
;
final
Map
<
String
,
dynamic
>
attributes
=
localeToResourceAttributes
[
'en'
][
key
];
output
.
writeln
(
generateGetter
(
key
,
localeResources
[
key
],
attributes
));
countryCodeCount
+=
1
;
final
Map
<
String
,
String
>
localeResources
=
localeToResources
[
locale
];
writeClassHeader
(
output
,
locale
,
'MaterialLocalization
${camelCase(languageLocale)}
'
);
for
(
String
key
in
localeResources
.
keys
)
{
if
(
languageResources
[
key
]
==
localeResources
[
key
])
continue
;
final
Map
<
String
,
dynamic
>
attributes
=
localeToResourceAttributes
[
canonicalLocale
][
key
];
output
.
writeln
(
generateGetter
(
key
,
localeResources
[
key
],
attributes
));
}
output
.
writeln
(
'}'
);
}
output
.
writeln
(
'}'
);
}
final
String
scriptCodeMessage
=
scriptCodeCount
==
0
?
''
:
' and
$scriptCodeCount
script'
+
(
scriptCodeCount
==
1
?
''
:
's'
);
if
(
countryCodeCount
==
0
)
{
supportedLocales
.
writeln
(
'/// * `
$languageName
` -
${describeLocale(languageName)}
'
);
if
(
scriptCodeCount
==
0
)
supportedLocales
.
writeln
(
'/// * `
$languageName
` -
${describeLocale(languageName)}
'
);
else
supportedLocales
.
writeln
(
'/// * `
$languageName
` -
${describeLocale(languageName)}
(plus
$scriptCodeCount
script'
+
(
scriptCodeCount
==
1
?
''
:
's'
)
+
')'
);
}
else
if
(
countryCodeCount
==
1
)
{
supportedLocales
.
writeln
(
'/// * `
$languageName
` -
${describeLocale(languageName)}
(plus one
variant
)'
);
supportedLocales
.
writeln
(
'/// * `
$languageName
` -
${describeLocale(languageName)}
(plus one
country variation
$scriptCodeMessage
)'
);
}
else
{
supportedLocales
.
writeln
(
'/// * `
$languageName
` -
${describeLocale(languageName)}
(plus
$countryCodeCount
variants
)'
);
supportedLocales
.
writeln
(
'/// * `
$languageName
` -
${describeLocale(languageName)}
(plus
$countryCodeCount
country variations
$scriptCodeMessage
)'
);
}
}
...
...
@@ -232,26 +301,104 @@ GlobalMaterialLocalizations getTranslation(
switch
(
locale
.
languageCode
)
{
''');
const String arguments = '
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
';
for (String language in languageToLocales.keys) {
// Only one instance of the language.
if (languageToLocales[language].length == 1) {
output.writeln('''
case
'
$language
'
:
return
MaterialLocalization
$
{
camelCase
(
languageToLocales
[
language
][
0
])}(
$arguments
);
''');
} else
{
} else
if (!languageToScriptCodes.containsKey(language)) { // Does not distinguish between scripts. Switch on countryCode directly.
output.writeln('''
case
'
$language
'
:
{
switch
(
locale
.
countryCode
)
{
''');
for (
String localeNam
e in languageToLocales[language]) {
if (locale
Name
== language)
for (
LocaleInfo local
e in languageToLocales[language]) {
if (locale
.originalString
== language)
continue;
assert(locale
Name.contains('
_
')
);
final String countryCode = locale
Name.substring(localeName.indexOf('
_
') + 1)
;
assert(locale
.length > 1
);
final String countryCode = locale
.countryCode
;
output.writeln('''
case
'
$countryCode
'
:
return
MaterialLocalization
$
{
camelCase
(
localeName
)}(
$arguments
);
''');
return
MaterialLocalization
$
{
camelCase
(
locale
)}(
$arguments
);
''');
}
output.writeln('''
}
return
MaterialLocalization
$
{
camelCase
(
LocaleInfo
.
fromString
(
language
))}(
$arguments
);
}
''');
} else { // Language has scriptCode, add additional switch logic.
bool hasCountryCode = false;
output.writeln('''
case
'
$language
'
:
{
switch
(
locale
.
scriptCode
)
{
''');
for (String scriptCode in languageToScriptCodes[language]) {
final LocaleInfo scriptLocale = LocaleInfo.fromString(language + '
_
' + scriptCode);
output.writeln('''
case
'
$scriptCode
'
:
{
''');
if (languageAndScriptToCountryCodes.containsKey(scriptLocale)) {
output.writeln('''
switch
(
locale
.
countryCode
)
{
''');
for (LocaleInfo locale in languageToLocales[language]) {
if (locale.countryCode == null)
continue;
else
hasCountryCode = true;
if (locale.originalString == language)
continue;
if (locale.scriptCode != scriptCode && locale.scriptCode != null)
continue;
final String countryCode = locale.countryCode;
output.writeln('''
case
'
$countryCode
'
:
return
MaterialLocalization
$
{
camelCase
(
locale
)}(
$arguments
);
''');
}
}
// Return a fallback locale that matches scriptCode, but not countryCode.
//
// Explicitly defined scriptCode fallback:
if (languageToLocales[language].contains(scriptLocale)) {
if (languageAndScriptToCountryCodes.containsKey(scriptLocale)) {
output.writeln('''
}
''');
}
output.writeln('''
return
MaterialLocalization
$
{
camelCase
(
scriptLocale
)}(
$arguments
);
}
''');
} else {
// Not Explicitly defined, fallback to first locale with the same language and
// script:
for (LocaleInfo locale in languageToLocales[language]) {
if (locale.scriptCode != scriptCode)
continue;
if (languageAndScriptToCountryCodes.containsKey(scriptLocale)) {
output.writeln('''
}
''');
}
output.writeln('''
return
MaterialLocalization
$
{
camelCase
(
scriptLocale
)}(
$arguments
);
}
''');
break;
}
}
}
output.writeln('''
}
''');
if (hasCountryCode) {
output.writeln('''
switch
(
locale
.
countryCode
)
{
''');
for (LocaleInfo locale in languageToLocales[language]) {
if (locale.originalString == language)
continue;
assert(locale.length > 1);
if (locale.countryCode == null)
continue;
final String countryCode = locale.countryCode;
output.writeln('''
case
'
$countryCode
'
:
return
MaterialLocalization
$
{
camelCase
(
locale
)}(
$arguments
);
''');
}
output.writeln('''
}
''');
}
return
MaterialLocalization
$
{
camelCase
(
language
)}(
$arguments
);
output.writeln('''
return
MaterialLocalization
$
{
camelCase
(
LocaleInfo
.
fromString
(
language
))}(
$arguments
);
}
''');
}
}
...
...
@@ -264,6 +411,17 @@ GlobalMaterialLocalizations getTranslation(
return output.toString();
}
/// Writes the header of each class which corresponds to a locale.
void writeClassHeader(StringBuffer output, LocaleInfo locale, String superClass) {
final String camelCaseName = camelCase(locale);
final String className = '
MaterialLocalization$camelCaseName
';
final String constructor = generateConstructor(className, locale);
output.writeln('');
output.writeln('
/// The translations for ${describeLocale(locale.originalString)} (`${locale.originalString}`).');
output
.
writeln
(
'class
$className
extends
$superClass
{'
);
output
.
writeln
(
constructor
);
}
/// Returns the appropriate type for getters with the given attributes.
///
/// Typically "String", but some (e.g. "timeOfDayFormat") return enums.
...
...
@@ -367,7 +525,8 @@ String generateGetter(String key, String value, Map<String, dynamic> attributes)
/// Returns the source of the constructor for a GlobalMaterialLocalizations
/// subclass.
String generateConstructor(String className, String localeName) {
String
generateConstructor
(
String
className
,
LocaleInfo
locale
)
{
final
String
localeName
=
locale
.
originalString
;
return
'''
/// Create an instance of the translation bundle for
${describeLocale(localeName)}
.
///
...
...
@@ -393,19 +552,45 @@ String generateConstructor(String className, String localeName) {
/// Parse the data for a locale from a file, and store it in the [attributes]
/// and [resources] keys.
void processBundle(File file, { @required String locale }) {
assert(locale != null);
localeToResources[locale] ??= <String, String>{};
localeToResourceAttributes[locale] ??= <String, dynamic>{};
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];
void
processBundle
(
File
file
,
{
@required
String
localeString
})
{
assert
(
localeString
!=
null
);
// Helper method to fill the maps with the correct data from file.
void
populateResources
(
LocaleInfo
locale
)
{
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
,
assume:
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
);
// Add an assumed locale to default to when there is no info on scriptOnly locales.
locale
=
LocaleInfo
.
fromString
(
localeString
,
assume:
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
);
}
}
}
...
...
@@ -431,7 +616,7 @@ Future<void> main(List<String> rawArgs) async {
for
(
FileSystemEntity
entity
in
directory
.
listSync
())
{
final
String
entityPath
=
entity
.
path
;
if
(
FileSystemEntity
.
isFileSync
(
entityPath
)
&&
filenameRE
.
hasMatch
(
entityPath
))
{
processBundle(File(entityPath), locale: filenameRE.firstMatch(entityPath)[1]);
processBundle
(
File
(
entityPath
),
locale
String
:
filenameRE
.
firstMatch
(
entityPath
)[
1
]);
}
}
...
...
dev/tools/localizations_utils.dart
View file @
aab92447
...
...
@@ -9,6 +9,123 @@ import 'dart:io';
import
'package:args/args.dart'
as
argslib
;
import
'package:meta/meta.dart'
;
/// Simple data class to hold parsed locale. Does not promise validity of any data.
class
LocaleInfo
implements
Comparable
<
LocaleInfo
>
{
LocaleInfo
({
this
.
languageCode
,
this
.
scriptCode
,
this
.
countryCode
,
this
.
length
,
this
.
originalString
,
});
/// Simple parser. Expects the locale string to be in the form of 'language_script_COUNTRY'
/// where the langauge is 2 characters, script is 4 characters with the first uppercase,
/// and country is 2-3 characters and all uppercase.
///
/// 'language_COUNTRY' or 'language_script' are also valid. Missing fields will be null.
factory
LocaleInfo
.
fromString
(
String
locale
,
{
bool
assume
=
false
})
{
final
List
<
String
>
codes
=
locale
.
split
(
'_'
);
// [language, script, country]
assert
(
codes
.
isNotEmpty
&&
codes
.
length
<
4
);
final
String
languageCode
=
codes
[
0
];
String
scriptCode
;
String
countryCode
;
int
length
=
codes
.
length
;
String
originalString
=
locale
;
if
(
codes
.
length
==
2
)
{
scriptCode
=
codes
[
1
].
length
>=
4
?
codes
[
1
]
:
null
;
countryCode
=
codes
[
1
].
length
<
4
?
codes
[
1
]
:
null
;
}
else
if
(
codes
.
length
==
3
)
{
scriptCode
=
codes
[
1
].
length
>
codes
[
2
].
length
?
codes
[
1
]
:
codes
[
2
];
countryCode
=
codes
[
1
].
length
<
codes
[
2
].
length
?
codes
[
1
]
:
codes
[
2
];
}
assert
(
codes
[
0
]
!=
null
&&
codes
[
0
].
isNotEmpty
);
assert
(
countryCode
==
null
||
countryCode
.
isNotEmpty
);
assert
(
scriptCode
==
null
||
scriptCode
.
isNotEmpty
);
/// Adds scriptCodes to locales where we are able to assume it to provide
/// finer granularity when resolving locales.
///
/// The basis of the assumptions here are based off of known usage of scripts
/// across various countries. For example, we know Taiwan uses traditional (Hant)
/// script, so it is safe to apply (Hant) to Taiwanese languages.
if
(
assume
&&
scriptCode
==
null
)
{
switch
(
languageCode
)
{
case
'zh'
:
{
if
(
countryCode
==
null
)
{
scriptCode
=
'Hans'
;
}
switch
(
countryCode
)
{
case
'CN'
:
case
'SG'
:
scriptCode
=
'Hans'
;
break
;
case
'TW'
:
case
'HK'
:
case
'MO'
:
scriptCode
=
'Hant'
;
break
;
}
break
;
}
case
'sr'
:
{
if
(
countryCode
==
null
)
{
scriptCode
=
'Cyrl'
;
}
break
;
}
}
// Increment length if we were able to assume a scriptCode.
if
(
scriptCode
!=
null
)
{
length
+=
1
;
}
// Update the base string to reflect assumed scriptCodes.
originalString
=
languageCode
;
if
(
scriptCode
!=
null
)
originalString
+=
'_'
+
scriptCode
;
if
(
countryCode
!=
null
)
originalString
+=
'_'
+
countryCode
;
}
return
LocaleInfo
(
languageCode:
languageCode
,
scriptCode:
scriptCode
,
countryCode:
countryCode
,
length:
length
,
originalString:
originalString
,
);
}
final
String
languageCode
;
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.
@override
bool
operator
==(
Object
other
)
{
if
(!(
other
is
LocaleInfo
))
return
false
;
final
LocaleInfo
otherLocale
=
other
;
return
originalString
==
otherLocale
.
originalString
;
}
@override
int
get
hashCode
{
return
originalString
.
hashCode
;
}
@override
String
toString
()
{
return
originalString
;
}
@override
int
compareTo
(
LocaleInfo
other
)
{
return
originalString
.
compareTo
(
other
.
originalString
);
}
}
void
exitWithError
(
String
errorMessage
)
{
assert
(
errorMessage
!=
null
);
stderr
.
writeln
(
'fatal:
$errorMessage
'
);
...
...
@@ -26,8 +143,8 @@ void checkCwdIsRepoRoot(String commandName) {
}
}
String
camelCase
(
String
locale
)
{
return
locale
String
camelCase
(
LocaleInfo
locale
)
{
return
locale
.
originalString
.
split
(
'_'
)
.
map
<
String
>((
String
part
)
=>
part
.
substring
(
0
,
1
).
toUpperCase
()
+
part
.
substring
(
1
).
toLowerCase
())
.
join
(
''
);
...
...
@@ -129,14 +246,21 @@ String describeLocale(String tag) {
assert
(
subtags
.
isNotEmpty
);
assert
(
_languages
.
containsKey
(
subtags
[
0
]));
final
String
language
=
_languages
[
subtags
[
0
]];
if
(
subtags
.
length
>=
2
)
{
final
String
region
=
_regions
[
subtags
[
1
]];
final
String
script
=
_scripts
[
subtags
[
1
]];
String
output
=
'
$language
'
;
String
region
;
String
script
;
if
(
subtags
.
length
==
2
)
{
region
=
_regions
[
subtags
[
1
]];
script
=
_scripts
[
subtags
[
1
]];
assert
(
region
!=
null
||
script
!=
null
);
if
(
region
!=
null
)
return
'
$language
, as used in
$region
'
;
if
(
script
!=
null
)
return
'
$language
, using the
$script
script'
;
}
else
if
(
subtags
.
length
>=
3
)
{
region
=
_regions
[
subtags
[
2
]]
;
script
=
_scripts
[
subtags
[
1
]];
assert
(
region
!=
null
&&
script
!=
null
)
;
}
return
'
$language
'
;
if
(
region
!=
null
)
output
+=
', as used in
$region
'
;
if
(
script
!=
null
)
output
+=
', using the
$script
script'
;
return
output
;
}
\ No newline at end of file
dev/tools/localizations_validator.dart
View file @
aab92447
...
...
@@ -5,6 +5,8 @@
import
'dart:convert'
show
json
;
import
'dart:io'
;
import
'localizations_utils.dart'
;
// The first suffix in kPluralSuffixes must be "Other". "Other" is special
// because it's the only one that is required.
const
List
<
String
>
kPluralSuffixes
=
<
String
>[
'Other'
,
'Zero'
,
'One'
,
'Two'
,
'Few'
,
'Many'
];
...
...
@@ -96,14 +98,14 @@ void validateEnglishLocalizations(File file) {
///
/// If validation fails, throws an exception.
void
validateLocalizations
(
Map
<
String
,
Map
<
String
,
String
>>
localeToResources
,
Map
<
String
,
Map
<
String
,
dynamic
>>
localeToAttributes
,
Map
<
LocaleInfo
,
Map
<
String
,
String
>>
localeToResources
,
Map
<
LocaleInfo
,
Map
<
String
,
dynamic
>>
localeToAttributes
,
)
{
final
Map
<
String
,
String
>
canonicalLocalizations
=
localeToResources
[
'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
String
locale
in
localeToResources
.
keys
)
{
for
(
final
LocaleInfo
locale
in
localeToResources
.
keys
)
{
final
Map
<
String
,
String
>
resources
=
localeToResources
[
locale
];
// Whether `key` corresponds to one of the plural variations of a key with
...
...
@@ -128,14 +130,12 @@ void validateLocalizations(
final
Set
<
String
>
invalidKeys
=
keys
.
difference
(
canonicalKeys
);
if
(
invalidKeys
.
isNotEmpty
)
errorMessages
.
writeln
(
'Locale "
$locale
" contains invalid resource keys:
${invalidKeys.join(', ')}
'
);
// For language-level locales only, check that they have a complete list of
// keys, or opted out of using certain ones.
if
(
locale
.
length
==
2
)
{
if
(
locale
.
length
==
1
)
{
final
Map
<
String
,
dynamic
>
attributes
=
localeToAttributes
[
locale
];
final
List
<
String
>
missingKeys
=
<
String
>[];
for
(
final
String
missingKey
in
canonicalKeys
.
difference
(
keys
))
{
for
(
final
String
missingKey
in
canonicalKeys
.
difference
(
keys
))
{
final
dynamic
attribute
=
attributes
[
missingKey
];
final
bool
intentionallyOmitted
=
attribute
is
Map
&&
attribute
.
containsKey
(
'notUsed'
);
if
(!
intentionallyOmitted
&&
!
isPluralVariation
(
missingKey
))
...
...
packages/flutter_localizations/lib/src/l10n/date_localizations.dart
View file @
aab92447
...
...
@@ -6779,10 +6779,10 @@ const Map<String, dynamic> dateSymbols = <String, dynamic>{
r''
'S'''
],
'SHORTQUARTERS'
:
<
dynamic
>[
r''
'1.
cet.'''
,
r''
'2.
cet.'''
,
r''
'3.
cet.'''
,
r''
'4.
cet.'''
r''
'1.
cet.'''
,
r''
'2.
cet.'''
,
r''
'3.
cet.'''
,
r''
'4.
cet.'''
],
'QUARTERS'
:
<
dynamic
>[
r''
'1. ceturksnis'''
,
...
...
@@ -13904,4 +13904,4 @@ const Map<String, Map<String, String>> datePatterns =
'zzzz'
:
r''
'zzzz'''
,
'ZZZZ'
:
r''
'ZZZZ'''
,
},
};
};
\ No newline at end of file
packages/flutter_localizations/lib/src/l10n/localizations.dart
View file @
aab92447
...
...
@@ -9927,6 +9927,30 @@ class MaterialLocalizationSr extends GlobalMaterialLocalizations {
String
get
viewLicensesButtonLabel
=>
r'ПРИКАЖИ ЛИЦЕНЦЕ'
;
}
/// The translations for Serbian, using the Cyrillic script (`sr_Cyrl`).
class
MaterialLocalizationSrCyrl
extends
MaterialLocalizationSr
{
/// Create an instance of the translation bundle for Serbian, using the Cyrillic script.
///
/// For details on the meaning of the arguments, see [GlobalMaterialLocalizations].
const
MaterialLocalizationSrCyrl
({
String
localeName
=
'sr_Cyrl'
,
@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
,
);
}
/// The translations for Serbian, using the Latin script (`sr_Latn`).
class
MaterialLocalizationSrLatn
extends
MaterialLocalizationSr
{
/// Create an instance of the translation bundle for Serbian, using the Latin script.
...
...
@@ -11712,13 +11736,37 @@ class MaterialLocalizationZh extends GlobalMaterialLocalizations {
String
get
viewLicensesButtonLabel
=>
r'查看许可'
;
}
/// The translations for Chinese, as used in Hong Kong (`zh_HK`).
class
MaterialLocalizationZhHk
extends
MaterialLocalizationZh
{
/// Create an instance of the translation bundle for Chinese, as used in Hong Kong.
/// The translations for Chinese, using the Han script (`zh_Hans`).
class
MaterialLocalizationZhHans
extends
MaterialLocalizationZh
{
/// Create an instance of the translation bundle for Chinese, using the Han script.
///
/// For details on the meaning of the arguments, see [GlobalMaterialLocalizations].
const
MaterialLocalizationZhHans
({
String
localeName
=
'zh_Hans'
,
@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
,
);
}
/// The translations for Chinese, using the Han script (`zh_Hant`).
class
MaterialLocalizationZhHant
extends
MaterialLocalizationZh
{
/// Create an instance of the translation bundle for Chinese, using the Han script.
///
/// For details on the meaning of the arguments, see [GlobalMaterialLocalizations].
const
MaterialLocalizationZhH
k
({
String
localeName
=
'zh_H
K
'
,
const
MaterialLocalizationZhH
ant
({
String
localeName
=
'zh_H
ant
'
,
@required
intl
.
DateFormat
fullYearFormat
,
@required
intl
.
DateFormat
mediumDateFormat
,
@required
intl
.
DateFormat
longDateFormat
,
...
...
@@ -11871,13 +11919,13 @@ class MaterialLocalizationZhHk extends MaterialLocalizationZh {
String
get
remainingTextFieldCharacterCountOther
=>
r'還可輸入 $remainingCount 個字元'
;
}
/// The translations for Chinese, as used in
Taiwan (`zh_TW
`).
class
MaterialLocalizationZh
Tw
extends
MaterialLocalizationZh
{
/// Create an instance of the translation bundle for Chinese, as used in
Taiwan
.
/// The translations for Chinese, as used in
Hong Kong, using the Han script (`zh_Hant_HK
`).
class
MaterialLocalizationZh
HantHk
extends
MaterialLocalizationZhHant
{
/// Create an instance of the translation bundle for Chinese, as used in
Hong Kong, using the Han script
.
///
/// For details on the meaning of the arguments, see [GlobalMaterialLocalizations].
const
MaterialLocalizationZh
Tw
({
String
localeName
=
'zh_
TW
'
,
const
MaterialLocalizationZh
HantHk
({
String
localeName
=
'zh_
Hant_HK
'
,
@required
intl
.
DateFormat
fullYearFormat
,
@required
intl
.
DateFormat
mediumDateFormat
,
@required
intl
.
DateFormat
longDateFormat
,
...
...
@@ -11893,141 +11941,30 @@ class MaterialLocalizationZhTw extends MaterialLocalizationZh {
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
,
);
}
@override
String
get
tabLabelRaw
=>
r'第 $tabIndex 個分頁 (共 $tabCount 個)'
;
@override
String
get
showAccountsLabel
=>
r'顯示帳戶'
;
@override
String
get
modalBarrierDismissLabel
=>
r'關閉'
;
@override
String
get
hideAccountsLabel
=>
r'隱藏帳戶'
;
@override
String
get
signedInLabel
=>
r'已登入帳戶'
;
@override
String
get
openAppDrawerTooltip
=>
r'開啟導覽選單'
;
@override
String
get
closeButtonTooltip
=>
r'關閉'
;
@override
String
get
deleteButtonTooltip
=>
r'刪除'
;
@override
String
get
nextMonthTooltip
=>
r'下個月'
;
@override
String
get
previousMonthTooltip
=>
r'上個月'
;
@override
String
get
nextPageTooltip
=>
r'下一頁'
;
@override
String
get
previousPageTooltip
=>
r'上一頁'
;
@override
String
get
showMenuTooltip
=>
r'顯示選單'
;
@override
String
get
aboutListTileTitleRaw
=>
r'關於「$applicationName」'
;
@override
String
get
licensesPageTitle
=>
r'授權'
;
@override
String
get
pageRowsInfoTitleRaw
=>
r'第 $firstRow - $lastRow 列 (總共 $rowCount 列)'
;
@override
String
get
pageRowsInfoTitleApproximateRaw
=>
r'第 $firstRow - $lastRow 列 (總共約 $rowCount 列)'
;
@override
String
get
rowsPerPageTitle
=>
r'每頁列數:'
;
@override
String
get
selectedRowCountTitleOne
=>
r'已選取 1 個項目'
;
@override
String
get
selectedRowCountTitleOther
=>
r'已選取 $selectedRowCount 個項目'
;
@override
String
get
closeButtonLabel
=>
r'關閉'
;
@override
String
get
continueButtonLabel
=>
r'繼續'
;
@override
String
get
copyButtonLabel
=>
r'複製'
;
@override
String
get
cutButtonLabel
=>
r'剪下'
;
@override
String
get
okButtonLabel
=>
r'確定'
;
@override
String
get
pasteButtonLabel
=>
r'貼上'
;
@override
String
get
selectAllButtonLabel
=>
r'全選'
;
@override
String
get
viewLicensesButtonLabel
=>
r'查看授權'
;
@override
String
get
timePickerHourModeAnnouncement
=>
r'選取小時數'
;
@override
String
get
timePickerMinuteModeAnnouncement
=>
r'選取分鐘數'
;
@override
String
get
drawerLabel
=>
r'導覽選單'
;
@override
String
get
popupMenuLabel
=>
r'彈出式選單'
;
@override
String
get
dialogLabel
=>
r'對話方塊'
;
@override
String
get
alertDialogLabel
=>
r'快訊'
;
@override
String
get
searchFieldLabel
=>
r'搜尋'
;
@override
String
get
reorderItemToStart
=>
r'移至開頭'
;
@override
String
get
reorderItemToEnd
=>
r'移至結尾'
;
@override
String
get
reorderItemUp
=>
r'向上移'
;
@override
String
get
reorderItemDown
=>
r'向下移'
;
@override
String
get
reorderItemLeft
=>
r'向左移'
;
@override
String
get
reorderItemRight
=>
r'向右移'
;
@override
String
get
expandedIconTapHint
=>
r'收合'
;
@override
String
get
collapsedIconTapHint
=>
r'展開'
;
@override
String
get
remainingTextFieldCharacterCountOne
=>
r'還可輸入 1 個字元'
;
@override
String
get
remainingTextFieldCharacterCountOther
=>
r'還可輸入 $remainingCount 個字元'
;
/// The translations for Chinese, as used in Taiwan, using the Han script (`zh_Hant_TW`).
class
MaterialLocalizationZhHantTw
extends
MaterialLocalizationZhHant
{
/// Create an instance of the translation bundle for Chinese, as used in Taiwan, using the Han script.
///
/// For details on the meaning of the arguments, see [GlobalMaterialLocalizations].
const
MaterialLocalizationZhHantTw
({
String
localeName
=
'zh_Hant_TW'
,
@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
,
);
}
/// The set of supported languages, as language code strings.
...
...
@@ -12107,15 +12044,15 @@ final Set<String> kSupportedLanguages = HashSet<String>.from(const <String>[
/// * `ca` - Catalan Valencian
/// * `cs` - Czech
/// * `da` - Danish
/// * `de` - German (plus one
variant
)
/// * `de` - German (plus one
country variation
)
/// * `el` - Modern Greek
/// * `en` - English (plus 7
variant
s)
/// * `es` - Spanish Castilian (plus 20
variant
s)
/// * `en` - English (plus 7
country variation
s)
/// * `es` - Spanish Castilian (plus 20
country variation
s)
/// * `et` - Estonian
/// * `fa` - Persian
/// * `fi` - Finnish
/// * `fil` - Filipino Pilipino
/// * `fr` - French (plus one
variant
)
/// * `fr` - French (plus one
country variation
)
/// * `gsw` - Swiss German Alemannic Alsatian
/// * `he` - Hebrew
/// * `hi` - Hindi
...
...
@@ -12134,12 +12071,12 @@ final Set<String> kSupportedLanguages = HashSet<String>.from(const <String>[
/// * `nl` - Dutch Flemish
/// * `pl` - Polish
/// * `ps` - Pushto Pashto
/// * `pt` - Portuguese (plus one
variant
)
/// * `pt` - Portuguese (plus one
country variation
)
/// * `ro` - Romanian Moldavian Moldovan
/// * `ru` - Russian
/// * `sk` - Slovak
/// * `sl` - Slovenian
/// * `sr` - Serbian (plus
one variant
)
/// * `sr` - Serbian (plus
2 scripts
)
/// * `sv` - Swedish
/// * `th` - Thai
/// * `tl` - Tagalog
...
...
@@ -12147,7 +12084,7 @@ final Set<String> kSupportedLanguages = HashSet<String>.from(const <String>[
/// * `uk` - Ukrainian
/// * `ur` - Urdu
/// * `vi` - Vietnamese
/// * `zh` - Chinese (plus 2
varian
ts)
/// * `zh` - Chinese (plus 2
country variations and 2 scrip
ts)
/// {@endtemplate}
///
/// Generally speaking, this method is only intended to be used by
...
...
@@ -12314,9 +12251,13 @@ GlobalMaterialLocalizations getTranslation(
case
'sl'
:
return
MaterialLocalizationSl
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
case
'sr'
:
{
switch
(
locale
.
countryCode
)
{
case
'Latn'
:
switch
(
locale
.
scriptCode
)
{
case
'Cyrl'
:
{
return
MaterialLocalizationSrCyrl
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
}
case
'Latn'
:
{
return
MaterialLocalizationSrLatn
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
}
}
return
MaterialLocalizationSr
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
}
...
...
@@ -12335,11 +12276,25 @@ GlobalMaterialLocalizations getTranslation(
case
'vi'
:
return
MaterialLocalizationVi
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
case
'zh'
:
{
switch
(
locale
.
scriptCode
)
{
case
'Hans'
:
{
return
MaterialLocalizationZhHans
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
}
case
'Hant'
:
{
switch
(
locale
.
countryCode
)
{
case
'HK'
:
return
MaterialLocalizationZhHantHk
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
case
'TW'
:
return
MaterialLocalizationZhHantTw
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
}
return
MaterialLocalizationZhHant
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
}
}
switch
(
locale
.
countryCode
)
{
case
'HK'
:
return
MaterialLocalizationZhHk
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
return
MaterialLocalizationZhH
antH
k
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
case
'TW'
:
return
MaterialLocalizationZhTw
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
return
MaterialLocalizationZh
Hant
Tw
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
}
return
MaterialLocalizationZh
(
fullYearFormat:
fullYearFormat
,
mediumDateFormat:
mediumDateFormat
,
longDateFormat:
longDateFormat
,
yearMonthFormat:
yearMonthFormat
,
decimalFormat:
decimalFormat
,
twoDigitZeroPaddedFormat:
twoDigitZeroPaddedFormat
);
}
...
...
packages/flutter_localizations/lib/src/material_localizations.dart
View file @
aab92447
...
...
@@ -568,7 +568,27 @@ class _MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocal
/// data. Subsequent invocations have no effect.
static
void
_loadDateIntlDataIfNotLoaded
()
{
if
(!
_dateIntlDataInitialized
)
{
// TODO(garyq): Add support for scriptCodes. Do not strip scriptCode from string.
// Keep track of initialzed locales, or will fail on attempted double init.
// This can only happen if a locale with a stripped scriptCode has already
// been initialzed. This should be removed when scriptCode stripping is removed.
final
Set
<
String
>
initializedLocales
=
Set
<
String
>();
date_localizations
.
dateSymbols
.
forEach
((
String
locale
,
dynamic
data
)
{
// Strip scriptCode from the locale, as we do not distinguish between scripts
// for dates.
final
List
<
String
>
codes
=
locale
.
split
(
'_'
);
String
countryCode
;
if
(
codes
.
length
==
2
)
{
countryCode
=
codes
[
1
].
length
<
4
?
codes
[
1
]
:
null
;
}
else
if
(
codes
.
length
==
3
)
{
countryCode
=
codes
[
1
].
length
<
codes
[
2
].
length
?
codes
[
1
]
:
codes
[
2
];
}
locale
=
codes
[
0
]
+
(
countryCode
!=
null
?
'_'
+
countryCode
:
''
);
if
(
initializedLocales
.
contains
(
locale
))
return
;
initializedLocales
.
add
(
locale
);
// Perform initialization.
assert
(
date_localizations
.
datePatterns
.
containsKey
(
locale
));
final
intl
.
DateSymbols
symbols
=
intl
.
DateSymbols
.
deserializeFromMap
(
data
);
date_symbol_data_custom
.
initializeDateFormattingCustom
(
...
...
packages/flutter_localizations/test/translations_test.dart
View file @
aab92447
...
...
@@ -153,4 +153,312 @@ void main() {
expect
(
localizations
.
formatMediumDate
(
DateTime
(
2015
,
7
,
23
)),
'Do., 23. Juli'
);
expect
(
localizations
.
formatFullDate
(
DateTime
(
2015
,
7
,
23
)),
'Donnerstag, 23. Juli 2015'
);
});
testWidgets
(
'Chinese resolution'
,
(
WidgetTester
tester
)
async
{
Locale
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
null
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
MaterialLocalizations
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZh
,
true
);
locale
=
const
Locale
(
'zh'
,
'TW'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHantTw
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
null
,
countryCode:
'HK'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHantHk
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
null
,
countryCode:
'TW'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHantTw
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Hans'
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHans
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Hant'
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHant
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Hans'
,
countryCode:
'US'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHans
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Hans'
,
countryCode:
'CN'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHans
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Hans'
,
countryCode:
'TW'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHans
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Hant'
,
countryCode:
'CN'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHant
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Hant'
,
countryCode:
'US'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHant
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
null
,
countryCode:
'US'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZh
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Latn'
,
countryCode:
'US'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZh
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Latn'
,
countryCode:
'TW'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZh
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'en'
,
scriptCode:
null
,
countryCode:
'TW'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEn
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Cyrl'
,
countryCode:
'RU'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZh
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
null
,
countryCode:
'RU'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZh
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Cyrl'
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZh
,
true
);
});
testWidgets
(
'Serbian resolution'
,
(
WidgetTester
tester
)
async
{
Locale
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'sr'
,
scriptCode:
null
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
MaterialLocalizations
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationSr
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'sr'
,
scriptCode:
'Cyrl'
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationSrCyrl
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'sr'
,
scriptCode:
'Latn'
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationSrLatn
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'sr'
,
scriptCode:
null
,
countryCode:
'SR'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationSr
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'sr'
,
scriptCode:
'Cyrl'
,
countryCode:
'SR'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationSrCyrl
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'sr'
,
scriptCode:
'Latn'
,
countryCode:
'SR'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationSrLatn
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'sr'
,
scriptCode:
'Cyrl'
,
countryCode:
'US'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationSrCyrl
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'sr'
,
scriptCode:
'Latn'
,
countryCode:
'US'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationSrLatn
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'sr'
,
scriptCode:
null
,
countryCode:
'US'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationSr
,
true
);
});
testWidgets
(
'Misc resolution'
,
(
WidgetTester
tester
)
async
{
Locale
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'en'
,
scriptCode:
null
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
MaterialLocalizations
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEn
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'en'
,
scriptCode:
'Cyrl'
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEn
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'en'
,
scriptCode:
null
,
countryCode:
'US'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEn
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'en'
,
scriptCode:
null
,
countryCode:
'AU'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEnAu
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'en'
,
scriptCode:
null
,
countryCode:
'GB'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEnGb
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'en'
,
scriptCode:
null
,
countryCode:
'SG'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEnSg
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'en'
,
scriptCode:
null
,
countryCode:
'MX'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEn
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'en'
,
scriptCode:
'Hant'
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEn
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'en'
,
scriptCode:
'Hant'
,
countryCode:
'US'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEn
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'en'
,
scriptCode:
'Hans'
,
countryCode:
'CN'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEn
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'es'
,
scriptCode:
null
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEs
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'es'
,
scriptCode:
null
,
countryCode:
'419'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEs419
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'es'
,
scriptCode:
null
,
countryCode:
'MX'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEsMx
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'es'
,
scriptCode:
null
,
countryCode:
'US'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEsUs
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'es'
,
scriptCode:
null
,
countryCode:
'AR'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEsAr
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'es'
,
scriptCode:
null
,
countryCode:
'ES'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEs
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'es'
,
scriptCode:
'Latn'
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEs
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'es'
,
scriptCode:
'Latn'
,
countryCode:
'US'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationEsUs
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'fr'
,
scriptCode:
null
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationFr
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'fr'
,
scriptCode:
null
,
countryCode:
'CA'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationFrCa
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'de'
,
scriptCode:
null
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationDe
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'de'
,
scriptCode:
null
,
countryCode:
'CH'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationDeCh
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'th'
,
scriptCode:
null
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationTh
,
true
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'ru'
,
scriptCode:
null
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationRu
,
true
);
});
testWidgets
(
'Chinese translations spot check'
,
(
WidgetTester
tester
)
async
{
Locale
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
null
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
MaterialLocalizations
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZh
,
true
);
expect
(
localizations
.
alertDialogLabel
,
'提醒'
);
expect
(
localizations
.
anteMeridiemAbbreviation
,
'上午'
);
expect
(
localizations
.
closeButtonLabel
,
'关闭'
);
expect
(
localizations
.
okButtonLabel
,
'确定'
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Hans'
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHans
,
true
);
expect
(
localizations
.
alertDialogLabel
,
'提醒'
);
expect
(
localizations
.
anteMeridiemAbbreviation
,
'上午'
);
expect
(
localizations
.
closeButtonLabel
,
'关闭'
);
expect
(
localizations
.
okButtonLabel
,
'确定'
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Hant'
,
countryCode:
null
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHant
,
true
);
expect
(
localizations
.
alertDialogLabel
,
'快訊'
);
expect
(
localizations
.
anteMeridiemAbbreviation
,
'上午'
);
expect
(
localizations
.
closeButtonLabel
,
'關閉'
);
expect
(
localizations
.
okButtonLabel
,
'確定'
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Hant'
,
countryCode:
'TW'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHantTw
,
true
);
expect
(
localizations
.
alertDialogLabel
,
'快訊'
);
expect
(
localizations
.
anteMeridiemAbbreviation
,
'上午'
);
expect
(
localizations
.
closeButtonLabel
,
'關閉'
);
expect
(
localizations
.
okButtonLabel
,
'確定'
);
locale
=
const
Locale
.
fromSubtags
(
languageCode:
'zh'
,
scriptCode:
'Hant'
,
countryCode:
'HK'
);
expect
(
GlobalMaterialLocalizations
.
delegate
.
isSupported
(
locale
),
isTrue
);
localizations
=
await
GlobalMaterialLocalizations
.
delegate
.
load
(
locale
);
expect
(
localizations
is
MaterialLocalizationZhHantHk
,
true
);
expect
(
localizations
.
alertDialogLabel
,
'快訊'
);
expect
(
localizations
.
anteMeridiemAbbreviation
,
'上午'
);
expect
(
localizations
.
closeButtonLabel
,
'關閉'
);
expect
(
localizations
.
okButtonLabel
,
'確定'
);
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment