fix(common): add locale currency values (#21783)
we now use locale currency symbols, since they may be different in each locale (we were only using english data previously) Fixes #20385 PR Close #21783
This commit is contained in:
parent
5fc77c90cb
commit
420cc7afc6
@ -9,8 +9,10 @@
|
|||||||
// THIS CODE IS GENERATED - DO NOT MODIFY
|
// THIS CODE IS GENERATED - DO NOT MODIFY
|
||||||
// See angular/tools/gulp-tasks/cldr/extract.js
|
// See angular/tools/gulp-tasks/cldr/extract.js
|
||||||
|
|
||||||
|
export type CurrenciesSymbols = [string] | [string | undefined, string];
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
export const CURRENCIES: {[code: string]: (string | undefined)[]} = {
|
export const CURRENCIES_EN: {[code: string]: CurrenciesSymbols} = {
|
||||||
'AOA': [, 'Kz'],
|
'AOA': [, 'Kz'],
|
||||||
'ARS': [, '$'],
|
'ARS': [, '$'],
|
||||||
'AUD': ['A$', '$'],
|
'AUD': ['A$', '$'],
|
||||||
@ -111,5 +113,5 @@ export const CURRENCIES: {[code: string]: (string | undefined)[]} = {
|
|||||||
'XOF': ['CFA'],
|
'XOF': ['CFA'],
|
||||||
'XPF': ['CFPF'],
|
'XPF': ['CFPF'],
|
||||||
'ZAR': [, 'R'],
|
'ZAR': [, 'R'],
|
||||||
'ZMW': [, 'ZK'],
|
'ZMW': [, 'ZK']
|
||||||
};
|
};
|
||||||
|
@ -18,33 +18,28 @@ const DIGIT_CHAR = '#';
|
|||||||
const CURRENCY_CHAR = '¤';
|
const CURRENCY_CHAR = '¤';
|
||||||
const PERCENT_CHAR = '%';
|
const PERCENT_CHAR = '%';
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export type FormatNumberRes = {
|
|
||||||
str: string | null,
|
|
||||||
error?: string
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform a number to a locale string based on a style and a format
|
* Transforms a string into a number (if needed)
|
||||||
*
|
|
||||||
* @internal
|
|
||||||
*/
|
*/
|
||||||
export function formatNumber(
|
function strToNumber(value: number | string): number {
|
||||||
value: number | string, locale: string, style: NumberFormatStyle, digitsInfo?: string | null,
|
|
||||||
currency: string | null = null): FormatNumberRes {
|
|
||||||
const res: FormatNumberRes = {str: null};
|
|
||||||
const format = getLocaleNumberFormat(locale, style);
|
|
||||||
let num;
|
|
||||||
|
|
||||||
// Convert strings to numbers
|
// Convert strings to numbers
|
||||||
if (typeof value === 'string' && !isNaN(+value - parseFloat(value))) {
|
if (typeof value === 'string' && !isNaN(+value - parseFloat(value))) {
|
||||||
num = +value;
|
return +value;
|
||||||
} else if (typeof value !== 'number') {
|
|
||||||
res.error = `${value} is not a number`;
|
|
||||||
return res;
|
|
||||||
} else {
|
|
||||||
num = value;
|
|
||||||
}
|
}
|
||||||
|
if (typeof value !== 'number') {
|
||||||
|
throw new Error(`${value} is not a number`);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms a number to a locale string based on a style and a format
|
||||||
|
*/
|
||||||
|
function formatNumber(
|
||||||
|
value: number | string, locale: string, style: NumberFormatStyle, groupSymbol: NumberSymbol,
|
||||||
|
decimalSymbol: NumberSymbol, digitsInfo?: string): string {
|
||||||
|
const format = getLocaleNumberFormat(locale, style);
|
||||||
|
const num = strToNumber(value);
|
||||||
|
|
||||||
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
|
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
|
||||||
let formattedText = '';
|
let formattedText = '';
|
||||||
@ -66,8 +61,7 @@ export function formatNumber(
|
|||||||
if (digitsInfo) {
|
if (digitsInfo) {
|
||||||
const parts = digitsInfo.match(NUMBER_FORMAT_REGEXP);
|
const parts = digitsInfo.match(NUMBER_FORMAT_REGEXP);
|
||||||
if (parts === null) {
|
if (parts === null) {
|
||||||
res.error = `${digitsInfo} is not a valid digit info`;
|
throw new Error(`${digitsInfo} is not a valid digit info`);
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
const minIntPart = parts[1];
|
const minIntPart = parts[1];
|
||||||
const minFractionPart = parts[3];
|
const minFractionPart = parts[3];
|
||||||
@ -125,12 +119,10 @@ export function formatNumber(
|
|||||||
groups.unshift(digits.join(''));
|
groups.unshift(digits.join(''));
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupSymbol = currency ? NumberSymbol.CurrencyGroup : NumberSymbol.Group;
|
|
||||||
formattedText = groups.join(getLocaleNumberSymbol(locale, groupSymbol));
|
formattedText = groups.join(getLocaleNumberSymbol(locale, groupSymbol));
|
||||||
|
|
||||||
// append the decimal digits
|
// append the decimal digits
|
||||||
if (decimals.length) {
|
if (decimals.length) {
|
||||||
const decimalSymbol = currency ? NumberSymbol.CurrencyDecimal : NumberSymbol.Decimal;
|
|
||||||
formattedText += getLocaleNumberSymbol(locale, decimalSymbol) + decimals.join('');
|
formattedText += getLocaleNumberSymbol(locale, decimalSymbol) + decimals.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,22 +137,42 @@ export function formatNumber(
|
|||||||
formattedText = pattern.posPre + formattedText + pattern.posSuf;
|
formattedText = pattern.posPre + formattedText + pattern.posSuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (style === NumberFormatStyle.Currency && currency !== null) {
|
return formattedText;
|
||||||
res.str = formattedText
|
}
|
||||||
.replace(CURRENCY_CHAR, currency)
|
|
||||||
// if we have 2 time the currency character, the second one is ignored
|
|
||||||
.replace(CURRENCY_CHAR, '');
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (style === NumberFormatStyle.Percent) {
|
/**
|
||||||
res.str = formattedText.replace(
|
* Formats a currency to a locale string
|
||||||
new RegExp(PERCENT_CHAR, 'g'), getLocaleNumberSymbol(locale, NumberSymbol.PercentSign));
|
*/
|
||||||
return res;
|
export function formatCurrency(
|
||||||
}
|
value: number | string, locale: string, currency: string, currencyCode?: string,
|
||||||
|
digitsInfo?: string): string {
|
||||||
|
const res = formatNumber(
|
||||||
|
value, locale, NumberFormatStyle.Currency, NumberSymbol.CurrencyGroup,
|
||||||
|
NumberSymbol.CurrencyDecimal, digitsInfo);
|
||||||
|
return res
|
||||||
|
.replace(CURRENCY_CHAR, currency)
|
||||||
|
// if we have 2 time the currency character, the second one is ignored
|
||||||
|
.replace(CURRENCY_CHAR, '');
|
||||||
|
}
|
||||||
|
|
||||||
res.str = formattedText;
|
/**
|
||||||
return res;
|
* Formats a percentage to a locale string
|
||||||
|
*/
|
||||||
|
export function formatPercent(value: number | string, locale: string, digitsInfo?: string): string {
|
||||||
|
const res = formatNumber(
|
||||||
|
value, locale, NumberFormatStyle.Percent, NumberSymbol.Group, NumberSymbol.Decimal,
|
||||||
|
digitsInfo);
|
||||||
|
return res.replace(
|
||||||
|
new RegExp(PERCENT_CHAR, 'g'), getLocaleNumberSymbol(locale, NumberSymbol.PercentSign));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a number to a locale string
|
||||||
|
*/
|
||||||
|
export function formatDecimal(value: number | string, locale: string, digitsInfo?: string): string {
|
||||||
|
return formatNumber(
|
||||||
|
value, locale, NumberFormatStyle.Decimal, NumberSymbol.Group, NumberSymbol.Decimal,
|
||||||
|
digitsInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ParsedNumberFormat {
|
interface ParsedNumberFormat {
|
||||||
|
@ -54,6 +54,7 @@ export const enum LocaleDataIndex {
|
|||||||
NumberFormats,
|
NumberFormats,
|
||||||
CurrencySymbol,
|
CurrencySymbol,
|
||||||
CurrencyName,
|
CurrencyName,
|
||||||
|
Currencies,
|
||||||
PluralCase,
|
PluralCase,
|
||||||
ExtraData
|
ExtraData
|
||||||
}
|
}
|
||||||
@ -66,3 +67,8 @@ export const enum ExtraLocaleDataIndex {
|
|||||||
ExtraDayPeriodStandalone,
|
ExtraDayPeriodStandalone,
|
||||||
ExtraDayPeriodsRules
|
ExtraDayPeriodsRules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index of each value in currency data (used to describe CURRENCIES_EN in currencies.ts)
|
||||||
|
*/
|
||||||
|
export const enum CurrencyIndex {Symbol = 0, SymbolNarrow}
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {CURRENCIES} from './currencies';
|
|
||||||
import localeEn from './locale_en';
|
import localeEn from './locale_en';
|
||||||
import {LOCALE_DATA, LocaleDataIndex, ExtraLocaleDataIndex} from './locale_data';
|
import {LOCALE_DATA, LocaleDataIndex, ExtraLocaleDataIndex, CurrencyIndex} from './locale_data';
|
||||||
|
import {CURRENCIES_EN, CurrenciesSymbols} from './currencies';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The different format styles that can be used to represent numbers.
|
* The different format styles that can be used to represent numbers.
|
||||||
@ -391,6 +391,14 @@ export function getLocaleCurrencyName(locale: string): string|null {
|
|||||||
return data[LocaleDataIndex.CurrencyName] || null;
|
return data[LocaleDataIndex.CurrencyName] || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currency values for the locale
|
||||||
|
*/
|
||||||
|
function getLocaleCurrencies(locale: string): {[code: string]: CurrenciesSymbols} {
|
||||||
|
const data = findLocaleData(locale);
|
||||||
|
return data[LocaleDataIndex.Currencies];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The locale plural function used by ICU expressions to determine the plural case to use.
|
* The locale plural function used by ICU expressions to determine the plural case to use.
|
||||||
* See {@link NgPlural} for more information.
|
* See {@link NgPlural} for more information.
|
||||||
@ -526,18 +534,19 @@ export function findLocaleData(locale: string): any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the currency symbol for a given currency code, or the code if no symbol available
|
* Returns the currency symbol for a given currency code, or the code if no symbol available
|
||||||
* (e.g.: format narrow = $, format wide = US$, code = USD)
|
* (e.g.: format narrow = $, format wide = US$, code = USD)
|
||||||
|
* If no locale is provided, it uses the locale "en" by default
|
||||||
*
|
*
|
||||||
* @experimental i18n support is experimental.
|
* @experimental i18n support is experimental.
|
||||||
*/
|
*/
|
||||||
export function getCurrencySymbol(code: string, format: 'wide' | 'narrow'): string {
|
export function getCurrencySymbol(code: string, format: 'wide' | 'narrow', locale = 'en'): string {
|
||||||
const currency = CURRENCIES[code] || [];
|
const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || [];
|
||||||
const symbolNarrow = currency[1];
|
const symbolNarrow = currency[CurrencyIndex.SymbolNarrow];
|
||||||
|
|
||||||
if (format === 'narrow' && typeof symbolNarrow === 'string') {
|
if (format === 'narrow' && typeof symbolNarrow === 'string') {
|
||||||
return symbolNarrow;
|
return symbolNarrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
return currency[0] || code;
|
return currency[CurrencyIndex.Symbol] || code;
|
||||||
}
|
}
|
||||||
|
@ -48,5 +48,5 @@ export default [
|
|||||||
'{1} \'at\' {0}',
|
'{1} \'at\' {0}',
|
||||||
],
|
],
|
||||||
['.', ',', ';', '%', '+', '-', 'E', '×', '‰', '∞', 'NaN', ':'],
|
['.', ',', ';', '%', '+', '-', 'E', '×', '‰', '∞', 'NaN', ':'],
|
||||||
['#,##0.###', '#,##0%', '¤#,##0.00', '#E0'], '$', 'US Dollar', plural
|
['#,##0.###', '#,##0%', '¤#,##0.00', '#E0'], '$', 'US Dollar', {}, plural
|
||||||
];
|
];
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Inject, LOCALE_ID, Pipe, PipeTransform} from '@angular/core';
|
import {Inject, LOCALE_ID, Pipe, PipeTransform} from '@angular/core';
|
||||||
import {formatNumber} from '../i18n/format_number';
|
import {formatCurrency, formatDecimal, formatPercent} from '../i18n/format_number';
|
||||||
import {NumberFormatStyle, getCurrencySymbol, getLocaleCurrencyName, getLocaleCurrencySymbol} from '../i18n/locale_data_api';
|
import {getCurrencySymbol} from '../i18n/locale_data_api';
|
||||||
import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
|
import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,18 +41,16 @@ import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
|
|||||||
export class DecimalPipe implements PipeTransform {
|
export class DecimalPipe implements PipeTransform {
|
||||||
constructor(@Inject(LOCALE_ID) private _locale: string) {}
|
constructor(@Inject(LOCALE_ID) private _locale: string) {}
|
||||||
|
|
||||||
transform(value: any, digits?: string, locale?: string): string|null {
|
transform(value: any, digitsInfo?: string, locale?: string): string|null {
|
||||||
if (isEmpty(value)) return null;
|
if (isEmpty(value)) return null;
|
||||||
|
|
||||||
locale = locale || this._locale;
|
locale = locale || this._locale;
|
||||||
|
|
||||||
const {str, error} = formatNumber(value, locale, NumberFormatStyle.Decimal, digits);
|
try {
|
||||||
|
return formatDecimal(value, locale, digitsInfo);
|
||||||
if (error) {
|
} catch (error) {
|
||||||
throw invalidPipeArgumentError(DecimalPipe, error);
|
throw invalidPipeArgumentError(DecimalPipe, error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +63,7 @@ export class DecimalPipe implements PipeTransform {
|
|||||||
*
|
*
|
||||||
* Formats a number as percentage.
|
* Formats a number as percentage.
|
||||||
*
|
*
|
||||||
* - `digitInfo` See {@link DecimalPipe} for detailed description.
|
* - `digitInfo` See {@link DecimalPipe} for a detailed description.
|
||||||
* - `locale` is a `string` defining the locale to use (uses the current {@link LOCALE_ID} by
|
* - `locale` is a `string` defining the locale to use (uses the current {@link LOCALE_ID} by
|
||||||
* default)
|
* default)
|
||||||
*
|
*
|
||||||
@ -79,18 +77,16 @@ export class DecimalPipe implements PipeTransform {
|
|||||||
export class PercentPipe implements PipeTransform {
|
export class PercentPipe implements PipeTransform {
|
||||||
constructor(@Inject(LOCALE_ID) private _locale: string) {}
|
constructor(@Inject(LOCALE_ID) private _locale: string) {}
|
||||||
|
|
||||||
transform(value: any, digits?: string, locale?: string): string|null {
|
transform(value: any, digitsInfo?: string, locale?: string): string|null {
|
||||||
if (isEmpty(value)) return null;
|
if (isEmpty(value)) return null;
|
||||||
|
|
||||||
locale = locale || this._locale;
|
locale = locale || this._locale;
|
||||||
|
|
||||||
const {str, error} = formatNumber(value, locale, NumberFormatStyle.Percent, digits);
|
try {
|
||||||
|
return formatPercent(value, locale, digitsInfo);
|
||||||
if (error) {
|
} catch (error) {
|
||||||
throw invalidPipeArgumentError(PercentPipe, error);
|
throw invalidPipeArgumentError(PercentPipe, error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,14 +100,15 @@ export class PercentPipe implements PipeTransform {
|
|||||||
*
|
*
|
||||||
* - `currencyCode` is the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code, such
|
* - `currencyCode` is the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code, such
|
||||||
* as `USD` for the US dollar and `EUR` for the euro.
|
* as `USD` for the US dollar and `EUR` for the euro.
|
||||||
* - `display` indicates whether to show the currency symbol or the code.
|
* - `display` indicates whether to show the currency symbol, the code or a custom value
|
||||||
* - `code`: use code (e.g. `USD`).
|
* - `code`: use code (e.g. `USD`).
|
||||||
* - `symbol`(default): use symbol (e.g. `$`).
|
* - `symbol`(default): use symbol (e.g. `$`).
|
||||||
* - `symbol-narrow`: some countries have two symbols for their currency, one regular and one
|
* - `symbol-narrow`: some countries have two symbols for their currency, one regular and one
|
||||||
* narrow (e.g. the canadian dollar CAD has the symbol `CA$` and the symbol-narrow `$`).
|
* narrow (e.g. the canadian dollar CAD has the symbol `CA$` and the symbol-narrow `$`).
|
||||||
|
* - `string`: use this value instead of a code or a symbol
|
||||||
* - boolean (deprecated from v5): `true` for symbol and false for `code`
|
* - boolean (deprecated from v5): `true` for symbol and false for `code`
|
||||||
* If there is no narrow symbol for the chosen currency, the regular symbol will be used.
|
* If there is no narrow symbol for the chosen currency, the regular symbol will be used.
|
||||||
* - `digitInfo` See {@link DecimalPipe} for detailed description.
|
* - `digitInfo` See {@link DecimalPipe} for a detailed description.
|
||||||
* - `locale` is a `string` defining the locale to use (uses the current {@link LOCALE_ID} by
|
* - `locale` is a `string` defining the locale to use (uses the current {@link LOCALE_ID} by
|
||||||
* default)
|
* default)
|
||||||
*
|
*
|
||||||
@ -127,7 +124,7 @@ export class CurrencyPipe implements PipeTransform {
|
|||||||
|
|
||||||
transform(
|
transform(
|
||||||
value: any, currencyCode?: string,
|
value: any, currencyCode?: string,
|
||||||
display: 'code'|'symbol'|'symbol-narrow'|boolean = 'symbol', digits?: string,
|
display: 'code'|'symbol'|'symbol-narrow'|string|boolean = 'symbol', digitsInfo?: string,
|
||||||
locale?: string): string|null {
|
locale?: string): string|null {
|
||||||
if (isEmpty(value)) return null;
|
if (isEmpty(value)) return null;
|
||||||
|
|
||||||
@ -141,18 +138,20 @@ export class CurrencyPipe implements PipeTransform {
|
|||||||
display = display ? 'symbol' : 'code';
|
display = display ? 'symbol' : 'code';
|
||||||
}
|
}
|
||||||
|
|
||||||
let currency = currencyCode || 'USD';
|
let currency: string = currencyCode || 'USD';
|
||||||
if (display !== 'code') {
|
if (display !== 'code') {
|
||||||
currency = getCurrencySymbol(currency, display === 'symbol' ? 'wide' : 'narrow');
|
if (display === 'symbol' || display === 'symbol-narrow') {
|
||||||
|
currency = getCurrencySymbol(currency, display === 'symbol' ? 'wide' : 'narrow', locale);
|
||||||
|
} else {
|
||||||
|
currency = display;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const {str, error} = formatNumber(value, locale, NumberFormatStyle.Currency, digits, currency);
|
try {
|
||||||
|
return formatCurrency(value, locale, currency, currencyCode, digitsInfo);
|
||||||
if (error) {
|
} catch (error) {
|
||||||
throw invalidPipeArgumentError(CurrencyPipe, error);
|
throw invalidPipeArgumentError(CurrencyPipe, error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ 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 localeFrCA from '@angular/common/locales/fr-CA';
|
||||||
|
import localeEnAU from '@angular/common/locales/en-AU';
|
||||||
import {registerLocaleData} from '../../src/i18n/locale_data';
|
import {registerLocaleData} from '../../src/i18n/locale_data';
|
||||||
import {findLocaleData, getCurrencySymbol, getLocaleDateFormat, FormatWidth} from '../../src/i18n/locale_data_api';
|
import {findLocaleData, getCurrencySymbol, getLocaleDateFormat, FormatWidth} from '../../src/i18n/locale_data_api';
|
||||||
|
|
||||||
@ -24,6 +25,7 @@ import {findLocaleData, getCurrencySymbol, getLocaleDateFormat, FormatWidth} fro
|
|||||||
registerLocaleData(localeFr, 'fake-id');
|
registerLocaleData(localeFr, 'fake-id');
|
||||||
registerLocaleData(localeFrCA, 'fake_Id2');
|
registerLocaleData(localeFrCA, 'fake_Id2');
|
||||||
registerLocaleData(localeZh);
|
registerLocaleData(localeZh);
|
||||||
|
registerLocaleData(localeEnAU);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('findLocaleData', () => {
|
describe('findLocaleData', () => {
|
||||||
@ -54,7 +56,7 @@ import {findLocaleData, getCurrencySymbol, getLocaleDateFormat, FormatWidth} fro
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getCurrencySymbolElseCode', () => {
|
describe('getting currency symbol', () => {
|
||||||
it('should return the correct symbol', () => {
|
it('should return the correct symbol', () => {
|
||||||
expect(getCurrencySymbol('USD', 'wide')).toEqual('$');
|
expect(getCurrencySymbol('USD', 'wide')).toEqual('$');
|
||||||
expect(getCurrencySymbol('USD', 'narrow')).toEqual('$');
|
expect(getCurrencySymbol('USD', 'narrow')).toEqual('$');
|
||||||
@ -62,8 +64,13 @@ import {findLocaleData, getCurrencySymbol, getLocaleDateFormat, FormatWidth} fro
|
|||||||
expect(getCurrencySymbol('AUD', 'narrow')).toEqual('$');
|
expect(getCurrencySymbol('AUD', 'narrow')).toEqual('$');
|
||||||
expect(getCurrencySymbol('CRC', 'wide')).toEqual('CRC');
|
expect(getCurrencySymbol('CRC', 'wide')).toEqual('CRC');
|
||||||
expect(getCurrencySymbol('CRC', 'narrow')).toEqual('₡');
|
expect(getCurrencySymbol('CRC', 'narrow')).toEqual('₡');
|
||||||
expect(getCurrencySymbol('FAKE', 'wide')).toEqual('FAKE');
|
expect(getCurrencySymbol('unexisting_ISO_code', 'wide')).toEqual('unexisting_ISO_code');
|
||||||
expect(getCurrencySymbol('FAKE', 'narrow')).toEqual('FAKE');
|
expect(getCurrencySymbol('unexisting_ISO_code', 'narrow')).toEqual('unexisting_ISO_code');
|
||||||
|
expect(getCurrencySymbol('USD', 'wide', 'en-AU')).toEqual('USD');
|
||||||
|
expect(getCurrencySymbol('USD', 'narrow', 'en-AU')).toEqual('$');
|
||||||
|
expect(getCurrencySymbol('AUD', 'wide', 'en-AU')).toEqual('$');
|
||||||
|
expect(getCurrencySymbol('AUD', 'narrow', 'en-AU')).toEqual('$');
|
||||||
|
expect(getCurrencySymbol('USD', 'wide', 'fr')).toEqual('$US');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -125,7 +125,15 @@ import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testin
|
|||||||
expect(pipe.transform(5.1234, 'CAD', 'symbol-narrow', '5.2-2')).toEqual('$00,005.12');
|
expect(pipe.transform(5.1234, 'CAD', 'symbol-narrow', '5.2-2')).toEqual('$00,005.12');
|
||||||
expect(pipe.transform(5.1234, 'CAD', 'symbol-narrow', '5.2-2', 'fr'))
|
expect(pipe.transform(5.1234, 'CAD', 'symbol-narrow', '5.2-2', 'fr'))
|
||||||
.toEqual('00 005,12 $');
|
.toEqual('00 005,12 $');
|
||||||
expect(pipe.transform(5.1234, 'FAKE', 'symbol')).toEqual('FAKE5.12');
|
expect(pipe.transform(5, 'USD', 'symbol', '', 'fr')).toEqual('5,00 $US');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support any currency code name', () => {
|
||||||
|
// currency code is unknown, default formatting options will be used
|
||||||
|
expect(pipe.transform(5.1234, 'unexisting_ISO_code', 'symbol'))
|
||||||
|
.toEqual('unexisting_ISO_code5.12');
|
||||||
|
// currency code is USD, the pipe will format based on USD but will display "Custom name"
|
||||||
|
expect(pipe.transform(5.1234, 'USD', 'Custom name')).toEqual('Custom name5.12');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not support other objects', () => {
|
it('should not support other objects', () => {
|
||||||
|
@ -54,33 +54,36 @@ module.exports = (gulp, done) => {
|
|||||||
if (!fs.existsSync(RELATIVE_I18N_DATA_EXTRA_FOLDER)) {
|
if (!fs.existsSync(RELATIVE_I18N_DATA_EXTRA_FOLDER)) {
|
||||||
fs.mkdirSync(RELATIVE_I18N_DATA_EXTRA_FOLDER);
|
fs.mkdirSync(RELATIVE_I18N_DATA_EXTRA_FOLDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(`Writing file ${I18N_FOLDER}/currencies.ts`);
|
||||||
|
fs.writeFileSync(`${RELATIVE_I18N_FOLDER}/currencies.ts`, generateCurrenciesFile());
|
||||||
|
|
||||||
|
const baseCurrencies = generateBaseCurrencies(new cldrJs('en'));
|
||||||
|
// additional "en" file that will be included in common
|
||||||
|
console.log(`Writing file ${I18N_FOLDER}/locale_en.ts`);
|
||||||
|
const localeEnFile = generateLocale('en', new cldrJs('en'), baseCurrencies);
|
||||||
|
fs.writeFileSync(`${RELATIVE_I18N_FOLDER}/locale_en.ts`, localeEnFile);
|
||||||
|
|
||||||
LOCALES.forEach((locale, index) => {
|
LOCALES.forEach((locale, index) => {
|
||||||
const localeData = new cldrJs(locale);
|
const localeData = new cldrJs(locale);
|
||||||
|
|
||||||
console.log(`${index + 1}/${LOCALES.length}`);
|
console.log(`${index + 1}/${LOCALES.length}`);
|
||||||
console.log(`\t${I18N_DATA_FOLDER}/${locale}.ts`);
|
console.log(`\t${I18N_DATA_FOLDER}/${locale}.ts`);
|
||||||
fs.writeFileSync(`${RELATIVE_I18N_DATA_FOLDER}/${locale}.ts`, generateLocale(locale, localeData));
|
fs.writeFileSync(`${RELATIVE_I18N_DATA_FOLDER}/${locale}.ts`, locale === 'en'? localeEnFile : generateLocale(locale, localeData, baseCurrencies));
|
||||||
console.log(`\t${I18N_DATA_EXTRA_FOLDER}/${locale}.ts`);
|
console.log(`\t${I18N_DATA_EXTRA_FOLDER}/${locale}.ts`);
|
||||||
fs.writeFileSync(`${RELATIVE_I18N_DATA_EXTRA_FOLDER}/${locale}.ts`, generateLocaleExtra(locale, localeData));
|
fs.writeFileSync(`${RELATIVE_I18N_DATA_EXTRA_FOLDER}/${locale}.ts`, generateLocaleExtra(locale, localeData));
|
||||||
});
|
});
|
||||||
console.log(`${LOCALES.length} locale files generated.`);
|
console.log(`${LOCALES.length} locale files generated.`);
|
||||||
|
|
||||||
// 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')));
|
|
||||||
|
|
||||||
console.log(`Writing file ${I18N_FOLDER}/currencies.ts`);
|
|
||||||
fs.writeFileSync(`${RELATIVE_I18N_FOLDER}/currencies.ts`, generateCurrencies());
|
|
||||||
|
|
||||||
console.log(`All i18n cldr files have been generated, formatting files..."`);
|
console.log(`All i18n cldr files have been generated, formatting files..."`);
|
||||||
const format = require('gulp-clang-format');
|
const format = require('gulp-clang-format');
|
||||||
const clangFormat = require('clang-format');
|
const clangFormat = require('clang-format');
|
||||||
return gulp
|
return gulp
|
||||||
.src([
|
.src([
|
||||||
`${I18N_DATA_FOLDER}/**/*.ts`,
|
`${I18N_DATA_FOLDER}/**/*.ts`,
|
||||||
`${I18N_FOLDER}/currencies.ts`,
|
`${I18N_FOLDER}/currencies.ts`,
|
||||||
`${I18N_FOLDER}/locale_en.ts`
|
`${I18N_FOLDER}/locale_en.ts`
|
||||||
], {base: '.'})
|
], {base: '.'})
|
||||||
.pipe(format.format('file', clangFormat))
|
.pipe(format.format('file', clangFormat))
|
||||||
.pipe(gulp.dest('.'));
|
.pipe(gulp.dest('.'));
|
||||||
};
|
};
|
||||||
@ -88,16 +91,17 @@ module.exports = (gulp, done) => {
|
|||||||
/**
|
/**
|
||||||
* Generate file that contains basic locale data
|
* Generate file that contains basic locale data
|
||||||
*/
|
*/
|
||||||
function generateLocale(locale, localeData) {
|
function generateLocale(locale, localeData, baseCurrencies) {
|
||||||
// [ localeId, dateTime, number, currency, pluralCase ]
|
// [ localeId, dateTime, number, currency, pluralCase ]
|
||||||
let data = stringify([
|
let data = stringify([
|
||||||
locale,
|
locale,
|
||||||
...getDateTimeTranslations(localeData),
|
...getDateTimeTranslations(localeData),
|
||||||
...getDateTimeSettings(localeData),
|
...getDateTimeSettings(localeData),
|
||||||
...getNumberSettings(localeData),
|
...getNumberSettings(localeData),
|
||||||
...getCurrencySettings(locale, localeData)
|
...getCurrencySettings(locale, localeData),
|
||||||
])
|
generateLocaleCurrencies(localeData, baseCurrencies)
|
||||||
// We remove "undefined" added by spreading arrays when there is no value
|
], true)
|
||||||
|
// We remove "undefined" added by spreading arrays when there is no value
|
||||||
.replace(/undefined/g, '');
|
.replace(/undefined/g, '');
|
||||||
|
|
||||||
// adding plural function after, because we don't want it as a string
|
// adding plural function after, because we don't want it as a string
|
||||||
@ -149,11 +153,12 @@ export default ${stringify(dayPeriodsSupplemental).replace(/undefined/g, '')};
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a file that contains the list of currencies and their symbols
|
* Generate a list of currencies to be used as a based for other currencies
|
||||||
|
* e.g.: {'ARS': [, '$'], 'AUD': ['A$', '$'], ...}
|
||||||
*/
|
*/
|
||||||
function generateCurrencies() {
|
function generateBaseCurrencies(localeData, addDigits) {
|
||||||
const currenciesData = new cldrJs('en').main('numbers/currencies');
|
const currenciesData = localeData.main('numbers/currencies');
|
||||||
const currencies = [];
|
const currencies = {};
|
||||||
Object.keys(currenciesData).forEach(key => {
|
Object.keys(currenciesData).forEach(key => {
|
||||||
let symbolsArray = [];
|
let symbolsArray = [];
|
||||||
const symbol = currenciesData[key].symbol;
|
const symbol = currenciesData[key].symbol;
|
||||||
@ -169,14 +174,52 @@ function generateCurrencies() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (symbolsArray.length > 0) {
|
if (symbolsArray.length > 0) {
|
||||||
currencies.push(` '${key}': ${stringify(symbolsArray)},\n`);
|
currencies[key] = symbolsArray;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return currencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To minimize the file even more, we only output the differences compared to the base currency
|
||||||
|
*/
|
||||||
|
function generateLocaleCurrencies(localeData, baseCurrencies) {
|
||||||
|
const currenciesData = localeData.main('numbers/currencies');
|
||||||
|
const currencies = {};
|
||||||
|
Object.keys(currenciesData).forEach(code => {
|
||||||
|
let symbolsArray = [];
|
||||||
|
const symbol = currenciesData[code].symbol;
|
||||||
|
const symbolNarrow = currenciesData[code]['symbol-alt-narrow'];
|
||||||
|
if (symbol && symbol !== code) {
|
||||||
|
symbolsArray.push(symbol);
|
||||||
|
}
|
||||||
|
if (symbolNarrow && symbolNarrow !== symbol) {
|
||||||
|
if (symbolsArray.length > 0) {
|
||||||
|
symbolsArray.push(symbolNarrow);
|
||||||
|
} else {
|
||||||
|
symbolsArray = [, symbolNarrow];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if locale data are different, set the value
|
||||||
|
if ((baseCurrencies[code] || []).toString() !== symbolsArray.toString()) {
|
||||||
|
currencies[code] = symbolsArray;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return currencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a file that contains the list of currencies and their symbols
|
||||||
|
*/
|
||||||
|
function generateCurrenciesFile() {
|
||||||
|
const baseCurrencies = generateBaseCurrencies(new cldrJs('en'), true);
|
||||||
|
|
||||||
return `${HEADER}
|
return `${HEADER}
|
||||||
|
export type CurrenciesSymbols = [string] | [string | undefined, string];
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
export const CURRENCIES: {[code: string]: (string | undefined)[]} = {
|
export const CURRENCIES_EN: {[code: string]: CurrenciesSymbols} = ${stringify(baseCurrencies, true)};
|
||||||
${currencies.join('')}};
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,10 @@
|
|||||||
* Like JSON.stringify, but without double quotes around keys, and without null instead of undefined
|
* Like JSON.stringify, but without double quotes around keys, and without null instead of undefined
|
||||||
* values
|
* values
|
||||||
* Based on https://github.com/json5/json5/blob/master/lib/json5.js
|
* Based on https://github.com/json5/json5/blob/master/lib/json5.js
|
||||||
|
* Use option "quoteKeys" to preserve quotes for keys
|
||||||
*/
|
*/
|
||||||
module.exports.stringify = function(obj, replacer, space) {
|
module.exports.stringify = function(obj, quoteKeys) {
|
||||||
if (replacer && (typeof(replacer) !== 'function' && !isArray(replacer))) {
|
var getReplacedValueOrUndefined = function(holder, key) {
|
||||||
throw new Error('Replacer must be a function or an array');
|
|
||||||
}
|
|
||||||
var getReplacedValueOrUndefined = function(holder, key, isTopLevel) {
|
|
||||||
var value = holder[key];
|
var value = holder[key];
|
||||||
|
|
||||||
// Replace the value with its toJSON value first, if possible
|
// Replace the value with its toJSON value first, if possible
|
||||||
@ -17,21 +15,7 @@ module.exports.stringify = function(obj, replacer, space) {
|
|||||||
value = value.toJSON();
|
value = value.toJSON();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user-supplied replacer if a function, call it. If it's an array, check objects' string
|
return value;
|
||||||
// keys for
|
|
||||||
// presence in the array (removing the key/value pair from the resulting JSON if the key is
|
|
||||||
// missing).
|
|
||||||
if (typeof(replacer) === 'function') {
|
|
||||||
return replacer.call(holder, key, value);
|
|
||||||
} else if (replacer) {
|
|
||||||
if (isTopLevel || isArray(holder) || replacer.indexOf(key) >= 0) {
|
|
||||||
return value;
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function isWordChar(c) {
|
function isWordChar(c) {
|
||||||
@ -80,34 +64,6 @@ module.exports.stringify = function(obj, replacer, space) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeIndent(str, num, noNewLine) {
|
|
||||||
if (!str) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
// indentation no more than 10 chars
|
|
||||||
if (str.length > 10) {
|
|
||||||
str = str.substring(0, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
var indent = noNewLine ? '' : '\n';
|
|
||||||
for (var i = 0; i < num; i++) {
|
|
||||||
indent += str;
|
|
||||||
}
|
|
||||||
|
|
||||||
return indent;
|
|
||||||
}
|
|
||||||
|
|
||||||
var indentStr;
|
|
||||||
if (space) {
|
|
||||||
if (typeof space === 'string') {
|
|
||||||
indentStr = space;
|
|
||||||
} else if (typeof space === 'number' && space >= 0) {
|
|
||||||
indentStr = makeIndent(' ', space, true);
|
|
||||||
} else {
|
|
||||||
// ignore space parameter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copied from Crokford's implementation of JSON
|
// Copied from Crokford's implementation of JSON
|
||||||
// See
|
// See
|
||||||
// https://github.com/douglascrockford/JSON-js/blob/e39db4b7e6249f04a195e7dd0840e610cc9e941e/json2.js#L195
|
// https://github.com/douglascrockford/JSON-js/blob/e39db4b7e6249f04a195e7dd0840e610cc9e941e/json2.js#L195
|
||||||
@ -123,24 +79,24 @@ module.exports.stringify = function(obj, replacer, space) {
|
|||||||
'"' : '\\"',
|
'"' : '\\"',
|
||||||
'\\': '\\\\'
|
'\\': '\\\\'
|
||||||
};
|
};
|
||||||
function escapeString(str) {
|
function escapeString(str, keepQuotes) {
|
||||||
// If the string contains no control characters, no quote characters, and no
|
// If the string contains no control characters, no quote characters, and no
|
||||||
// backslash characters, then we can safely slap some quotes around it.
|
// backslash characters, then we can safely slap some quotes around it.
|
||||||
// Otherwise we must also replace the offending characters with safe escape
|
// Otherwise we must also replace the offending characters with safe escape
|
||||||
// sequences.
|
// sequences.
|
||||||
escapable.lastIndex = 0;
|
escapable.lastIndex = 0;
|
||||||
return escapable.test(str) ? '"' + str.replace(escapable, function(a) {
|
return escapable.test(str) && !keepQuotes ? '"' + str.replace(escapable, function(a) {
|
||||||
var c = meta[a];
|
var c = meta[a];
|
||||||
return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||||
}) + '"' : '"' + str + '"';
|
}) + '"' : '"' + str + '"';
|
||||||
}
|
}
|
||||||
// End
|
// End
|
||||||
|
|
||||||
function internalStringify(holder, key, isTopLevel) {
|
function internalStringify(holder, key) {
|
||||||
var buffer, res;
|
var buffer, res;
|
||||||
|
|
||||||
// Replace the value, if necessary
|
// Replace the value, if necessary
|
||||||
var obj_part = getReplacedValueOrUndefined(holder, key, isTopLevel);
|
var obj_part = getReplacedValueOrUndefined(holder, key);
|
||||||
|
|
||||||
if (obj_part && !isDate(obj_part)) {
|
if (obj_part && !isDate(obj_part)) {
|
||||||
// unbox objects
|
// unbox objects
|
||||||
@ -169,8 +125,7 @@ module.exports.stringify = function(obj, replacer, space) {
|
|||||||
objStack.push(obj_part);
|
objStack.push(obj_part);
|
||||||
|
|
||||||
for (var i = 0; i < obj_part.length; i++) {
|
for (var i = 0; i < obj_part.length; i++) {
|
||||||
res = internalStringify(obj_part, i, false);
|
res = internalStringify(obj_part, i);
|
||||||
buffer += makeIndent(indentStr, objStack.length);
|
|
||||||
if (res === null) {
|
if (res === null) {
|
||||||
buffer += 'null';
|
buffer += 'null';
|
||||||
} else if (typeof res === 'undefined') { // modified to support empty array values
|
} else if (typeof res === 'undefined') { // modified to support empty array values
|
||||||
@ -180,14 +135,9 @@ module.exports.stringify = function(obj, replacer, space) {
|
|||||||
}
|
}
|
||||||
if (i < obj_part.length - 1) {
|
if (i < obj_part.length - 1) {
|
||||||
buffer += ',';
|
buffer += ',';
|
||||||
} else if (indentStr) {
|
|
||||||
buffer += '\n';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
objStack.pop();
|
objStack.pop();
|
||||||
if (obj_part.length) {
|
|
||||||
buffer += makeIndent(indentStr, objStack.length, true);
|
|
||||||
}
|
|
||||||
buffer += ']';
|
buffer += ']';
|
||||||
} else {
|
} else {
|
||||||
checkForCircular(obj_part);
|
checkForCircular(obj_part);
|
||||||
@ -197,19 +147,16 @@ module.exports.stringify = function(obj, replacer, space) {
|
|||||||
for (var prop in obj_part) {
|
for (var prop in obj_part) {
|
||||||
if (obj_part.hasOwnProperty(prop)) {
|
if (obj_part.hasOwnProperty(prop)) {
|
||||||
var value = internalStringify(obj_part, prop, false);
|
var value = internalStringify(obj_part, prop, false);
|
||||||
isTopLevel = false;
|
|
||||||
if (typeof value !== 'undefined' && value !== null) {
|
if (typeof value !== 'undefined' && value !== null) {
|
||||||
buffer += makeIndent(indentStr, objStack.length);
|
|
||||||
nonEmpty = true;
|
nonEmpty = true;
|
||||||
key = isWord(prop) ? prop : escapeString(prop);
|
key = isWord(prop) && !quoteKeys ? prop : escapeString(prop, quoteKeys);
|
||||||
buffer += key + ':' + (indentStr ? ' ' : '') + value + ',';
|
buffer += key + ':' + value + ',';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
objStack.pop();
|
objStack.pop();
|
||||||
if (nonEmpty) {
|
if (nonEmpty) {
|
||||||
buffer = buffer.substring(0, buffer.length - 1) +
|
buffer = buffer.substring(0, buffer.length - 1) + '}';
|
||||||
makeIndent(indentStr, objStack.length) + '}';
|
|
||||||
} else {
|
} else {
|
||||||
buffer = '{}';
|
buffer = '{}';
|
||||||
}
|
}
|
||||||
@ -228,5 +175,5 @@ module.exports.stringify = function(obj, replacer, space) {
|
|||||||
if (obj === undefined) {
|
if (obj === undefined) {
|
||||||
return getReplacedValueOrUndefined(topLevelHolder, '', true);
|
return getReplacedValueOrUndefined(topLevelHolder, '', true);
|
||||||
}
|
}
|
||||||
return internalStringify(topLevelHolder, '', true);
|
return internalStringify(topLevelHolder, '');
|
||||||
};
|
};
|
||||||
|
8
tools/public_api_guard/common/common.d.ts
vendored
8
tools/public_api_guard/common/common.d.ts
vendored
@ -18,7 +18,7 @@ export declare class CommonModule {
|
|||||||
/** @stable */
|
/** @stable */
|
||||||
export declare class CurrencyPipe implements PipeTransform {
|
export declare class CurrencyPipe implements PipeTransform {
|
||||||
constructor(_locale: string);
|
constructor(_locale: string);
|
||||||
transform(value: any, currencyCode?: string, display?: 'code' | 'symbol' | 'symbol-narrow' | boolean, digits?: string, locale?: string): string | null;
|
transform(value: any, currencyCode?: string, display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean, digitsInfo?: string, locale?: string): string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @stable */
|
/** @stable */
|
||||||
@ -30,7 +30,7 @@ export declare class DatePipe implements PipeTransform {
|
|||||||
/** @stable */
|
/** @stable */
|
||||||
export declare class DecimalPipe implements PipeTransform {
|
export declare class DecimalPipe implements PipeTransform {
|
||||||
constructor(_locale: string);
|
constructor(_locale: string);
|
||||||
transform(value: any, digits?: string, locale?: string): string | null;
|
transform(value: any, digitsInfo?: string, locale?: string): string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @stable */
|
/** @stable */
|
||||||
@ -79,7 +79,7 @@ export declare enum FormStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
export declare function getCurrencySymbol(code: string, format: 'wide' | 'narrow'): string;
|
export declare function getCurrencySymbol(code: string, format: 'wide' | 'narrow', locale?: string): string;
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
export declare function getLocaleCurrencyName(locale: string): string | null;
|
export declare function getLocaleCurrencyName(locale: string): string | null;
|
||||||
@ -386,7 +386,7 @@ export declare class PathLocationStrategy extends LocationStrategy {
|
|||||||
/** @stable */
|
/** @stable */
|
||||||
export declare class PercentPipe implements PipeTransform {
|
export declare class PercentPipe implements PipeTransform {
|
||||||
constructor(_locale: string);
|
constructor(_locale: string);
|
||||||
transform(value: any, digits?: string, locale?: string): string | null;
|
transform(value: any, digitsInfo?: string, locale?: string): string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @stable */
|
/** @stable */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user