Angular Universal (SSR) 不预渲染语言
Angular Universal (SSR) doesn't pre-render language
我正在为多语言应用程序使用 ngx-translate。
app.module.ts
import {TranslateLoader, TranslateModule, TranslateService} from '@ngx-translate/core';
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, './assets/i18n');
}
@NgModule({
[
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
...
]
export class AppModule {
constructor(translate: TranslateService) {
translate.setDefaultLang('en');
translate.use( 'en');
}
已遵循 Angular Universal: server-side rendering 说明,运行 应用处于 SSR 模式:
- 页面加载了 lang 字符串 ('Home.Title')
- 有一个针对 en.json
的 HTTP 调用
- 字符串被替换为翻译 ('My site')
我需要更改什么才能在服务器中呈现翻译?
我不确定这是最好的方法,但据我所知,我们需要以某种方式在服务器端加载翻译。我为此使用了快递:
app.get('/path/to/your/translations/*.json',(req, res) => {
res.download( `/path/to/your/translations/${lang}`)
});
和 AppServerModule 中的 HttpInterceptor
you can see here
https://github.com/Angular-RU/angular-universal-starter 带翻译。
服务器和浏览器部分的不同模块加载器
翻译服务器-loader.service.ts
public getTranslation(lang: string): Observable<any> {
return Observable.create((observer) => {
const jsonData: any = JSON.parse(
fs.readFileSync(`${this.prefix}/${lang}${this.suffix}`, 'utf8'),
);
const key: StateKey<number> = makeStateKey<number>(`transfer-translate-${lang}`);
this.transferState.set(key, jsonData);
observer.next(jsonData);
observer.complete();
});
}
translates-browser-loader.service.ts - 重要用途 transferState
public getTranslation(lang: string): Observable<any> {
const key: StateKey<number> = makeStateKey<number>(`transfer-translate-${lang}`);
const data: any = this.transferState.get(key, null);
if (data) {
return Observable.create((observer) => {
observer.next(data);
observer.complete();
});
} else {
return new TranslateHttpLoader(this.http, this.prefix, this.suffix).getTranslation(lang);
}
}
您需要在服务器上添加一个 http 拦截器,这将更改翻译文件路径以便能够将它们加载到服务器上。这是我个人的问题,我按照这篇文章的解释修复了它:https://itnext.io/angular-universal-how-to-add-multi-language-support-68d83f6dfc4d
值得一看!
我找到的最好的教程就是这里的教程:
implementing-multi-language-angular-applications-rendered-on-server
我使用 Angular 10,angular 通用 (SSR) 和 ngx-translate,它对我有用。
本教程有助于避免使用服务器不支持的 localstorage,它将服务器和浏览器的 translateLoaderFactory 分开,它使用 TransferState 来避免对语言 json 文件的不必要的 http 调用(作为服务器已经加载它们,它们嵌入在页面服务器 returns) 中,最后它有一个完整的 git-hub 存储库,用于逐步实施。感谢 Dmitry Efimenko 的出色工作。
一旦按照他的建议实施,页面就会使用 html 中嵌入的翻译正确呈现,因此不会执行额外的 http 请求来获取语言 json 文件。这避免了页面闪烁和不得不看到页面中显示的语言键的问题,即使是一瞬间。
唯一悬而未决的问题是,如果在加载页面后更改语言,因为 ngx-translate 没有重新加载页面,它会保持 html 中最初加载的语言,所以然后完成一个 http 请求来加载新语言,但我不知道如何避免这种情况。至少已经在 cookie 中选择了语言的用户,或者对检测到的语言感到满意的用户不会对语言 json 完成任何 http 请求。如果我找到在服务器上呈现语言更改的解决方案,我将使用此信息更新此答案。
我正在为多语言应用程序使用 ngx-translate。
app.module.ts
import {TranslateLoader, TranslateModule, TranslateService} from '@ngx-translate/core';
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, './assets/i18n');
}
@NgModule({
[
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
...
]
export class AppModule {
constructor(translate: TranslateService) {
translate.setDefaultLang('en');
translate.use( 'en');
}
已遵循 Angular Universal: server-side rendering 说明,运行 应用处于 SSR 模式:
- 页面加载了 lang 字符串 ('Home.Title')
- 有一个针对 en.json 的 HTTP 调用
- 字符串被替换为翻译 ('My site')
我需要更改什么才能在服务器中呈现翻译?
我不确定这是最好的方法,但据我所知,我们需要以某种方式在服务器端加载翻译。我为此使用了快递:
app.get('/path/to/your/translations/*.json',(req, res) => {
res.download( `/path/to/your/translations/${lang}`)
});
和 AppServerModule 中的 HttpInterceptor you can see here
https://github.com/Angular-RU/angular-universal-starter 带翻译。 服务器和浏览器部分的不同模块加载器
翻译服务器-loader.service.ts
public getTranslation(lang: string): Observable<any> {
return Observable.create((observer) => {
const jsonData: any = JSON.parse(
fs.readFileSync(`${this.prefix}/${lang}${this.suffix}`, 'utf8'),
);
const key: StateKey<number> = makeStateKey<number>(`transfer-translate-${lang}`);
this.transferState.set(key, jsonData);
observer.next(jsonData);
observer.complete();
});
}
translates-browser-loader.service.ts - 重要用途 transferState
public getTranslation(lang: string): Observable<any> {
const key: StateKey<number> = makeStateKey<number>(`transfer-translate-${lang}`);
const data: any = this.transferState.get(key, null);
if (data) {
return Observable.create((observer) => {
observer.next(data);
observer.complete();
});
} else {
return new TranslateHttpLoader(this.http, this.prefix, this.suffix).getTranslation(lang);
}
}
您需要在服务器上添加一个 http 拦截器,这将更改翻译文件路径以便能够将它们加载到服务器上。这是我个人的问题,我按照这篇文章的解释修复了它:https://itnext.io/angular-universal-how-to-add-multi-language-support-68d83f6dfc4d
值得一看!
我找到的最好的教程就是这里的教程:
implementing-multi-language-angular-applications-rendered-on-server
我使用 Angular 10,angular 通用 (SSR) 和 ngx-translate,它对我有用。
本教程有助于避免使用服务器不支持的 localstorage,它将服务器和浏览器的 translateLoaderFactory 分开,它使用 TransferState 来避免对语言 json 文件的不必要的 http 调用(作为服务器已经加载它们,它们嵌入在页面服务器 returns) 中,最后它有一个完整的 git-hub 存储库,用于逐步实施。感谢 Dmitry Efimenko 的出色工作。
一旦按照他的建议实施,页面就会使用 html 中嵌入的翻译正确呈现,因此不会执行额外的 http 请求来获取语言 json 文件。这避免了页面闪烁和不得不看到页面中显示的语言键的问题,即使是一瞬间。
唯一悬而未决的问题是,如果在加载页面后更改语言,因为 ngx-translate 没有重新加载页面,它会保持 html 中最初加载的语言,所以然后完成一个 http 请求来加载新语言,但我不知道如何避免这种情况。至少已经在 cookie 中选择了语言的用户,或者对检测到的语言感到满意的用户不会对语言 json 完成任何 http 请求。如果我找到在服务器上呈现语言更改的解决方案,我将使用此信息更新此答案。