| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const fs = require('fs'); | 
					
						
							|  |  |  | const yargs = require('yargs').argv; | 
					
						
							| 
									
										
										
										
											2019-11-08 14:14:27 -08:00
										 |  |  | const shelljs = require('shelljs'); | 
					
						
							| 
									
										
										
										
											2017-08-29 17:02:20 -07:00
										 |  |  | const {I18N_DATA_FOLDER, RELATIVE_I18N_DATA_FOLDER, HEADER} = require('./extract'); | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  | const OUTPUT_NAME = `closure-locale.ts`; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-22 19:51:03 +02:00
										 |  |  | // tslint:disable:no-console
 | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  | module.exports = (gulp, done) => { | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  |   // the locales used by closure that will be used to generate the closure-locale file
 | 
					
						
							|  |  |  |   // extracted from:
 | 
					
						
							|  |  |  |   // https://github.com/google/closure-library/blob/master/closure/goog/i18n/datetimepatterns.js#L2136
 | 
					
						
							|  |  |  |   let GOOG_LOCALES = [ | 
					
						
							|  |  |  |     'af',    'am',    'ar',    'ar-DZ', 'az',    'be',    'bg',    'bn',     'br',    'bs', | 
					
						
							|  |  |  |     'ca',    'chr',   'cs',    'cy',    'da',    'de',    'de-AT', 'de-CH',  'el',    'en-AU', | 
					
						
							|  |  |  |     'en-CA', 'en-GB', 'en-IE', 'en-IN', 'en-SG', 'en-ZA', 'es',    'es-419', 'es-MX', 'es-US', | 
					
						
							|  |  |  |     'et',    'eu',    'fa',    'fi',    'fr',    'fr-CA', 'ga',    'gl',     'gsw',   'gu', | 
					
						
							|  |  |  |     'haw',   'hi',    'hr',    'hu',    'hy',    'in',    'is',    'it',     'iw',    'ja', | 
					
						
							|  |  |  |     'ka',    'kk',    'km',    'kn',    'ko',    'ky',    'ln',    'lo',     'lt',    'lv', | 
					
						
							|  |  |  |     'mk',    'ml',    'mn',    'mo',    'mr',    'ms',    'mt',    'my',     'ne',    'nl', | 
					
						
							|  |  |  |     'no',    'or',    'pa',    'pl',    'pt',    'pt-PT', 'ro',    'ru',     'sh',    'si', | 
					
						
							|  |  |  |     'sk',    'sl',    'sq',    'sr',    'sv',    'sw',    'ta',    'te',     'th',    'tl', | 
					
						
							|  |  |  |     'tr',    'uk',    'ur',    'uz',    'vi',    'zh',    'zh-CN', 'zh-HK',  'zh-TW', 'zu' | 
					
						
							|  |  |  |   ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // locale id aliases to support deprecated locale ids used by closure
 | 
					
						
							|  |  |  |   // it maps deprecated ids --> new ids
 | 
					
						
							|  |  |  |   // manually extracted from ./cldr-data/supplemental/aliases.json
 | 
					
						
							|  |  |  |   const ALIASES = { | 
					
						
							|  |  |  |     'in': 'id', | 
					
						
							|  |  |  |     'iw': 'he', | 
					
						
							|  |  |  |     'mo': 'ro-MD', | 
					
						
							|  |  |  |     'no': 'nb', | 
					
						
							|  |  |  |     'nb': 'no-NO', | 
					
						
							|  |  |  |     'sh': 'sr-Latn', | 
					
						
							|  |  |  |     'tl': 'fil', | 
					
						
							|  |  |  |     'pt': 'pt-BR', | 
					
						
							|  |  |  |     'zh-CN': 'zh-Hans-CN', | 
					
						
							|  |  |  |     'zh-Hans-CN': 'zh-Hans', | 
					
						
							|  |  |  |     'zh-HK': 'zh-Hant-HK', | 
					
						
							|  |  |  |     'zh-TW': 'zh-Hant-TW', | 
					
						
							| 
									
										
										
										
											2017-08-29 17:02:20 -07:00
										 |  |  |     'zh-Hant-TW': 'zh-Hant', | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  |   if (yargs.locales) { | 
					
						
							|  |  |  |     GOOG_LOCALES = yargs.locales.split(','); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   console.log(`Writing file ${I18N_DATA_FOLDER}/${OUTPUT_NAME}`); | 
					
						
							|  |  |  |   fs.writeFileSync( | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  |       `${RELATIVE_I18N_DATA_FOLDER}/${OUTPUT_NAME}`, generateAllLocalesFile(GOOG_LOCALES, ALIASES)); | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   console.log(`Formatting ${I18N_DATA_FOLDER}/${OUTPUT_NAME}..."`); | 
					
						
							| 
									
										
										
										
											2019-11-08 14:14:27 -08:00
										 |  |  |   shelljs.exec(`yarn clang-format -i ${I18N_DATA_FOLDER}/${OUTPUT_NAME}`, {silent: true}); | 
					
						
							|  |  |  |   done(); | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Generate a file that contains all locale to import for closure. | 
					
						
							|  |  |  |  * Tree shaking will only keep the data for the `goog.LOCALE` locale. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  | function generateAllLocalesFile(LOCALES, ALIASES) { | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |   const existingLocalesAliases = {}; | 
					
						
							|  |  |  |   const existingLocalesData = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // for each locale, get the data and the list of equivalent locales
 | 
					
						
							|  |  |  |   LOCALES.forEach(locale => { | 
					
						
							|  |  |  |     const eqLocales = new Set(); | 
					
						
							|  |  |  |     eqLocales.add(locale); | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  |     if (locale.match(/-/)) { | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |       eqLocales.add(locale.replace(/-/g, '_')); | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // check for aliases
 | 
					
						
							|  |  |  |     const alias = ALIASES[locale]; | 
					
						
							|  |  |  |     if (alias) { | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |       eqLocales.add(alias); | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-30 00:29:21 +02:00
										 |  |  |       if (alias.match(/-/)) { | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |         eqLocales.add(alias.replace(/-/g, '_')); | 
					
						
							| 
									
										
										
										
											2017-08-30 00:29:21 +02:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  |       // to avoid duplicated "case" we regroup all locales in the same "case"
 | 
					
						
							|  |  |  |       // the simplest way to do that is to have alias aliases
 | 
					
						
							|  |  |  |       // e.g. 'no' --> 'nb', 'nb' --> 'no-NO'
 | 
					
						
							|  |  |  |       // which means that we'll have 'no', 'nb' and 'no-NO' in the same "case"
 | 
					
						
							|  |  |  |       const aliasKeys = Object.keys(ALIASES); | 
					
						
							|  |  |  |       for (let i = 0; i < aliasKeys.length; i++) { | 
					
						
							|  |  |  |         const aliasValue = ALIASES[alias]; | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |         if (aliasKeys.indexOf(alias) !== -1 && !eqLocales.has(aliasValue)) { | 
					
						
							|  |  |  |           eqLocales.add(aliasValue); | 
					
						
							| 
									
										
										
										
											2017-08-30 00:29:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |           if (aliasValue.match(/-/)) { | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |             eqLocales.add(aliasValue.replace(/-/g, '_')); | 
					
						
							| 
									
										
										
										
											2017-08-30 00:29:21 +02:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |     for (let l of eqLocales) { | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  |       // find the existing content file
 | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |       const path = `${RELATIVE_I18N_DATA_FOLDER}/${l}.ts`; | 
					
						
							|  |  |  |       if (fs.existsSync(`${RELATIVE_I18N_DATA_FOLDER}/${l}.ts`)) { | 
					
						
							| 
									
										
										
										
											2018-01-29 22:22:06 +01:00
										 |  |  |         const localeName = formatLocale(locale); | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |         existingLocalesData[locale] = | 
					
						
							| 
									
										
										
										
											2018-01-29 22:22:06 +01:00
										 |  |  |             fs.readFileSync(path, 'utf8') | 
					
						
							|  |  |  |                 .replace(`${HEADER}\n`, '') | 
					
						
							|  |  |  |                 .replace('export default ', `export const locale_${localeName} = `) | 
					
						
							|  |  |  |                 .replace('function plural', `function plural_${localeName}`) | 
					
						
							| 
									
										
										
										
											2018-04-13 23:35:20 +02:00
										 |  |  |                 .replace(/,(\n  | )plural/, `, plural_${localeName}`) | 
					
						
							|  |  |  |                 .replace('const u = undefined;\n\n', ''); | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |     existingLocalesAliases[locale] = eqLocales; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function generateCases(locale) { | 
					
						
							|  |  |  |     let str = ''; | 
					
						
							| 
									
										
										
										
											2018-09-07 11:26:11 -07:00
										 |  |  |     let locales = []; | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |     const eqLocales = existingLocalesAliases[locale]; | 
					
						
							|  |  |  |     for (let l of eqLocales) { | 
					
						
							|  |  |  |       str += `case '${l}':\n`; | 
					
						
							| 
									
										
										
										
											2018-09-07 11:26:11 -07:00
										 |  |  |       locales.push(`'${l}'`); | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-07 11:26:11 -07:00
										 |  |  |     let localesStr = '[' + locales.join(',') + ']'; | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 22:22:06 +01:00
										 |  |  |     str += `  l = locale_${formatLocale(locale)};
 | 
					
						
							| 
									
										
										
										
											2018-09-07 11:26:11 -07:00
										 |  |  |     locales = ${localesStr}; | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  |     break;\n`;
 | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  |     return str; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 22:22:06 +01:00
										 |  |  |   function formatLocale(locale) { return locale.replace(/-/g, '_'); } | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  |   // clang-format off
 | 
					
						
							|  |  |  |   return `${HEADER}
 | 
					
						
							|  |  |  | import {registerLocaleData} from '../src/i18n/locale_data'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-13 23:35:20 +02:00
										 |  |  | const u = undefined; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 22:22:06 +01:00
										 |  |  | ${LOCALES.map(locale => `${existingLocalesData[locale]}`).join('\n')} | 
					
						
							| 
									
										
										
										
											2017-08-31 12:13:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  | let l: any; | 
					
						
							| 
									
										
										
										
											2018-09-07 11:26:11 -07:00
										 |  |  | let locales: string[] = []; | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-30 00:29:21 +02:00
										 |  |  | switch (goog.LOCALE) { | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  | ${LOCALES.map(locale => generateCases(locale)).join('')}} | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  | if(l) { | 
					
						
							| 
									
										
										
										
											2018-09-07 11:26:11 -07:00
										 |  |  |   locales.forEach(locale => registerLocaleData(l, locale)); | 
					
						
							| 
									
										
										
										
											2017-08-29 20:54:43 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-08-21 19:11:07 +02:00
										 |  |  | `;
 | 
					
						
							|  |  |  |   // clang-format on
 | 
					
						
							|  |  |  | } |