Лучшая практика javascript и многоязычность

Какова наилучшая практика для многоязычного сайта с использованием DOM Manipulating с javascript? Я создаю некоторые динамические части веб-сайта, используя javascript. Моя первая мысль заключалась в использовании массива с текстовыми строками и кода языка в качестве индекса. Это хорошая идея?

Ответ 1

Когда я создавал многоязычные сайты раньше (не очень большие, поэтому это может не слишком хорошо масштабироваться), я сохраняю ряд "языковых" файлов:

  • lang.en.js
  • lang.it.js
  • lang.fr.js

Каждый из файлов объявляет объект, который в основном представляет собой карту от ключевого слова до фразы языка:

// lang.en.js
lang = {
    greeting : "Hello"
};

// lang.fr.js
lang = {
    greeting : "Bonjour"
};

Динамически загружайте один из этих файлов, а затем все, что вам нужно сделать, это ссылка на ключ с вашей карты:

document.onload = function() {
    alert(lang.greeting);
};

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

var l = new Language('en');
l.get('greeting');

Ответ 2

Есть несколько вещей, которые вам нужно иметь в виду при разработке многоязычной поддержки:

1 - Отделите код от данных (т.е. не вставляйте строки строго в ваши функции)

2 - создайте функцию привязки форматирования для устранения различий в локализации. Разрешить форматируемые строки ("{0}" ) лучше, чем конкатенация ( "Добро пожаловать в" + значение) по многим причинам:

  • на некоторых языках число отформатировано как 1.234.678,00 вместо 1,234,567.00.
  • плюрализация часто бывает не такой простой, как добавление "s" в конце единственного числа
  • правила грамматики различны и могут влиять на порядок вещей, поэтому вы должны разрешить добавление динамических данных после крючка перевода: например, "Добро пожаловать в {0}" превращается в "{0} он youkoso" на японском языке (это происходит практически в каждом языке, заметьте).

3 - Убедитесь, что вы действительно можете форматировать строки после, когда выполняется перехват перевода, поэтому вы можете повторно использовать клавиши.

4 - Не подпадайте под любое подключение к выходу базы данных транслятора утилите переводчика. Если у вас есть многоязычные данные, создайте отдельные таблицы/строки в своей базе данных. Я видел, как люди часто ошибаются неправильно (обычно для стран и штатов/провинций в формах).

