私は自分のプライベートangular複数のコンポーネントを備えたライブラリを作成して、自分の生活を楽にしています。これを実行することで、このライブラリを作成しました tutorial 。別のプロジェクトにそれをテストしてください。
私はベルギーに住んでいるので、複数の言語をサポートする必要がある部分は今ですか????。私は過去に問題なくngx-translateパッケージを使用したことがあるので、これは簡単だと思いました。
私のプロジェクトに、翻訳jsonを含むassets/i18nフォルダーを追加しました。
angular cliにはビルド時のアセットが含まれていないため、パッケージを作成する前に手動またはgulpを使用してdistフォルダーに追加する必要があります。これを行った後、メインアプリケーションのjsonファイルへの翻訳を含めない限り、ラベルは翻訳されていませんでした。
ライブラリの各コンポーネントには独自のモジュールがあるため、これらのモジュールに翻訳モジュールを追加するだけでよいと思いました。だから私は次のことをしました。
export function httpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
@NgModule({
imports: [
CommonModule,
FormsModule,
DirectivesModule,
ButtonModule,
IconModule,
PillModule,
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
useFactory: (httpLoaderFactory),
deps: [HttpClient]
},
isolate: true
})
],
declarations: [
FilterComponent
],
exports: [
FilterComponent
]
})
これにより事態はさらに悪化しました。ラベルがまだ翻訳されていないだけでなく、私のメインアプリケーションも独自の翻訳を使用していません。ライブラリモジュールでこれらの変更が行われる前は、メインアプリケーションの翻訳に問題はありませんでした...
ええ、あなたはそれを推測しました、私は行き詰まっています...私は正しい解決策を見つけることができないようです。
私はどこにも行かなかったので、この post で説明されている別のアプローチを試しました。そこで、jsonファイルをtsファイルに変換し、jsonオブジェクトを返しました。次に、投稿で説明されているように、既存の翻訳(メインアプリケーションのjsonファイルによって追加されたもの)に翻訳を追加する独自のtranslateServiceを作成しました。
これは機能しましたが、以前の翻訳を却下したか、ロードが遅すぎました。これにより、アプリケーションでは、翻訳の代わりに翻訳キーのみが表示されました。そのため、投稿のように翻訳を初期化する代わりに、サブスクライブを使用して最初にメインの翻訳を待機しました。
//Library
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { en } from "../localization/en";
import { nl } from "../localization/nl";
@Injectable()
export class TranslateUiService {
private availableLanguages = { en, nl };
constructor(private translateService: TranslateService) {
}
public init(language: string = null): any {
if (language) {
//initialize one specific language
this.translateService.setTranslation(language, this.availableLanguages[language], true);
} else {
//initialize all
Object.keys(this.availableLanguages).forEach((language) => {
this.translateService.setTranslation(language, this.availableLanguages[language], true);
});
}
}
}
//App
constructor(private translateUiService: TranslateUiService, private translateService: TranslateService) {
this.translateService.setDefaultLang('en');
this.translateService.use('en').subscribe(() => {
this.translateUiService.init('en');
});
}
ビージーと同様の方法で行いましたが、翻訳サービスを拡張しました。 TranslateServiceの拡張で、ルートアプリと同じインスタンスを使用しており、ルートアプリの翻訳を上書きしたくないため、グローバルアプリの翻訳のサブレベル(ui。[language])の下にライブラリの翻訳を追加します。次に、コンポーネントレベルで通常のTranslateServiceの代わりに拡張機能を提供したので、このコンポーネント内の変換ディレクティブにも使用され、分離されます。つまり、currentLangとdefautlLangのゲッターをオーバーライドしてルートアプリの翻訳を破棄しません。
i-translate.service.ts:
const availableLanguages: any = {
'de' : { ... YOUR DE TRANSLATIONS ... },
'en' : { ... YOUR EN TRANSLATIONS ... }
...
};
const langPrefix = 'ui';
@Injectable({
providedIn: 'root'
})
export class UiTranslateService extends TranslateService implements TranslateService {
constructor(public store: TranslateStore,
public currentLoader: TranslateLoader,
public compiler: TranslateCompiler,
public parser: TranslateParser,
public missingTranslationHandler: MissingTranslationHandler,
@Inject(USE_DEFAULT_LANG) useDefaultLang: boolean = true,
@Inject(USE_STORE) isolate: boolean = false) {
super(store, currentLoader, compiler, parser, missingTranslationHandler, useDefaultLang, isolate);
this.onTranslationChange.subscribe((_res: TranslationChangeEvent) => {
// ensure after translation change we (re-)add our translations
if (_res.lang.indexOf(langPrefix) !== 0) {
this.applyUiTranslations();
}
});
this.applyUiTranslations();
}
private applyUiTranslations() {
for (var lang in availableLanguages) {
if (availableLanguages.hasOwnProperty(lang)) {
this.setTranslation(langPrefix + '.' + lang, availableLanguages[lang], true);
}
}
}
/**
* The default lang to fallback when translations are missing on the current lang
*/
get defaultLang(): string {
return langPrefix + '.' + this.store.defaultLang;
}
/**
* The lang currently used
*/
get currentLang(): string {
return this.store.currentLang === undefined ? undefined : langPrefix + '.' + this.store.currentLang;
}
public getParsedResult(translations: any, key: any, interpolateParams?: Object): any {
// apply our translations here
var lang = (this.currentLang || this.defaultLang).split('.')[1];
translations = lang == 'de' ? de : en;
return super.getParsedResult(translations, key, interpolateParams);
}
public get(key: string | Array<string>, interpolateParams?: Object): Observable<string | any> {
return super.get(key, interpolateParams);
}
}
my.component.ts:
@Component({
selector: 'xxx',
template: 'xxx',
providers: [
{ provide: TranslateService, useClass: UiTranslateService }
]
})
export class MyComponent implements OnInit { }
my.module.ts:
@NgModule({
imports: [
CommonModule,
TranslateModule
]
})
export class ComponentsModule {}
ビルドステップがメインアプリケーションの_en.json
_などをライブラリのファイルで上書きしていると思います。したがって、メインアプリケーションの翻訳がありません。
分離オプション(翻訳をロードするためにサーバーへの要求が増える)の代わりに検討できることの1つは、ビルドステップを変更して、ライブラリ内のファイルをメインアプリケーションの翻訳ファイルとマージすることです。
起こり得る衝突を回避するために、何らかの方法でライブラリ変換キーの名前空間を設定することをお勧めします。
次に、ライブラリでTranslateModule.forChild()
を使用できます
あるいは、分離を維持したい場合は、ライブラリの翻訳ファイルをi18nのサブディレクトリに置き、必要に応じてhttpLoaderFactory
を変更してみてください
このようなものを作ることができます。
<div (click)="switchLanguage('en')"></div>
switchLanguage(language: string) {
this.selectedLanguage = language
}
別のコンポーネントでは、HTMLで次のように記述します。
<button><i class="fa fa-history"></i>{{'general.#time'|translate}}</button>
これはen.jsonです
"general": {
"#time": "Time"
}