From ca1bc7e80b84e5a262381548da619528d0812336 Mon Sep 17 00:00:00 2001 From: Hayouung Date: Sat, 14 Dec 2019 10:39:41 +0000 Subject: [PATCH] feat(common): allow default currency code to be configurable (#32584) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Default currency code in CurrencyPipe is currently hardcoded to USD and is not configurable. This commit allows the default currency code to be configurable by adding a DEFAULT_CURRENCY_CODE injection token. Example: ``` providers: [{ provide: DEFAULT_CURRENCY_CODE, useValue: "GBP" }] ... {{ 123.45 | currency }} // outputs £123.45 as opposed to always $123.45 before ``` Closes: #25461 PR Close #32584 --- packages/common/src/pipes/number_pipe.ts | 13 +++++++---- .../common/test/pipes/number_pipe_spec.ts | 2 +- packages/core/src/application_module.ts | 5 ++-- packages/core/src/core.ts | 2 +- packages/core/src/i18n/localization.ts | 6 +++++ packages/core/src/i18n/tokens.ts | 23 +++++++++++++++++++ packages/core/test/application_module_spec.ts | 7 +++++- tools/public_api_guard/common/common.d.ts | 2 +- tools/public_api_guard/core/core.d.ts | 2 ++ 9 files changed, 52 insertions(+), 10 deletions(-) diff --git a/packages/common/src/pipes/number_pipe.ts b/packages/common/src/pipes/number_pipe.ts index 8f00995e73..f832e59365 100644 --- a/packages/common/src/pipes/number_pipe.ts +++ b/packages/common/src/pipes/number_pipe.ts @@ -6,11 +6,13 @@ * found in the LICENSE file at https://angular.io/license */ -import {Inject, LOCALE_ID, Pipe, PipeTransform} from '@angular/core'; +import {DEFAULT_CURRENCY_CODE, Inject, LOCALE_ID, Pipe, PipeTransform} from '@angular/core'; import {formatCurrency, formatNumber, formatPercent} from '../i18n/format_number'; import {getCurrencySymbol} from '../i18n/locale_data_api'; + import {invalidPipeArgumentError} from './invalid_pipe_argument_error'; + /** * @ngModule CommonModule * @description @@ -155,13 +157,16 @@ export class PercentPipe implements PipeTransform { */ @Pipe({name: 'currency'}) export class CurrencyPipe implements PipeTransform { - constructor(@Inject(LOCALE_ID) private _locale: string) {} + constructor( + @Inject(LOCALE_ID) private _locale: string, + @Inject(DEFAULT_CURRENCY_CODE) private _defaultCurrencyCode: string = 'USD') {} /** * * @param value The number to be formatted as currency. * @param currencyCode The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code, - * such as `USD` for the US dollar and `EUR` for the euro. + * such as `USD` for the US dollar and `EUR` for the euro. The default currency code can be + * configured using the `DEFAULT_CURRENCY_CODE` injection token. * @param display The format for the currency indicator. One of the following: * - `code`: Show the code (such as `USD`). * - `symbol`(default): Show the symbol (such as `$`). @@ -205,7 +210,7 @@ export class CurrencyPipe implements PipeTransform { display = display ? 'symbol' : 'code'; } - let currency: string = currencyCode || 'USD'; + let currency: string = currencyCode || this._defaultCurrencyCode; if (display !== 'code') { if (display === 'symbol' || display === 'symbol-narrow') { currency = getCurrencySymbol(currency, display === 'symbol' ? 'wide' : 'narrow', locale); diff --git a/packages/common/test/pipes/number_pipe_spec.ts b/packages/common/test/pipes/number_pipe_spec.ts index 97b7970a0e..c0a456451d 100644 --- a/packages/common/test/pipes/number_pipe_spec.ts +++ b/packages/common/test/pipes/number_pipe_spec.ts @@ -89,7 +89,7 @@ import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testin describe('CurrencyPipe', () => { let pipe: CurrencyPipe; - beforeEach(() => { pipe = new CurrencyPipe('en-US'); }); + beforeEach(() => { pipe = new CurrencyPipe('en-US', 'USD'); }); describe('transform', () => { it('should return correct value for numbers', () => { diff --git a/packages/core/src/application_module.ts b/packages/core/src/application_module.ts index 3f71df4468..f59eb86cd3 100644 --- a/packages/core/src/application_module.ts +++ b/packages/core/src/application_module.ts @@ -14,8 +14,8 @@ import {Console} from './console'; import {Injector, StaticProvider} from './di'; import {Inject, Optional, SkipSelf} from './di/metadata'; import {ErrorHandler} from './error_handler'; -import {DEFAULT_LOCALE_ID} from './i18n/localization'; -import {LOCALE_ID} from './i18n/tokens'; +import {DEFAULT_LOCALE_ID, USD_CURRENCY_CODE} from './i18n/localization'; +import {DEFAULT_CURRENCY_CODE, LOCALE_ID} from './i18n/tokens'; import {ivyEnabled} from './ivy_switch'; import {ComponentFactoryResolver} from './linker'; import {Compiler} from './linker/compiler'; @@ -96,6 +96,7 @@ export const APPLICATION_MODULE_PROVIDERS: StaticProvider[] = [ useFactory: _localeFactory, deps: [[new Inject(LOCALE_ID), new Optional(), new SkipSelf()]] }, + {provide: DEFAULT_CURRENCY_CODE, useValue: USD_CURRENCY_CODE}, ]; /** diff --git a/packages/core/src/core.ts b/packages/core/src/core.ts index 9ac30bca8b..7c2daeedb8 100644 --- a/packages/core/src/core.ts +++ b/packages/core/src/core.ts @@ -26,7 +26,7 @@ export {DebugElement, DebugEventListener, DebugNode, asNativeElements, getDebugN export {GetTestability, Testability, TestabilityRegistry, setTestabilityGetter} from './testability/testability'; export * from './change_detection'; export * from './platform_core_providers'; -export {TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID, MissingTranslationStrategy} from './i18n/tokens'; +export {TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID, DEFAULT_CURRENCY_CODE, MissingTranslationStrategy} from './i18n/tokens'; export {ApplicationModule} from './application_module'; export {AbstractType, Type} from './interface/type'; export {EventEmitter} from './event_emitter'; diff --git a/packages/core/src/i18n/localization.ts b/packages/core/src/i18n/localization.ts index 27cd62fecf..beeea95c51 100644 --- a/packages/core/src/i18n/localization.ts +++ b/packages/core/src/i18n/localization.ts @@ -34,3 +34,9 @@ export function getPluralCase(value: any, locale: string): string { * The locale id that the application is using by default (for translations and ICU expressions). */ export const DEFAULT_LOCALE_ID = 'en-US'; + +/** + * USD currency code that the application uses by default for CurrencyPipe when no + * DEFAULT_CURRENCY_CODE is provided. + */ +export const USD_CURRENCY_CODE = 'USD'; diff --git a/packages/core/src/i18n/tokens.ts b/packages/core/src/i18n/tokens.ts index 46c7e6d88e..6c79eaec54 100644 --- a/packages/core/src/i18n/tokens.ts +++ b/packages/core/src/i18n/tokens.ts @@ -32,6 +32,29 @@ import {InjectionToken} from '../di/injection_token'; */ export const LOCALE_ID = new InjectionToken('LocaleId'); +/** + * Provide this token to set the default currency code your application uses for + * CurrencyPipe when there is no currency code passed into it. This is only used by + * CurrencyPipe and has no relation to locale currency. Defaults to USD if not configured. + * + * See the [i18n guide](guide/i18n#setting-up-locale) for more information. + * + * @usageNotes + * ### Example + * + * ```typescript + * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + * import { AppModule } from './app/app.module'; + * + * platformBrowserDynamic().bootstrapModule(AppModule, { + * providers: [{provide: DEFAULT_CURRENCY_CODE, useValue: 'EUR' }] + * }); + * ``` + * + * @publicApi + */ +export const DEFAULT_CURRENCY_CODE = new InjectionToken('DefaultCurrencyCode'); + /** * Use this token at bootstrap to provide the content of your translation file (`xtb`, * `xlf` or `xlf2`) when you want to translate your application in another language. diff --git a/packages/core/test/application_module_spec.ts b/packages/core/test/application_module_spec.ts index ea97692f3f..2cb36d26b5 100644 --- a/packages/core/test/application_module_spec.ts +++ b/packages/core/test/application_module_spec.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {LOCALE_ID} from '@angular/core'; +import {DEFAULT_CURRENCY_CODE, LOCALE_ID} from '@angular/core'; import {ivyEnabled} from '@angular/private/testing'; import {getLocaleId} from '../src/render3'; @@ -19,6 +19,11 @@ import {describe, expect, inject, it} from '../testing/src/testing_internal'; it('should set the default locale to "en-US"', inject([LOCALE_ID], (defaultLocale: string) => { expect(defaultLocale).toEqual('en-US'); })); + it('should set the default currency code to "USD"', + inject([DEFAULT_CURRENCY_CODE], (defaultCurrencyCode: string) => { + expect(defaultCurrencyCode).toEqual('USD'); + })); + if (ivyEnabled) { it('should set the ivy locale with the configured LOCALE_ID', () => { TestBed.configureTestingModule({providers: [{provide: LOCALE_ID, useValue: 'fr'}]}); diff --git a/tools/public_api_guard/common/common.d.ts b/tools/public_api_guard/common/common.d.ts index 8abc8bf99b..a240bb4c34 100644 --- a/tools/public_api_guard/common/common.d.ts +++ b/tools/public_api_guard/common/common.d.ts @@ -13,7 +13,7 @@ export declare class CommonModule { } export declare class CurrencyPipe implements PipeTransform { - constructor(_locale: string); + constructor(_locale: string, _defaultCurrencyCode?: string); transform(value: any, currencyCode?: string, display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean, digitsInfo?: string, locale?: string): string | null; } diff --git a/tools/public_api_guard/core/core.d.ts b/tools/public_api_guard/core/core.d.ts index 7d0e7e2417..c4870b5c02 100644 --- a/tools/public_api_guard/core/core.d.ts +++ b/tools/public_api_guard/core/core.d.ts @@ -257,6 +257,8 @@ export declare const DebugNode: { new (...args: any[]): DebugNode; }; +export declare const DEFAULT_CURRENCY_CODE: InjectionToken; + /** @deprecated */ export declare class DefaultIterableDiffer implements IterableDiffer, IterableChanges { readonly collection: V[] | Iterable | null;