feat(common): support loading locales from a global (#33523)
To support compile time localization, we need to be able to provide the locales via a well known global property. This commit changes `getLocaleData()` so that it will attempt to read the local from the global `ng.common.locales` if the locale has not already been registered via `registerLocaleData()`. PR Close #33523
This commit is contained in:
parent
7e8eec57f0
commit
c5894e08bc
|
@ -33,6 +33,5 @@ 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 {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, getLocalePluralCase as ɵgetLocalePluralCase, findLocaleData as ɵfindLocaleData, registerLocaleData as ɵregisterLocaleData, unregisterAllLocaleData as ɵunregisterLocaleData} 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';
|
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';
|
||||||
|
|
|
@ -1,52 +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 const is used to store the locale data registered with `registerLocaleData`
|
|
||||||
*/
|
|
||||||
export const LOCALE_DATA: {[localeId: string]: any} = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Index of each type of locale data from the locale data array
|
|
||||||
*/
|
|
||||||
export enum LocaleDataIndex {
|
|
||||||
LocaleId = 0,
|
|
||||||
DayPeriodsFormat,
|
|
||||||
DayPeriodsStandalone,
|
|
||||||
DaysFormat,
|
|
||||||
DaysStandalone,
|
|
||||||
MonthsFormat,
|
|
||||||
MonthsStandalone,
|
|
||||||
Eras,
|
|
||||||
FirstDayOfWeek,
|
|
||||||
WeekendRange,
|
|
||||||
DateFormat,
|
|
||||||
TimeFormat,
|
|
||||||
DateTimeFormat,
|
|
||||||
NumberSymbols,
|
|
||||||
NumberFormats,
|
|
||||||
CurrencySymbol,
|
|
||||||
CurrencyName,
|
|
||||||
Currencies,
|
|
||||||
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}
|
|
|
@ -5,9 +5,13 @@
|
||||||
* 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 {LOCALE_DATA, LocaleDataIndex} from './locale_data';
|
|
||||||
import localeEn from './locale_en';
|
import localeEn from './locale_en';
|
||||||
|
import {global} from '../util/global';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This const is used to store the locale data registered with `registerLocaleData`
|
||||||
|
*/
|
||||||
|
let LOCALE_DATA: {[localeId: string]: any} = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register locale data to be used internally by Angular. See the
|
* Register locale data to be used internally by Angular. See the
|
||||||
|
@ -75,19 +79,64 @@ export function getLocalePluralCase(locale: string): (value: number) => number {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to get the given `normalizedLocale` from `LOCALE_DATA`.
|
* Helper function to get the given `normalizedLocale` from `LOCALE_DATA`
|
||||||
|
* or from the global `ng.common.locale`.
|
||||||
*/
|
*/
|
||||||
export function getLocaleData(normalizedLocale: string): any {
|
export function getLocaleData(normalizedLocale: string): any {
|
||||||
|
if (!(normalizedLocale in LOCALE_DATA)) {
|
||||||
|
LOCALE_DATA[normalizedLocale] = global.ng && global.ng.common && global.ng.common.locales &&
|
||||||
|
global.ng.common.locales[normalizedLocale];
|
||||||
|
}
|
||||||
return LOCALE_DATA[normalizedLocale];
|
return LOCALE_DATA[normalizedLocale];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to remove all the locale data from `LOCALE_DATA`.
|
* Helper function to remove all the locale data from `LOCALE_DATA`.
|
||||||
*/
|
*/
|
||||||
export function unregisterLocaleData() {
|
export function unregisterAllLocaleData() {
|
||||||
Object.keys(LOCALE_DATA).forEach(key => delete LOCALE_DATA[key]);
|
LOCALE_DATA = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index of each type of locale data from the locale data array
|
||||||
|
*/
|
||||||
|
export enum LocaleDataIndex {
|
||||||
|
LocaleId = 0,
|
||||||
|
DayPeriodsFormat,
|
||||||
|
DayPeriodsStandalone,
|
||||||
|
DaysFormat,
|
||||||
|
DaysStandalone,
|
||||||
|
MonthsFormat,
|
||||||
|
MonthsStandalone,
|
||||||
|
Eras,
|
||||||
|
FirstDayOfWeek,
|
||||||
|
WeekendRange,
|
||||||
|
DateFormat,
|
||||||
|
TimeFormat,
|
||||||
|
DateTimeFormat,
|
||||||
|
NumberSymbols,
|
||||||
|
NumberFormats,
|
||||||
|
CurrencySymbol,
|
||||||
|
CurrencyName,
|
||||||
|
Currencies,
|
||||||
|
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}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the canonical form of a locale name - lowercase with `_` replaced with `-`.
|
* Returns the canonical form of a locale name - lowercase with `_` replaced with `-`.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -5,18 +5,23 @@
|
||||||
* 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 {findLocaleData, registerLocaleData, unregisterLocaleData} from '../../src/i18n/locale_data_api';
|
import {findLocaleData, registerLocaleData, unregisterAllLocaleData} from '../../src/i18n/locale_data_api';
|
||||||
|
import {global} from '../../src/util/global';
|
||||||
|
|
||||||
{
|
{
|
||||||
describe('locale data api', () => {
|
describe('locale data api', () => {
|
||||||
const localeCaESVALENCIA: any[] = ['ca-ES-VALENCIA'];
|
const localeCaESVALENCIA: any[] = ['ca-ES-VALENCIA'];
|
||||||
|
const localeDe: any[] = ['de'];
|
||||||
|
const localeDeCH: any[] = ['de-CH'];
|
||||||
const localeEn: any[] = ['en'];
|
const localeEn: any[] = ['en'];
|
||||||
const localeFr: any[] = ['fr'];
|
const localeFr: any[] = ['fr'];
|
||||||
const localeFrCA: any[] = ['fr-CA'];
|
const localeFrCA: any[] = ['fr-CA'];
|
||||||
const localeZh: any[] = ['zh'];
|
const localeZh: any[] = ['zh'];
|
||||||
const localeEnAU: any[] = ['en-AU'];
|
const localeEnAU: any[] = ['en-AU'];
|
||||||
|
const fakeGlobalFr: any[] = ['fr'];
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
// Sumulate manually registering some locale data
|
||||||
registerLocaleData(localeCaESVALENCIA);
|
registerLocaleData(localeCaESVALENCIA);
|
||||||
registerLocaleData(localeEn);
|
registerLocaleData(localeEn);
|
||||||
registerLocaleData(localeFr);
|
registerLocaleData(localeFr);
|
||||||
|
@ -25,9 +30,20 @@ import {findLocaleData, registerLocaleData, unregisterLocaleData} from '../../sr
|
||||||
registerLocaleData(localeFrCA, 'fake_Id2');
|
registerLocaleData(localeFrCA, 'fake_Id2');
|
||||||
registerLocaleData(localeZh);
|
registerLocaleData(localeZh);
|
||||||
registerLocaleData(localeEnAU);
|
registerLocaleData(localeEnAU);
|
||||||
|
|
||||||
|
// Simulate some locale data existing on the global already
|
||||||
|
global.ng = global.ng || {};
|
||||||
|
global.ng.common = global.ng.common || {locales: {}};
|
||||||
|
global.ng.common.locales = global.ng.common.locales || {};
|
||||||
|
global.ng.common.locales['fr'] = fakeGlobalFr;
|
||||||
|
global.ng.common.locales['de'] = localeDe;
|
||||||
|
global.ng.common.locales['de-ch'] = localeDeCH;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => unregisterLocaleData());
|
afterAll(() => {
|
||||||
|
unregisterAllLocaleData();
|
||||||
|
global.ng.common.locales = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
describe('findLocaleData', () => {
|
describe('findLocaleData', () => {
|
||||||
it('should throw if the LOCALE_DATA for the chosen locale or its parent locale is not available',
|
it('should throw if the LOCALE_DATA for the chosen locale or its parent locale is not available',
|
||||||
|
@ -55,6 +71,15 @@ import {findLocaleData, registerLocaleData, unregisterLocaleData} from '../../sr
|
||||||
expect(findLocaleData('fake_iD')).toEqual(localeFr);
|
expect(findLocaleData('fake_iD')).toEqual(localeFr);
|
||||||
expect(findLocaleData('fake-id2')).toEqual(localeFrCA);
|
expect(findLocaleData('fake-id2')).toEqual(localeFrCA);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should find the exact LOCALE_DATA if the locale is on the global object',
|
||||||
|
() => { expect(findLocaleData('de-CH')).toEqual(localeDeCH); });
|
||||||
|
|
||||||
|
it('should find the parent LOCALE_DATA if the exact locale is not available and the parent locale is on the global object',
|
||||||
|
() => { expect(findLocaleData('de-BE')).toEqual(localeDe); });
|
||||||
|
|
||||||
|
it('should find the registered LOCALE_DATA even if the same locale is on the global object',
|
||||||
|
() => { expect(findLocaleData('fr')).not.toBe(fakeGlobalFr); });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue