【问题标题】:Ionic3 / Ngx-translate - TranslateHttpLoader with external URLIonic3 / Ngx-translate - 带有外部 URL 的 TranslateHttpLoader
【发布时间】:2017-07-24 12:40:30
【问题描述】:

我正在使用我的 app.module.ts 中的 TranslateHttpLoader 从服务器加载翻译文件,如下所示:

export function createTranslateLoader(http: Http) {
   return new TranslateHttpLoader(http, AppConfig.API_URL+'/static/i18n/', '.json');
}

@NgModule({
  ...

  imports: [

    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: (createTranslateLoader),
        deps: [Http]
      }
    }), 

  ],
  ...
})

一切正常,但我想知道当加载器因任何原因(服务器问题、网络配置等)未能检索语言文件时是否有办法捕获事件,并可能加载带有一些的本地 json 文件默认翻译字符串?

如果第一次加载的应用程序无法获取语言文件,我想捕获此事件,并回退到最小的本地 json 文件以仅显示翻译的维护页面/错误页面或其他内容。

【问题讨论】:

    标签: ionic3 ngx-translate


    【解决方案1】:

    Angular >= 4.3 更新

    由于新的 Angular 版本使用 HttpClient 而不是 Httpmike_t's CustomTranslateLoader 的更新且更短的版本将是:

    import { HttpClient, HttpHeaders } from '@angular/common/http';
    import { Injectable } from '@angular/core';
    import { TranslateLoader } from '@ngx-translate/core';
    import { Observable } from 'rxjs/Observable';
    import { catchError } from 'rxjs/operators';
    import { AppConfig } from './config';
    
    
    @Injectable()
    export class CustomTranslateLoader implements TranslateLoader  {
        contentHeader = new HttpHeaders({
          'Content-Type': 'application/json',
          'Access-Control-Allow-Origin': '*',
        });
    
        constructor(private httpClient: HttpClient) {}
        getTranslation(lang: string): Observable<any> {
            const apiAddress = AppConfig.API_URL + `/static/i18n/${lang}.json`;
            return this.httpClient.get(apiAddress, { headers: this.contentHeader })
              .pipe(
                catchError(_ => this.httpClient.get(`/assets/i18n/en.json`))
              );
        }
    }
    
    
    

    【讨论】:

    • 感谢您更新此内容,我将您的答案更改为可接受的解决方案!
    • 我得到:没有'new'就不能调用CustomTranslateLoader
    【解决方案2】:

    Angular 12+ 更新

    1. 创建新的自定义翻译加载器
    // loader/customTranslate.loader.ts
    import { TranslateLoader } from '@ngx-translate/core';
    import { HttpClient } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { catchError } from 'rxjs/operators';
    
    const LOCAL_URL = 'http://your.url.blanik.me/api';
    
    export class CustomTranslateLoader implements TranslateLoader {
      constructor(private httpClient: HttpClient) {}
    
      getTranslation(lang: string): Observable<any> {
        const url = `${LOCAL_URL}/assets/i18n/${lang}.json`;
    
        return this.httpClient.get(url).pipe(catchError((_) => this.httpClient.get(`/assets/i18n/en.json`)));
      }
    }
    
    1. 更新 Angular 应用模块
    // app.module.ts
    // {...}
    import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
    import { HttpClient } from '@angular/common/http';
    import { CustomTranslateLoader } from './loader/customTranslate.loader';
    
    @NgModule({
      declarations: [AppComponent, OtherComponent],
      imports: [
        BrowserModule,
        // ...
        TranslateModule.forRoot({
          loader: {
            provide: TranslateLoader,
            useClass: CustomTranslateLoader,
            deps: [HttpClient],
          },
        }),
      ],
      providers: [],
      bootstrap: [AppComponent],
    })
    export class AppModule {}
    
    1. 为您的组件添加语言切换
    <select class="form-control" #langauge (change)="translateSite(langauge.value)">
      <option *ngFor="let localization of translateService.getLangs()" [value]="localization"
              [selected]="localization === translateService.currentLang">
        {{ localization }}
      </option>
    </select>
    
    import { Component, OnInit } from '@angular/core';
    import { TranslateService } from '@ngx-translate/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
    })
    export class AppComponent{
      title = 'your-app-name';
    
      constructor(public translateService: TranslateService) {
        translateService.addLangs(['en', 'fr', 'pl']);
        translateService.setDefaultLang('en');
      }
    
      translateSite(langauge: string) {
        this.translateService.use(langauge);
      }
    }
    

    请记住在您的服务器上设置正确的 CORS 和/或(推荐)将您的翻译文件保存在同一个域下。

    不要在 httpClient 中添加自定义 CORS 标头。否则,浏览器会阻止读取文件。

    干杯!

    【讨论】:

      【解决方案3】:

      最后我写了一个自定义加载器来解决这个需求:

      import { Injectable } from '@angular/core';
      import { Headers, Http, Response } from "@angular/http";
      import { TranslateLoader } from '@ngx-translate/core';
      import { AppConfig } from "./config"
      import { Observable } from 'rxjs/Observable'; 
      
      
      @Injectable()
      export class CustomTranslateLoader implements TranslateLoader  {
          contentHeader = new Headers({"Content-Type": "application/json","Access-Control-Allow-Origin":"*"});
      
          constructor(private http: Http) {}
          getTranslation(lang: string): Observable<any>{
              var apiAddress = AppConfig.API_URL+"/static/i18n/"+ lang+".json";
              return Observable.create(observer => {
                this.http.get(apiAddress, { headers: this.contentHeader }).subscribe((res: Response) => {
                          observer.next(res.json());
                          observer.complete();               
                      },
                  error => {
                      //  failed to retrieve from api, switch to local
                      this.http.get("/assets/i18n/en.json").subscribe((res: Response) => {
                          observer.next(res.json());
                          observer.complete();               
                      })
                  }
                  );
              }); 
          }
      }
      

      在 app.module.ts 中

      ...
      import { CustomTranslateLoader } from "../services/trans-loader"
      ...
      
      @NgModule({
        ...
      
        imports: [
      
          TranslateModule.forRoot({
            loader: {
              provide: TranslateLoader,
              useClass: CustomTranslateLoader,
              deps: [Http]
            }
          }), 
      
        ],
        ...
      })
      

      【讨论】:

      • 你将如何处理 html 部分?
      • 只喜欢这个? {{'登录' |翻译}}?
      • 是的,只使用translate 管道。不要忘记在您的 ngmodule 导入中添加 TranslateModule.forChild()
      • 这是我们在这里重写的原始 TranslateLoader 的方法,它在使用指定的加载器加载翻译时由 ionic 自动调用
      • 好的。知道了。你能告诉我你的 app.component.ts 文件吗?
      猜你喜欢
      • 2017-11-24
      • 1970-01-01
      • 2019-05-27
      • 1970-01-01
      • 2019-07-02
      • 2018-04-01
      • 1970-01-01
      • 2020-06-16
      • 2019-02-09
      相关资源
      最近更新 更多