【问题标题】:ngx-translate-multi-http-loader : Something went wrong for the following translation filengx-translate-multi-http-loader :以下翻译文件出现问题
【发布时间】:2021-11-02 04:04:35
【问题描述】:

我使用这个库 ngx-translate-multi-http-loader 能够为我的 ionic 5 App 加载多种语言文件。

我没有任何错误,但翻译无法正常工作。

然后我在TranslateModule.forRoot({})里面添加了defaultLanguage: 'en',然后就出现了下面的错误信息

以下翻译文件出现问题:./assets/i18n/en.json
未创建数据库。必须先调用 create()

我花了很多时间想办法解决它,但在互联网上找不到任何帮助。

【问题讨论】:

    标签: angular ionic-framework ngx-translate ngx-translate-multi-http-loader


    【解决方案1】:

    错误

    This topic 为我指明了正确的方向。基本上,我们用来导入翻译文件所需的加载器

    export function HttpLoaderFactory(httpClient: HttpClient) {
      return new MultiTranslateHttpLoader(httpClient, [
        { prefix: './assets/i18n/', suffix: '.json' },
        { prefix: `./assets/i18n/${APP_CONFIG.appType}/`, suffix: '.json' },
      ])
    }
    

    是直接导入到app.module.ts @ngModule

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

    如果你找到这篇文章,那肯定意味着你在你的应用程序中使用了HttpInterceptor,它确实从离子存储(或任何其他服务)请求数据以将特定逻辑应用于请求 -> 让比如说,你想在请求中添加一个令牌。

    让我们举个例子

    
    @Injectable()
    export class AuthHttpInterceptor implements HttpInterceptor {
      constructor(private _storage: Storage) {}
    
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<any> {
    
        // Clone the request to add the new header.
        let authReq: any
        return from(this.getToken()).pipe(
          switchMap((token) => {
            if (!req.headers.get('Authorization'))
              authReq = req.clone({
                headers: req.headers.set('Authorization', `Bearer ${token}`),
              })
            else authReq = req.clone()
    
            //send the newly created request
            return next.handle(authReq).pipe(
              retry(1),
              catchError((err, caught) => {
    
                const error = (err && err.error && err.error.message) || err.statusText
                return throwError(error)
              }) as any,
            )
          }),
        )
      }
    
      getToken(): Observable<any> {
        const token$ = new Observable((observer) => {
          this._storage.get('token').then(async (token) => {
            if (token) {
              observer.next(token)
            } else {
              observer.next(ORGANISATION_TOKEN)
            }
          })
        })
    
        return token$
      }
    }
    

    然后,因为ngx-translate-multi-http-loader 正在请求具有角度默认http 类的翻译文件,所以您将通过这个http 拦截器。但_storage 尚未实例化。这导致Database not created. Must call create() first 导致我们的请求失败到Something went wrong for the following translation file: ./assets/i18n/en.json

    修复

    对于该特定请求,我们必须忽略此拦截器。

    为此目的:

    1. 您可以使用httpBackend -> here an explanation 来实现。 但它不起作用,因为您不会在 http 调用之前实例化您的服务。

    2. 您必须添加一个特定的标头,告诉您的HttpInterceptor 忽略该请求并让它通过而无需进一步调查。 谢谢JohnrSharpe

    export const InterceptorSkipHeader = 'X-Skip-Interceptor'
    
    @Injectable()
    export class UsHttpInterceptor implements HttpInterceptor {
      constructor(private _storage: Storage, private _statusService: MegaphoneStatusService) {}
    
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<any> {
        if (req.headers.has(InterceptorSkipHeader)) {
          const headers = req.headers.delete(InterceptorSkipHeader)
          return next.handle(req.clone({ headers }))
        }
    
       //... Intercept
    
    

    为了能够将该标头传递到ngx-translate-multi-http-loader,嗯.. 你不能。因为图书馆不接受,但复制起来并不复杂。

    // core.ngx-loader.ts
    
    import { HttpClient, HttpHeaders } from '@angular/common/http'
    import { TranslateLoader } from '@ngx-translate/core'
    import merge from 'deepmerge'
    import { forkJoin, Observable, of } from 'rxjs'
    import { catchError, map } from 'rxjs/operators'
    import { InterceptorSkipHeader } from '../http.interceptor'
    
    export class MultiTranslateHttpLoader implements TranslateLoader {
      constructor(
        private http: HttpClient,
        private resources: {
          prefix: string
          suffix: string
        }[],
      ) {}
    
      public getTranslation(lang: string): Observable<any> {
        const headers = new HttpHeaders().set(InterceptorSkipHeader, '') // <-- Our Skip interceptor
    
        const requests = this.resources.map((resource) => {
          const path = resource.prefix + lang + resource.suffix
    
          return this.http.get(path, { headers }).pipe( // <-- We add the header into the request
            catchError((res) => {
              console.error('Something went wrong for the following translation file:', path)
              console.error(res.message)
              return of({})
            }),
          )
        })
    
        return forkJoin(requests).pipe(map((response) => merge.all(response)))
      }
    }
    

    你来了。

    【讨论】:

      猜你喜欢
      • 2023-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-04
      • 2019-06-10
      • 1970-01-01
      • 2022-06-23
      • 2021-04-22
      相关资源
      最近更新 更多