ngx-translate-multi-http-loader :以下翻译文件出了点问题
ngx-translate-multi-http-loader : Something went wrong for the following translation file
我使用这个库 ngx-translate-multi-http-loader 来为我的 ionic 5 应用程序加载多语言文件。
我没有任何错误,但翻译不工作。
然后我在TranslateModule.forRoot({})
里面添加了defaultLanguage: 'en'
,结果出现了下面的错误信息
Something went wrong for the following translation file: ./assets/i18n/en.json
Database not created. Must call create() first
我花了很多时间来弄清楚如何修复它,但在互联网上找不到任何帮助。
错误
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],
},
}),
如果您发现这个 post,这肯定意味着您在您的应用程序中使用 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
正在请求使用 angular 默认值 http
class 的翻译文件,您将通过此 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 调用之前实例化您的服务。
您必须添加一个特定的 header,告诉您的 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
因为能够将 header 传递给 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)))
}
}
你来了。
我使用这个库 ngx-translate-multi-http-loader 来为我的 ionic 5 应用程序加载多语言文件。
我没有任何错误,但翻译不工作。
然后我在TranslateModule.forRoot({})
里面添加了defaultLanguage: 'en'
,结果出现了下面的错误信息
Something went wrong for the following translation file: ./assets/i18n/en.json
Database not created. Must call create() first
我花了很多时间来弄清楚如何修复它,但在互联网上找不到任何帮助。
错误
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],
},
}),
如果您发现这个 post,这肯定意味着您在您的应用程序中使用 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
正在请求使用 angular 默认值 http
class 的翻译文件,您将通过此 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 调用之前实例化您的服务。您必须添加一个特定的 header,告诉您的
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
因为能够将 header 传递给 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)))
}
}
你来了。