Какова наилучшая практика для многоязычного сайта с использованием DOM Manipulating с javascript? Я создаю некоторые динамические части веб-сайта, используя 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