diff --git a/packages/common/src/common.ts b/packages/common/src/common.ts index b2198fee38..3391cd21a3 100644 --- a/packages/common/src/common.ts +++ b/packages/common/src/common.ts @@ -13,8 +13,8 @@ */ 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 {registerLocaleData} from './i18n/locale_data'; +export {Plural, 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 {CURRENCIES} from './i18n/currencies'; export {parseCookieValue as ɵparseCookieValue} from './cookie'; export {CommonModule, DeprecatedI18NPipesModule} from './common_module'; diff --git a/packages/common/src/i18n/locale_data.ts b/packages/common/src/i18n/locale_data.ts index cbcbaf1afe..64e828c96c 100644 --- a/packages/common/src/i18n/locale_data.ts +++ b/packages/common/src/i18n/locale_data.ts @@ -6,17 +6,55 @@ * found in the LICENSE file at https://angular.io/license */ -/** @experimental */ -export enum Plural { - Zero, - One, - Two, - Few, - Many, - Other, -} - /** * @experimental i18n support is experimental. */ export const LOCALE_DATA: {[localeId: string]: any} = {}; + +/** + * Register global data to be used internally by Angular. See the + * {@linkDocs guide/i18n#i18n-pipes "I18n guide"} to know how to import additional locale data. + * + * @experimental i18n support is experimental. + */ +export function registerLocaleData(data: any, extraData?: any) { + const localeId = data[LocaleDataIndex.LocaleId].toLowerCase(); + LOCALE_DATA[localeId] = data; + if (extraData) { + LOCALE_DATA[localeId][LocaleDataIndex.ExtraData] = extraData; + } +} + +/** + * Index of each type of locale data from the locale data array + */ +export const enum LocaleDataIndex { + LocaleId = 0, + DayPeriodsFormat, + DayPeriodsStandalone, + DaysFormat, + DaysStandalone, + MonthsFormat, + MonthsStandalone, + Eras, + FirstDayOfWeek, + WeekendRange, + DateFormat, + TimeFormat, + DateTimeFormat, + NumberSymbols, + NumberFormats, + CurrencySymbol, + CurrencyName, + PluralCase, + ExtraData +} + +/** + * Index of each type of locale data from the extra locale data array + */ +export const enum ExtraLocaleDataIndex { + ExtraDayPeriodFormats = 0, + ExtraDayPeriodStandalone, + ExtraDayPeriodsRules +} diff --git a/packages/common/src/i18n/locale_data_api.ts b/packages/common/src/i18n/locale_data_api.ts index 71b4d534b1..3d15818de0 100644 --- a/packages/common/src/i18n/locale_data_api.ts +++ b/packages/common/src/i18n/locale_data_api.ts @@ -8,7 +8,7 @@ import {CURRENCIES} from './currencies'; import localeEn from './locale_en'; -import {LOCALE_DATA, Plural} from './locale_data'; +import {LOCALE_DATA, LocaleDataIndex, ExtraLocaleDataIndex} from './locale_data'; /** * The different format styles that can be used to represent numbers. @@ -23,6 +23,16 @@ export enum NumberFormatStyle { Scientific } +/** @experimental */ +export enum Plural { + Zero = 0, + One = 1, + Two = 2, + Few = 3, + Many = 4, + Other = 5, +} + /** * Some languages use two different forms of strings (standalone and format) depending on the * context. @@ -130,40 +140,6 @@ export enum WeekDay { Saturday } -/** - * Use this enum to find the index of each type of locale data from the locale data array - */ -enum LocaleDataIndex { - LocaleId = 0, - DayPeriodsFormat, - DayPeriodsStandalone, - DaysFormat, - DaysStandalone, - MonthsFormat, - MonthsStandalone, - Eras, - FirstDayOfWeek, - WeekendRange, - DateFormat, - TimeFormat, - DateTimeFormat, - NumberSymbols, - NumberFormats, - CurrencySymbol, - CurrencyName, - PluralCase, - ExtraData -} - -/** - * Use this enum to find the index of each type of locale data from the extra locale data array - */ -enum ExtraLocaleDataIndex { - ExtraDayPeriodFormats = 0, - ExtraDayPeriodStandalone, - ExtraDayPeriodsRules -} - /** * The locale id for the chosen locale (e.g `en-GB`). * @@ -537,6 +513,7 @@ export function findLocaleData(locale: string): any { // let's try to find a parent locale const parentLocale = normalizedLocale.split('-')[0]; match = LOCALE_DATA[parentLocale]; + if (match) { return match; } @@ -545,8 +522,7 @@ export function findLocaleData(locale: string): any { 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.`); + throw new Error(`Missing locale data for the locale "${locale}".`); } /** @@ -559,18 +535,4 @@ export function findCurrencySymbol(code: string, format: 'wide' | 'narrow') { const currency = CURRENCIES[code] || {}; const symbol = currency[0] || code; return format === 'wide' ? symbol : currency[1] || symbol; -} - -/** - * Register global data to be used internally by Angular. See the - * {@linkDocs guide/i18n#i18n-pipes "I18n guide"} to know how to import additional locale data. - * - * @experimental i18n support is experimental. - */ -export function registerLocaleData(data: any, extraData?: any) { - const localeId = data[LocaleDataIndex.LocaleId].toLowerCase(); - LOCALE_DATA[localeId] = data; - if (extraData) { - LOCALE_DATA[localeId][LocaleDataIndex.ExtraData] = extraData; - } -} +} \ No newline at end of file diff --git a/packages/common/src/i18n/localization.ts b/packages/common/src/i18n/localization.ts index 2ac5a1a0e1..7b1ba6e943 100644 --- a/packages/common/src/i18n/localization.ts +++ b/packages/common/src/i18n/localization.ts @@ -7,8 +7,7 @@ */ import {Inject, Injectable, LOCALE_ID} from '@angular/core'; -import {Plural} from './locale_data'; -import {getLocalePluralCase} from './locale_data_api'; +import {Plural, getLocalePluralCase} from './locale_data_api'; /** * @experimental diff --git a/packages/common/test/i18n/locale_data_api_spec.ts b/packages/common/test/i18n/locale_data_api_spec.ts index e7d1c629ea..d7d98a57f6 100644 --- a/packages/common/test/i18n/locale_data_api_spec.ts +++ b/packages/common/test/i18n/locale_data_api_spec.ts @@ -10,7 +10,8 @@ import localeCaESVALENCIA from '../../i18n_data/locale_ca-ES-VALENCIA'; import localeEn from '../../i18n_data/locale_en'; import localeFr from '../../i18n_data/locale_fr'; import localeFrCA from '../../i18n_data/locale_fr-CA'; -import {registerLocaleData, findLocaleData} from '../../src/i18n/locale_data_api'; +import {findLocaleData} from '../../src/i18n/locale_data_api'; +import {registerLocaleData} from '../../src/i18n/locale_data'; export function main() { describe('locale data api', () => { diff --git a/packages/common/test/i18n/localization_spec.ts b/packages/common/test/i18n/localization_spec.ts index 069b963492..d22db4b448 100644 --- a/packages/common/test/i18n/localization_spec.ts +++ b/packages/common/test/i18n/localization_spec.ts @@ -13,7 +13,7 @@ import localeFr from '../../i18n_data/locale_fr'; import {LOCALE_ID} from '@angular/core'; import {TestBed, inject} from '@angular/core/testing'; import {NgLocaleLocalization, NgLocalization, getPluralCategory} from '../../src/i18n/localization'; -import {registerLocaleData} from '../../src/i18n/locale_data_api'; +import {registerLocaleData} from '../../src/i18n/locale_data'; export function main() { describe('l10n', () => { diff --git a/packages/common/test/pipes/number_pipe_spec.ts b/packages/common/test/pipes/number_pipe_spec.ts index 41bb7feb39..f5cc5a2837 100644 --- a/packages/common/test/pipes/number_pipe_spec.ts +++ b/packages/common/test/pipes/number_pipe_spec.ts @@ -56,7 +56,7 @@ export function main() { }); describe('transform with custom locales', () => { - it('should return the correct format for es-US in IE11', () => { + it('should return the correct format for es-US', () => { const pipe = new DecimalPipe('es-US'); expect(pipe.transform('9999999.99', '1.2-2')).toEqual('9,999,999.99'); }); diff --git a/tools/gulp-tasks/cldr/extract.js b/tools/gulp-tasks/cldr/extract.js index 0404b1a527..968fd7679b 100644 --- a/tools/gulp-tasks/cldr/extract.js +++ b/tools/gulp-tasks/cldr/extract.js @@ -58,7 +58,7 @@ module.exports = (gulp, done) => { console.log(`${index + 1}/${LOCALES.length}`); console.log(`\t${I18N_DATA_FOLDER}/locale_${locale}.ts`); - fs.writeFileSync(`${RELATIVE_I18N_DATA_FOLDER}/locale_${locale}.ts`, generateLocale(locale, localeData, '@angular/common')); + fs.writeFileSync(`${RELATIVE_I18N_DATA_FOLDER}/locale_${locale}.ts`, generateLocale(locale, localeData)); console.log(`\t${I18N_DATA_EXTRA_FOLDER}/locale_${locale}.ts`); fs.writeFileSync(`${RELATIVE_I18N_DATA_EXTRA_FOLDER}/locale_${locale}.ts`, generateLocaleExtra(locale, localeData)); }); @@ -66,7 +66,7 @@ module.exports = (gulp, done) => { // additional "en" file that will be included in common console.log(`Writing file ${I18N_FOLDER}/locale_en.ts`); - fs.writeFileSync(`${RELATIVE_I18N_FOLDER}/locale_en.ts`, generateLocale('en', new cldrJs('en'), './locale_data')); + fs.writeFileSync(`${RELATIVE_I18N_FOLDER}/locale_en.ts`, generateLocale('en', new cldrJs('en'))); console.log(`Writing file ${I18N_FOLDER}/currencies.ts`); fs.writeFileSync(`${RELATIVE_I18N_FOLDER}/currencies.ts`, generateCurrencies()); @@ -87,7 +87,7 @@ module.exports = (gulp, done) => { /** * Generate file that contains basic locale data */ -function generateLocale(locale, localeData, ngLocalePath) { +function generateLocale(locale, localeData) { // [ localeId, dateTime, number, currency, pluralCase ] let data = stringify([ locale, @@ -103,8 +103,6 @@ function generateLocale(locale, localeData, ngLocalePath) { data = data.substring(0, data.lastIndexOf(']')) + `, ${getPluralFunction(locale)}]`; return `${HEADER} -import {Plural} from '${ngLocalePath}'; - export default ${data}; `; } @@ -450,24 +448,28 @@ function toRegExp(s) { */ function getPluralFunction(locale) { let fn = cldr.extractPluralRuleFunction(locale).toString(); + if (fn === EMPTY_RULE) { fn = DEFAULT_RULE; } - return fn + fn = fn .replace( toRegExp('function anonymous(n\n/**/) {\n'), - 'function(n: number): Plural {\n ') + 'function(n: number): number {\n ') .replace(toRegExp('var'), 'let') .replace(toRegExp('if(typeof n==="string")n=parseInt(n,10);'), '') - .replace(toRegExp('"zero"'), ' Plural.Zero') - .replace(toRegExp('"one"'), ' Plural.One') - .replace(toRegExp('"two"'), ' Plural.Two') - .replace(toRegExp('"few"'), ' Plural.Few') - .replace(toRegExp('"many"'), ' Plural.Many') - .replace(toRegExp('"other"'), ' Plural.Other') .replace(toRegExp('\n}'), ';\n}'); - return normalizePluralRule(); + + // The replacement values must match the `Plural` enum from common. + // We do not use the enum directly to avoid depending on that package. + return fn + .replace(toRegExp('"zero"'), ' 0') + .replace(toRegExp('"one"'), ' 1') + .replace(toRegExp('"two"'), ' 2') + .replace(toRegExp('"few"'), ' 3') + .replace(toRegExp('"many"'), ' 4') + .replace(toRegExp('"other"'), ' 5'); } /** @@ -484,13 +486,6 @@ function stringify(obj) { return util.inspect(obj, {depth: null, maxArrayLength: null}) } -/** - * Transform a string to camelCase - */ -function toCamelCase(str) { - return str.replace(/-+([a-z0-9A-Z])/g, (...m) => m[1].toUpperCase()); -} - /** * To create smaller locale files, we remove duplicated data. * To be make this work we need to store similar data in arrays, if some value in an array diff --git a/tools/public_api_guard/common/common.d.ts b/tools/public_api_guard/common/common.d.ts index 78ced632b6..05cadf276a 100644 --- a/tools/public_api_guard/common/common.d.ts +++ b/tools/public_api_guard/common/common.d.ts @@ -69,9 +69,6 @@ export declare class DeprecatedPercentPipe implements PipeTransform { /** @stable */ export declare const DOCUMENT: InjectionToken; -/** @experimental */ -export declare function findLocaleData(locale: string): any; - /** @experimental */ export declare enum FormatWidth { Short = 0, @@ -182,11 +179,6 @@ export declare class JsonPipe implements PipeTransform { transform(value: any): string; } -/** @experimental */ -export declare const LOCALE_DATA: { - [localeId: string]: any; -}; - /** @stable */ export declare class Location { constructor(platformStrategy: LocationStrategy);