Подтвердить что ты не робот

Angular Универсальный с i18n (на стороне сервера)

Я пытаюсь использовать официальные инструменты интернационализации Angular с универсальным Angular. До сих пор я мог перевести визуализацию на стороне клиента, используя следующую процедуру (благодаря этому ответу qaru.site/info/231126/...):

Я добавляю атрибуты "i18n", как указано в документации в моих шаблонах:

./src/+ app/about/about.component.html:

<h1 i18n="H1 of the about component">About</h1>
...

Затем я запускаю:

./node_modules/.bin/ng-xi18n

для создания базового файла messages.xlf.

Затем я копирую этот файл для каждой локали, которую хочу поддерживать как " сообщения. [locale].xlf" в папке "locale". Когда я готов, я создаю " сообщения. [Locale].ts" для каждого файла xlf, содержащего экспортированную строку его содержимого:

./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>
`;

Наконец, мой файл client.ts выглядит следующим образом:

./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);

Это работает и делает приложение "клиентская сторона" работающим, как ожидалось. " О" заменяется на " Предложение". НО, потому что Angular универсальный предварительный рендеринг страницы со стороны сервера, используя выражение, текст не переводится до тех пор, пока не будет завершена загрузка на стороне клиента.

Итак, когда вы впервые заходите на страницу, вы видите " О" в течение примерно 1 секунды, прежде чем клиентская сторона начнет заменять ее " Предложение".

Решение кажется очевидным, просто запустите службу перевода на стороне сервера! Но я не знаю, как это сделать.

Мой server.ts выглядит следующим образом:

./ЦСИ/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}`);
});

У меня нет прямого доступа к методу bootstrapModule, например, на стороне клиента. Клавиша провайдеров на объекте параметра createEngine уже существует на исходном сервере .ts.

Что мне не хватает?

4b9b3361

Ответ 1

Решением является предварительная сборка пакетов для каждого языка и наличие прокси-сервера, для которого пакет будет использоваться по умолчанию.

Из Angular docs на i8n:

Объединить с компилятором AOT Компилятор AOT (Ahead of the Time) является частью процесса сборки, который создает небольшой, быстрый, готовый к запуску пакет приложений.

Когда вы интернационализируете с помощью компилятора AOT, вы должны предварительно создать отдельный пакет приложений для каждого языка и соответствующий пакет, основанный либо на обнаружении на стороне сервера, либо на Параметры URL.

Вам также необходимо дать указание компилятору AOT использовать ваш перевод файл. Для этого вы используете три варианта с помощью ng serve или ng build команды:

- i18nFile: путь к файлу перевода. --i18nFormat: формат файла перевода. --locale: идентификатор локали. В приведенном ниже примере показано, как обслуживать файл французского языка, созданный в предыдущих разделах этого руководства:

ng build --aot --i18nFile=src/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr