Динамическое изменение языкового стандарта для DatePipe в Angular 2
Я создаю проект Angular, где пользователь имеет возможность переключать языки. Можно ли сделать динамику локали?
Я видел, что вы можете добавить его в NgModule, но я предполагаю, что он не динамический, когда я его там положил? Или я могу изменить его каким-то образом через сервис или что-то еще?
Ответы
Ответ 1
Используя providers
, вы можете изменить языковой стандарт по умолчанию в своем NgModule
.
для этого вам нужно импортировать LOCALE_ID из angular/core и выбрать язык языкового стандарта для передачи того же самого поставщикам.
import { LOCALE_ID } from '@angular/core';
@NgModule({
imports: [//your imports],
providers: [
{ provide: LOCALE_ID, useValue: "en-US" }
]
})
...
...
{
provide: LOCALE_ID,
deps: [SettingsService], //some service handling global settings
useFactory: (settingsService) => settingsService.getLanguage() //returns locale string
}
Надеюсь, это поможет вам.
Ответ 2
Чтобы установить локаль из сервиса, вам нужно добавить провайдера LOCALE_ID
с фабрикой к app.module
, как в ответе @AmolBhor
{
provide: LOCALE_ID,
deps: [SettingsService], //some service handling global settings
useFactory: (settingsService) => settingsService.getLanguage() //returns locale string
}
К сожалению, вы не можете изменить язык для DatePipe JIT. Angular компилятор требует LOCALE_ID
во время начальной загрузки.
Для Angular есть несколько сообщений об ошибках:
Для этого есть несколько способов:
Обходной путь № 1
Повторная загрузка angular модуля:
let _platformRef: NgModuleRef<Object>;
if(_platformRef) { _platformRef.destroy(); }
platformBrowserDynamic(providers)
.bootstrapModule(AppModule, {providers})
.then(platformRef => {
_platformRef = platformRef;
})
* Это не будет работать для Hybrid Angular/AngularJS, поскольку нет способа уничтожить AngularJS с помощью UpgradeModule.
Обходной путь № 2
Чтобы перезаписать DatePipe, NumberPipe - все, что вам нужно:
@Pipe({name: 'datepipe', pure: true})
export class MyDatePipe implements PipeTransform {
transform(value: any, pattern?: string): string | null {
// transform value as you like (you can use moment.js and format by locale_id from your custom service)
return DateUtils.format(value);
}
}
Обходной путь № 3
Чтобы использовать библиотеку, которая уже обрабатывает локализацию с помощью пользовательских Pipes, например:
Обходной путь № 4
Каждый канал, который использует LOCALE_ID
, имеет закрытое поле locale или _locale, поэтому вы можете переопределить это поле в этих каналах при смене языка, так как существует один экземпляр канала.
Это будет работать, потому что TypeScript - это просто синтаксический сахар для JavaScript. А в JavaScript нет приватных полей.
Также не забудьте обработать обнаружение изменений в приложении, используя метод tick()
в ApplicationRef.
@Injectable()
export class DynamicLocaleService {
private i18nPipes: PipeTransform[];
constructor(
datePipe: DatePipe,
currencyPipe: CurrencyPipe,
decimalPipe: DecimalPipe,
percentPipe: PercentPipe,
private applicationRef: ApplicationRef,
) {
this.i18nPipes = [
datePipe,
currencyPipe,
decimalPipe,
percentPipe,
]
}
setLocale(lang: string): void {
this.i18nPipes.forEach(pipe => {
if(pipe.hasOwnProperty("locale")) {
pipe["locale"] = lang;
} else if (pipe.hasOwnProperty("_locale")) {
pipe["_locale"] = lang
}
})
this.applicationRef.tick()
}
}
Обходной путь # 5
Перезагрузить приложение при смене языка.
window.location.reload()
К сожалению, все вышеперечисленное - обходной путь.
Но есть и другое решение - вы можете иметь несколько пакетов для каждого языка, что, вероятно, будет лучше, так как приложение будет работать быстрее. Но это решение не применимо для каждого приложения и не отвечает на вопрос.
Ответ 3
Имейте свое Обслуживание как
import { Injectable } from '@angular/core';
@Injectable()
export class LocaleService {
//Chosse Locale From This Link
//https://github.com/angular/angular/tree/master/packages/common/locales
constructor() { }
private _locale: string;
set locale(value: string) {
this._locale = value;
}
get locale(): string {
return this._locale || 'en-US';
}
public registerCulture(culture: string) {
debugger;
if (!culture) {
return;
}
switch (culture) {
case 'en-uk': {
this._locale = 'en';
console.log('Application Culture Set to English');
break;
}
case 'zh-hk': {
this._locale = 'zh-Hant';
console.log('Application Culture Set to Traditional Chinese');
break;
}
case 'zh-cn': {
this._locale = 'zh-Hans';
console.log('Application Culture Set to Simplified Chinese');
break;
}
default: {
this._locale = 'en';
console.log('Application Culture Set to English');
break;
}
}
}
}
И в App.module.ts
Первая локализация импорта, которая вам нужна, скажем,
import localeEN from '@angular/common/locales/en';
import localezhHant from '@angular/common/locales/zh-Hant';
import localezhHans from '@angular/common/locales/zh-Hans';
Чем в разделе поставщиков
{
provide: LOCALE_ID,
deps: [LocaleService],
useFactory: (LocaleService: { locale: string; }) => LocaleService.locale
}
В конце
registerLocaleData(localeEN);
registerLocaleData(localezhHant);
registerLocaleData(localezhHans);
Надеюсь, это поможет кому-то
если вы хотите динамически менять локаль, внедрите LocaleService в желаемый компонент и используйте метод registerCulture, передайте необходимую культуру в эту