UNPKG

4.68 kBJavaScriptView Raw
1/* global Promise */
2import * as fs from 'fs';
3import * as p from 'path';
4import {sync as mkdirpSync} from 'mkdirp';
5
6function writeFile(filename, contents) {
7 return new Promise((resolve, reject) => {
8 fs.writeFile(filename, contents, (err) => {
9 if (err) {
10 reject(err);
11 } else {
12 resolve(p.resolve(filename));
13 }
14 });
15 });
16}
17
18function mergeData(...sources) {
19 return sources.reduce((data, source) => {
20 Object.keys(source || {}).forEach((locale) => {
21 data[locale] = Object.assign(data[locale] || {}, source[locale]);
22 });
23
24 return data;
25 }, {});
26}
27
28function reviver (k, v) {
29 let idx;
30
31 if (k === 'locale')
32 return v;
33
34 else if (typeof v === 'string') {
35 idx = prims.indexOf(v);
36 valCount++;
37
38 if (idx === -1)
39 idx += prims.push(v);
40
41 return '###prims['+ idx +']###';
42 }
43
44 else if (typeof v === 'object' && v !== null) {
45 const str = JSON.stringify(v);
46 objCount++;
47
48 if (objStrs.hasOwnProperty(str))
49 return objStrs[str];
50
51 // We need to make sure this object is not added to the same
52 // array as an object it references (and we need to check
53 // this recursively)
54 let depth;
55 let objDepths = [0];
56
57 for (let key in v) {
58 if (typeof v[key] === 'string' && (depth = v[key].match(/^###objs\[(\d+)/)))
59 objDepths.push(+depth[1] + 1);
60 }
61
62 depth = Math.max.apply(Math, objDepths);
63
64 if (!Array.isArray(objs[depth]))
65 objs[depth] = [];
66
67 idx = objs[depth].push(v) - 1;
68 objStrs[str] = '###objs['+ depth +']['+ idx +']###';
69
70 return objStrs[str];
71 }
72
73 return v;
74}
75
76// -----------------------------------------------------------------------------
77
78mkdirpSync('locale-data/');
79mkdirpSync('locale-data/json/');
80mkdirpSync('locale-data/jsonp/');
81
82// extracting data into CLDR
83
84// Regex for converting locale JSON to object grammar, obviously simple and
85// incomplete but should be good enough for the CLDR JSON
86const jsonpExp = /"(?!default)([\w$][\w\d$]+)":/g;
87
88import reduceLocaleData from './utils/reduce';
89
90import extractCalendars from './utils/extract-calendars';
91import extractNumbersFields from './utils/extract-numbers';
92import {getAllLocales} from './utils/locales';
93
94// Default to all CLDR locales.
95const locales = getAllLocales();
96
97// Each type of data has the structure: `{"<locale>": {"<key>": <value>}}`,
98// which is well suited for merging into a single object per locale. This
99// performs that deep merge and returns the aggregated result.
100let locData = mergeData(
101 extractCalendars(locales),
102 extractNumbersFields(locales)
103);
104
105let locStringData = {};
106
107Object.keys(locData).forEach((locale) => {
108 // Ignore en-US-POSIX and root
109 if (locale.toLowerCase() === 'en-us-posix') {
110 return;
111 }
112
113 const obj = reduceLocaleData(locale, locData[locale]);
114 locStringData[locale] = JSON.stringify(obj, null, 4);
115 const jsonpContent = `IntlPolyfill.__addLocaleData(${JSON.stringify(obj).replace(jsonpExp, '$1:')});`;
116 writeFile('locale-data/json/' + locale + '.json', locStringData[locale]);
117 writeFile('locale-data/jsonp/' + locale + '.js', jsonpContent);
118});
119
120console.log('Total number of locales is ' + Object.keys(locData).length);
121
122// compiling `locale-date/complete.js`
123
124function replacer($0, type, loc) {
125 return (type === 'prims' ? 'a' : 'b') + loc;
126}
127
128let
129 objStrs = {},
130 objs = [],
131 prims = [],
132
133 valCount = 0,
134 objCount = 0,
135
136 fileData = '';
137
138fileData += '(function(addLocaleData){\n';
139
140let locReducedData = {};
141Object.keys(locStringData).forEach((k) => {
142 const c = locStringData[k];
143 locReducedData[k] = JSON.parse(c, reviver);
144});
145
146fileData += `var a=${JSON.stringify(prims)},b=[];`;
147objs.forEach((val, idx) => {
148 const ref = JSON.stringify(val).replace(/"###(objs|prims)(\[[^#]+)###"/g, replacer);
149
150 fileData += `b[${idx}]=${ref};`;
151});
152
153for (let k in locReducedData) {
154 fileData += `addLocaleData(${locReducedData[k].replace(/###(objs|prims)(\[[^#]+)###/, replacer)});
155`;
156}
157
158fileData += `})(IntlPolyfill.__addLocaleData);`;
159
160// writting the complete optimized bundle
161writeFile('locale-data/complete.js', fileData);
162
163console.log('Total number of reused strings is ' + prims.length + ' (reduced from ' + valCount + ')');
164console.log('Total number of reused objects is ' + Object.keys(objStrs).length + ' (reduced from ' + objCount + ')');
165
166process.on('unhandledRejection', (reason) => {throw reason;});
167console.log('Writing locale data files...');