Можно ли читать текстовое содержимое элемента в Angular без чтения из DOM?

Мне нужно иметь возможность использовать переведенные строки в коде в моем приложении Angular, но с инструментами i18n, которые еще не достигли этой задачи, я реализовал слегка взломанную версию, которая использует преимущества Angular существующих возможностей i18n, с намерением отказаться от моего решения для родного Angular, поскольку его возможности i18n догоняют мои потребности (должен быть 5.x release, пальцы скрещены).

В принципе, у меня есть TranslationDirective, который читает текст из DOM и испускает события при изменении текста:

@Directive({
  selector: '[myAppTranslation]'
})
export class TranslationDirective implements AfterViewChecked, OnChanges {
  /**
   * dependencies takes an array of the values needed to calculate the output translation
   * we use this for change detection, to minimize the DOM interaction to only when it is necessary
   */
  @Input() dependencies: any[];
  isDirty = true;
  @Input() messageKey: string;
  message: string;
  @Output() messageUpdated = new EventEmitter<TranslationEvent>();

  constructor(public el: ElementRef) {}

  /**
   * sets the translated message and triggers the TranslationEvent
   */
  setMessage() {
    const message = (this.el.nativeElement.textContent || '').trim();
    const oldMessage = (this.message || '');
    if (oldMessage !== message) {
      this.message = message;
      this.isDirty = false;
      this.triggerTranslationEvent();
    }
  }

  ngOnChanges() {
    this.isDirty = true;
  }

  ngAfterViewChecked() {
    if (this.isDirty) {
      this.setMessage();
    }
  }

  /**
   * triggers the messageUpdated EventEmitter with the TranslationEvent
   */
  triggerTranslationEvent() {
    // need to delay a tick so Angular doesn't throw an ExpressionChangedAfterItHasBeenCheckedError
    setTimeout(() => {
      const event = new TranslationEvent(this.messageKey, this.message);
      this.messageUpdated.emit(event);
    });
  }
}

export class TranslationEvent {
  constructor(public messageKey: string, public message: string) {}
}

который используется следующим образом:

<span
  myAppTranslation
  i18n
  [dependencies]="[today]"
  [messageKey]="todaysDateKey"
  (messageUpdated)="setTodaysDateTranslation($event)"
>
  Today is {{today | date:'short'}}
</span>

Поскольку строки, которые нужно перевести, все находятся в шаблонах, инструмент Angular xi18n читает их просто отлично, а компилятор Angular заменит их на переведенные строки.

Это функционально, но не очень. Я подозреваю, что есть ошибка времени, которая просто ждет, чтобы укусить меня, что пока еще не проявилось. Существует неэффективный и медленный цикл записи в DOM-read-from-DOM, который было бы очень приятно устранить.

Я бы хотел устранить один источник проблем, минуя DOM, если вообще не смогу его избежать. Поддерживает ли Angular копию в памяти содержимого доступного элемента, не проходя через DOM? Если это возможно, могу ли я полностью отказаться от записи элемента перевода в DOM?

Ответ 1

Похоже, что большая сложность заключается в том, что вы хотите поддерживать динамический текст - что текст может измениться во время выполнения. Я не думаю, что вам нужно это сделать, потому что текст i18n должен быть статическим, чтобы:

  • Его можно извлечь во время компиляции.

  • Он может быть переведен заранее, и у вас есть все переводы, хранящиеся в более позднее время компиляции.

Ваш пример "Сегодня есть..." - прекрасный пример непереводимого текста.:-) Вы должны изменить его, чтобы просто "Сегодня" быть текстовым фрагментом сам по себе, а затем показывать дату с текущей локалью вне этого диапазона.