Angular Universal with i18n (Server Side Rendering)
I try to use Angular official internationalization tools with angular universal. So far I'm able to translate the client side rendering using the following procedure (thanks to this answer https://stackoverflow.com/a/40930110/1110635) :
I add "i18n" attributes as stated in the documentation in my templates :
./src/+app/about/about.component.html :
<h1 i18n="H1 of the about component">About</h1>
...
Then I run :
./node_modules/.bin/ng-xi18n
to generate the base messages.xlf file.
Then I copy this file for each locale I want to support as " messages.[locale].xlf " in a "locale" folder. When ready, I create a " messages.[locale].ts " for each xlf file containing an exported string of its content :
./locale/messages.fr.ts :
// TRANSLATION_FR is only for "messages.fr.ts" of course.
// I would create a TRANSLATION_ES const inside "messages.es.ts" for spanish for example.
export const TRANSLATION_FR: string = `<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="ng2.template">
<body>
<trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
<source>About</source>
<target>A propos</target>
<note priority="1" from="description">H1 of the about component</note>
</trans-unit>
</body>
</file>
</xliff>
`;
Finally, my client.ts file looks like the following :
./src/client.ts :
[...]
// i18n
import { TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID } from '@angular/core';
import { TRANSLATION_FR } from '../locale/messages.fr';
import { MainModule } from './browser.module';
export const platformRef = platformUniversalDynamic();
// on document ready bootstrap Angular 2
export function main() {
return platformRef.bootstrapModule(MainModule, {
providers: [
{provide: TRANSLATIONS, useValue: TRANSLATION_FR},
{provide: TRANSLATIONS_FORMAT, useValue: "xlf"},
{provide: LOCALE_ID, useValue: 'fr'}
]
});
}
bootloader(main);
This works and make the "client side" application work as expected. " About " is replaced by " A propos ". BUT , because angular universal pre-render the page on the server side using express the text is not translated until the client side bootstraping is done.
So when you first go on the page you see " About " for about 1 second before the client side kicks in an replace it with " A propos ".
The solution seem obvious, simply run the translation service on the server side ! But I have no idea how to do that.
My server.ts looks like this :
./src/server.ts
[...]
// i18n
import { TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID } from '@angular/core';
import { TRANSLATION_FR } from '../locale/messages.fr';
const app = express();
const ROOT = path.join(path.resolve(__dirname, '..', 'dist'));
// Express View
app.engine('.html', createEngine({
ngModule: MainModule,
providers: [
/**
* HERE IS THE IMPORTANT PART.
* I tried to declare providers but it has no effect.
*/
{provide: TRANSLATIONS, useValue: TRANSLATION_FR},
{provide: TRANSLATIONS_FORMAT, useValue: "xlf"},
{provide: LOCALE_ID, useValue: 'fr'}
]
}));
app.set('port', process.env.PORT || 3000);
app.set('views', ROOT);
app.set('view engine', 'html');
[...]
function ngApp(req, res) {
res.render('index', {
req,
res,
preboot: false,
baseUrl: '/',
requestUrl: req.originalUrl,
originUrl: `http://localhost:${ app.get('port') }`
});
}
app.get('*', ngApp);
// Server
let server = app.listen(app.get('port'), () => {
console.log(`Listening on: http://localhost:${server.address().port}`);
});
I have no direct access to the bootstrapModule method like on the client side. The providers key on the " createEngine " parameter object was already there in the original server.ts code.
What am I missing?
A solution is to pre-build packages for each language, and have a proxy detect which bundle to serve as default.
From the Angular docs on i8n:
Merge with the AOT compiler The AOT (Ahead-of-Time) compiler is part of a build process that produces a small, fast, ready-to-run application package.
When you internationalize with the AOT compiler, you must pre-build a separate application package for each language and serve the appropriate package based on either server-side language detection or url parameters.
You also need to instruct the AOT compiler to use your translation file. To do so, you use three options with the ng serve or ng build commands:
--i18nFile: the path to the translation file. --i18nFormat: the format of the translation file. --locale: the locale id. The example below shows how to serve the French language file created in previous sections of this guide:
ng build --aot --i18nFile=src/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr
链接地址: http://www.djcxy.com/p/31360.html
上一篇: 服务器端请求为客户端缓存
下一篇: 带i18n的角度通用(服务器端渲染)