diff --git a/packages/common/src/common.ts b/packages/common/src/common.ts index 05f6156a22..b2198fee38 100644 --- a/packages/common/src/common.ts +++ b/packages/common/src/common.ts @@ -15,7 +15,6 @@ export * from './location/index'; export {NgLocaleLocalization, NgLocalization} from './i18n/localization'; export {Plural, LOCALE_DATA} from './i18n/locale_data'; export {findLocaleData, registerLocaleData, NumberFormatStyle, FormStyle, Time, TranslationWidth, FormatWidth, NumberSymbol, WeekDay, getLocaleDayPeriods, getLocaleDayNames, getLocaleMonthNames, getLocaleId, getLocaleEraNames, getLocaleWeekEndRange, getLocaleFirstDayOfWeek, getLocaleDateFormat, getLocaleDateTimeFormat, getLocaleExtraDayPeriodRules, getLocaleExtraDayPeriods, getLocalePluralCase, getLocaleTimeFormat, getLocaleNumberSymbol, getLocaleNumberFormat, getLocaleCurrencyName, getLocaleCurrencySymbol} from './i18n/locale_data_api'; -export {AVAILABLE_LOCALES} from './i18n/available_locales'; export {CURRENCIES} from './i18n/currencies'; export {parseCookieValue as ɵparseCookieValue} from './cookie'; export {CommonModule, DeprecatedI18NPipesModule} from './common_module'; diff --git a/packages/common/src/i18n/available_locales.ts b/packages/common/src/i18n/available_locales.ts deleted file mode 100644 index 6a68e04e43..0000000000 --- a/packages/common/src/i18n/available_locales.ts +++ /dev/null @@ -1,186 +0,0 @@ -/** - * @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 - */ - -// THIS CODE IS GENERATED - DO NOT MODIFY -// See angular/tools/gulp-tasks/cldr/extract.js - -/** @experimental */ -export const AVAILABLE_LOCALES = [ - 'af', 'af-NA', 'agq', - 'ak', 'am', 'ar', - 'ar-AE', 'ar-BH', 'ar-DJ', - 'ar-DZ', 'ar-EG', 'ar-EH', - 'ar-ER', 'ar-IL', 'ar-IQ', - 'ar-JO', 'ar-KM', 'ar-KW', - 'ar-LB', 'ar-LY', 'ar-MA', - 'ar-MR', 'ar-OM', 'ar-PS', - 'ar-QA', 'ar-SA', 'ar-SD', - 'ar-SO', 'ar-SS', 'ar-SY', - 'ar-TD', 'ar-TN', 'ar-YE', - 'as', 'asa', 'ast', - 'az', 'az-Cyrl', 'az-Latn', - 'bas', 'be', 'bem', - 'bez', 'bg', 'bm', - 'bn', 'bn-IN', 'bo', - 'bo-IN', 'br', 'brx', - 'bs', 'bs-Cyrl', 'bs-Latn', - 'ca', 'ca-AD', 'ca-ES-VALENCIA', - 'ca-FR', 'ca-IT', 'ce', - 'cgg', 'chr', 'ckb', - 'ckb-IR', 'cs', 'cu', - 'cy', 'da', 'da-GL', - 'dav', 'de', 'de-AT', - 'de-BE', 'de-CH', 'de-IT', - 'de-LI', 'de-LU', 'dje', - 'dsb', 'dua', 'dyo', - 'dz', 'ebu', 'ee', - 'ee-TG', 'el', 'el-CY', - 'en', 'en-001', 'en-150', - 'en-AG', 'en-AI', 'en-AS', - 'en-AT', 'en-AU', 'en-BB', - 'en-BE', 'en-BI', 'en-BM', - 'en-BS', 'en-BW', 'en-BZ', - 'en-CA', 'en-CC', 'en-CH', - 'en-CK', 'en-CM', 'en-CX', - 'en-CY', 'en-DE', 'en-DG', - 'en-DK', 'en-DM', 'en-ER', - 'en-FI', 'en-FJ', 'en-FK', - 'en-FM', 'en-GB', 'en-GD', - 'en-GG', 'en-GH', 'en-GI', - 'en-GM', 'en-GU', 'en-GY', - 'en-HK', 'en-IE', 'en-IL', - 'en-IM', 'en-IN', 'en-IO', - 'en-JE', 'en-JM', 'en-KE', - 'en-KI', 'en-KN', 'en-KY', - 'en-LC', 'en-LR', 'en-LS', - 'en-MG', 'en-MH', 'en-MO', - 'en-MP', 'en-MS', 'en-MT', - 'en-MU', 'en-MW', 'en-MY', - 'en-NA', 'en-NF', 'en-NG', - 'en-NL', 'en-NR', 'en-NU', - 'en-NZ', 'en-PG', 'en-PH', - 'en-PK', 'en-PN', 'en-PR', - 'en-PW', 'en-RW', 'en-SB', - 'en-SC', 'en-SD', 'en-SE', - 'en-SG', 'en-SH', 'en-SI', - 'en-SL', 'en-SS', 'en-SX', - 'en-SZ', 'en-TC', 'en-TK', - 'en-TO', 'en-TT', 'en-TV', - 'en-TZ', 'en-UG', 'en-UM', - 'en-US-POSIX', 'en-VC', 'en-VG', - 'en-VI', 'en-VU', 'en-WS', - 'en-ZA', 'en-ZM', 'en-ZW', - 'eo', 'es', 'es-419', - 'es-AR', 'es-BO', 'es-BR', - 'es-BZ', 'es-CL', 'es-CO', - 'es-CR', 'es-CU', 'es-DO', - 'es-EA', 'es-EC', 'es-GQ', - 'es-GT', 'es-HN', 'es-IC', - 'es-MX', 'es-NI', 'es-PA', - 'es-PE', 'es-PH', 'es-PR', - 'es-PY', 'es-SV', 'es-US', - 'es-UY', 'es-VE', 'et', - 'eu', 'ewo', 'fa', - 'fa-AF', 'ff', 'ff-CM', - 'ff-GN', 'ff-MR', 'fi', - 'fil', 'fo', 'fo-DK', - 'fr', 'fr-BE', 'fr-BF', - 'fr-BI', 'fr-BJ', 'fr-BL', - 'fr-CA', 'fr-CD', 'fr-CF', - 'fr-CG', 'fr-CH', 'fr-CI', - 'fr-CM', 'fr-DJ', 'fr-DZ', - 'fr-GA', 'fr-GF', 'fr-GN', - 'fr-GP', 'fr-GQ', 'fr-HT', - 'fr-KM', 'fr-LU', 'fr-MA', - 'fr-MC', 'fr-MF', 'fr-MG', - 'fr-ML', 'fr-MQ', 'fr-MR', - 'fr-MU', 'fr-NC', 'fr-NE', - 'fr-PF', 'fr-PM', 'fr-RE', - 'fr-RW', 'fr-SC', 'fr-SN', - 'fr-SY', 'fr-TD', 'fr-TG', - 'fr-TN', 'fr-VU', 'fr-WF', - 'fr-YT', 'fur', 'fy', - 'ga', 'gd', 'gl', - 'gsw', 'gsw-FR', 'gsw-LI', - 'gu', 'guz', 'gv', - 'ha', 'ha-GH', 'ha-NE', - 'haw', 'he', 'hi', - 'hr', 'hr-BA', 'hsb', - 'hu', 'hy', 'id', - 'ig', 'ii', 'is', - 'it', 'it-CH', 'it-SM', - 'it-VA', 'ja', 'jgo', - 'jmc', 'ka', 'kab', - 'kam', 'kde', 'kea', - 'khq', 'ki', 'kk', - 'kkj', 'kl', 'kln', - 'km', 'kn', 'ko', - 'ko-KP', 'kok', 'ks', - 'ksb', 'ksf', 'ksh', - 'kw', 'ky', 'lag', - 'lb', 'lg', 'lkt', - 'ln', 'ln-AO', 'ln-CF', - 'ln-CG', 'lo', 'lrc', - 'lrc-IQ', 'lt', 'lu', - 'luo', 'luy', 'lv', - 'mas', 'mas-TZ', 'mer', - 'mfe', 'mg', 'mgh', - 'mgo', 'mk', 'ml', - 'mn', 'mr', 'ms', - 'ms-BN', 'ms-SG', 'mt', - 'mua', 'my', 'mzn', - 'naq', 'nb', 'nb-SJ', - 'nd', 'nds', 'nds-NL', - 'ne', 'ne-IN', 'nl', - 'nl-AW', 'nl-BE', 'nl-BQ', - 'nl-CW', 'nl-SR', 'nl-SX', - 'nmg', 'nn', 'nnh', - 'nus', 'nyn', 'om', - 'om-KE', 'or', 'os', - 'os-RU', 'pa', 'pa-Arab', - 'pa-Guru', 'pl', 'prg', - 'ps', 'pt', 'pt-AO', - 'pt-CH', 'pt-CV', 'pt-GQ', - 'pt-GW', 'pt-LU', 'pt-MO', - 'pt-MZ', 'pt-PT', 'pt-ST', - 'pt-TL', 'qu', 'qu-BO', - 'qu-EC', 'rm', 'rn', - 'ro', 'ro-MD', 'rof', - 'root', 'ru', 'ru-BY', - 'ru-KG', 'ru-KZ', 'ru-MD', - 'ru-UA', 'rw', 'rwk', - 'sah', 'saq', 'sbp', - 'se', 'se-FI', 'se-SE', - 'seh', 'ses', 'sg', - 'shi', 'shi-Latn', 'shi-Tfng', - 'si', 'sk', 'sl', - 'smn', 'sn', 'so', - 'so-DJ', 'so-ET', 'so-KE', - 'sq', 'sq-MK', 'sq-XK', - 'sr', 'sr-Cyrl', 'sr-Cyrl-BA', - 'sr-Cyrl-ME', 'sr-Cyrl-XK', 'sr-Latn', - 'sr-Latn-BA', 'sr-Latn-ME', 'sr-Latn-XK', - 'sv', 'sv-AX', 'sv-FI', - 'sw', 'sw-CD', 'sw-KE', - 'sw-UG', 'ta', 'ta-LK', - 'ta-MY', 'ta-SG', 'te', - 'teo', 'teo-KE', 'th', - 'ti', 'ti-ER', 'tk', - 'to', 'tr', 'tr-CY', - 'twq', 'tzm', 'ug', - 'uk', 'ur', 'ur-IN', - 'uz', 'uz-Arab', 'uz-Cyrl', - 'uz-Latn', 'vai', 'vai-Latn', - 'vai-Vaii', 'vi', 'vo', - 'vun', 'wae', 'xog', - 'yav', 'yi', 'yo', - 'yo-BJ', 'yue', 'zgh', - 'zh', 'zh-Hans', 'zh-Hans-HK', - 'zh-Hans-MO', 'zh-Hans-SG', 'zh-Hant', - 'zh-Hant-HK', 'zh-Hant-MO', 'zu' -]; diff --git a/packages/common/src/i18n/locale_data_api.ts b/packages/common/src/i18n/locale_data_api.ts index bf8bb9739b..71b4d534b1 100644 --- a/packages/common/src/i18n/locale_data_api.ts +++ b/packages/common/src/i18n/locale_data_api.ts @@ -6,7 +6,6 @@ * found in the LICENSE file at https://angular.io/license */ -import {AVAILABLE_LOCALES} from './available_locales'; import {CURRENCIES} from './currencies'; import localeEn from './locale_en'; import {LOCALE_DATA, Plural} from './locale_data'; @@ -528,57 +527,28 @@ function extractTime(time: string): Time { * @experimental i18n support is experimental. */ export function findLocaleData(locale: string): any { - const normalizedLocale = getNormalizedLocale(locale); + const normalizedLocale = locale.toLowerCase().replace(/_/g, '-'); - if (normalizedLocale === 'en') { - return LOCALE_DATA['en'] || localeEn; - } - - const match = LOCALE_DATA[toCamelCase(normalizedLocale)]; + let match = LOCALE_DATA[normalizedLocale]; if (match) { return match; } + // let's try to find a parent locale + const parentLocale = normalizedLocale.split('-')[0]; + match = LOCALE_DATA[parentLocale]; + if (match) { + return match; + } + + if (parentLocale === 'en') { + return localeEn; + } + throw new Error( `Missing locale data for the locale "${locale}". Use "registerLocaleData" to load new data. See the "I18n guide" on angular.io to know more.`); } -const NORMALIZED_LOCALES: any = {}; - -/** - * Returns the closest matching locale that exists or throw - * e.g.: "en-US" will return "en", and "fr_ca" will return "fr-CA" - * Rules for locale id equivalences are defined in - * http://cldr.unicode.org/index/cldr-spec/language-tag-equivalences - * and in https://tools.ietf.org/html/rfc4647#section-3.4 - */ -function getNormalizedLocale(locale: string): string { - if (NORMALIZED_LOCALES[locale]) { - return NORMALIZED_LOCALES[locale]; - } - - const normalizedLocale = locale.toLowerCase().replace(/_/g, '-'); - const match = AVAILABLE_LOCALES.find((l: string) => l.toLowerCase() === normalizedLocale); - - if (match) { - NORMALIZED_LOCALES[locale] = match; - return match; - } - - const parentLocale = normalizedLocale.split('-')[0]; - if (AVAILABLE_LOCALES.find((l: string) => l.toLowerCase() === parentLocale)) { - NORMALIZED_LOCALES[locale] = parentLocale; - return parentLocale; - } - - throw new Error( - `"${locale}" is not a valid LOCALE_ID value. See https://github.com/unicode-cldr/cldr-core/blob/master/availableLocales.json for a list of valid locales`); -} - -function toCamelCase(str: string): string { - return str.replace(/-+([a-z0-9A-Z])/g, (...m: string[]) => m[1].toUpperCase()); -} - /** * Return the currency symbol for a given currency code, or the code if no symbol available * (e.g.: $, US$, or USD) @@ -598,7 +568,7 @@ export function findCurrencySymbol(code: string, format: 'wide' | 'narrow') { * @experimental i18n support is experimental. */ export function registerLocaleData(data: any, extraData?: any) { - const localeId = toCamelCase(data[LocaleDataIndex.LocaleId]); + const localeId = data[LocaleDataIndex.LocaleId].toLowerCase(); LOCALE_DATA[localeId] = data; if (extraData) { LOCALE_DATA[localeId][LocaleDataIndex.ExtraData] = extraData; diff --git a/packages/common/test/i18n/locale_data_api_spec.ts b/packages/common/test/i18n/locale_data_api_spec.ts index 44620c022e..e7d1c629ea 100644 --- a/packages/common/test/i18n/locale_data_api_spec.ts +++ b/packages/common/test/i18n/locale_data_api_spec.ts @@ -22,16 +22,11 @@ export function main() { }); describe('findLocaleData', () => { - it('should throw if the locale provided is not a valid LOCALE_ID', () => { - expect(() => findLocaleData('invalid')) - .toThrow(new Error( - `"invalid" is not a valid LOCALE_ID value. See https://github.com/unicode-cldr/cldr-core/blob/master/availableLocales.json for a list of valid locales`)); - }); - - it('should throw if the LOCALE_DATA for the chosen locale if not available', () => { - expect(() => findLocaleData('fr-BE')) - .toThrowError(/Missing locale data for the locale "fr-BE"/); - }); + it('should throw if the LOCALE_DATA for the chosen locale or its parent locale is not available', + () => { + expect(() => findLocaleData('pt-AO')) + .toThrowError(/Missing locale data for the locale "pt-AO"/); + }); it('should return english data if the locale is en-US', () => { expect(findLocaleData('en-US')).toEqual(localeEn); }); @@ -40,7 +35,7 @@ export function main() { () => { expect(findLocaleData('fr-CA')).toEqual(localeFrCA); }); it('should return the parent LOCALE_DATA if it exists and exact locale is not available', - () => { expect(findLocaleData('fr-FR')).toEqual(localeFr); }); + () => { expect(findLocaleData('fr-BE')).toEqual(localeFr); }); it(`should find the LOCALE_DATA even if the locale id is badly formatted`, () => { expect(findLocaleData('ca-ES-VALENCIA')).toEqual(localeCaESVALENCIA); diff --git a/tools/gulp-tasks/cldr/extract.js b/tools/gulp-tasks/cldr/extract.js index dcc602a0ae..0404b1a527 100644 --- a/tools/gulp-tasks/cldr/extract.js +++ b/tools/gulp-tasks/cldr/extract.js @@ -68,9 +68,6 @@ module.exports = (gulp, done) => { console.log(`Writing file ${I18N_FOLDER}/locale_en.ts`); fs.writeFileSync(`${RELATIVE_I18N_FOLDER}/locale_en.ts`, generateLocale('en', new cldrJs('en'), './locale_data')); - console.log(`Writing file ${I18N_FOLDER}/available_locales.ts`); - fs.writeFileSync(`${RELATIVE_I18N_FOLDER}/available_locales.ts`, generateAvailableLocales(LOCALES)); - console.log(`Writing file ${I18N_FOLDER}/currencies.ts`); fs.writeFileSync(`${RELATIVE_I18N_FOLDER}/currencies.ts`, generateCurrencies()); @@ -80,7 +77,6 @@ module.exports = (gulp, done) => { return gulp .src([ `${I18N_DATA_FOLDER}/**/*.ts`, - `${I18N_FOLDER}/available_locales.ts`, `${I18N_FOLDER}/currencies.ts`, `${I18N_FOLDER}/locale_en.ts` ], {base: '.'}) @@ -151,16 +147,6 @@ export default ${stringify(dayPeriodsSupplemental).replace(/undefined/g, '')}; `; } -/** - * Generate a file that contains the complete list of locales - */ -function generateAvailableLocales(LOCALES) { - return `${HEADER} -/** @experimental */ -export const AVAILABLE_LOCALES = ${stringify(LOCALES)}; -`; -} - /** * Generate a file that contains the list of currencies and their symbols */ diff --git a/tools/public_api_guard/common/common.d.ts b/tools/public_api_guard/common/common.d.ts index 612f58d72f..78ced632b6 100644 --- a/tools/public_api_guard/common/common.d.ts +++ b/tools/public_api_guard/common/common.d.ts @@ -11,9 +11,6 @@ export declare class AsyncPipe implements OnDestroy, PipeTransform { transform(obj: null): null; } -/** @experimental */ -export declare const AVAILABLE_LOCALES: string[]; - /** @stable */ export declare class CommonModule { }