Лучшая практика javascript и многоязычие
какова лучшая практика для многоязычного веб-сайта с использованием DOM манипулирования с javascript? Я создаю некоторые динамические части веб-сайта с помощью javascript. Моя первая мысль была использовать массив с текстовыми строками и кодом языка в качестве индекса. Это хорошая идея?
7 ответов:
когда я раньше создавал многоязычные сайты (не очень большие, поэтому это может быть не слишком хорошо масштабировано), я сохраняю ряд "языковых" файлов:
- Лэнг.эн.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');
есть несколько вещей, которые вы должны иметь в виду при проектировании мультиязычность:
1 - отделить код от данных (т. е. не жестко кодировать строки в ваши функции)
2-создать функцию форматирования крюк, чтобы иметь дело с различиями локализации. Разрешение форматируемых строк ("{0}") лучше, чем конкатенация ( "Добро пожаловать" + value), по многим причинам:
- в некоторых языках, число отформатирован как 1.234.678, 00 вместо 1,234,567. 00
- плюрализация часто не так проста, как добавление "s" в конце единственного числа
- правила грамматики различны и могут влиять на порядок вещей, поэтому вы должны разрешить добавление динамических данных после крючка перевода: например,"Добро пожаловать в {0}" превращается в "{0} он youkoso" на японском языке (это происходит почти на каждом языке, заметьте).
3 - Убедитесь, что вы действительно можете форматировать строки после перевод крюк работает, так что вы можете использовать ключи.
4 - ни при каких обстоятельствах не подключайте выходы базы данных к утилите translator. Если у вас есть многоязычные данные, создайте отдельные таблицы / строки в своей базе данных. Я видел, как люди довольно часто ошибаются в этом без проблем (обычно для стран и Штатов/провинций в формах).
5-Создание явных правил кодирования для создание ключей. Функция утилиты форматирования (которая будет выглядеть примерно как перевести("Привет мир") примет ключ как параметр, и ключи с небольшими изменениями делают обслуживание очень надоедливым. Например, вы можете получить три ключа в следующем примере: "введите свое имя", "введите свое имя:", "введите свое имя: ". Выберите один формат (например, без двоеточия, обрезанный) и поймайте несоответствия в обзорах кода. Не выполняйте эту фильтрацию программно, так как она может вызвать false позитивы.
6 - имейте в виду, что разметка HTML потенциально может потребоваться в таблице перевода (например, если вам нужно выделить слово жирным шрифтом в предложении или иметь медицинские ссылки на сноски). Тест для этого обширно.
7-Существует несколько способов импорта языковых строк. В идеале, вы должны иметь несколько версий языка.ленг.js-файл, переключение между ними с помощью кода на стороне сервера и ссылка на файл из нижней части HTML-файла. Вытягивание файла через AJAX это также альтернатива, но может привести к задержкам. Слияние языков.js в ваш основной файл кода не рекомендуется, так как вы теряете преимущества кэширования файлов.
8 - тест с вашими целевыми языками. это звучит глупо, но я видел серьезную ошибку один раз, потому что программист не потрудился проверить наличие "é" в ключе.
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Если вы вызываете класс с языком, который вы не определили, английский( en) будет выбран.
только что нашел хорошую статью о i18n в javascript:
http://24ways.org/2007/javascript-internationalisationхотя простой поиск google с i18n + javascript показывает множество альтернатив.
В конце концов, это зависит от того, как глубокий вы хотите, чтобы это было. Для нескольких языков достаточно одного файла.
вы могли бы использовать фреймворк, как Jquery, используйте промежуток для идентификации текста (с a класс), а затем использовать идентификатор каждого диапазона, чтобы найти соответствующий текст на выбранном языке.
1 строка Jquery, готово.
прочитав отличные ответы никфа и Лео,я создал следующий язык CommonJS style.js для управления всеми моими строками (и необязательно,ус форматировать их):
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'});
вы должны посмотреть, что было сделано в классических компонентах JS - возьмите такие вещи, как Dojo, Ext, FCKEditor, TinyMCE и т. д. Вы найдете много хороших идей.
обычно это заканчивается тем, что вы устанавливаете какие-то атрибуты на тегах, а затем заменяете содержимое тега переводом, найденным в вашем файле перевода, на основе значения атрибута.
одна вещь, чтобы иметь в виду, это эволюция набора языков (когда ваш код развивается, вам понадобится чтобы перевести все это или нет). Мы сохраняем переводы в PO-файлах (Gnu Gettext), и у нас есть скрипт, который преобразует Po-файл в готовые к использованию JS-файлы.
кроме того:
- всегда используйте UTF-8-это звучит глупо, но если вы не находитесь в utf-8 с самого начала (HTML head + JS encoding), вы быстро лопнете.
- используйте английскую строку в качестве ключа к вашим переводам - таким образом, вы не будете в конечном итоге с такими вещами, как: lang.Приветствие = 'Привет мир' - но Лэнг ['Hello world'] = 'Hello world';
для Spring bundles и 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
Comments