Как я могу повторно использовать ключи перевода i18n в Angular?

Я использую поддержку i18n для Angular2 (4.0.3), как описано здесь. Я создал файлы xlf, и все работает счастливо.

Однако скажем, что у меня есть кнопка меню, которая ссылается на мою домашнюю страницу. Я создаю DOM node, используя атрибут i18n="@@homeTitle". Теперь в компоненте моей домашней страницы я хотел бы использовать тот же самый идентификатор перевода в теге <h1>, чтобы получить тот же перевод, не поддерживая несколько записей с тем же содержимым в файлах xlf.

Я надеялся сделать что-то вроде приведенного ниже и автоматически заполнить свой <a> node соответствующим переводом.

// home.component.html
<h1 i18n="@@homeTitle">Home</h1>

// menu.component.html
<a routerLink="/" i18n="@@homeTitle"></a>

Однако это не работает. <a> node отображается с пустым текстом, а не с целью перевода. (Кроме того, по умолчанию в автогенерированном файле messages.xlf нет цели перевода).

Фактически документы вызывают эту ситуацию, но не предлагают решения. Проблема также была вызвана пользователем в GitHub для обычных строк, таких как понедельник и отмена, но эта проблема не распространяется на решение этой проблемы особая проблема.

Как я могу повторно использовать переводы i18n, определенные в моих файлах xlf на нескольких узлах?

Изменить: Вот xlf, сгенерированный с помощью ng-xi18n --i18nFormat=xlf:

<?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="homeTitle" datatype="html">
        <source>Home</source>
        <target/>
      </trans-unit>
    </body>
  </file>
</xliff>

Если порядок разбора двух узлов @@homeTitle переключается, <source> изменяется соответственно.

Ответ 1

TL;DR; Просто не беспокойтесь о пользовательских идентификаторах и правильно напишите строки. Инструмент ng xi18n позаботится о совпадении идентичных строк под одним <trans-unit>. Ваши переводы затем будут применены ко всему блоку.

Более длинное объяснение: инструмент xi18n сопоставляет строки в приложении с помощью равенства строк. Всякий раз, когда он находит новую строку, она сравнивает ее с уже найденными. Если есть точное совпадение, оно включает новую строку в существующем <trans-unit>. Если этого не происходит, он создает новый и генерирует новый идентификатор.

Однако это поведение можно изменить, используя пользовательские идентификаторы и подсказки для перевода. Если новая строка найдена и содержит пользовательский идентификатор, текущие сообщения будут проверяться для этого конкретного идентификатора и назначены существующим <trans-group>, если они найдены. Обратите внимание, что этот процесс игнорирует сама строка, поэтому любое непустое значение будет объединено с найденным <trans-group> с пользовательским идентификатором. Пустые строки опущены.

Как упоминается в документации, только первый элемент с пользовательским идентификатором будет проверен для исходной строки. Когда есть второй элемент с тем же идентификатором, это строковое значение не будет анализироваться. Это означает, что вы можете изменить свое решение, чтобы все остальные узлы с вашим пользовательским идентификатором содержали строку-заполнитель. Тогда локализация будет работать так, как вы ожидаете.

// home.component.html
<h1 i18n="@@homeTitle">Home</h1>
// menu.component.html
<a routerLink="/" i18n="@@homeTitle">ANY PLACEHOLDER STRING YOU WANT</a>

Как вы могли видеть, это не выглядит особенно причудливым. Кроме того, вы должны помнить пользовательский идентификатор для дальнейшего повторного использования. Я бы посоветовал не делать этого, если это абсолютно необходимо. На мой взгляд, проще просто написать строку (в вашем случае "Home"), нанести атрибут i18n на элемент и не беспокоиться о повторном использовании, так как это будет сделано автоматически. Я бы использовал пользовательские идентификаторы в основном, если вам нужно иметь несколько различных (контекстных) переводов одной строки.