Как сделать I18n на стороне клиента с помощью mustache.js

У меня есть несколько статических html-файлов, и я хочу изменить статический текст внутри с модификацией на стороне клиента через mustache.js.

кажется, это было возможным расширением усов Twitter на github: https://github.com/bcherry/mustache.js

Но в последнее время конкретное расширение I18n было удалено или изменено.

Я представляю себе решение, в котором http:/server/static.html?lang=en загружает mustache.js и языковой файл JSON на основе параметра lang data_en.json.

Затем ус заменяет {{tags}} отправленными данными.

Может ли кто-нибудь дать мне пример, как это сделать?


person mancereus    schedule 22.03.2011    source источник


Ответы (5)


Вы можете использовать лямбды вместе с какой-нибудь библиотекой, такой как i18next или что-то еще.

{{#i18n}}greeting{{/i18n}} {{name}}

И данные прошли:

{
    name: 'Mike',
    i18n: function() {
        return function(text, render) {
            return render(i18n.t(text));
        };
    }
}

Это решило проблему для меня

person categulario    schedule 14.03.2014
comment
Лучший комментарий ИМХО, очень простой, но эффективный. - person StackHola; 16.06.2014
comment
runction → function Я не могу редактировать, потому что редактирование будет ‹ 6 символов! - person tuxayo; 12.07.2016

Я не думаю, что ответ Silent действительно решает/объясняет проблему.

Настоящая проблема в том, что вам нужно дважды запустить Mustache (или использовать что-то еще, а затем Mustache).

То есть большинство i18n работает как двухэтапный процесс, например:

  1. Визуализируйте текст i18n с заданными переменными.
  2. Визуализируйте HTML с текстом i18n, отображаемым после публикации.

Вариант 1. Используйте частичные усы

<p>{{> i18n.title}}</p>
{{#somelist}}{{> i18n.item}}{{/somelist}}

Данные, передаваемые этому шаблону усов, могут быть следующими:

{ 
  "amount" : 10, 
  "somelist" : [ "description" : "poop" ]
}

Затем вы должны хранить все свои шаблоны/сообщения i18n в виде массивного JSON-объекта шаблонов усов на сервере:

Ниже приведены переводы на «en»:

{ 
   "title" : "You have {{amount}} fart(s) left", 
   "item" : "Smells like {{description}}"
}

Теперь у этого подхода есть довольно большая проблема, заключающаяся в том, что у Усов нет логики, поэтому обработка таких вещей, как множественное число, становится беспорядочной. Другая проблема заключается в том, что производительность может быть плохой при таком количестве частичных загрузок (а может и нет).

Вариант 2: Пусть i18n Сервера сделает всю работу.

Другой вариант — позволить серверу выполнить первый проход расширения (шаг 1). У Java есть много вариантов расширения i18n, я полагаю, что и другие языки тоже.

Что довольно раздражает в этом решении, так это то, что вам придется дважды загружать свою модель. Один раз с обычной моделью и второй раз с расширенными шаблонами i18n. Это довольно раздражает, так как вам нужно будет точно знать, какие расширения/шаблоны i18n расширять и вставлять в модель (иначе вам пришлось бы расширять все шаблоны i18n). Другими словами, вы получите несколько хороших нарушений DRY.

Одним из способов решения предыдущей проблемы является предварительная обработка шаблонов усов.

person Adam Gent    schedule 04.04.2012
comment
Это хорошее обобщающее описание проблем с интернационализацией и усами! - person Florian Mertens; 22.06.2018

Мой ответ основан на разработке. Его ответ очень хорош, я просто добавлю возможность использовать теги усов в коде сообщения. Это действительно необходимо, если вы хотите иметь возможность получать сообщения в соответствии с текущим состоянием усов или в циклах.

Он основан на простом двойном рендеринге.

 info.i18n = function(){
        return function(text, render){
            var code = render(text); //Render first to get all variable name codes set
            var value = i18n.t(code)
            return render(value); //then render the messages
        }
    }

Таким образом, выступления не получаются из-за того, что усы работают на очень маленькой струне.

Вот небольшой пример:

JSON-данные:

 array : 
    [
        { name : "banana"},
        { name : "cucomber" }
    ]

Шаблон усов:

{{#array}}
    {{#i18n}}description_{{name}}{{/i18n}}
{{/array}}

Сообщения

description_banana = "{{name}} is yellow"
description_cucomber = "{{name}} is green"

Результат:

banana is yellow
cucomber is green

множественное число

[Изменить]: как было сказано в комментарии, следует пример с псевдокодом обработки множественного числа для английского и французского языков. Это очень простой и не проверенный пример, но он дает вам подсказку.

description_banana = "{{#plurable}}a {{name}} is{{/plurable}} green" (Adjectives not getting "s" in plurals)

description_banana = "{{#plurable}}Une {{name}} est verte{{/plurable}}" (Adjectives getting an "s" in plural, so englobing the adjective as well)

info.plurable = function() 
{
  //Check if needs plural
  //Parse each word with a space separation
  //Add an s at the end of each word except ones from a map of common exceptions such as "a"=>"/*nothing*/", "is"=>"are" and for french "est"=>"sont", "une" => "des"
  //This map/function is specific to each language and should be expanded at need.
}
person StackHola    schedule 16.06.2014
comment
Как бы вы обратились ко множественному числу? - person Florian Mertens; 22.06.2018
comment
Трудно ответить, множественное число сильно различается в зависимости от языка, французского, немецкого, английского, японского и т. д. иногда вам нужно адаптировать слово только ко множественному числу, в других случаях вам также придется удалять/добавлять элементы к окружающим словам, или даже изменить слово само по себе. По моему опыту, множественное число должно обрабатываться с помощью подфункций, специфичных для языка и местного синтаксиса. - person StackHola; 28.03.2019

Это довольно просто и довольно просто.

Во-первых, вам нужно будет добавить код для определения строки запроса lang. Для этого я использую фрагмент взятый из ответа здесь.

function getParameterByName(name) {

    var match = RegExp('[?&]' + name + '=([^&]*)')
                    .exec(window.location.search);

    return match && decodeURIComponent(match[1].replace(/\+/g, ' '));

}

Затем я использую jQuery для обработки состояний ajax и onReady:

$(document).ready(function(){
    var possibleLang = ['en', 'id'];
    var currentLang = getParameterByName("lang");
    console.log("parameter lang: " + currentLang);
    console.log("possible lang: " + (jQuery.inArray(currentLang, possibleLang)));
    if(jQuery.inArray(currentLang, possibleLang) > -1){
        console.log("fetching AJAX");
        var request = jQuery.ajax({
            processData: false,
            cache: false,
            url: "data_" + currentLang + ".json"
        });
        console.log("done AJAX");

        request.done(function(data){
            console.log("got data: " + data);
            var output = Mustache.render("<h1>{{title}}</h1><div id='content'>{{content}}</div>", data);
            console.log("output: " + output);
            $("#output").append(output);
        });

        request.fail(function(xhr, textStatus){
            console.log("error: " + textStatus);
        });
    }
});

Для этого ответа я пытаюсь использовать простые данные JSON:

{"title": "this is title", "content": "this is english content"}

Получите этот GIST для получения полного HTML-ответа.

person ariefbayu    schedule 07.03.2012
comment
Как бы вы обратились ко множественному числу? - person Florian Mertens; 22.06.2018

Обязательно помните, что другие языки значительно отличаются от EN.

В FR и ES прилагательные стоят после существительного. "зеленая фасоль" становится "haricots verts" (зеленая фасоль) в FR, поэтому, если вы подключаете переменные, ваши переведенные шаблоны должны иметь переменные в обратном порядке. Так, например, printf не будет работать, потому что аргументы не могут изменить порядок. Вот почему вы используете именованные переменные, как в варианте 1 выше, и переведенные шаблоны в целых предложениях и абзацах, а не объединяете фразы.

Ваши данные также должны быть переведены, поэтому слово «какашки», которое произошло от данных, должно быть каким-то образом переведено. В разных языках множественное число по-разному, как и в английском, например, в зубах/зубах, ступнях/ступнях и т. д. В EN также есть очки и штаны, которые всегда стоят во множественном числе. В других языках также есть исключения и странные идомы. В Великобритании IBM «присутствует» на выставке, тогда как в США IBM «присутствует» на выставке. В русском языке есть несколько различных правил для множественного числа в зависимости от того, являются ли они людьми, животными, длинными узкими предметами и т. д. В других странах разделителями тысяч являются пробелы, точки или апострофы, и в некоторых случаях они не работают с 3 цифрами: 4 в Япония, непоследовательно в Индии.

Довольствуйтесь посредственной языковой поддержкой; это просто слишком много работы.

И не путайте смену языка со сменой страны — в Швейцарии, Бельгии и Канаде тоже есть носители FR, не говоря уже о Таити, Гаити и Чаде. Австрия говорит на DE, Аруба говорит на NL, а Макао говорит на PT.

person OsamaBinLogin    schedule 01.02.2013