Skip to content
This repository has been archived by the owner on Mar 6, 2024. It is now read-only.

[i18n] Add number formatting to the translation service based on the user locale #545

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import MessageFormat from '@messageformat/core';
import { combineLatest, Observable, ReplaySubject } from 'rxjs';
import { map } from 'rxjs/operators';
import { TranslationLoader } from '../loader/translation-loader';
import { FormatDateOptions, TRANSLATION_MAPPING, TranslationService, TranslationSet } from './translation-service';
import { FormatDateOptions, FormatNumberOptions, TRANSLATION_MAPPING, TranslationService, TranslationSet } from './translation-service';

/**
* Translation service to implement ICU MessageFormat.
Expand Down Expand Up @@ -92,7 +92,7 @@ export class MessageFormatTranslationService extends TranslationService {
* Otherwise uses message-format to format the string.
* @param key translation key
* @param params array of substitutions. arrays can be of the form [a, b, c] for positional parameters
* or [{'key1': a, 'key2' b}]
* or [{'key1': a, 'key2': b}]
* @return an observable of the translated string.
*/
public translateAsync(key: string, params?: any[]): Observable<string> {
Expand All @@ -101,10 +101,14 @@ export class MessageFormatTranslationService extends TranslationService {

private translateHelper(key: string, translations: TranslationSet, params?: any[]): string {
let paramsToUse: any = params;
const paramObject = params ? (params.length ? params[0] : {}) : {};
const paramObject = params?.length ? params[0] : {};
if (paramObject !== null && typeof paramObject === 'object') {
paramsToUse = paramObject;
} else {
// localize params if number
paramsToUse = paramsToUse.map((element) => typeof element === 'number' ? this.formatNumber(element) : element);
}

if (translations[this.preferredLocale] && translations[this.preferredLocale][key]) {
return this.formatString(this.preferredLocale, key, paramsToUse, translations);
} else if (translations[this.fallbackLocale] && translations[this.fallbackLocale][key]) {
Expand All @@ -119,6 +123,20 @@ export class MessageFormatTranslationService extends TranslationService {
return message(translationMap);
}

/**
* Use Intl services to format number.
* @param number number to format
* @param options to specify the format of the number string.
* If is not set, it will use internal default option for number.
* @return formatted number.
*/
public formatNumber(number: number, options?: FormatNumberOptions): string {
if (options) {
return new Intl.NumberFormat(this.preferredLocale, options).format(number);
}
return new Intl.NumberFormat(this.preferredLocale, this.defaultNumberFormat).format(number);
}

/**
* Use Intl services to format date.
* @param date date to format
Expand Down
4 changes: 4 additions & 0 deletions projects/i18n/src/lib/service/mock-translation-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class MockTranslationService extends TranslationService {
return new BehaviorSubject(this.translate(key, params));
}

formatNumber(number: number): string {
return number.toLocaleString();
}

formatDate(date: Date): string {
return date.toLocaleString();
}
Expand Down
19 changes: 19 additions & 0 deletions projects/i18n/src/lib/service/translation-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import DateTimeFormatOptions = Intl.DateTimeFormatOptions;
import NumberFormatOptions = Intl.NumberFormatOptions;

/**
* Basic translations.
Expand Down Expand Up @@ -53,6 +54,15 @@ abstract class TranslationService {
...this.defaultTimeFormat,
};

/**
* Options to format Number
*/
protected readonly defaultNumberFormat: NumberFormatOptions = {
// override the default which is 3 to be able to respect user defined precision
maximumFractionDigits: 20,
useGrouping: false
};

/**
* Register translations (used by moådules)
*/
Expand All @@ -74,6 +84,14 @@ abstract class TranslationService {
*/
abstract translate(key: string, params?: any[]): string;

/**
* Format a number with current locale.
* @param number number
* @param options to specify the format of the number string.
* @return formatted number.
*/
abstract formatNumber(number: number, options?: object): string;

/**
* Format a date with current locale.
* @param date date
Expand Down Expand Up @@ -120,4 +138,5 @@ export const TRANSLATION_MAPPING = {
* false (for 24-hour format)
*/
export type FormatDateOptions = DateTimeFormatOptions;
export type FormatNumberOptions = NumberFormatOptions;
export { TranslationService };
Loading