ユーザーが言語を切り替えることができるAngularプロジェクトを作成しています。ロケールを動的にすることは可能ですか?
NgModuleに追加できることを見てきましたが、そこに置くと動的ではないと推測していますか?または、サービスまたは何かを通じてそれを何らかの形で変更できますか?
providers
を使用すると、NgModule
のデフォルトロケールを変更できます。これを行うには、angle/coreからLOCALE_IDをインポートし、ロケール言語をフェッチして、同じものをプロバイダーに渡す必要があります。
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
}
これがお役に立てば幸いです。
サービスからロケールを設定するには、@ AmolBhorの回答のように、工場で_LOCALE_ID
_プロバイダーを_app.module
_に追加する必要があります
_{
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;
})
_
* UpgradeModuleを使用してAngularJSを破棄する方法がないため、これはHybrid Angular/AngularJSでは機能しません。
回避策#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
Ex用のカスタムPipesですでにローカライズを処理するライブラリを使用するには:
回避策#4
_LOCALE_ID
_を使用するすべてのパイプには、プライベートフィールドlocaleまたは_ locale、パイプのインスタンスが1つあるため、言語変更時にそのパイプでこのフィールドをオーバーライドできます。
TypeScriptはJavaScriptの単なる構文糖だからです。 JavaScriptにはプライベートフィールドはありません。
また、ApplicationRefのtick()
メソッドを使用して、アプリケーションの変更検出を処理することを忘れないでください。
_@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()
_
残念ながら、上記のすべては回避策です。
しかし、別の解決策もあります。言語ごとに複数のバンドルを使用できます。これは、アプリが高速になるため、おそらくより良いアプローチになるでしょう。しかし、このソリューションはすべてのアプリケーションに適用できるわけではなく、質問に答えることはありません。
あなたのサービスを
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メソッドを使用して、必要なカルチャをこれに渡します