Skip to content

Commit 6d680ad

Browse files
Merge pull request #948 from kszczek:ignore-script-subtags
PiperOrigin-RevId: 735705695
2 parents bdeec25 + 88ab7a8 commit 6d680ad

File tree

5 files changed

+58
-8
lines changed

5 files changed

+58
-8
lines changed

pkgs/intl/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
* Updated the Turkish Lira (TRY) currency symbol in `simpleCurrencySymbols`
33
from "TL" to "₺" (U+20BA). This ensures accuracy and alignment with the
44
official symbol introduced in 2012.
5+
* Fix parsing of locale strings containing script codes in `verifiedLocale`.
6+
For example, `zh-Hans-CN` would have been previously parsed as `zh`, but is
7+
now parsed as `zh_CN`.
58

69
## 0.20.2
710
* Remove the dependency on `package:http`.

pkgs/intl/lib/intl.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,8 @@ class Intl {
208208
helpers.verifiedLocale(newLocale, localeExists, onFailure);
209209

210210
/// Return the short version of a locale name, e.g. 'en_US' => 'en'
211-
static String shortLocale(String aLocale) => helpers.shortLocale(aLocale);
211+
static String shortLocale(String aLocale) =>
212+
helpers.languageOnlyLocale(aLocale);
212213

213214
/// Return the name [aLocale] turned into xx_YY where it might possibly be
214215
/// in the wrong case or with a hyphen instead of an underscore. If

pkgs/intl/lib/src/intl_helpers.dart

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,10 @@ String? computeMessageName(String? name, String? text, String? meaning) {
128128
return meaning == null ? text : '${text}_$meaning';
129129
}
130130

131-
/// Returns an index of a separator between language and region.
131+
/// Returns an index of a separator between language and other subtags.
132132
///
133133
/// Assumes that language length can be only 2 or 3.
134-
int _separatorIndex(String locale) {
134+
int _languageSeparatorIndex(String locale) {
135135
if (locale.length < 3) {
136136
return -1;
137137
}
@@ -147,6 +147,19 @@ int _separatorIndex(String locale) {
147147
return -1;
148148
}
149149

150+
/// Returns an index of a separator between script and region.
151+
///
152+
/// Assumes that script contains exactly 4 characters.
153+
int _scriptSeparatorIndex(String region) {
154+
if (region.length < 5) {
155+
return -1;
156+
}
157+
if (region[4] == '-' || region[4] == '_') {
158+
return 4;
159+
}
160+
return -1;
161+
}
162+
150163
String canonicalizedLocale(String? aLocale) {
151164
// Locales of length < 5 are presumably two-letter forms, or else malformed.
152165
// We return them unmodified and if correct they will be found.
@@ -159,7 +172,7 @@ String canonicalizedLocale(String? aLocale) {
159172
if (aLocale == 'C') return 'en_ISO';
160173
if (aLocale.length < 5) return aLocale;
161174

162-
var separatorIndex = _separatorIndex(aLocale);
175+
var separatorIndex = _languageSeparatorIndex(aLocale);
163176
if (separatorIndex == -1) {
164177
return aLocale;
165178
}
@@ -186,9 +199,10 @@ String? verifiedLocale(String? newLocale, bool Function(String) localeExists,
186199
}
187200
final fallbackOptions = [
188201
canonicalizedLocale,
189-
shortLocale,
202+
languageRegionOnlyLocale,
203+
languageOnlyLocale,
190204
deprecatedLocale,
191-
(locale) => deprecatedLocale(shortLocale(locale)),
205+
(locale) => deprecatedLocale(languageOnlyLocale(locale)),
192206
(locale) => deprecatedLocale(canonicalizedLocale(locale)),
193207
(_) => 'fallback'
194208
];
@@ -233,15 +247,15 @@ String deprecatedLocale(String aLocale) {
233247
}
234248

235249
/// Return the short version of a locale name, e.g. 'en_US' => 'en'
236-
String shortLocale(String aLocale) {
250+
String languageOnlyLocale(String aLocale) {
237251
// TODO(b/241094372): Remove this check.
238252
if (aLocale == 'invalid') {
239253
return 'in';
240254
}
241255
if (aLocale.length < 2) {
242256
return aLocale;
243257
}
244-
var separatorIndex = _separatorIndex(aLocale);
258+
var separatorIndex = _languageSeparatorIndex(aLocale);
245259
if (separatorIndex == -1) {
246260
if (aLocale.length < 4) {
247261
// aLocale is already only a language code.
@@ -253,3 +267,19 @@ String shortLocale(String aLocale) {
253267
}
254268
return aLocale.substring(0, separatorIndex).toLowerCase();
255269
}
270+
271+
String languageRegionOnlyLocale(String aLocale) {
272+
if (aLocale.length < 10) return aLocale;
273+
274+
var separatorIndex = _languageSeparatorIndex(aLocale);
275+
if (separatorIndex == -1) {
276+
return aLocale;
277+
}
278+
var language = aLocale.substring(0, separatorIndex);
279+
var subtags = aLocale.substring(separatorIndex + 1);
280+
separatorIndex = _scriptSeparatorIndex(subtags);
281+
var region = subtags.substring(separatorIndex + 1);
282+
// If it's longer than three it's something odd, so don't touch it.
283+
if (region.length <= 3) region = region.toUpperCase();
284+
return '${language}_$region';
285+
}

pkgs/intl/test/intl_test.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ void main() {
5151
expect(Intl.verifiedLocale('en-ZZ', NumberFormat.localeExists), 'en');
5252
expect(Intl.verifiedLocale('es-999', NumberFormat.localeExists), 'es');
5353
expect(Intl.verifiedLocale('gsw-CH', NumberFormat.localeExists), 'gsw');
54+
expect(
55+
Intl.verifiedLocale('zh-Hant-CN', NumberFormat.localeExists),
56+
'zh_CN',
57+
);
5458

5559
void checkAsNumberDefault(String locale, String expected) {
5660
var oldDefault = Intl.defaultLocale;
@@ -74,6 +78,7 @@ void main() {
7478
expect(Intl.verifiedLocale('en-ZZ', DateFormat.localeExists), 'en');
7579
expect(Intl.verifiedLocale('es-999', DateFormat.localeExists), 'es');
7680
expect(Intl.verifiedLocale('gsw-CH', DateFormat.localeExists), 'gsw');
81+
expect(Intl.verifiedLocale('zh-Hant-CN', DateFormat.localeExists), 'zh_CN');
7782
// TODO(b/241094372): Remove this check.
7883
expect(Intl.verifiedLocale('invalid', DateFormat.localeExists), 'in');
7984

pkgs/intl/test/number_format_test_core.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,17 @@ void runTests(Map<String, num> allTestNumbers) {
650650
});
651651
}
652652
});
653+
654+
test('Use script', () {
655+
expect(
656+
NumberFormat.currency(locale: 'zh_Hant_TW').format(12),
657+
'TWD12.00',
658+
);
659+
expect(
660+
NumberFormat.currency(locale: 'zh_Hant_CN').format(12),
661+
'CNY12.00',
662+
);
663+
});
653664
}
654665

655666
String stripExtras(String input) {

0 commit comments

Comments
 (0)