Angular интернационализация с вызовами базы данных REST, возвращающими двуязычный контент

Я конвертирую свое двуязычное веб-приложение в Angular. Это интерфейс, в котором пользователь выбирает контент, который он хочет просмотреть, и после выбора данные загружаются из REST API, который подключается к базе данных SQL. Способы его настройки заключаются в том, что вызовы базы данных возвращают содержимое на двух языках. Например, ответ JSON для TableComponent будет таким:

GET /api/tables/1
{
    "title": "Hello",
    "titleFr": "Bonjour",

    "time": "05:23 PM",
    "timeFr": "17:23",

    "content": "I am a grapefruit",
    "contentFr": "Je suis un pamplemousse"
}

Разные компоненты получают разные значения, но всегда для обоих языков. Одновременно отображается только один язык, но вверху есть кнопка, позволяющая пользователю мгновенно переключать язык содержимого. Насколько я понимаю, для такого поведения я должен использовать ngx-translate. Будучи совершенно новым в этом, я не совсем уверен, с чего начать. Я прочитал некоторые документы; это звучит так: мне либо нужно иметь контент и его перевод в файлах JSON, связанных с приложением, либо я делаю HTTP-вызовы в базу данных, которая возвращает переведенный контент.

Ни один из этих подходов не работает с моей текущей настройкой. Как уже упоминалось, все вызовы базы данных возвращают текст для обоих языков, а не разделяют их. Есть ли способ добиться локализации без необходимости их разделения?

Причина, по которой у меня это так, заключается в том, что в моей исходной реализации я загрузил все данные из базы данных и выбрал, какой HTML-шаблон отображать, в зависимости от выбранного языка. Например, с TableComponent, если выбран английский язык, шаблон будет использовать title, time, content, а если французский, то titleFr, timeFr, contentFr. Чтобы все мои компоненты знали текущий язык и обнаруживали языковые изменения, было немного обременительно, поэтому я хочу воспользоваться преимуществами библиотек интернационализации.

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


person robev    schedule 08.02.2021    source источник


Ответы (1)


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

translation.service.ts

@Injectable()
export class TranslationService {
  constructor() {}

  async public getTranslation(language: string): Observable<any> {
    // Get your text from database (assuming it's an Observable)
    return db.get().pipe(
      map(translations => {
        // Just a suggestion, you can also have a mapping for better syntax
        if (language === 'french') {
          return {
            title: translations.titleFr,
            time: translations.timeFr,
            content: translations.contentFr
          }
        }

        // Otherwise, return default language
        return {
          title: translations.title,
          time: translations.time,
          content: translations.content
        }
      }),
      // You can add shareReplay from rxjs/operators to cache results
      shareReplay(1)
    );
  }
}

А затем в своем компоненте вы можете просто получить доступ к данным из этого сервиса и воспользоваться преимуществами модульности Angular.

component.ts

import { Component, OnInit } from '@angular/core';

import { TranslationService } from './path-to/translation.service';

@Component({
  selector: 'some-component',
  templateUrl: './some.component.html',
  styleUrls: ['./some.component.scss']
})
export class SomeComponent implements OnInit {
  public texts: {
    title: string;
    time: string;
    content: string;
  }

  constructor(
    private readonly translationService: TranslationService
  ) { }

  ngOnInit() {
    this.translationService.getTranslations('french').subscribe(result => this.texts = result);
  }

}

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

person Bruno Duarte Brito    schedule 08.02.2021
comment
Как я уже упоминал, я не могу связывать переводы с приложением (которое, если я правильно понимаю, использует angular i18n), поскольку текст поступает из API. Вот почему я нашел ngx-translate. Я рассмотрю ваш перевод. Спасибо - person robev; 08.02.2021
comment
Проблема с вашим сервисом в том, что он возвращает только один язык. Суть моей настройки в том, что один http-запрос дает оба языка. Таким образом, переключение языка происходит мгновенно и не ждет возврата запроса. Я уточнил в своем вопросе. - person robev; 08.02.2021
comment
Вы также можете обновить службу, чтобы получить несколько языков, просто укажите нужный язык в компоненте. Вы можете использовать RxJS shareReplay и кэшировать результаты своей базы данных, см. эту ссылку для получения информации, поэтому вам не нужно вызывать его каждый раз. - person Bruno Duarte Brito; 09.02.2021
comment
Проблема с этим подходом заключается в том, что у меня есть разные типы компонентов, которые принимают разные поля из базы данных. Я только что привел один пример в своем вопросе. Служба перевода не будет знать, какие данные отображать (в зависимости от текущего языка), поскольку она не знает, какие поля и компоненты ожидают от базы данных. - person robev; 12.02.2021