Skip to content

Commit 74bc20c

Browse files
committed
Made several improvements to l10n.js to facilitate fallbacks.
Changed several tests to accommodate the changes to l10n.js. Added tests for language and region fallback.
1 parent 4c476cf commit 74bc20c

File tree

5 files changed

+443
-26
lines changed

5 files changed

+443
-26
lines changed

l10n.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
if (evalResult === false) {
137137
return 1;
138138
}
139+
return evalResult;
139140
}
140141
return 0;
141142
},
@@ -152,7 +153,6 @@
152153
} else if (localization[this_val]) {
153154
return localization[this_val];
154155
}
155-
return this_val;
156156
},
157157
/**
158158
* The actual function called when calling toLocaleString.
@@ -182,23 +182,30 @@
182182
pluralForms.indexOf('nplurals=1') !== -1) {
183183
//i.e. nplurals=1, use [0]
184184
plural = getPlural(localizations[locale], 0, this_val);
185-
return plural.replace('__n__', cardinality);
185+
//only return if plural form is found
186+
if (plural) {
187+
return plural.replace('__n__', cardinality);
188+
}
186189
}
187190
if (pluralForms.indexOf('nplurals=2') !== -1) {
188191
position = parsePlural(pluralForms, cardinality);
189192
plural = getPlural(localizations[locale], position, this_val);
190-
return plural.replace('__n__', cardinality);
193+
//only return if plural form is found
194+
if (plural) {
195+
return plural.replace('__n__', cardinality);
196+
}
191197
}
192198
}
193199
if (localizations[locale][this_val]) {
194200
return localizations[locale][this_val];
195201
}
196202
}
203+
//not returning anything will result in fallback
197204
} while (i-- > 1);
198205

199206
if (!using_default && String.defaultLocale) {
200207
use_default = true;
201-
return localize.call(this_val);
208+
return localize.call(this_val, cardinality);
202209
}
203210

204211
return this_val;

tests/one-locale-plural.html

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
phrase5 = '%phrase5', //in singular form only, with fallback
2020
phrase6 = '%phrase6', //in plural form only, with fallback
2121
phrase7 = '%phrase7', //in both forms, with fallback
22-
e1noPlural = '%phrase1',
23-
e1singular = '%phrase1',
24-
e1plural = '%phrase1',
22+
e0noPlural = 'Peace and harmony in the neighborhood.',
23+
e1noPlural = 'Peace and harmony in the neighborhood.',
24+
e1singular = 'Peace and harmony in the neighborhood.',
25+
e1plural = 'Peace and harmony in the neighborhood.',
2526
e2noPlural = '%phrase2',
2627
e2singular = 'There is 1 book on the shelf.',
2728
e2plural = '%phrase2', //bcos plural form is default, so not translated
@@ -31,9 +32,9 @@
3132
e4noPlural = 'There are many colors in this painting.',
3233
e4singular = 'There is a color in this painting.',
3334
e4plural = 'There are many colors in this painting.',
34-
e5noPlural = "%phrase5",
35+
e5noPlural = "I'm sorry I loved you.",
3536
e5singular = "I'm sorry I love you.",
36-
e5plural = '%phrase5',
37+
e5plural = "I'm sorry I loved you.",
3738
e6noPlural = 'Ice cream flavors',
3839
e6singular = 'Ice cream flavors',
3940
e6plural = 'Ice cream flavors',
@@ -42,7 +43,6 @@
4243
e7plural = 'Impossibilities';
4344

4445
test('1 locale (default)', function () {
45-
//initiate 1 locale
4646
String.toLocaleString({
4747
'en': {
4848
'%phrase1': 'Peace and harmony in the neighborhood.',
@@ -68,32 +68,56 @@
6868
});
6969

7070
equal(phrase1, phrase1, 'No translation expected.');
71-
equal(phrase1.toLocaleString(), phrase1,
72-
'No translation facilitated.');
73-
equal(phrase1.toLocaleString(1), phrase1,
74-
'No translation facilitated.');
75-
equal(phrase1.toLocaleString(2), phrase1,
76-
'No translation facilitated.');
71+
equal(phrase1.toLocaleString(), e0noPlural,
72+
'NULL: Translated as "' + e0noPlural + '" because of fallback.');
73+
equal(phrase1.toLocaleString(1), e0noPlural,
74+
'1: Translated as "' + e0noPlural + '" because of fallback.');
75+
equal(phrase1.toLocaleString(2), e0noPlural,
76+
'2: Translated as "' + e0noPlural + '" because of fallback.');
7777
});
7878

7979
test('1 locale (specified)', function () {
80+
String.toLocaleString({
81+
'en': {
82+
'%phrase1': 'Peace and harmony in the neighborhood.',
83+
'%phrase5': "I'm sorry I loved you.",
84+
'%phrase6': 'Ice cream flavor',
85+
'%phrase7': 'Impossible',
86+
'&plural-forms': 'nplurals=2; plural=(n!=1)',
87+
'&plurals': [
88+
{
89+
'%phrase3': 'For Honors & Glories.',
90+
'%phrase4': 'There are many colors in this painting.',
91+
'%phrase6': 'Ice cream flavors',
92+
'%phrase7': 'Impossibilities'
93+
},
94+
{
95+
'%phrase2': 'There is 1 book on the shelf.',
96+
'%phrase4': 'There is a color in this painting.',
97+
'%phrase5': "I'm sorry I love you.",
98+
'%phrase7': 'Impossibility'
99+
}
100+
]
101+
}
102+
});
103+
80104
String.locale = 'en';
81105

82106
equal(phrase1, phrase1, 'No translation expected.');
83107
equal(phrase1.toLocaleString(), e1noPlural,
84-
'NULL: Not translated when plurality is specified.');
108+
'NULL: Translated as "' + e1noPlural + '" because of fallback.');
85109
equal(phrase1.toLocaleString(1), e1singular,
86-
'1: Not translated - not specified in singular form');
110+
'1: Translated as "' + e1singular + '" because of fallback.');
87111
equal(phrase1.toLocaleString(2), e1plural,
88-
'2: Not translated - not specified in plural form');
112+
'2: Translated as "' + e1plural + '" because of fallback.');
89113

90114
equal(phrase2, phrase2, 'No translation expected.');
91115
equal(phrase2.toLocaleString(), e2noPlural,
92-
'NULL: Not translated when plurality is specified.');
116+
'NULL: Not translated - not in fallback.');
93117
equal(phrase2.toLocaleString(1), e2singular,
94118
'1: Translated as "' + e2singular + '".');
95119
equal(phrase2.toLocaleString(2), e2plural,
96-
'2: Not translated - not specified in plural form');
120+
'2: Not translated - not specified in plural and not in fallback.');
97121

98122
equal(phrase3, phrase3, 'No translation expected.');
99123
equal(phrase3.toLocaleString(), e3noPlural,
@@ -107,17 +131,17 @@
107131
equal(phrase4.toLocaleString(), e4noPlural,
108132
'NULL: Translated as "' + e4noPlural + '" because plural form is default.');
109133
equal(phrase4.toLocaleString(1), e4singular,
110-
'1: Translated as "' + e4singular + '" because plural form is default.');
134+
'1: Translated as "' + e4singular + '".');
111135
equal(phrase4.toLocaleString(2), e4plural,
112136
'2: Translated as "' + e4plural + '".');
113137

114138
equal(phrase5, phrase5, 'No translation expected.');
115139
equal(phrase5.toLocaleString(), e5noPlural,
116140
'NULL: Not translated when plurality is specified.');
117141
equal(phrase5.toLocaleString(1), e5singular,
118-
'1: Translated as "' + e5singular + '" because plural form is default.');
142+
'1: Translated as "' + e5singular + '".');
119143
equal(phrase5.toLocaleString(0), e5plural,
120-
'2: Not translated - not specified in plural form');
144+
'0: Translated as "' + e5plural + '" because of fallback.');
121145

122146
equal(phrase6, phrase6, 'No translation expected.');
123147
equal(phrase6.toLocaleString(), e6noPlural,

tests/plural-language-fallback.html

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>One Locale Test</title>
6+
<link rel="stylesheet" href="qunit.css">
7+
</head>
8+
<body>
9+
<div id="qunit"></div>
10+
<div id="qunit-fixture"></div>
11+
<script src="../l10n.js"></script>
12+
<script src="qunit.js"></script>
13+
</body>
14+
<script>
15+
var phrase1 = "%all",
16+
phrase2 = "%noZhTw",
17+
phrase3 = "%noZh",
18+
phrase4 = "%noZhEnGb",
19+
p1 = '友善的鄰里。',
20+
p2 = '友善的邻里。',
21+
p3 = 'The neighbourhood is very friendly.',
22+
p4 = 'The neighbourhoods are very friendly.',
23+
p5 = 'The neighborhood is very friendly.',
24+
p6 = 'The neighborhoods are very friendly.';
25+
26+
test('en, en-GB, zh & zh-TW: default', function () {
27+
String.toLocaleString({
28+
'en': {
29+
'&plural-forms': 'nplurals=2; plural=(n!=1)',
30+
'&plurals': [
31+
{
32+
'%all': 'The neighborhoods are very friendly.',
33+
'%noZhTw': 'The neighborhoods are very friendly.',
34+
'%noZh': 'The neighborhoods are very friendly.',
35+
'%noZhEnGb': 'The neighborhoods are very friendly.'
36+
},
37+
{
38+
'%all': 'The neighborhood is very friendly.',
39+
'%noZhTw': 'The neighborhood is very friendly.',
40+
'%noZh': 'The neighborhood is very friendly.',
41+
'%noZhEnGb': 'The neighborhood is very friendly.'
42+
}
43+
]
44+
},
45+
'en-GB': {
46+
'&plural-forms': 'nplurals=2; plural=(n!=1)',
47+
'&plurals': [
48+
{
49+
'%all': 'The neighbourhoods are very friendly.',
50+
'%noZhTw': 'The neighbourhoods are very friendly.',
51+
'%noZh': 'The neighbourhoods are very friendly.'
52+
},
53+
{
54+
'%all': 'The neighbourhood is very friendly.',
55+
'%noZhTw': 'The neighbourhood is very friendly.',
56+
'%noZh': 'The neighbourhood is very friendly.'
57+
}
58+
]
59+
},
60+
'zh': {
61+
'&plural-forms': 'nplurals=1; plural=0',
62+
'&plurals': [
63+
{
64+
'%all': '友善的邻里。',
65+
'%noZhTw': '友善的邻里。',
66+
}
67+
]
68+
},
69+
'zh-TW': {
70+
'&plural-forms': 'nplurals=1; plural=0',
71+
'&plurals': [
72+
{
73+
'%all': '友善的鄰里。',
74+
}
75+
]
76+
}
77+
});
78+
79+
equal(phrase1.toLocaleString(), p6,
80+
'NULL: Translated as "' + p6 + '" because plural form is default and implicit default.');
81+
equal(phrase1.toLocaleString(0), p6,
82+
'0: Translated as "' + p6 + '" because of implicit default.');
83+
equal(phrase1.toLocaleString(1), p5,
84+
'1: Translated as "' + p5 + '" because of implicit default.');
85+
equal(phrase1.toLocaleString(2), p6,
86+
'2: Translated as "' + p6 + '" because of implicit default.');
87+
88+
equal(phrase2.toLocaleString(), p6,
89+
'NULL: Translated as "' + p6 + '" because plural form is default and implicit default.');
90+
equal(phrase2.toLocaleString(0), p6,
91+
'0: Translated as "' + p6 + '" because of implicit default.');
92+
equal(phrase2.toLocaleString(1), p5,
93+
'1: Translated as "' + p5 + '" because of implicit default.');
94+
equal(phrase2.toLocaleString(2), p6,
95+
'2: Translated as "' + p6 + '" because of implicit default.');
96+
97+
equal(phrase3.toLocaleString(), p6,
98+
'NULL: Translated as "' + p6 + '" because plural form is default and implicit default.');
99+
equal(phrase3.toLocaleString(0), p6,
100+
'0: Translated as "' + p6 + '" because of implicit default.');
101+
equal(phrase3.toLocaleString(1), p5,
102+
'1: Translated as "' + p5 + '" because of implicit default.');
103+
equal(phrase3.toLocaleString(2), p6,
104+
'2: Translated as "' + p6 + '" because of implicit default.');
105+
106+
equal(phrase4.toLocaleString(), p6,
107+
'NULL: Translated as "' + p6 + '" because plural form is default and implicit default.');
108+
equal(phrase4.toLocaleString(0), p6,
109+
'0: Translated as "' + p6 + '" because of implicit default.');
110+
equal(phrase4.toLocaleString(1), p5,
111+
'1: Translated as "' + p5 + '" because of implicit default.');
112+
equal(phrase4.toLocaleString(2), p6,
113+
'2: Translated as "' + p6 + '" because of implicit default.');
114+
});
115+
116+
test('en, en-GB, zh & zh-TW: zh-TW', function () {
117+
String.locale = 'zh-TW';
118+
119+
equal(phrase1.toLocaleString(), p1,
120+
'NULL: Translated as "' + p1 + '".');
121+
equal(phrase1.toLocaleString(0), p1,
122+
'0: Translated as "' + p1 + '".');
123+
equal(phrase1.toLocaleString(1), p1,
124+
'1: Translated as "' + p1 + '".');
125+
equal(phrase1.toLocaleString(2), p1,
126+
'2: Translated as "' + p1 + '".');
127+
128+
equal(phrase2.toLocaleString(), p2,
129+
'NULL: Translated as "' + p2 + '" because of region fallback.');
130+
equal(phrase2.toLocaleString(0), p2,
131+
'0: Translated as "' + p2 + '" because of region fallback.');
132+
equal(phrase2.toLocaleString(1), p2,
133+
'1: Translated as "' + p2 + '" because of region fallback.');
134+
equal(phrase2.toLocaleString(2), p2,
135+
'2: Translated as "' + p2 + '" because of region fallback.');
136+
137+
equal(phrase3.toLocaleString(), phrase3,
138+
'NULL: Translated as "' + phrase3 + '" because no default.');
139+
equal(phrase3.toLocaleString(0), phrase3,
140+
'0: Translated as "' + phrase3 + '" because no default.');
141+
equal(phrase3.toLocaleString(1), phrase3,
142+
'1: Translated as "' + phrase3 + '" because no default.');
143+
equal(phrase3.toLocaleString(2), phrase3,
144+
'2: Translated as "' + phrase3 + '" because no default.');
145+
146+
equal(phrase4.toLocaleString(), phrase4,
147+
'NULL: Translated as "' + phrase4 + '" because no default.');
148+
equal(phrase4.toLocaleString(0), phrase4,
149+
'0: Translated as "' + phrase4 + '" because no default.');
150+
equal(phrase4.toLocaleString(1), phrase4,
151+
'1: Translated as "' + phrase4 + '" because no default.');
152+
equal(phrase4.toLocaleString(2), phrase4,
153+
'2: Translated as "' + phrase4 + '" because no default.');
154+
});
155+
156+
test('en, en-GB, zh & zh-TW: zh-TW with en-GB default', function () {
157+
String.defaultLocale = 'en-GB';
158+
String.locale = 'zh-TW';
159+
160+
equal(phrase1.toLocaleString(), p1,
161+
'NULL: Translated as "' + p1 + '".');
162+
equal(phrase1.toLocaleString(0), p1,
163+
'0: Translated as "' + p1 + '".');
164+
equal(phrase1.toLocaleString(1), p1,
165+
'1: Translated as "' + p1 + '".');
166+
equal(phrase1.toLocaleString(2), p1,
167+
'2: Translated as "' + p1 + '".');
168+
169+
equal(phrase2.toLocaleString(), p2,
170+
'NULL: Translated as "' + p2 + '" because of region fallback.');
171+
equal(phrase2.toLocaleString(0), p2,
172+
'0: Translated as "' + p2 + '" because of region fallback.');
173+
equal(phrase2.toLocaleString(1), p2,
174+
'1: Translated as "' + p2 + '" because of region fallback.');
175+
equal(phrase2.toLocaleString(2), p2,
176+
'2: Translated as "' + p2 + '" because of region fallback.');
177+
178+
equal(phrase3.toLocaleString(), p4,
179+
'NULL: Translated as "' + p4 + '" because of default fallback.');
180+
equal(phrase3.toLocaleString(0), p4,
181+
'0: Translated as "' + p4 + '" because of default fallback.');
182+
equal(phrase3.toLocaleString(1), p3,
183+
'1: Translated as "' + p3 + '" because of default fallback.');
184+
equal(phrase3.toLocaleString(2), p4,
185+
'2: Translated as "' + p4 + '" because of default fallback.');
186+
187+
equal(phrase4.toLocaleString(), p6,
188+
'NULL: Translated as "' + p6 + '" because of default & region fallback.');
189+
equal(phrase4.toLocaleString(0), p6,
190+
'0: Translated as "' + p6 + '" because of default & region fallback.');
191+
equal(phrase4.toLocaleString(1), p5,
192+
'1: Translated as "' + p5 + '" because of default & region fallback.');
193+
equal(phrase4.toLocaleString(2), p6,
194+
'2: Translated as "' + p6 + '" because of default & region fallback.');
195+
});
196+
197+
</script>
198+
</html>
199+

0 commit comments

Comments
 (0)