错误
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
修复
对于该特定请求,我们必须忽略此拦截器。
为此目的:
-
您可以使用httpBackend -> here an explanation 来实现。
但它不起作用,因为您不会在 http 调用之前实例化您的服务。
-
您必须添加一个特定的标头,告诉您的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)))
}
}
你来了。