refactor(common): move the low level locale registering to core (#33523)
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
This commit is contained in:
parent
5b21b71c9a
commit
7e8eec57f0
|
@ -12,6 +12,5 @@
|
||||||
* Entry point for all public APIs of this package.
|
* Entry point for all public APIs of this package.
|
||||||
*/
|
*/
|
||||||
export * from './src/common';
|
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.
|
// This file only reexports content of the `src` folder. Keep it that way.
|
||||||
|
|
|
@ -6,40 +6,16 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* 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
|
* 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.
|
* ["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
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
// The signature registerLocaleData(data: any, extraData?: any) is deprecated since v5.1
|
|
||||||
export function registerLocaleData(data: any, localeId?: string | any, extraData?: any): void {
|
export function registerLocaleData(data: any, localeId?: string | any, extraData?: any): void {
|
||||||
if (typeof localeId !== 'string') {
|
return ɵregisterLocaleData(data, localeId, extraData);
|
||||||
extraData = localeId;
|
|
||||||
localeId = data[LocaleDataIndex.LocaleId];
|
|
||||||
}
|
|
||||||
|
|
||||||
localeId = localeId.toLowerCase().replace(/_/g, '-');
|
|
||||||
|
|
||||||
LOCALE_DATA[localeId] = data;
|
|
||||||
|
|
||||||
if (extraData) {
|
|
||||||
LOCALE_DATA[localeId][LocaleDataIndex.ExtraData] = 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}
|
|
||||||
|
|
|
@ -6,9 +6,8 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* 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 {CURRENCIES_EN, CurrenciesSymbols} from './currencies';
|
||||||
import {CurrencyIndex, ExtraLocaleDataIndex} from './locale_data';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format styles that can be used to represent numbers.
|
* 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])[] {
|
export function getLocaleExtraDayPeriodRules(locale: string): (Time | [Time, Time])[] {
|
||||||
const data = ɵfindLocaleData(locale);
|
const data = ɵfindLocaleData(locale);
|
||||||
checkFullData(data);
|
checkFullData(data);
|
||||||
const rules = data[ɵLocaleDataIndex.ExtraData][ExtraLocaleDataIndex.ExtraDayPeriodsRules] || [];
|
const rules = data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodsRules] || [];
|
||||||
return rules.map((rule: string | [string, string]) => {
|
return rules.map((rule: string | [string, string]) => {
|
||||||
if (typeof rule === 'string') {
|
if (typeof rule === 'string') {
|
||||||
return extractTime(rule);
|
return extractTime(rule);
|
||||||
|
@ -555,8 +554,8 @@ export function getLocaleExtraDayPeriods(
|
||||||
const data = ɵfindLocaleData(locale);
|
const data = ɵfindLocaleData(locale);
|
||||||
checkFullData(data);
|
checkFullData(data);
|
||||||
const dayPeriodsData = <string[][][]>[
|
const dayPeriodsData = <string[][][]>[
|
||||||
data[ɵLocaleDataIndex.ExtraData][ExtraLocaleDataIndex.ExtraDayPeriodFormats],
|
data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodFormats],
|
||||||
data[ɵLocaleDataIndex.ExtraData][ExtraLocaleDataIndex.ExtraDayPeriodStandalone]
|
data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodStandalone]
|
||||||
];
|
];
|
||||||
const dayPeriods = getLastDefinedValue(dayPeriodsData, formStyle) || [];
|
const dayPeriods = getLastDefinedValue(dayPeriodsData, formStyle) || [];
|
||||||
return getLastDefinedValue(dayPeriods, width) || [];
|
return getLastDefinedValue(dayPeriods, width) || [];
|
||||||
|
@ -621,13 +620,13 @@ function extractTime(time: string): Time {
|
||||||
*/
|
*/
|
||||||
export function getCurrencySymbol(code: string, format: 'wide' | 'narrow', locale = 'en'): string {
|
export function getCurrencySymbol(code: string, format: 'wide' | 'narrow', locale = 'en'): string {
|
||||||
const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || [];
|
const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || [];
|
||||||
const symbolNarrow = currency[CurrencyIndex.SymbolNarrow];
|
const symbolNarrow = currency[ɵCurrencyIndex.SymbolNarrow];
|
||||||
|
|
||||||
if (format === 'narrow' && typeof symbolNarrow === 'string') {
|
if (format === 'narrow' && typeof symbolNarrow === 'string') {
|
||||||
return symbolNarrow;
|
return symbolNarrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
return currency[CurrencyIndex.Symbol] || code;
|
return currency[ɵCurrencyIndex.Symbol] || code;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Most currencies have cents, that's why the default is 2
|
// Most currencies have cents, that's why the default is 2
|
||||||
|
@ -647,7 +646,7 @@ export function getNumberOfCurrencyDigits(code: string): number {
|
||||||
let digits;
|
let digits;
|
||||||
const currency = CURRENCIES_EN[code];
|
const currency = CURRENCIES_EN[code];
|
||||||
if (currency) {
|
if (currency) {
|
||||||
digits = currency[CurrencyIndex.NbOfDigits];
|
digits = currency[ɵCurrencyIndex.NbOfDigits];
|
||||||
}
|
}
|
||||||
return typeof digits === 'number' ? digits : DEFAULT_NB_OF_CURRENCY_DIGITS;
|
return typeof digits === 'number' ? digits : DEFAULT_NB_OF_CURRENCY_DIGITS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {registerLocaleData} from '@angular/common';
|
|
||||||
import localeAr from '@angular/common/locales/ar';
|
import localeAr from '@angular/common/locales/ar';
|
||||||
import localeDe from '@angular/common/locales/de';
|
import localeDe from '@angular/common/locales/de';
|
||||||
import localeEn from '@angular/common/locales/en';
|
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 localeSr from '@angular/common/locales/sr';
|
||||||
import localeTh from '@angular/common/locales/th';
|
import localeTh from '@angular/common/locales/th';
|
||||||
import {isDate, toDate, formatDate} from '@angular/common/src/i18n/format_date';
|
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('Format date', () => {
|
||||||
describe('toDate', () => {
|
describe('toDate', () => {
|
||||||
|
@ -57,14 +55,16 @@ describe('Format date', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
registerLocaleData(localeEn, localeEnExtra);
|
ɵregisterLocaleData(localeEn, localeEnExtra);
|
||||||
registerLocaleData(localeDe);
|
ɵregisterLocaleData(localeDe);
|
||||||
registerLocaleData(localeHu);
|
ɵregisterLocaleData(localeHu);
|
||||||
registerLocaleData(localeSr);
|
ɵregisterLocaleData(localeSr);
|
||||||
registerLocaleData(localeTh);
|
ɵregisterLocaleData(localeTh);
|
||||||
registerLocaleData(localeAr);
|
ɵregisterLocaleData(localeAr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => ɵunregisterLocaleData());
|
||||||
|
|
||||||
beforeEach(() => { date = new Date(2015, 5, 15, 9, 3, 1, 550); });
|
beforeEach(() => { date = new Date(2015, 5, 15, 9, 3, 1, 550); });
|
||||||
|
|
||||||
it('should format each component correctly', () => {
|
it('should format each component correctly', () => {
|
||||||
|
|
|
@ -10,18 +10,20 @@ import localeEn from '@angular/common/locales/en';
|
||||||
import localeEsUS from '@angular/common/locales/es-US';
|
import localeEsUS from '@angular/common/locales/es-US';
|
||||||
import localeFr from '@angular/common/locales/fr';
|
import localeFr from '@angular/common/locales/fr';
|
||||||
import localeAr from '@angular/common/locales/ar';
|
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 {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', () => {
|
describe('Format number', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
registerLocaleData(localeEn);
|
ɵregisterLocaleData(localeEn);
|
||||||
registerLocaleData(localeEsUS);
|
ɵregisterLocaleData(localeEsUS);
|
||||||
registerLocaleData(localeFr);
|
ɵregisterLocaleData(localeFr);
|
||||||
registerLocaleData(localeAr);
|
ɵregisterLocaleData(localeAr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => ɵunregisterLocaleData());
|
||||||
|
|
||||||
describe('Number', () => {
|
describe('Number', () => {
|
||||||
describe('transform', () => {
|
describe('transform', () => {
|
||||||
it('should return correct value for numbers', () => {
|
it('should return correct value for numbers', () => {
|
||||||
|
|
|
@ -6,56 +6,24 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {ɵfindLocaleData} from '@angular/core';
|
import {ɵregisterLocaleData, ɵunregisterLocaleData} from '@angular/core';
|
||||||
import localeCaESVALENCIA from '@angular/common/locales/ca-ES-VALENCIA';
|
|
||||||
import localeEn from '@angular/common/locales/en';
|
import localeEn from '@angular/common/locales/en';
|
||||||
import localeFr from '@angular/common/locales/fr';
|
import localeFr from '@angular/common/locales/fr';
|
||||||
import localeZh from '@angular/common/locales/zh';
|
import localeZh from '@angular/common/locales/zh';
|
||||||
import localeFrCA from '@angular/common/locales/fr-CA';
|
|
||||||
import localeEnAU from '@angular/common/locales/en-AU';
|
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';
|
import {getCurrencySymbol, getLocaleDateFormat, FormatWidth, getNumberOfCurrencyDigits} from '../../src/i18n/locale_data_api';
|
||||||
|
|
||||||
{
|
{
|
||||||
describe('locale data api', () => {
|
describe('locale data api', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
registerLocaleData(localeCaESVALENCIA);
|
ɵregisterLocaleData(localeEn);
|
||||||
registerLocaleData(localeEn);
|
ɵregisterLocaleData(localeFr);
|
||||||
registerLocaleData(localeFr);
|
ɵregisterLocaleData(localeZh);
|
||||||
registerLocaleData(localeFrCA);
|
ɵregisterLocaleData(localeEnAU);
|
||||||
registerLocaleData(localeFr, 'fake-id');
|
|
||||||
registerLocaleData(localeFrCA, 'fake_Id2');
|
|
||||||
registerLocaleData(localeZh);
|
|
||||||
registerLocaleData(localeEnAU);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('findLocaleData', () => {
|
afterAll(() => { ɵunregisterLocaleData(); });
|
||||||
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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getting currency symbol', () => {
|
describe('getting currency symbol', () => {
|
||||||
it('should return the correct symbol', () => {
|
it('should return the correct symbol', () => {
|
||||||
|
|
|
@ -10,20 +10,21 @@ import localeRo from '@angular/common/locales/ro';
|
||||||
import localeSr from '@angular/common/locales/sr';
|
import localeSr from '@angular/common/locales/sr';
|
||||||
import localeZgh from '@angular/common/locales/zgh';
|
import localeZgh from '@angular/common/locales/zgh';
|
||||||
import localeFr from '@angular/common/locales/fr';
|
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 {TestBed, inject} from '@angular/core/testing';
|
||||||
import {NgLocaleLocalization, NgLocalization, getPluralCategory} from '@angular/common/src/i18n/localization';
|
import {NgLocaleLocalization, NgLocalization, getPluralCategory} from '@angular/common/src/i18n/localization';
|
||||||
import {registerLocaleData} from '../../src/i18n/locale_data';
|
|
||||||
|
|
||||||
{
|
{
|
||||||
describe('l10n', () => {
|
describe('l10n', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
registerLocaleData(localeRo);
|
ɵregisterLocaleData(localeRo);
|
||||||
registerLocaleData(localeSr);
|
ɵregisterLocaleData(localeSr);
|
||||||
registerLocaleData(localeZgh);
|
ɵregisterLocaleData(localeZgh);
|
||||||
registerLocaleData(localeFr);
|
ɵregisterLocaleData(localeFr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => ɵunregisterLocaleData());
|
||||||
|
|
||||||
describe('NgLocalization', () => {
|
describe('NgLocalization', () => {
|
||||||
function roTests() {
|
function roTests() {
|
||||||
it('should return plural cases for the provided locale',
|
it('should return plural cases for the provided locale',
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* 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 localeEn from '@angular/common/locales/en';
|
||||||
import localeEnExtra from '@angular/common/locales/extra/en';
|
import localeEnExtra from '@angular/common/locales/extra/en';
|
||||||
import {PipeResolver} from '@angular/compiler/src/pipe_resolver';
|
import {PipeResolver} from '@angular/compiler/src/pipe_resolver';
|
||||||
import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_reflector';
|
import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_reflector';
|
||||||
|
import {ɵunregisterLocaleData, ɵregisterLocaleData} from '@angular/core';
|
||||||
|
|
||||||
{
|
{
|
||||||
let date: Date;
|
let date: Date;
|
||||||
|
@ -18,12 +19,8 @@ import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_refle
|
||||||
const isoStringWithoutTime = '2015-01-01';
|
const isoStringWithoutTime = '2015-01-01';
|
||||||
let pipe: DatePipe;
|
let pipe: DatePipe;
|
||||||
|
|
||||||
// Check the transformation of a date into a pattern
|
beforeAll(() => ɵregisterLocaleData(localeEn, localeEnExtra));
|
||||||
function expectDateFormatAs(date: Date | string, pattern: any, output: string): void {
|
afterAll(() => ɵunregisterLocaleData());
|
||||||
expect(pipe.transform(date, pattern)).toEqual(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeAll(() => { registerLocaleData(localeEn, localeEnExtra); });
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
date = new Date(2015, 5, 15, 9, 3, 1, 550);
|
date = new Date(2015, 5, 15, 9, 3, 1, 550);
|
||||||
|
|
|
@ -11,19 +11,22 @@ import localeEsUS from '@angular/common/locales/es-US';
|
||||||
import localeFr from '@angular/common/locales/fr';
|
import localeFr from '@angular/common/locales/fr';
|
||||||
import localeAr from '@angular/common/locales/ar';
|
import localeAr from '@angular/common/locales/ar';
|
||||||
import localeDeAt from '@angular/common/locales/de-AT';
|
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';
|
import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testing_internal';
|
||||||
|
|
||||||
{
|
{
|
||||||
describe('Number pipes', () => {
|
describe('Number pipes', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
registerLocaleData(localeEn);
|
ɵregisterLocaleData(localeEn);
|
||||||
registerLocaleData(localeEsUS);
|
ɵregisterLocaleData(localeEsUS);
|
||||||
registerLocaleData(localeFr);
|
ɵregisterLocaleData(localeFr);
|
||||||
registerLocaleData(localeAr);
|
ɵregisterLocaleData(localeAr);
|
||||||
registerLocaleData(localeDeAt);
|
ɵregisterLocaleData(localeDeAt);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => ɵunregisterLocaleData());
|
||||||
|
|
||||||
describe('DecimalPipe', () => {
|
describe('DecimalPipe', () => {
|
||||||
describe('transform', () => {
|
describe('transform', () => {
|
||||||
let pipe: DecimalPipe;
|
let pipe: DecimalPipe;
|
||||||
|
|
|
@ -33,6 +33,6 @@ export {makeDecorator as ɵmakeDecorator} from './util/decorators';
|
||||||
export {isObservable as ɵisObservable, isPromise as ɵisPromise} from './util/lang';
|
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 {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 {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 {unregisterLocaleData as ɵunregisterLocaleData, getLocalePluralCase as ɵgetLocalePluralCase, findLocaleData as ɵfindLocaleData, registerLocaleData as ɵregisterLocaleData} from './i18n/locale_data_api';
|
||||||
export {LOCALE_DATA as ɵLOCALE_DATA, LocaleDataIndex as ɵLocaleDataIndex} from './i18n/locale_data';
|
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';
|
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';
|
||||||
|
|
|
@ -36,3 +36,17 @@ export enum LocaleDataIndex {
|
||||||
PluralCase,
|
PluralCase,
|
||||||
ExtraData
|
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}
|
||||||
|
|
|
@ -9,6 +9,56 @@
|
||||||
import {LOCALE_DATA, LocaleDataIndex} from './locale_data';
|
import {LOCALE_DATA, LocaleDataIndex} from './locale_data';
|
||||||
import localeEn from './locale_en';
|
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
|
* Retrieves the plural function used by ICU expressions to determine the plural case to use
|
||||||
* for a given locale.
|
* for a given locale.
|
||||||
|
@ -22,32 +72,25 @@ export function getLocalePluralCase(locale: string): (value: number) => number {
|
||||||
return data[LocaleDataIndex.PluralCase];
|
return data[LocaleDataIndex.PluralCase];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the locale data for a given locale.
|
* Helper function to get the given `normalizedLocale` from `LOCALE_DATA`.
|
||||||
*
|
|
||||||
* @param locale The locale code.
|
|
||||||
* @returns The locale data.
|
|
||||||
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
|
|
||||||
*/
|
*/
|
||||||
export function findLocaleData(locale: string): any {
|
export function getLocaleData(normalizedLocale: string): any {
|
||||||
const normalizedLocale = locale.toLowerCase().replace(/_/g, '-');
|
return LOCALE_DATA[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}".`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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, '-');
|
||||||
|
}
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue