Частичная локализация 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, - это настроить файлы ресурсов на стороне сервера и привязку данных ваши метки и значения с простой привязкой нокаута.

Другие вопросы по тегам