From 7e8eec57f01441ddb01b5fdd7ec3590254e0dac3 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Fri, 1 Nov 2019 09:43:43 +0000 Subject: [PATCH] refactor(common): move the low level locale registering to core (#33523) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To limit the exposure of the private `LOCALE_DATA` from outside `@angular/core` this commit exposes private functions in the core to hide the internal structures better. * The `registerLocaleData()` implementation has moved from `@angular/common` to `@angular/core`. A stub that delegates to core has been left in common for backward compatibility. * A new `ɵunregisterLocaleData()` function has been provided, which is particularly useful in tests to clear out registered locales to prevent subsequent tests from being affected. * A private export of `ɵregisterLocaleData()` has been removed from `@angular/common`. This was not being used and is accessible via `@angular/core` anyway. PR Close #33523 --- packages/common/public_api.ts | 1 - packages/common/src/i18n/locale_data.ts | 32 +------ packages/common/src/i18n/locale_data_api.ts | 15 ++- packages/common/test/i18n/format_date_spec.ts | 18 ++-- .../common/test/i18n/format_number_spec.ts | 14 +-- .../common/test/i18n/locale_data_api_spec.ts | 46 ++------- .../common/test/i18n/localization_spec.ts | 13 +-- packages/common/test/pipes/date_pipe_spec.ts | 11 +-- .../common/test/pipes/number_pipe_spec.ts | 15 +-- packages/core/src/core_private_export.ts | 4 +- packages/core/src/i18n/locale_data.ts | 14 +++ packages/core/src/i18n/locale_data_api.ts | 95 ++++++++++++++----- .../core/test/i18n/locale_data_api_spec.ts | 60 ++++++++++++ 13 files changed, 200 insertions(+), 138 deletions(-) create mode 100644 packages/core/test/i18n/locale_data_api_spec.ts diff --git a/packages/common/public_api.ts b/packages/common/public_api.ts index 308ff0cf65..7dfd92837b 100644 --- a/packages/common/public_api.ts +++ b/packages/common/public_api.ts @@ -12,6 +12,5 @@ * Entry point for all public APIs of this package. */ export * from './src/common'; -export {registerLocaleData as ɵregisterLocaleData} from './src/i18n/locale_data'; // This file only reexports content of the `src` folder. Keep it that way. diff --git a/packages/common/src/i18n/locale_data.ts b/packages/common/src/i18n/locale_data.ts index 975dcc0b69..cfbdee94d9 100644 --- a/packages/common/src/i18n/locale_data.ts +++ b/packages/common/src/i18n/locale_data.ts @@ -6,40 +6,16 @@ * found in the LICENSE file at https://angular.io/license */ -import {ɵLOCALE_DATA as LOCALE_DATA, ɵLocaleDataIndex as LocaleDataIndex} from '@angular/core'; +import {ɵregisterLocaleData} from '@angular/core'; /** * Register global data to be used internally by Angular. See the * ["I18n guide"](guide/i18n#i18n-pipes) to know how to import additional locale data. * + * The signature registerLocaleData(data: any, extraData?: any) is deprecated since v5.1 + * * @publicApi */ -// The signature registerLocaleData(data: any, extraData?: any) is deprecated since v5.1 export function registerLocaleData(data: any, localeId?: string | any, extraData?: any): void { - if (typeof localeId !== 'string') { - extraData = localeId; - localeId = data[LocaleDataIndex.LocaleId]; - } - - localeId = localeId.toLowerCase().replace(/_/g, '-'); - - LOCALE_DATA[localeId] = data; - - if (extraData) { - LOCALE_DATA[localeId][LocaleDataIndex.ExtraData] = extraData; - } + return ɵregisterLocaleData(data, localeId, extraData); } - -/** - * Index of each type of locale data from the extra locale data array - */ -export const enum ExtraLocaleDataIndex { - ExtraDayPeriodFormats = 0, - ExtraDayPeriodStandalone, - ExtraDayPeriodsRules -} - -/** - * Index of each value in currency data (used to describe CURRENCIES_EN in currencies.ts) - */ -export const enum CurrencyIndex {Symbol = 0, SymbolNarrow, NbOfDigits} diff --git a/packages/common/src/i18n/locale_data_api.ts b/packages/common/src/i18n/locale_data_api.ts index 7c8ab3c5c9..9570ad3eb2 100644 --- a/packages/common/src/i18n/locale_data_api.ts +++ b/packages/common/src/i18n/locale_data_api.ts @@ -6,9 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {ɵLocaleDataIndex, ɵfindLocaleData, ɵgetLocalePluralCase} from '@angular/core'; +import {ɵCurrencyIndex, ɵExtraLocaleDataIndex, ɵLocaleDataIndex, ɵfindLocaleData, ɵgetLocalePluralCase} from '@angular/core'; import {CURRENCIES_EN, CurrenciesSymbols} from './currencies'; -import {CurrencyIndex, ExtraLocaleDataIndex} from './locale_data'; /** * Format styles that can be used to represent numbers. @@ -524,7 +523,7 @@ function checkFullData(data: any) { export function getLocaleExtraDayPeriodRules(locale: string): (Time | [Time, Time])[] { const data = ɵfindLocaleData(locale); checkFullData(data); - const rules = data[ɵLocaleDataIndex.ExtraData][ExtraLocaleDataIndex.ExtraDayPeriodsRules] || []; + const rules = data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodsRules] || []; return rules.map((rule: string | [string, string]) => { if (typeof rule === 'string') { return extractTime(rule); @@ -555,8 +554,8 @@ export function getLocaleExtraDayPeriods( const data = ɵfindLocaleData(locale); checkFullData(data); const dayPeriodsData = [ - data[ɵLocaleDataIndex.ExtraData][ExtraLocaleDataIndex.ExtraDayPeriodFormats], - data[ɵLocaleDataIndex.ExtraData][ExtraLocaleDataIndex.ExtraDayPeriodStandalone] + data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodFormats], + data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodStandalone] ]; const dayPeriods = getLastDefinedValue(dayPeriodsData, formStyle) || []; return getLastDefinedValue(dayPeriods, width) || []; @@ -621,13 +620,13 @@ function extractTime(time: string): Time { */ export function getCurrencySymbol(code: string, format: 'wide' | 'narrow', locale = 'en'): string { const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || []; - const symbolNarrow = currency[CurrencyIndex.SymbolNarrow]; + const symbolNarrow = currency[ɵCurrencyIndex.SymbolNarrow]; if (format === 'narrow' && typeof symbolNarrow === 'string') { return symbolNarrow; } - return currency[CurrencyIndex.Symbol] || code; + return currency[ɵCurrencyIndex.Symbol] || code; } // Most currencies have cents, that's why the default is 2 @@ -647,7 +646,7 @@ export function getNumberOfCurrencyDigits(code: string): number { let digits; const currency = CURRENCIES_EN[code]; if (currency) { - digits = currency[CurrencyIndex.NbOfDigits]; + digits = currency[ɵCurrencyIndex.NbOfDigits]; } return typeof digits === 'number' ? digits : DEFAULT_NB_OF_CURRENCY_DIGITS; } diff --git a/packages/common/test/i18n/format_date_spec.ts b/packages/common/test/i18n/format_date_spec.ts index 6da8c504c7..7bbe339388 100644 --- a/packages/common/test/i18n/format_date_spec.ts +++ b/packages/common/test/i18n/format_date_spec.ts @@ -5,8 +5,6 @@ * 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 */ - -import {registerLocaleData} from '@angular/common'; import localeAr from '@angular/common/locales/ar'; import localeDe from '@angular/common/locales/de'; import localeEn from '@angular/common/locales/en'; @@ -15,7 +13,7 @@ import localeHu from '@angular/common/locales/hu'; import localeSr from '@angular/common/locales/sr'; import localeTh from '@angular/common/locales/th'; import {isDate, toDate, formatDate} from '@angular/common/src/i18n/format_date'; -import {ɵDEFAULT_LOCALE_ID} from '@angular/core'; +import {ɵDEFAULT_LOCALE_ID, ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core'; describe('Format date', () => { describe('toDate', () => { @@ -57,14 +55,16 @@ describe('Format date', () => { } beforeAll(() => { - registerLocaleData(localeEn, localeEnExtra); - registerLocaleData(localeDe); - registerLocaleData(localeHu); - registerLocaleData(localeSr); - registerLocaleData(localeTh); - registerLocaleData(localeAr); + ɵregisterLocaleData(localeEn, localeEnExtra); + ɵregisterLocaleData(localeDe); + ɵregisterLocaleData(localeHu); + ɵregisterLocaleData(localeSr); + ɵregisterLocaleData(localeTh); + ɵregisterLocaleData(localeAr); }); + afterAll(() => ɵunregisterLocaleData()); + beforeEach(() => { date = new Date(2015, 5, 15, 9, 3, 1, 550); }); it('should format each component correctly', () => { diff --git a/packages/common/test/i18n/format_number_spec.ts b/packages/common/test/i18n/format_number_spec.ts index faba94d4ea..d70bdf6a85 100644 --- a/packages/common/test/i18n/format_number_spec.ts +++ b/packages/common/test/i18n/format_number_spec.ts @@ -10,18 +10,20 @@ import localeEn from '@angular/common/locales/en'; import localeEsUS from '@angular/common/locales/es-US'; import localeFr from '@angular/common/locales/fr'; import localeAr from '@angular/common/locales/ar'; -import {formatCurrency, formatNumber, formatPercent, registerLocaleData} from '@angular/common'; +import {formatCurrency, formatNumber, formatPercent} from '@angular/common'; import {describe, expect, it} from '@angular/core/testing/src/testing_internal'; -import {ɵDEFAULT_LOCALE_ID} from '@angular/core'; +import {ɵDEFAULT_LOCALE_ID, ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core'; describe('Format number', () => { beforeAll(() => { - registerLocaleData(localeEn); - registerLocaleData(localeEsUS); - registerLocaleData(localeFr); - registerLocaleData(localeAr); + ɵregisterLocaleData(localeEn); + ɵregisterLocaleData(localeEsUS); + ɵregisterLocaleData(localeFr); + ɵregisterLocaleData(localeAr); }); + afterAll(() => ɵunregisterLocaleData()); + describe('Number', () => { describe('transform', () => { it('should return correct value for numbers', () => { diff --git a/packages/common/test/i18n/locale_data_api_spec.ts b/packages/common/test/i18n/locale_data_api_spec.ts index ba160ec855..5e7fd24f1e 100644 --- a/packages/common/test/i18n/locale_data_api_spec.ts +++ b/packages/common/test/i18n/locale_data_api_spec.ts @@ -6,56 +6,24 @@ * found in the LICENSE file at https://angular.io/license */ -import {ɵfindLocaleData} from '@angular/core'; -import localeCaESVALENCIA from '@angular/common/locales/ca-ES-VALENCIA'; +import {ɵregisterLocaleData, ɵunregisterLocaleData} from '@angular/core'; + import localeEn from '@angular/common/locales/en'; import localeFr from '@angular/common/locales/fr'; import localeZh from '@angular/common/locales/zh'; -import localeFrCA from '@angular/common/locales/fr-CA'; import localeEnAU from '@angular/common/locales/en-AU'; -import {registerLocaleData} from '../../src/i18n/locale_data'; import {getCurrencySymbol, getLocaleDateFormat, FormatWidth, getNumberOfCurrencyDigits} from '../../src/i18n/locale_data_api'; { describe('locale data api', () => { beforeAll(() => { - registerLocaleData(localeCaESVALENCIA); - registerLocaleData(localeEn); - registerLocaleData(localeFr); - registerLocaleData(localeFrCA); - registerLocaleData(localeFr, 'fake-id'); - registerLocaleData(localeFrCA, 'fake_Id2'); - registerLocaleData(localeZh); - registerLocaleData(localeEnAU); + ɵregisterLocaleData(localeEn); + ɵregisterLocaleData(localeFr); + ɵregisterLocaleData(localeZh); + ɵregisterLocaleData(localeEnAU); }); - describe('findLocaleData', () => { - 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); }); - - it('should return the exact LOCALE_DATA if it is available', - () => { 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-BE')).toEqual(localeFr); }); - - it(`should find the LOCALE_DATA even if the locale id is badly formatted`, () => { - expect(ɵfindLocaleData('ca-ES-VALENCIA')).toEqual(localeCaESVALENCIA); - expect(ɵfindLocaleData('CA_es_Valencia')).toEqual(localeCaESVALENCIA); - }); - - it(`should find the LOCALE_DATA if the locale id was registered`, () => { - expect(ɵfindLocaleData('fake-id')).toEqual(localeFr); - expect(ɵfindLocaleData('fake_iD')).toEqual(localeFr); - expect(ɵfindLocaleData('fake-id2')).toEqual(localeFrCA); - }); - }); + afterAll(() => { ɵunregisterLocaleData(); }); describe('getting currency symbol', () => { it('should return the correct symbol', () => { diff --git a/packages/common/test/i18n/localization_spec.ts b/packages/common/test/i18n/localization_spec.ts index 66d8f7d6b6..dd078c6d89 100644 --- a/packages/common/test/i18n/localization_spec.ts +++ b/packages/common/test/i18n/localization_spec.ts @@ -10,20 +10,21 @@ import localeRo from '@angular/common/locales/ro'; import localeSr from '@angular/common/locales/sr'; import localeZgh from '@angular/common/locales/zgh'; import localeFr from '@angular/common/locales/fr'; -import {LOCALE_ID} from '@angular/core'; +import {LOCALE_ID, ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core'; import {TestBed, inject} from '@angular/core/testing'; import {NgLocaleLocalization, NgLocalization, getPluralCategory} from '@angular/common/src/i18n/localization'; -import {registerLocaleData} from '../../src/i18n/locale_data'; { describe('l10n', () => { beforeAll(() => { - registerLocaleData(localeRo); - registerLocaleData(localeSr); - registerLocaleData(localeZgh); - registerLocaleData(localeFr); + ɵregisterLocaleData(localeRo); + ɵregisterLocaleData(localeSr); + ɵregisterLocaleData(localeZgh); + ɵregisterLocaleData(localeFr); }); + afterAll(() => ɵunregisterLocaleData()); + describe('NgLocalization', () => { function roTests() { it('should return plural cases for the provided locale', diff --git a/packages/common/test/pipes/date_pipe_spec.ts b/packages/common/test/pipes/date_pipe_spec.ts index 5b84bb45c6..d651ceb7d4 100644 --- a/packages/common/test/pipes/date_pipe_spec.ts +++ b/packages/common/test/pipes/date_pipe_spec.ts @@ -6,11 +6,12 @@ * found in the LICENSE file at https://angular.io/license */ -import {DatePipe, registerLocaleData} from '@angular/common'; +import {DatePipe} from '@angular/common'; import localeEn from '@angular/common/locales/en'; import localeEnExtra from '@angular/common/locales/extra/en'; import {PipeResolver} from '@angular/compiler/src/pipe_resolver'; import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_reflector'; +import {ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core'; { let date: Date; @@ -18,12 +19,8 @@ import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_refle const isoStringWithoutTime = '2015-01-01'; let pipe: DatePipe; - // Check the transformation of a date into a pattern - function expectDateFormatAs(date: Date | string, pattern: any, output: string): void { - expect(pipe.transform(date, pattern)).toEqual(output); - } - - beforeAll(() => { registerLocaleData(localeEn, localeEnExtra); }); + beforeAll(() => ɵregisterLocaleData(localeEn, localeEnExtra)); + afterAll(() => ɵunregisterLocaleData()); beforeEach(() => { date = new Date(2015, 5, 15, 9, 3, 1, 550); diff --git a/packages/common/test/pipes/number_pipe_spec.ts b/packages/common/test/pipes/number_pipe_spec.ts index 3dee0a97f1..e377b6ce61 100644 --- a/packages/common/test/pipes/number_pipe_spec.ts +++ b/packages/common/test/pipes/number_pipe_spec.ts @@ -11,19 +11,22 @@ import localeEsUS from '@angular/common/locales/es-US'; import localeFr from '@angular/common/locales/fr'; import localeAr from '@angular/common/locales/ar'; import localeDeAt from '@angular/common/locales/de-AT'; -import {registerLocaleData, CurrencyPipe, DecimalPipe, PercentPipe, formatNumber} from '@angular/common'; +import {ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core'; +import {CurrencyPipe, DecimalPipe, PercentPipe} from '@angular/common'; import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testing_internal'; { describe('Number pipes', () => { beforeAll(() => { - registerLocaleData(localeEn); - registerLocaleData(localeEsUS); - registerLocaleData(localeFr); - registerLocaleData(localeAr); - registerLocaleData(localeDeAt); + ɵregisterLocaleData(localeEn); + ɵregisterLocaleData(localeEsUS); + ɵregisterLocaleData(localeFr); + ɵregisterLocaleData(localeAr); + ɵregisterLocaleData(localeDeAt); }); + afterAll(() => ɵunregisterLocaleData()); + describe('DecimalPipe', () => { describe('transform', () => { let pipe: DecimalPipe; diff --git a/packages/core/src/core_private_export.ts b/packages/core/src/core_private_export.ts index 07f37b8684..5094aa1fda 100644 --- a/packages/core/src/core_private_export.ts +++ b/packages/core/src/core_private_export.ts @@ -33,6 +33,6 @@ export {makeDecorator as ɵmakeDecorator} from './util/decorators'; export {isObservable as ɵisObservable, isPromise as ɵisPromise} from './util/lang'; export {clearOverrides as ɵclearOverrides, initServicesIfNeeded as ɵinitServicesIfNeeded, overrideComponentView as ɵoverrideComponentView, overrideProvider as ɵoverrideProvider} from './view/index'; export {NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR} from './view/provider'; -export {getLocalePluralCase as ɵgetLocalePluralCase, findLocaleData as ɵfindLocaleData} from './i18n/locale_data_api'; -export {LOCALE_DATA as ɵLOCALE_DATA, LocaleDataIndex as ɵLocaleDataIndex} from './i18n/locale_data'; +export {unregisterLocaleData as ɵunregisterLocaleData, getLocalePluralCase as ɵgetLocalePluralCase, findLocaleData as ɵfindLocaleData, registerLocaleData as ɵregisterLocaleData} from './i18n/locale_data_api'; +export {LocaleDataIndex as ɵLocaleDataIndex, CurrencyIndex as ɵCurrencyIndex, ExtraLocaleDataIndex as ɵExtraLocaleDataIndex} from './i18n/locale_data'; export {allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, getSanitizationBypassType as ɵgetSanitizationBypassType, BypassType as ɵBypassType, unwrapSafeValue as ɵunwrapSafeValue, SafeHtml as ɵSafeHtml, SafeResourceUrl as ɵSafeResourceUrl, SafeScript as ɵSafeScript, SafeStyle as ɵSafeStyle, SafeUrl as ɵSafeUrl, SafeValue as ɵSafeValue} from './sanitization/bypass'; diff --git a/packages/core/src/i18n/locale_data.ts b/packages/core/src/i18n/locale_data.ts index 734cc16680..875b6f53d1 100644 --- a/packages/core/src/i18n/locale_data.ts +++ b/packages/core/src/i18n/locale_data.ts @@ -36,3 +36,17 @@ export enum LocaleDataIndex { PluralCase, ExtraData } + +/** + * Index of each type of locale data from the extra locale data array + */ +export const enum ExtraLocaleDataIndex { + ExtraDayPeriodFormats = 0, + ExtraDayPeriodStandalone, + ExtraDayPeriodsRules +} + +/** + * Index of each value in currency data (used to describe CURRENCIES_EN in currencies.ts) + */ +export const enum CurrencyIndex {Symbol = 0, SymbolNarrow, NbOfDigits} diff --git a/packages/core/src/i18n/locale_data_api.ts b/packages/core/src/i18n/locale_data_api.ts index cc30c20348..cdc2bd20d7 100644 --- a/packages/core/src/i18n/locale_data_api.ts +++ b/packages/core/src/i18n/locale_data_api.ts @@ -9,6 +9,56 @@ import {LOCALE_DATA, LocaleDataIndex} from './locale_data'; import localeEn from './locale_en'; +/** + * Register locale data to be used internally by Angular. See the + * ["I18n guide"](guide/i18n#i18n-pipes) to know how to import additional locale data. + * + * The signature `registerLocaleData(data: any, extraData?: any)` is deprecated since v5.1 + */ +export function registerLocaleData(data: any, localeId?: string | any, extraData?: any): void { + if (typeof localeId !== 'string') { + extraData = localeId; + localeId = data[LocaleDataIndex.LocaleId]; + } + + localeId = localeId.toLowerCase().replace(/_/g, '-'); + + LOCALE_DATA[localeId] = data; + + if (extraData) { + LOCALE_DATA[localeId][LocaleDataIndex.ExtraData] = extraData; + } +} + +/** + * Finds the locale data for a given locale. + * + * @param locale The locale code. + * @returns The locale data. + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + */ +export function findLocaleData(locale: string): any { + const normalizedLocale = normalizeLocale(locale); + + let match = getLocaleData(normalizedLocale); + if (match) { + return match; + } + + // let's try to find a parent locale + const parentLocale = normalizedLocale.split('-')[0]; + match = getLocaleData(parentLocale); + if (match) { + return match; + } + + if (parentLocale === 'en') { + return localeEn; + } + + throw new Error(`Missing locale data for the locale "${locale}".`); +} + /** * Retrieves the plural function used by ICU expressions to determine the plural case to use * for a given locale. @@ -22,32 +72,25 @@ export function getLocalePluralCase(locale: string): (value: number) => number { return data[LocaleDataIndex.PluralCase]; } + + /** - * Finds the locale data for a given locale. - * - * @param locale The locale code. - * @returns The locale data. - * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * Helper function to get the given `normalizedLocale` from `LOCALE_DATA`. */ -export function findLocaleData(locale: string): any { - const normalizedLocale = locale.toLowerCase().replace(/_/g, '-'); - - 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}".`); +export function getLocaleData(normalizedLocale: string): any { + return LOCALE_DATA[normalizedLocale]; } + +/** + * Helper function to remove all the locale data from `LOCALE_DATA`. + */ +export function unregisterLocaleData() { + Object.keys(LOCALE_DATA).forEach(key => delete LOCALE_DATA[key]); +} + +/** + * Returns the canonical form of a locale name - lowercase with `_` replaced with `-`. + */ +function normalizeLocale(locale: string): string { + return locale.toLowerCase().replace(/_/g, '-'); +} \ No newline at end of file diff --git a/packages/core/test/i18n/locale_data_api_spec.ts b/packages/core/test/i18n/locale_data_api_spec.ts new file mode 100644 index 0000000000..00ab67726f --- /dev/null +++ b/packages/core/test/i18n/locale_data_api_spec.ts @@ -0,0 +1,60 @@ +/** + * @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 + */ +import {findLocaleData, registerLocaleData, unregisterLocaleData} from '../../src/i18n/locale_data_api'; + +{ + describe('locale data api', () => { + const localeCaESVALENCIA: any[] = ['ca-ES-VALENCIA']; + const localeEn: any[] = ['en']; + const localeFr: any[] = ['fr']; + const localeFrCA: any[] = ['fr-CA']; + const localeZh: any[] = ['zh']; + const localeEnAU: any[] = ['en-AU']; + + beforeAll(() => { + registerLocaleData(localeCaESVALENCIA); + registerLocaleData(localeEn); + registerLocaleData(localeFr); + registerLocaleData(localeFrCA); + registerLocaleData(localeFr, 'fake-id'); + registerLocaleData(localeFrCA, 'fake_Id2'); + registerLocaleData(localeZh); + registerLocaleData(localeEnAU); + }); + + afterAll(() => unregisterLocaleData()); + + describe('findLocaleData', () => { + 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); }); + + it('should return the exact LOCALE_DATA if it is available', + () => { 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-BE')).toEqual(localeFr); }); + + it(`should find the LOCALE_DATA even if the locale id is badly formatted`, () => { + expect(findLocaleData('ca-ES-VALENCIA')).toEqual(localeCaESVALENCIA); + expect(findLocaleData('CA_es_Valencia')).toEqual(localeCaESVALENCIA); + }); + + it(`should find the LOCALE_DATA if the locale id was registered`, () => { + expect(findLocaleData('fake-id')).toEqual(localeFr); + expect(findLocaleData('fake_iD')).toEqual(localeFr); + expect(findLocaleData('fake-id2')).toEqual(localeFrCA); + }); + }); + }); +}