Skip to content

Commit 23abb99

Browse files
committed
chore($ngLocale): refactor i18n closure slurper logic and parse extended datetime symbols
1 parent 0c72708 commit 23abb99

8 files changed

+501
-108
lines changed

i18n/run-tests.sh

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
3+
set -e
4+
PARENT_DIR="$(dirname "$0")"
5+
jasmine-node "$PARENT_DIR"/spec/

i18n/spec/closureI18nExtractorSpec.js

+250
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
var closureI18nExtractor = require('../src/closureI18nExtractor.js');
2+
var converter = require('../src/converter.js');
3+
findLocaleId = closureI18nExtractor.findLocaleId;
4+
extractNumberSymbols = closureI18nExtractor.extractNumberSymbols;
5+
extractCurrencySymbols = closureI18nExtractor.extractCurrencySymbols;
6+
extractDateTimeSymbols = closureI18nExtractor.extractDateTimeSymbols;
7+
8+
9+
function newTestLocaleInfo() {
10+
return { fr_CA: {
11+
DATETIME_FORMATS: {
12+
MONTH: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre',
13+
'octobre', 'novembre', 'décembre'],
14+
SHORTMONTH: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.',
15+
'nov.', 'déc.'],
16+
DAY: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
17+
SHORTDAY: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
18+
AMPMS: ['AM', 'PM'],
19+
medium: 'yyyy-MM-dd HH:mm:ss',
20+
short: 'yy-MM-dd HH:mm',
21+
fullDate: 'EEEE d MMMM y',
22+
longDate: 'd MMMM y',
23+
mediumDate: 'yyyy-MM-dd',
24+
shortDate: 'yy-MM-dd',
25+
mediumTime: 'HH:mm:ss',
26+
shortTime: 'HH:mm'
27+
},
28+
NUMBER_FORMATS: {
29+
"DECIMAL_SEP": ".",
30+
"GROUP_SEP": ",",
31+
"PATTERNS": [{
32+
"minInt": 1,
33+
"minFrac": 0,
34+
"macFrac": 0,
35+
"posPre": "",
36+
"posSuf": "",
37+
"negPre": "-",
38+
"negSuf": "",
39+
"gSize": 3,
40+
"lgSize": 3,
41+
"maxFrac": 3
42+
}, {
43+
"minInt": 1,
44+
"minFrac": 2,
45+
"macFrac": 0,
46+
"posPre": "¤",
47+
"posSuf": "",
48+
"negPre": "¤-",
49+
"negSuf": "",
50+
"gSize": 3,
51+
"lgSize": 3,
52+
"maxFrac": 2
53+
}],
54+
"CURRENCY_SYM": "£"
55+
}}};
56+
}
57+
58+
59+
describe("findLocaleId", function () {
60+
it("should find the id from numbers", function() {
61+
expect(findLocaleId("NumberFormatSymbols_en_GB", "num")).toEqual("en_GB");
62+
});
63+
64+
65+
it("should find the id from datetime", function() {
66+
expect(findLocaleId("DateTimeSymbols_en_ISO", "datetime")).toEqual("en_ISO");
67+
});
68+
69+
70+
it("should throw an error otherwise", function() {
71+
expect(function() {
72+
findLocaleId("str", "otherwise")
73+
}).toThrow("unknown type in findLocaleId: otherwise");
74+
});
75+
});
76+
77+
describe("extractNumberSymbols", function () {
78+
it("should extract number data", function() {
79+
var CONTENT = [
80+
"goog.provide('goog.i18n.NumberFormatSymbols_en_GB');",
81+
"goog.i18n.NumberFormatSymbols_en_GB = {",
82+
"DECIMAL_SEP: '.',",
83+
"GROUP_SEP: ',',",
84+
"PERCENT: '%',",
85+
"ZERO_DIGIT: '0',",
86+
"PLUS_SIGN: '+',",
87+
"MINUS_SIGN: '-',",
88+
"EXP_SYMBOL: 'E',",
89+
"PERMILL: '\u2030',",
90+
"INFINITY: '\u221E',",
91+
"NAN: 'NaN',",
92+
"DECIMAL_PATTERN: '#,##0.###',",
93+
"SCIENTIFIC_PATTERN: '#E0',",
94+
"PERCENT_PATTERN: '#,##0%',",
95+
"CURRENCY_PATTERN: '\u00A4#,##0.00',",
96+
"DEF_CURRENCY_CODE: 'GBP' };"
97+
].join('\n');
98+
99+
var currencySymbols = {'GBP':[2, '£', 'GB£']};
100+
101+
var expectedNumberFormats = converter.convertNumberData(
102+
{
103+
DECIMAL_SEP:'.',
104+
GROUP_SEP:',',
105+
DECIMAL_PATTERN:'#,##0.###',
106+
CURRENCY_PATTERN:'\u00A4#,##0.00',
107+
DEF_CURRENCY_CODE: 'GBP'
108+
}, currencySymbols
109+
);
110+
111+
var localeInfo = {};
112+
extractNumberSymbols(CONTENT, localeInfo, currencySymbols);
113+
114+
expect(localeInfo).toEqual({
115+
'en_GB': { NUMBER_FORMATS: expectedNumberFormats }
116+
});
117+
})
118+
});
119+
120+
describe("extractCurrencySymbols", function () {
121+
it("should extract currency data", function() {
122+
var CONTENT = [
123+
"goog.i18n.currency.CurrencyInfo = {",
124+
" 'GBP':[2, '£', 'GB£'],",
125+
"};",
126+
"goog.i18n.currency.CurrencyInfoTier2 = {",
127+
" 'AOA':[2, 'Kz', 'Kz'],",
128+
"};"
129+
].join('\n');
130+
131+
var localeInfo = {};
132+
expect(extractCurrencySymbols(CONTENT)).toEqual({
133+
'GBP':[2, '£', 'GB£'],
134+
'AOA':[2, 'Kz', 'Kz']
135+
});
136+
});
137+
});
138+
139+
140+
describe("extractDateTimeSymbols", function () {
141+
it("should extract date time data", function() {
142+
var CONTENT = [
143+
"goog.i18n.DateTimeSymbols_fr_CA = {",
144+
" ERAS: ['av. J.-C.', 'ap. J.-C.'],",
145+
" ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],",
146+
" NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],",
147+
" STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',",
148+
" 'N', 'D'],",
149+
" MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',",
150+
" 'août', 'septembre', 'octobre', 'novembre', 'décembre'],",
151+
" STANDALONEMONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin',",
152+
" 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],",
153+
" SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',",
154+
" 'août', 'sept.', 'oct.', 'nov.', 'déc.'],",
155+
" STANDALONESHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin',",
156+
" 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'],",
157+
" WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',",
158+
" 'samedi'],",
159+
" STANDALONEWEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi',",
160+
" 'vendredi', 'samedi'],",
161+
" SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],",
162+
" STANDALONESHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.',",
163+
" 'sam.'],",
164+
" NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],",
165+
" STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],",
166+
" SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],",
167+
" QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],",
168+
" AMPMS: ['AM', 'PM'],",
169+
" DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'yyyy-MM-dd', 'yy-MM-dd'],",
170+
" TIMEFORMATS: ['HH \\'h\\' mm \\'min\\' ss \\'s\\' zzzz', 'HH:mm:ss z',",
171+
" 'HH:mm:ss', 'HH:mm'],",
172+
" FIRSTDAYOFWEEK: 6,",
173+
" WEEKENDRANGE: [5, 6],",
174+
" FIRSTWEEKCUTOFFDAY: 2",
175+
"};"
176+
].join('\n');
177+
var localeInfo = {};
178+
var expectedLocaleInfo = {
179+
fr_CA: {
180+
DATETIME_FORMATS: {
181+
MONTH: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre',
182+
'octobre', 'novembre', 'décembre'],
183+
SHORTMONTH: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.',
184+
'nov.', 'déc.'],
185+
DAY: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
186+
SHORTDAY: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
187+
AMPMS: ['AM', 'PM'],
188+
medium: 'yyyy-MM-dd HH:mm:ss',
189+
short: 'yy-MM-dd HH:mm',
190+
fullDate: 'EEEE d MMMM y',
191+
longDate: 'd MMMM y',
192+
mediumDate: 'yyyy-MM-dd',
193+
shortDate: 'yy-MM-dd',
194+
mediumTime: 'HH:mm:ss',
195+
shortTime: 'HH:mm'
196+
}
197+
}
198+
};
199+
extractDateTimeSymbols(CONTENT, localeInfo);
200+
expect(localeInfo).toEqual(expectedLocaleInfo);
201+
})
202+
});
203+
204+
describe("pluralExtractor", function() {
205+
it("should output PLURAL_CAT in the output string code", function() {
206+
var localeIds = ["fr_CA"];
207+
var content = (
208+
"goog.provide('goog.i18n.pluralRules');\n" +
209+
"\n" +
210+
"goog.i18n.pluralRules.Keyword = {\n" +
211+
" ZERO: 'zero',\n" +
212+
" ONE: 'one',\n" +
213+
" TWO: 'two',\n" +
214+
" FEW: 'few',\n" +
215+
" MANY: 'many',\n" +
216+
" OTHER: 'other'\n" +
217+
"};\n" +
218+
"\n" +
219+
"goog.i18n.pluralRules.frSelect_ = function(n) {\n" +
220+
" if (n >= 0 && n < 2) {\n" +
221+
" return goog.i18n.pluralRules.Keyword.ONE;\n" +
222+
" }\n" +
223+
" return goog.i18n.pluralRules.Keyword.OTHER;\n" +
224+
"};\n" +
225+
"\n" +
226+
"if (goog.LOCALE == 'fr') {\n" +
227+
" goog.i18n.pluralRules.select = goog.i18n.pluralRules.frSelect_;\n" +
228+
"}"
229+
);
230+
var localeInfo = newTestLocaleInfo();
231+
closureI18nExtractor.pluralExtractor(content, localeInfo);
232+
var pluralCat = localeInfo["fr_CA"].pluralCat;
233+
expect(pluralCat).toBeDefined();
234+
// pluralCat is the source text for the pluralCat and contains @@
235+
// placeholders that need to be stripped before evaluation.
236+
// Ref: closureI18nExtractor.pluralExtractor.
237+
pluralCat = pluralCat.replace(/^@@|@@$/g, '');
238+
// pluralCat requires these constants to exist.
239+
var PLURAL_CATEGORY = {
240+
ZERO: "zero", ONE: "one", TWO: "two",
241+
FEW: "few", MANY: "many", OTHER: "other"
242+
};
243+
// Obtain the function by evaluating the source text.
244+
pluralCat = eval("(" + pluralCat + ")");
245+
// Confirm some expectations for pluralCat in fr_CA.
246+
expect(pluralCat(0)).toEqual("one");
247+
expect(pluralCat(3)).toEqual("other");
248+
})
249+
});
250+

i18n/spec/parserSpec.js

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ describe('parsePattern', function() {
2424
parseAndExpect('#,##,##0.###', '', '-', '', '', 1, 0, 3, 2, 3);
2525
parseAndExpect("#,##0.###;\'\u202A\'-#,##0.###\'\u202C\'",
2626
'', '\u202A-', '', '\u202C', 1, 0, 3, 3, 3);
27+
parseAndExpect('#0.###;#0.###-', '', '', '', '-', 1, 0, 3, 0, 0);
28+
2729
});
2830

2931
it('should parse CURRENCY patterns', function() {

0 commit comments

Comments
 (0)