Частичная локализация HTML
Эта проблема
Мне нужно локализовать свое веб-приложение. Я использую два языка - английский и норвежский (это не должно иметь значения).
Я использую файлы ресурсов для локализации стандартных представлений. Они находятся в отдельном проекте под названием Myproject.Localisation:
- Localised.resx
- Localised.no.resx
Это выглядит следующим образом:
<li>@Localised.WhatEverINeedToLocalise</li>
Затем у меня есть два стандартных частичных html-файла с некоторыми html и некоторыми knockout.js, которые загружаются как зависимости amd и используются в моем классе машинописи позже:
///<amd-dependency path="text!./productTemplate.html" />
///<amd-dependency path="text!./anotherTemplate .html" />
var contentTemplate = require("text!./productTemplate.html");
var anotherTemplate = require("text!./anotherTemplate .html");
Вопрос
Очевидно, я должен сделать перевод в них также. Есть ли способ, которым я могу сгенерировать эти частичные HTML-файлы, используя бритву и файлы ресурсов, которые у меня есть?
Если нет, есть ли другие варианты, возможно, более простые, чем мое решение (см. Ниже)?
Мое решение
Единственный способ, которым я пришел, - это установить i18next и его привязку для нокаута, написать шаблон T4, который будет генерировать jsons для перевода из файлов resx, а затем транслировать частичные htmls, используя knockout. Тем не менее, это кажется слишком сложным.
1 ответ
В моих проектах я использую базовый класс viewmodel для обработки извлечения текстовых данных с сервера. Каждая модель представления имеет свой собственный идентификатор, который совпадает с идентификатором ресурса, используемым на сервере. Извлеченные тексты хранятся в базовом классе viewmodel в такой структуре:
public texts: KnockoutObservableArray<ITextItem> = ko.observableArray<ITextItem>();
.. где ITextItem является структурой, подобной этой:
interface ITextItem {
id: string;
value: KnockoutObservable<string>;
}
.. взято с такой функцией:
public updateTexts(cultId: string): Q.Promise<any> {
if (this.textsName === '')
this.textsName = this.modelId;
if (this.lastCultureIdFetched != cultId) {
this.lastCultureIdFetched = cultId;
return mm_cspData.cspCtx.getTexts(this.textsName, this.texts);
}
else
return Q.resolve(true);
}
.. конкретный текст, извлекаемый из модели представления следующим образом:
public tx(id: string): string {
var match: ITextItem = ko.utils.arrayFirst(this.texts(), item=> item.id === id);
if (!match)
return '';
else
return match.value();
}
Таким образом, каждый раз, когда активируется модель представления или изменяется язык приложения, запускается метод updateText.
Чтобы отобразить текст в моем представлении html, я использую обработчик привязки knockout, чтобы получить правильный текст из модели представления. Как правило, каждая viewmodel экспортируется в переменную с именем vm, поэтому мне не терпится сделать это так:
ko.getVmTx = (label: any, bindingContext: any) : string => {
if (label === null)
return '';
var vm: any;
var labelId;
if (typeof label === 'object' && typeof label.vm === 'object' && typeof label.vm.tx !== 'function') {
vm = label.vm;
labelId = label.tx;
} else {
vm = bindingContext.$root.vm;
labelId = ko.unwrap(label);
}
if (vm === null || typeof vm === 'undefined' || typeof vm.tx !== 'function') {
console.log('tx binding: unable to find vm for ' + label);
return '';
}
else
return vm.tx(labelId);
}
ko.bindingHandlers.tx = {
update: (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) => {
$(element).text(ko.getVmTx(valueAccessor(),bindingContext));
}
};
ko.bindingHandlers.txVal = {
update: (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) => {
$(element).val(ko.getVmTx(valueAccessor(), bindingContext));
}
};
Наконец, в своих представлениях я использую обработчики привязки, например так:
<span class="app-badge-label-bg" data-bind="tx: 'FinInvAmount'"></span>
Это масштабная установка, но когда она будет создана, базовый класс viewmodel выполняет обработку текста, и единственное, что вам нужно сделать для каждой viewmodel, - это настроить файлы ресурсов на стороне сервера и привязку данных ваши метки и значения с простой привязкой нокаута.