5 - Создайте правила правил кодирования для создания ключей. Функция утилиты formatter (которая будет выглядеть примерно как translate ( "hello world" ), возьмет ключ в качестве параметра, а клавиши с небольшими изменениями очень удобны для обслуживания. Например, вы можете три ключа в следующем примере: "введите имя", "введите свое имя:", "введите свое имя:". Выберите один формат (например, без двоеточия, обрезать) и уловить несоответствия в просмотрах кода. программно, поскольку он может вызывать ложные срабатывания.

6 - Помните, что разметка HTML может потенциально понадобиться в таблице переводов (например, если вам нужно выделить слово в предложении или иметь ссылки на медицинские сноски). Протестируйте это для этого.

7 - Существует несколько способов импорта языковых строк. В идеале вы должны иметь несколько версий файла language.lang.js, переключаться между ними с кодом на стороне сервера и ссылаться на файл из нижней части HTML файла. Вытягивание файла через AJAX также является альтернативой, но может привести к задержкам. Слияние языка .js в ваш основной файл кода не рекомендуется, так как вы теряете преимущества кэширования файлов.

8 - Проверьте свои целевые языки. Это звучит глупо, но я видел серьезную ошибку однажды, потому что программист не потрудился проверить наличие "é" в ключе.

Ответ 3

function Language(lang)
{
    var __construct = function() {
        if (eval('typeof ' + lang) == 'undefined')
        {
            lang = "en";
        }
        return;
    }()

    this.getStr = function(str, defaultStr) {
        var retStr = eval('eval(lang).' + str);
        if (typeof retStr != 'undefined')
        {
            return retStr;
        } else {
            if (typeof defaultStr != 'undefined')
            {
                return defaultStr;
            } else {
                return eval('en.' + str);
            }
        }
    }
}

После добавления этого на свою страницу вы можете работать с ним следующим образом:

var en = {
    SelPlace:"Select this place?",
    Save:"Saved."
};

var tr = {
    SelPlace:"Burayı seçmek istiyor musunuz?"
};

var translator = new Language("en");
alert(translator.getStr("SelPlace")); // result: Select this place?
alert(translator.getStr("Save")); // result: Saved.
alert(translator.getStr("DFKASFASDFJK", "Default string for non-existent string")); // result: Default string for non-existent string

var translator = new Language("tr");
alert(translator.getStr("SelPlace")); // result: Burayı seçmek istiyor musunuz?
alert(translator.getStr("Save")); // result: Saved. (because it doesn't exist in this language, borrowed from english as default)
alert(translator.getStr("DFKASFASDFJK", "Default string for non-existent string")); // result: Default string for non-existent string

Если вы вызываете класс с указанным вами языком, будет выбран английский (ru).

Ответ 4

Просто нашел хорошую статью о i18n в javascript:
http://24ways.org/2007/javascript-internationalisation

Хотя простой поиск в google с i18n + javascript показывает множество альтернатив.

В конце концов, это зависит от того, насколько глубоко вы хотите. Для нескольких языков достаточно одного файла.

Вы можете использовать фреймворк, например Jquery, использовать диапазон для идентификации текста (с классом), а затем использовать идентификатор каждого пролета, чтобы найти соответствующий текст на выбранном языке.
1 строка JQuery, сделанная.

Ответ 5

После прочтения замечательных ответов nickf и Leo, я создал следующий язык language.js в стиле CommonJS для управления всеми моими строками (и, необязательно, Mustache для их форматирования):

var Mustache = require('mustache');

var LANGUAGE = {
    general: {
        welcome: "Welcome {{name}}!"
    }
};

function _get_string(key) {
    var parts = key.split('.');
    var result = LANGUAGE, i;
    for (i = 0; i < parts.length; ++i) {
        result = result[parts[i]];
    }
    return result;
}

module.exports = function(key, params) {
    var str = _get_string(key);
    if (!params || _.isEmpty(params)) {
        return str;
    }
    return Mustache.render(str, params);
};

И вот как я получаю строку:

var L = require('language');
var the_string = L('general.welcome', {name='Joe'});

Ответ 6

Вы должны посмотреть на то, что было сделано в классических компонентах JS - взять такие вещи, как Dojo, Ext, FCKEditor, TinyMCE и т.д. Вы найдете много хороших идей.

Обычно это заканчивается тем, что вы устанавливаете теги, и затем вы заменяете содержимое тега на перевод, найденный в вашем файле перевода, на основе значения атрибута.

Одна вещь, о которой нужно помнить, - это эволюция набора языков (когда ваш код развивается, вам нужно будет ретранслировать все это или нет). Мы сохраняем переводы в файлах PO (Gnu Gettext), и у нас есть script, который преобразует PO файл в готовый к использованию JS файл.

Кроме того:

  • Всегда используйте UTF-8 - это звучит глупо, но если вы не в utf-8 от начала (HTML-заголовок + JS-кодировка), вы быстро разойдетесь.
  • Используйте английскую строку как ключ к вашим переводам - ​​таким образом вы не получите таких вещей, как: lang.Greeting = 'Hello world' - но lang ['Hello world'] = 'Hello world';

Ответ 7

Для пакетов Spring и JavaScript есть простое решение: сгенерируйте массив i18n в шаблоне (например, JSP) и используйте его в JavaScript:

JSP:

<html>
<script type="text/javascript">
    var i18n = [];
    <c:forEach var='key' items='<%=new String[]{"common.deleted","common.saved","common.enabled","common.disabled","...}%>'>
        i18n['${key}'] = '<spring:message code="${key}"/>';
    </c:forEach>
</script>
</html>

И в JS:

alert(i18n["common.deleted"]);

См. также Разрешение spring: сообщения в javascript для интернационализации i18n