Ответ 1
Здесь мой подход к работе с i18n, включая использование ngx-translate при загрузке переводов из базы данных.
Когда речь заходит о переводах, мои бэкэнд и интерфейс отделены друг от друга. Переводы не отправляются в сборку angular или серверный пакет, а через вызов HTTP rest, который получил информацию из базовой базы данных. Все переводы загружаются при запуске, вносятся в структуру JSON и затем могут быть доставлены во внешний интерфейс, где ngx-translate заботится обо всем остальном. Здесь простой порядок событий для успешной загрузки перевода из базы данных и обеспечения их доступности для интерфейс.
- безопасные переводы в базе данных
- загружать переводы при запуске бэкэнда (или реализовать механизм перезагрузки, возможно через REST)
- преобразования карт в объекты JSON с ключом-значением пары
- сделать объекты JSON доступными через REST api
- frontend загружает объекты JSON через этот REST api
- используйте объект JSON в angular с ngx-translate
преимущества
Позже я расскажу больше о том, как это может выглядеть, просто краткая заметка о том, какие преимущества приносит этот подход к базе данных-rest:
- все переводы, хранящиеся в одном месте (одна таблица)
- недостающие переводы для языка можно избежать (NULL-проверки)
- можно выделить двойное распределение ключей (PRIMARY KEY)
- возможно обновление переводов во время выполнения.
- процесс перевода может быть проведен за пределами проекта (обновление файлов в структуре проекта не требуется)
Посмотрите, как это может быть достигнуто.
База данных
Переводы обычно состоят из простых пар ключей, основанных на файлах перевода, которые мне никогда не нравились. Поэтому вместо этого я сохраняю свои переводы в одной таблице с ключевым столбцом и столбцом перевода для каждого языка, который у меня есть, например, что-то вроде KEY | EN | FR | DE
со значениями, такими как button.close | close | près | schließen
. Ключ представляет тот же ключ, что и в обычном файле, но вместо отдельного файла на язык переводы сохраняются в одном столбце каждый.
Бэкэнд-сопоставление объектов JSON
Мне нравится загружать всю таблицу сразу, чтобы подготовить каждый язык для доставки интерфейса сразу. Обычно это можно сделать один раз при запуске бэкэнд, и результат можно сохранить в памяти, чтобы избежать многих вызовов базы данных. Таблица должна быть разделена на объекты JSON с ключом-значением для каждого столбца языка. Каждый результирующий объект языка затем содержит ключи базы данных в качестве своих ключей и переводы как их значения.
var EN = {
...
"button.close": "close",
...
}
var FR = {
...
"button.close": "près",
...
}
var DE = {
...
"button.close": "schließen",
...
}
Это просто сопоставление между массивами и объектами, которое, в зависимости от языка сервера, обычно довольно просто (я могу поделиться своим кодом для node.js, если это необходимо). Результатом является список объектов языка JSON, каждый из которых имеет их перевод в виде пар ключ-значение, которые впоследствии могут быть доступны.
вызов HTTP rest
Перевод теперь в значительной степени в том же формате, что и обычный файл перевода (пары ключ-значение), просто хранится в памяти, а не в файле. С помощью простого HTTP-вызова api для определенного языка вы можете получить доступ к этому списку, взять объект перевода этого языка и отправить его прямо в интерфейс. Здесь приведен пример node.js
.
translationRouter.route('/:lang').get(function (request, response) {
// load translation key-value-pair object for requested language
response.send(translationService.getTranslations(request.params.lang));
});
NGX-перевод
Способ ngx-translate работает довольно прямолинейно. Переводы загружаются в приложение angular, ключи перевода указаны в приложении, а затем динамически заменяются значениями перевода с предоставленного языка. Как указано другими, он поддерживает различные способы загрузки переводов, например, простые старые файлы переводов или самозагружаемые загрузчики, такие как загрузчики HTTP. Здесь простой HTTP-загрузчик, который загружает переводы через вызов REST (см. Выше).
import { TranslateLoader } from '@ngx-translate/core';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http';
import '../rxjs-operators';
export class TranslationLoader implements TranslateLoader {
constructor(private http: HttpClient) { }
getTranslation(lang: string): Observable<any> {
return this.http.get("/api/translation/" + lang);
}
}
Единственный трюк - указать этот загрузчик в качестве основного загрузчика, который можно сделать в app.module. Вот пример, который использует вышеупомянутый HTTP-загрузчик (и также работает для AOT).
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
export function HttpLoaderFactory(http: HttpClient) {
return new TranslationLoader(http);
}
...
@NgModule({
imports: [...,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (HttpLoaderFactory),
deps: [HttpClient]
}
}), ...]
})
Вместо запроса файла ngx-translate использует указанный TranslationLoader для получения своих пар ключ-значение, что является именно тем, предоставляя через наш отдых вызов. Очень просто. Для этого случая можно указать язык для загрузки, а также язык возврата в случае, если значение не найдено. Здесь приведен пример загрузки текстов по умолчанию и языков перевода.
// fallback language
this.translate.setDefaultLang('en');
// browser language
this.translate.use(this.translate.getBrowserLang());
Документация по ngx-translate довольно хороша, есть разные способы ее использования, например, через службу, директиву или канал, а также вы можете параметризовать переводы.
дополнительная информация
перезагрузка переводов
Как указано в списке преимуществ, вы также можете перезагружать переводы во время выполнения, что, вероятно, является более сложной задачей при наборе приложения для доставки. Вы можете просто предоставить HTTP-вызов для админов, который выполняет точно такую же процедуру загрузки текста, что и при запуске. Таким образом, переводы могут быть перезагружены, переназначены и сохранены в памяти. Новые запросы страницы будут автоматически использовать перезагруженные объекты перевода.
изменение живого языка
Некоторые способы использования ngx-translate позволяют переключатели мгновенного перевода (например, через директиву). Таким образом, загрузка другого языка в angular (через простой вызов this.translate.use(lang)
) мгновенно переключит показанные переводы без переустановки страницы или видимых компонентов, что на самом деле довольно аккуратно, но, к сожалению, не работает для всех способов использования.
пределы ngx-translate
Хотя ngx-translate действительно прост в использовании, он имеет ограничения. Одним из них является, например, использование директивы ngx-translate в сочетании с большинством директив angular, поскольку angular материал директивы (например, кнопки) будут создавать структуры поддерева, а ngx-translate только переводит ключи на первого ребенка (по крайней мере, я думаю, что это так). Так что здорово использовать, но иногда немного сложно.
Я думаю, что это так. В настоящее время я использую этот подход, и я очень доволен тем, как это получилось. Это небольшая работа, чтобы начать работу, но как только все будет кататься, это может быть очень полезно.