UNPKG

intl

Version:

Polyfill the ECMA-402 Intl API (except collation)

168 lines (124 loc) 4.68 kB
/* global Promise */ import * as fs from 'fs'; import * as p from 'path'; import {sync as mkdirpSync} from 'mkdirp'; function writeFile(filename, contents) { return new Promise((resolve, reject) => { fs.writeFile(filename, contents, (err) => { if (err) { reject(err); } else { resolve(p.resolve(filename)); } }); }); } function mergeData(...sources) { return sources.reduce((data, source) => { Object.keys(source || {}).forEach((locale) => { data[locale] = Object.assign(data[locale] || {}, source[locale]); }); return data; }, {}); } function reviver (k, v) { let idx; if (k === 'locale') return v; else if (typeof v === 'string') { idx = prims.indexOf(v); valCount++; if (idx === -1) idx += prims.push(v); return '###prims['+ idx +']###'; } else if (typeof v === 'object' && v !== null) { const str = JSON.stringify(v); objCount++; if (objStrs.hasOwnProperty(str)) return objStrs[str]; // We need to make sure this object is not added to the same // array as an object it references (and we need to check // this recursively) let depth; let objDepths = [0]; for (let key in v) { if (typeof v[key] === 'string' && (depth = v[key].match(/^###objs\[(\d+)/))) objDepths.push(+depth[1] + 1); } depth = Math.max.apply(Math, objDepths); if (!Array.isArray(objs[depth])) objs[depth] = []; idx = objs[depth].push(v) - 1; objStrs[str] = '###objs['+ depth +']['+ idx +']###'; return objStrs[str]; } return v; } // ----------------------------------------------------------------------------- mkdirpSync('locale-data/'); mkdirpSync('locale-data/json/'); mkdirpSync('locale-data/jsonp/'); // extracting data into CLDR // Regex for converting locale JSON to object grammar, obviously simple and // incomplete but should be good enough for the CLDR JSON const jsonpExp = /"(?!default)([\w$][\w\d$]+)":/g; import reduceLocaleData from './utils/reduce'; import extractCalendars from './utils/extract-calendars'; import extractNumbersFields from './utils/extract-numbers'; import {getAllLocales} from './utils/locales'; // Default to all CLDR locales. const locales = getAllLocales(); // Each type of data has the structure: `{"<locale>": {"<key>": <value>}}`, // which is well suited for merging into a single object per locale. This // performs that deep merge and returns the aggregated result. let locData = mergeData( extractCalendars(locales), extractNumbersFields(locales) ); let locStringData = {}; Object.keys(locData).forEach((locale) => { // Ignore en-US-POSIX and root if (locale.toLowerCase() === 'en-us-posix') { return; } const obj = reduceLocaleData(locale, locData[locale]); locStringData[locale] = JSON.stringify(obj, null, 4); const jsonpContent = `IntlPolyfill.__addLocaleData(${JSON.stringify(obj).replace(jsonpExp, '$1:')});`; writeFile('locale-data/json/' + locale + '.json', locStringData[locale]); writeFile('locale-data/jsonp/' + locale + '.js', jsonpContent); }); console.log('Total number of locales is ' + Object.keys(locData).length); // compiling `locale-date/complete.js` function replacer($0, type, loc) { return (type === 'prims' ? 'a' : 'b') + loc; } let objStrs = {}, objs = [], prims = [], valCount = 0, objCount = 0, fileData = ''; fileData += '(function(addLocaleData){\n'; let locReducedData = {}; Object.keys(locStringData).forEach((k) => { const c = locStringData[k]; locReducedData[k] = JSON.parse(c, reviver); }); fileData += `var a=${JSON.stringify(prims)},b=[];`; objs.forEach((val, idx) => { const ref = JSON.stringify(val).replace(/"###(objs|prims)(\[[^#]+)###"/g, replacer); fileData += `b[${idx}]=${ref};`; }); for (let k in locReducedData) { fileData += `addLocaleData(${locReducedData[k].replace(/###(objs|prims)(\[[^#]+)###/, replacer)}); `; } fileData += `})(IntlPolyfill.__addLocaleData);`; // writting the complete optimized bundle writeFile('locale-data/complete.js', fileData); console.log('Total number of reused strings is ' + prims.length + ' (reduced from ' + valCount + ')'); console.log('Total number of reused objects is ' + Object.keys(objStrs).length + ' (reduced from ' + objCount + ')'); process.on('unhandledRejection', (reason) => {throw reason;}); console.log('Writing locale data files...');