Содержание

I18n и L10n / Хабр

Это четырнадцатая статья в серии, где я описываю свой опыт написания веб-приложения на Python с использованием микрофреймворка Flask.

Цель данного руководства — разработать довольно функциональное приложение-микроблог, которое я за полным отсутствием оригинальности решил назвать microblog.



Темами сегодняшней статьи являются Интернационализация и Локализация, сокращенно I18n и L10n. Мы хотели бы сделать наш microblog доступным как можно большему числу людей, поэтому мы не должны забывать что много людей в мире не владеют английским языком, или, возможно, владеют, но предпочитают свой родной язык.

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

Если вы еще не установили Flask-Babel, то пришло время это сделать. Для пользователей Linux и Mac:

flask/bin/pip install flask-babel

И для пользователей Windows:
flask\Scripts\pip install flask-babel
Настройка

Flask-Babel инициализируется простым созданием экземпляра класса Babel и передачей в него нашего основного приложения Flask (файл app/__init__.py):
from flask.ext.babel import Babel babel = Babel(app)

Мы также должны решить, какие языки мы будем поддерживать в нашем приложении. Давайте начнем с поддержки испанского языка, т. к. у нас под рукой имеется переводчик с этого языка(Ваш покорный слуга), но не переживайте — в будущем будет достаточно просто добавить поддержку и других языков языков. Список поддерживаемых языков мы поместим в наш конфигурационный файл (файл config.py):
# -*- coding: utf-8 -*-
# ...
# available languages
LANGUAGES = {
    'en': 'English',
    'es': 'Español'
}

Словарь LANGUAGES содержит ключи представляющие собой коды поддерживаемых языков, а значения — названия языков. Здесь мы используем короткие версии кодов, но при необходимости также могут быть использованы полные коды, указывающие язык и регион. Например, если мы захотим поддерживать Британский и Американский вариации английского языка по отдельности, мы сможем добавить ‘en-US’ и ‘en-GB’ в наш словарь.

Обратите внимание, что т. к. слово Español содержит символ не входящий в базовый набор ascii символов, мы должны добавить строку-комментарий coding в начало файла, чтобы сообщить интерпретатору python что мы используем кодировку UTF-8, а не ascii (в которой, естественно, отсутствует символ ñ).

Следующим шагом в настройке, будет создание функции, которую будет использовать Babel для определения того, какой язык использовать (файл app/views.py):

from app import babel
from config import LANGUAGES

@babel.localeselector
def get_locale():
    return request.accept_languages.best_match(LANGUAGES.keys())

Эта функция, обёрнутая декоратором localeselector, будет вызываться перед каждым запросом, давая нам шанс выбрать язык для генерации ответа. Для начала мы применим очень простой подход, мы будем читать содержимое заголовка Accept-Languages, пришедшего от браузера вместе с http запросом и будем выбирать максимально подходящий язык из нашего списка поддерживаемых языков. На деле, это еще проще чем кажется — метод best_match сделает всю работу за нас.

Заголовок Accept-Languages в большинстве браузеров по умолчанию содержит язык, установленный основным в ОС, но все браузеры предоставляют пользователю возможность выбрать другие языки. Пользователь даже может указать список языков, с указанием приоритета (веса) каждого языка. В качестве примера рассмотрим сложный заголовок Accept-Languages:

Accept-Language: da, en-gb;q=0.8, en;q=0.7

Этот заголовок сообщает нам, что предпочитаемым языком пользователя является датский (вес = 1.0), далее идет Британский английский (вес = 0.8) и последним вариантом идет просто английский язык (без указания региона) (вес = 0.7).

И последним шагом в настройке, будет конфигурационный файл Babel, который подскажет Babel где искать тексты для перевода, содержащиеся в нашем коде и шаблонах (файл babel.cfg):

[python: **.py]
[jinja2: **/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_

Первые две строки сообщают Babel паттерны имен файлов для наших файлов с кодом на python и шаблонов соответственно. Третья строка сообщает Babel расширения, которые необходимо активировать, и благодаря которым становится возможным поиск подлежащего переводу текста в шаблонах Jinja2.
Отмечаем текст для перевода

Приступаем к самому утомительному этапу этой задачи. Мы должны пересмотреть весь наш код и шаблоны и отметить все английские предложения, подлежащие переводу так, чтобы Babel смог их найти. Для примера, взгляните на этот фрагмент кода функции after_login:
if resp.email is None or resp.email == "": flash('Invalid login. Please try again.') redirect(url_for('login'))

Здесь у нас имеется flash сообщение, которые мы хотели бы перевести. Чтобы отметить этот текст для Babel, мы просто передадим строку в функцию gettext():
from flask.ext.babel import gettext
# ...
if resp.email is None or resp.email == "":
    flash(gettext('Invalid login. Please try again.'))
    redirect(url_for('login'))

В шаблоне мы поступим похожим образом, но тут у нас есть альтернативный вариант — использовать функцию _(), которая по сути является псевдонимом для всё той же функции gettext(). Например, слово Home в ссылке из нашего базового шаблона:
  <li><a href="{{ url_for('index') }}">Home</a></li>

может быть отмечено для перевода следующим образом:
  <li><a href="{{ url_for('index') }}">{{ _('Home') }}</a></li>

К сожалению, не весь текст который мы хотели бы перевести, так прост как представленный выше. В качестве более сложного примера, рассмотрим следующий фрагмент кода из нашего шаблона post.html:
<p><a href="{{url_for('user', nickname = post.author.nickname)}}">{{post.author.nickname}}</a> said {{momentjs(post.timestamp).fromNow()}}:</p>

Здесь предложение, которое мы бы хотели перевести имеет следующую структуру: » said «. Весьма заманчиво отметить для перевод только лишь слово «said», но мы не можем быть на 100% уверены, что порядок следования имени и времени в предложении, будет одинаковым в различных языках. Правильным решением тут будет отметить всё предложение целиком для перевода, используя заполнители (placeholders) для имени и времени, так, чтобы переводчик мог изменить порядок следования при необходимости. Ситуация, кроме того, усложняется еще и тем, что компонент name является ссылкой!

Не существует простого и красивого варианта решения этой задачи. Функция gettext поддерживает зполнители (placeholders) используя синтаксис %(name) и это всё, что мы можем сделать. Вот простой пример применения заполнителей в гораздо более простой ситуации:

gettext('Hello, %(name)s', name = user.nickname)

Переводчик должен знать, что здесь имеются заполнители и их не нужно касаться. Понятно, что имя заполнителя (то, что находится между «%(« и «)s») не должно переводиться, иначе мы просто потеряем истинное значение переменной.
Но вернемся к нашему шаблону поста. Вот как мы отметим текст подлежащий переводу:
{% autoescape false %}
<p>{{ _('%(nickname)s said %(when)s:', nickname = '<a href="%s">%s</a>' % (url_for('user', nickname = post.author.nickname), post.author.nickname), when = momentjs(post.timestamp).fromNow()) }}</p>
{% endautoescape %}

Текст, который увидит переводчик для этого примера:
%(nickname)s said %(when)s:

Что вполне неплохо. Значение переменных nickname и when это то, что составляет основную сложность переводимого предложения, но они передаются как дополнительные аргументы в функцию _() и не видимы переводчику.
Заполнители nickname и when содержат в себе много чего. В частности, для nickname мы должны создать целую гиперссылку, т. к. мы хотим чтобы имя пользователя было ссылкой на его профиль.

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

Текст, который будет присвоен заполнителю when безопасен, т. к. это текст полностью сгенерированный нашей функцией momentjs(). Значение, которое попадет на место заполнителя nickname, однако, происходит из поля nickname нашей модели User, который, в свою очередь, берется из базы данных, куда попадает из веб формы, заполненной пользователем. Если кто-то зарегистрируется в нашем приложении с ником, содержащим html разметку или javascript, а затем мы отрендерим этот ник неэкранированным, то это можно считать приглашение ко взлому. Конечно же, мы хотим избежать этого, поэтому мы проведем осмотр и удалим все потенциальные риски.

Наиболее разумное решение — ограничить возможность атак, путём ограничения набора символов допустимых для использования в нике. Мы начнем с создания функции, которая бедет преобразовывать некорректные имена пользователей в корректные (файл app/models.py):

import re

class User(db.Model):
    #...
    @staticmethod
    def make_valid_nickname(nickname):
        return re.sub('[^a-zA-Z0-9_\.]', '', nickname)

Здесь мы просто удаляем из ника все символы не являющиеся буквами, цифрами, точкой или знаком подчеркивания.
Когда пользователь регистрируется на сайте, мы получаем его(её) ник от провайдера OpenID, и преобразовываем его, в случае необходимости, в корректный вид (файл app/views.py):
@oid.after_login
def after_login(resp):
    #...
    nickname = User.make_valid_nickname(nickname)
    nickname = User.make_unique_nickname(nickname)
    user = User(nickname = nickname, email = resp.email, role = ROLE_USER)
    #...

Кроме того, в форме редактирования профиля, где пользователь может изменить свой ник, мы должны расширить валидацию проверкой нового ника на наличие недопустимых символов (file app/forms.py):
class EditForm(Form):
    #...
    def validate(self):
        if not Form.validate(self):
            return False
        if self.nickname.data == self.original_nickname:
            return True
        if self.nickname.data != User.make_valid_nickname(self.nickname.data):
            self.nickname.errors.append(gettext('This nickname has invalid characters. Please use letters, numbers, dots and underscores only.'))
            return False
        user = User.query.filter_by(nickname = self.nickname.data).first()
        if user != None:
            self.nickname.errors.append(gettext('This nickname is already in use. Please choose another one.'))
            return False
        return True

При помощи таких, довольно простых, мер, мы исключили возможность атаки при рендеринге ника на странице без экранирования.
Извлечение текста подлежащего переводу

Я не буду перечислять здесь все необходимые изменения для отметки всего текста в коде и в шаблонах. Интересующиеся читатели могут изучить страницу изменений на GitHub.
Давайте представим, что мы нашли весь, требующий перевода текст, и обернули его в вызовы gettext() или _(). Что дальше?
Теперь мы запустим pybabel для извлечения всего текста в отдельный файл:
flask/bin/pybabel extract -F babel.cfg -o messages.pot app

Пользователи Windows, используйте эту команду:
flask\Scripts\pybabel extract -F babel.cfg -o messages.pot app

Команда extract утилиты pybabel читает полученный конфигурационный файл, затем сканирует весь код и файлы шаблонов в указанных при вызове команды папках(в нашем случае только app) и когда находит текст, отмеченный для перевода, копирует его в файл messages.pot.
Файл messages.pot представляет собой шаблонный файл, содержащий весь требующий перевода текст. Этот файл используется как образец для создания языковых файлов.
Генерация справочника языка

Следующим этапом является создание перевода для нового языка. Как мы и собирались, добавим поддержку испанского языка (код языка es). Вот команда, которая добавит испанский язык к поддерживаемым нашим приложением языкам:
flask/bin/pybabel init -i messages.pot -d app/translations -l es

pybabel, запущенный с параметром init принимает .pot файл к качестве входного значения и создает справочник нового языка в каталоге указанном в параметре -d для языка указанного в параметре -l. По умолчанию, Babel ожидает найти переводы в каталоге translations на одном уровне с каталогом шаблонов (templates), значит там мы их и создадим.

После запуска приведенной выше команды будет создан каталог app/translations/es. Внутри будет создан еще один каталог LC_MESSAGES, а внутри него файл messages.po. Команда может быть запущена несколько раз с разными кодами языков, для добавления поддержки этих языков.

Файл messages.po, создаваемый в каждом языковом каталоге использует формат, являющийся де-факто стандартом для языковых переводов, тот самый формат который используется утилитой gettext. Существует много приложений для работы с .po файлами. Для нужд перевода мы будем использовать poedit, т. к. это одно из наиболее популярных приложений, являющееся кроме того кросс-платформенным.

Если вы не собираетесь останавливаться, и решите совершить-таки перевод — скачайте poedit по этой ссылке. Использовать это приложение весьма просто. Ниже приведен скриншот окна программы после перевода всего текста на испанский язык:

В верхней части окна расположен текст в оригинале и на языке перевода. Внизу слева расположено окно, в которое переводчик вносит перевод.

После окончания перевода и сохранения его в файл messages.po, осталось сделать последний шаг:

flask/bin/pybabel compile -d app/translations

pybabel запущенный с параметром compile просто читает содержимое .po файла и сохраняет скомпилированную версию как .mo файл в том же каталоге. Этот файл содержит переведенный текст в оптимизированном виде, который может быть использован нашим приложением.

Перевод готов к использованию. Чтобы проверить его, вы можете указать испанский язык предпочитаемым в настройках вашего браузера, или, если не хотите заморачиваться с настройками браузера, вы можете просто всегда возвращать «es»(код испанского языка) из функции localeselector (file app/views.py):

@babel.localeselector
def get_locale():
    return "es" #request.accept_languages.best_match(LANGUAGES.keys())

Теперь, после перезапуска сервера, при каждом вызове функции gettext() или _() вместо английского текста, будет отдаваться перевод определяемый языком, который возвращает функция localeselector.
Обновление перевода

Что если мы создадим messages.po неполным, т. е. если часть текста подлежащего переводу не будет в нем представлена? Ничего страшного не произойдет, просто текст не имеющий перевода будет отображаться на английском языке…

Что произойдет, если мы пропустим некоторый текст на английском языке в нашем коде или в шаблонах? Все строки, которые не обернуты в вызов функции gettext() или _() просто будут отсутствовать в файлах перевода, а следовательно Babel не будет обращать на них внимание и они останутся на английском. Как только мы заметим пропущенный текст, мы можем обернуть его в вызов функции gettext(), а затем запустить следующие команды для обновления файлов перевода:

flask/bin/pybabel extract -F babel.cfg -o messages.pot app
flask/bin/pybabel update -i messages.pot -d app/translations

Команда extract идентична использованной нами ранее, она просто генерирует обновленный файл messages.pot с новым текстом. Вызов update принимает новый файл messages.pot и добавляет новый текст во все файлы перевода найденные в каталоге указанном в параметре -d.

Когда messages.po фвйлы во всех каталогах будут обновлены, мы можем снова запустить poedit для перевода новых текстов, а затем повторить команду pybabel compile чтобы сделать перевод новых текстов доступным нашему приложению.

Перевод moment.js

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

И тут же мы замечаем, что все метки времени остались на английском языке. Библиотека moment.js, которую мы использовали для отображения дат и времени ничего не знает о нашем желании поддерживать еще какай-то язык.

Почитав документацию к moment.js мы обнаруживаем, что существует приличный список поддерживаемых языков и что нам просто нужно скачать еще один javascript файл с требуемым языком. Таким образом, мы просто скачиваем испанскую версию с сайта moment.js и помещаем его в каталог static/js с именем moment-es.min.js. Тут мы следуем соглашению именования файлов библиотеки moment.js по шаблону moment-<код_языка>.min.js, чтобы иметь возможность выбрать требуемый файл динамически.

Чтобы иметь возможность выбора какой javascript файл загружать, мы должны передать код языка в шаблон. Наиболее простой способ — добавить код языка в глобальную переменную g, подобно тому, как добавляется информация о пользователе (file app/views.py):

@app.before_request
def before_request():
    g.user = current_user
    if g.user.is_authenticated():
        g.user.last_seen = datetime.utcnow()
        db.session.add(g.user)
        db.session.commit()
        g.search_form = SearchForm()
    g.locale = get_locale()

И теперь когда нам в шаблоне доступен код языка, мы можем загрузить требуемый moment.js в нашем базовом шаблоне (файл app/templates/base.html):
{% if g.locale != 'en' %}
<script src="/static/js/moment-{{g.locale}}.min.js"></script>
{% endif %}

Заметьте, что здесь присутствуте условие, т. к. если мы отображаем английскую версию сайта, то у нас все тексты находятся в нужном виде после загрузки первого moment.js.
Ленивые вычисления

Если мы продолжим работать с испанской версией сайта какое-то время, мы заметим еще одну проблему. Когда мы разлогиниваемся на сайте, а затем пытаемся войти снова, мы видим flash сообщение, гласящее «Please log in to access this page.» на английском языке. Откуда это сообщение? К несчастью, это не мы отображаем это сообщение, оно принадлежит и выводится сторонним расширением Flask-Login.

Flask-Login позволяет пользователю настроить это сообщение, и мы собираемся воспользоваться этой возможностью но не для изменения сообщения, а для его перевода. Итак, первая попытка (file app/__init__.py):

from flask.ext.babel import gettext
lm.login_message = gettext('Please log in to access this page.')

Но это не работает. Функция gettext должна использоваться в контексте запроса, чтобы выдать переведенное сообщение. Если мы вызываем эту функцию вне запроса, она просто отдаст нам текст по умолчанию, а это английская версия…

Для случаев вроде этого, Flask-Babel предоставляет другую функцию lazy_gettext, которая не ищет перевод немедленно как gettext() и _(), а вместо этого откладывает поиск до момента использования строки. А вот как правильно настроить это сообщение (file app/__init__.py):


from flask.ext.babel import lazy_gettext
lm.login_message = lazy_gettext('Please log in to access this page.')

И наконец, при использовании lazy_gettext мы должны проинформировать команду pybabel extract что функция lazy_gettext также применяется для оборачивания текста подлежащего переводу. Это можно сделать при помощи параметра -k:
flask/bin/pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot app

Итак после создания очередного messages.pot, мы обновляем языковые каталоги (pybabel update), переводим добавленный текст (poedit) и снова компилируем переводы (pybabel compile).

И теперь мы можем сказать, что наше приложение полностью интернационализировано!

Shortcuts

Поскольку команды pybabel довольно длинные и труднозапоминаемые, мы закончим эту статью небольшими скриптами, призванными упростить наиболее сложные задачи из увиденных нами ранее.
Скрипт для добавления языка в каталог переводов (файл tr_init.py):
#!flask/bin/python
import os
import sys
if sys.platform == 'win32':
    pybabel = 'flask\\Scripts\\pybabel'
else:
    pybabel = 'flask/bin/pybabel'
if len(sys.argv) != 2:
    print "usage: tr_init <language-code>"
    sys.exit(1)
os.system(pybabel + ' extract -F babel.cfg -k lazy_gettext -o messages.pot app')
os.system(pybabel + ' init -i messages.pot -d app/translations -l ' + sys.argv[1])
os.unlink('messages.pot')

Скрипт для обновления справочника новым текстом из исходных кодов и шаблонов (файл tr_update.py):
#!flask/bin/python
import os
import sys
if sys.platform == 'win32':
    pybabel = 'flask\\Scripts\\pybabel'
else:
    pybabel = 'flask/bin/pybabel'
os.system(pybabel + ' extract -F babel.cfg -k lazy_gettext -o messages.pot app')
os.system(pybabel + ' update -i messages.pot -d app/translations')
os.unlink('messages.pot')

Скрипт для компиляции справочника (файл tr_compile.py):
#!flask/bin/python
import os
import sys
if sys.platform == 'win32':
    pybabel = 'flask\\Scripts\\pybabel'
else:
    pybabel = 'flask/bin/pybabel'
os.system(pybabel + ' compile -d app/translations')

Эти скрипты должны превратить работу с переводом в простую задачу.
Заключение

Сегодня мы реализовали аспект нашего приложения, который часто выпадает из поля зрения разработчика. Пользователи предпочитают иметь дело с родным языком, т.ч. мы сможем обеспечить перевод на то количество языков, какое количество переводчиков мы сможем найти. Users want to work in their native language, so being able to publish our application in as many languages as we can find translators for is a huge accomplishment.

В следующей статье мы рассмотрим то, что является пожалуй наиболее сложной задачей в области I18n и L10n — автоматический перевод генерируемого пользователем контента в режиме реального времени. И мы используем это в качестве предлога для добавления некоторой Ajax магии в наше приложение.

Вот ссылка на последнюю версию microblog, включая полный перевод на испанский:

Скачать microblog-0.14.zip.

Или, если Вам так больше нравится, вы можете найти исходный код на GitHub.

Miguel

Интернационализации и Локализации – Devcolibri

В этом уроке мы поговорим о интернационализации и локализации в Spring 3.0 MVC. Мы добавим поддержку i18n с l10n для приложения Spring.

Что такое i18n и l10n?

В программировании, интернационализации и локализации являются средством адаптации компьютерных программ на различные языки и региональные различия. Интернационализация представляет собой процесс проектирования программного приложения таким образом, что оно может быть адаптировано к различным языкам и регионам без технических изменений.

Локализация это процесс адаптации разного программного обеспечение для конкретного региона или языка, добавив локали компонентов и их перевод.

В английском языке для слова «internationalization» принято сокращение «i18n». При этом число 18 означает количество пропущенных между «i» и «n» букв. Для Локализации «Localization» применяют сокращение «L10n». Заглавная буква «L» используется чтобы не путать с «i» в «i18n», число 10 — количество букв между «L» и «n».

Цель:

Наша цель заключается в добавлении интернационализации и локализации для нашего приложения Spring MVC. После завершения нашего приложения будет выглядеть.

 
Мы добавим поддержку двух языков : английский и русский. В зависимости от языковых параметров браузера пользователя, будет выбран соответствующий язык. Кроме того, пользователь сможет выбрать язык из верхнего правого угла приложения в виде флажков.
Resouces File

Создадим два propperty файла, который будет содержать все сообщения, которое будет отображаться в приложении.

Эти файлы хранятся в исходной папке под названием “resources”.

Создадим два файла lable_en.properties and lable_ru.properties в папке resources.

language = en
label.registration = Registration
label.login = Log In
language = ru
label.registration = Регистрация
label.login = Войти на сайт
Настройка интернационализации (i18n) / локализации (l10n) в Spring MVC

Мы создали resource properties для нашего приложения. Теперь мы должны объявить эти файлы в конфигурационом файле spring *-servlet.xml.

Будем использовать класс org.springframework.context.support.ReloadableResourceBundleMessageSource для определения resource properties.

Кроме того, обратите внимание, что мы будем предоставлять функцию, где пользователь сможет выбрать язык для приложения в виде влагов. Это реализуется с помощью org.springframework.web.servlet.i18n.LocaleChangeInterceptor класс.

LocaleChangeInterceptor будет перехватывать любые изменения в локали. Эти изменения будут сохранены в cookies для будущего запроса.

org.springframework.web.servlet.i18n.CookieLocaleResolver класс будет использоваться для хранения локализации изменений в cookies.

Добавить следующий код в *-servlet.xml файл.

<bean
   >
    <property name="basename" value="classpath:label" />
    <property name="defaultEncoding" value="UTF-8"/>
</bean>

<bean
   >
    <property name="paramName" value="lang" />
</bean>

<bean
   >
    <property name="defaultLocale" value="en"/>
</bean>

<bean
   >
    <property name="interceptors">
        <ref bean="localeChangeInterceptor" />
    </property>
</bean>

<mvc:interceptors>
    <bean>
        <property name="paramName" value="lang" />
    </bean>
</mvc:interceptors>

Отметим, что в вышеуказанной конфигурации мы определили базовое свойство в MessageSource classpath:messages. По этому spring будет определить, что label_  ресурс и будет использоваться в этом приложении.

Изменить вид – JSP

Теперь, когда мы создали два message resources фала и настроить его в Spring MVC, мы будем использовать эти сообщения в файлах JSP. Откройте все файлы JSP вашего приложения и добавьте в начало каждого файла следующую строку:

<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>

эта библиотека которую мы подключили выше даст нам возможность использовать теги spring.

Для переключение локали добавьте следующий код:

<span>
    <a href="?lang=en">en</a> 
    | 
    <a href="?lang=de">ru</a>
</span>

В *-servlet.xml мы указали <property name="paramName" value="lang" /> это значит что параметр передаваемый GET lang методом будет определять локаль.

И последний шаг, это вывод сообщений:

<p><spring:message code="label.registration"/></p>
<p><spring:message code="label.login"/></p>

Отметим, что в JSP выше, мы использовали <spring:message> теги для отображения сообщения от ресурсов.

Многоязычное приложение готово!

  • Как реализовать тёмную тему в Android-приложении?

i18n Википедия

Интернационализа́ция (англ. internationalization) — технологические приёмы разработки, упрощающие адаптацию продукта (такого как программное или аппаратное обеспечение) к языковым и культурным особенностям региона (регионов), отличного от того, в котором разрабатывался продукт.

Есть важное различие между интернационализацией и локализацией. Интернационализация — это адаптация продукта для потенциального использования практически в любом месте, в то время как локализация — это добавление специальных функций для использования в некотором определённом регионе. Интернационализация производится на начальных этапах разработки, в то время как локализация — для каждого целевого языка.

В английском языке для слова «internationalization» принято сокращение «i18n». При этом число 18 означает количество пропущенных между «i» и «n» букв. Для Локализации «Localization» применяют сокращение «L10n» (L7d — Localized). Заглавная буква «L» используется чтобы не путать с «i» в «L10n», число 10 — количество букв между «L» и «n».[1]

Параметры[ | ]

Параметры, важные для интернационализации и локализации, включают в себя:

Средства интернационализации[ | ]

Упрощение перевода[ | ]

Текстовые строки хранятся в отдельных файлах — языковых ресурсах. Интенсивно используется Unicode.

Поскольку строки в процессе перевода могут удлиняться и укорачиваться, в диалоговых окнах применяют такие меры:

  • Окна специально компонуют «с запасом».
    • Плюс: простота.
    • Минус: на языках с короткими фразами окно будет выглядеть неряшливо, на языках с длинными фразами — нет гарантии, что текст поместится.
  • Либо в языковые ресурсы вносят компоновку диалоговых окон.
    • Плюс: универсальное решение, позволяет точно подогнать компоновку окон по длинам строк.
    • Минус: усложняется локализация; требуется поддержка со стороны оконной библиотеки, желательно — и со стороны языка (

I18N — это… Что такое I18N?

  • I18N — Internationalisierung bedeutet in der Informatik bzw. in der Softwareentwicklung, ein Programm so zu gestalten, dass es leicht (ohne den Quellcode ändern zu müssen) an andere Sprachen und Kulturen angepasst werden kann. Internationalisierung… …   Deutsch Wikipedia

  • I18n — Internationalisierung bedeutet in der Informatik bzw. in der Softwareentwicklung, ein Programm so zu gestalten, dass es leicht (ohne den Quellcode ändern zu müssen) an andere Sprachen und Kulturen angepasst werden kann. Internationalisierung… …   Deutsch Wikipedia

  • I18N — Internationalisation de logiciel Pour les articles homonymes, voir Internationalisation (homonymie). L internationalisation d un logiciel consiste à le préparer à la régionalisation ((en) localization), c est à dire à l adaptation à des langues… …   Wikipédia en Français

  • I18n — Internationalisation de logiciel Pour les articles homonymes, voir Internationalisation (homonymie). L internationalisation d un logiciel consiste à le préparer à la régionalisation ((en) localization), c est à dire à l adaptation à des langues… …   Wikipédia en Français

  • i18n — internacionalizacija statusas T sritis informatika apibrėžtis Programinės įrangos ir jos duomenų struktūrų projektavimas taip, kad visa tai būtų galima lengvai adaptuoti įvairioms kalboms ir kultūroms. Programos komponentai, kurie būdingi kuriai… …   Enciklopedinis kompiuterijos žodynas

  • I18n — …   Википедия

  • i18n — noun internationalisation …   Wiktionary

  • I18N — Internationalization …   Acronyms

  • I18N — ● ►en sg. f. ►PROG Contraction de Internationalisation , c est à dire, un I , puis 18 lettres, puis un N . Voir internationalisation. Souvent écrit en minuscules pour distinguer le I d un 1 …   Dictionnaire d’informatique francophone

  • I18N — Internationalization …   Acronyms von A bis Z

  • I18n — это… Что такое I18n?

  • I18N — Internationalisierung bedeutet in der Informatik bzw. in der Softwareentwicklung, ein Programm so zu gestalten, dass es leicht (ohne den Quellcode ändern zu müssen) an andere Sprachen und Kulturen angepasst werden kann. Internationalisierung… …   Deutsch Wikipedia

  • I18n — Internationalisierung bedeutet in der Informatik bzw. in der Softwareentwicklung, ein Programm so zu gestalten, dass es leicht (ohne den Quellcode ändern zu müssen) an andere Sprachen und Kulturen angepasst werden kann. Internationalisierung… …   Deutsch Wikipedia

  • I18N — Internationalisation de logiciel Pour les articles homonymes, voir Internationalisation (homonymie). L internationalisation d un logiciel consiste à le préparer à la régionalisation ((en) localization), c est à dire à l adaptation à des langues… …   Wikipédia en Français

  • I18n — Internationalisation de logiciel Pour les articles homonymes, voir Internationalisation (homonymie). L internationalisation d un logiciel consiste à le préparer à la régionalisation ((en) localization), c est à dire à l adaptation à des langues… …   Wikipédia en Français

  • i18n — internacionalizacija statusas T sritis informatika apibrėžtis Programinės įrangos ir jos duomenų struktūrų projektavimas taip, kad visa tai būtų galima lengvai adaptuoti įvairioms kalboms ir kultūroms. Programos komponentai, kurie būdingi kuriai… …   Enciklopedinis kompiuterijos žodynas

  • I18N — …   Википедия

  • i18n — noun internationalisation …   Wiktionary

  • I18N — Internationalization …   Acronyms

  • I18N — ● ►en sg. f. ►PROG Contraction de Internationalisation , c est à dire, un I , puis 18 lettres, puis un N . Voir internationalisation. Souvent écrit en minuscules pour distinguer le I d un 1 …   Dictionnaire d’informatique francophone

  • I18N — Internationalization …   Acronyms von A bis Z

  • I18N — это… Что такое I18N?

  • I18N — Internationalisierung bedeutet in der Informatik bzw. in der Softwareentwicklung, ein Programm so zu gestalten, dass es leicht (ohne den Quellcode ändern zu müssen) an andere Sprachen und Kulturen angepasst werden kann. Internationalisierung… …   Deutsch Wikipedia

  • I18n — Internationalisierung bedeutet in der Informatik bzw. in der Softwareentwicklung, ein Programm so zu gestalten, dass es leicht (ohne den Quellcode ändern zu müssen) an andere Sprachen und Kulturen angepasst werden kann. Internationalisierung… …   Deutsch Wikipedia

  • I18N — Internationalisation de logiciel Pour les articles homonymes, voir Internationalisation (homonymie). L internationalisation d un logiciel consiste à le préparer à la régionalisation ((en) localization), c est à dire à l adaptation à des langues… …   Wikipédia en Français

  • I18n — Internationalisation de logiciel Pour les articles homonymes, voir Internationalisation (homonymie). L internationalisation d un logiciel consiste à le préparer à la régionalisation ((en) localization), c est à dire à l adaptation à des langues… …   Wikipédia en Français

  • i18n — internacionalizacija statusas T sritis informatika apibrėžtis Programinės įrangos ir jos duomenų struktūrų projektavimas taip, kad visa tai būtų galima lengvai adaptuoti įvairioms kalboms ir kultūroms. Programos komponentai, kurie būdingi kuriai… …   Enciklopedinis kompiuterijos žodynas

  • I18N — …   Википедия

  • I18n — …   Википедия

  • i18n — noun internationalisation …   Wiktionary

  • I18N — Internationalization …   Acronyms

  • I18N — ● ►en sg. f. ►PROG Contraction de Internationalisation , c est à dire, un I , puis 18 lettres, puis un N . Voir internationalisation. Souvent écrit en minuscules pour distinguer le I d un 1 …   Dictionnaire d’informatique francophone

  • I18N — Internationalization …   Acronyms von A bis Z

  • i18n — translation — English-Russian Dictionary

    en I fail to see why Bdale cannot support flavours, i18n and communication within the community without having «DPL» stamped on his forehead.

    Common crawlru Если только вас не привлекает титул пэра?

    en For the history of document changes, search for qa-doc-charset in the i18n blog.

    Common crawlru Её тоже увезли

    en Be aware that this process is only a part of internationalization (which is abbreviated into i18n because there is 18 letters between the «i» and the «n») and localization (or l10n).

    Common crawlru Вы настоящие молодцы

    en If the i18n allows you to change the way the date is printed, you may express the way to do that in your part of the world.

    Common crawlru Он хочет подбородок, как у Вигго Мортенсена

    en For the history of document changes, search for qa-forms-utf-8 in the i18n blog.

    Common crawlru Пэрис, мне не нужны офисы

    en Internationalization is often written «i18n», where 18 is the number of letters between ‘i’ and ‘n’ in the English word.

    Common crawlru Это настолько тонкое мастерство, что его бы стоило внести в учебники шиноби

    en Note that these requirements are preconditions for all other parts of i18n and l10n for these languages, though this is a very difficult part of i18n.

    Common crawlru Ты думаешь у него есть способности?

    en The process of developing software for use in multiple languages, cultures and countries can be viewed as two separate processes, those of internationalisation (I18N) and localisation (L10N).

    UN-2ru Это твой отец, выкрашенный в зелёный

    en Please note that character encoding support, including multibyte, doublewidth, combining, bi-direction, and so on, is a prerequisite for all other part of i18n and l10n, including translation, for some (mainly non-European) languages.

    Common crawlru Что, без оружия?

    en For the history of document changes, search for article-O-charset in the i18n blog.

    Common crawlru Я столько раз прокалывалась в отношениях

    en There’s hope for some of them to eventually help with Gentoo development, especially in i18n and CJK.

    Common crawlru Такая красивая ваза.Выпей что- нибудь. Успокойся, дорогая

    en For the history of document changes, search for qa-mono-multilingual in the i18n blog.

    Common crawlru Я не собираюсь

    en If the i18n allows you to change the character encoding, l10n is the act of setting the character encoding you need for a given language.

    Common crawlru Он хотел меня научить

    en The location of these files on mirrors is dists/main/sid/i18n/ .

    Common crawlru Ты что- то сказала

    en l10n and i18n are tied, but the difficulties related to each of them are very different.

    Common crawlru посмотрел в низ и увидел # струйки крови

    en For the history of document changes, search for qa-i18n in the i18n blog.

    Common crawlru Ваши зубы будут выбиты из черепа как предупреждение остальным бесам

    en For the history of document changes, search for qa-select-sorting in the i18n blog.

    Common crawlru Оно здесь, верно?- Здесь что- то есть

    en For example, if your i18n only allows you to change the text of a message, l10n merely means translating this text.

    Common crawlru Ромуланцы, как правило, предпочитают бездействовать и, если есть возможность, руководить из- за кулис

    en You can help translating applications or Debian-related information (web pages, documentation) to your own language by getting involved in a translation project (discussion is generally handled through the i18n mailing list ).

    Common crawlru О, спасибо за все, пока

    en i18n sets up the globalization framework, and l10n adds a specific «flesh» for each language and country into this framework.

    Common crawlru С тобой всё в порядке?

    en I18n support for package descriptions: Update package management frontends to use the translated descriptions of packages.

    Common crawlru Ты уж меня прости

    en That’s why the tasks to do for l10n depend on the achieved i18n.

    Common crawlru У вас сейчас есть дело поважнее

    интернационализация — что означает безопасность I18N?

    Переполнение стека
    1. Около
    2. Товары
    3. Для команд
    1. Переполнение стека Общественные вопросы и ответы
    2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
    3. работы Программирование и связанные с ним технические возможности карьерного роста
    4. Талант Нанимайте технических специалистов и создавайте свой бренд работодателя
    5. реклама Обратитесь к разработчикам и технологам со всего мира
    6. О компании

    Загрузка…

    .

    Что такое i18n, что такое l10n

    Drakconf multiflag.png

    Термины i18n и l10n часто путают и неправильно используют. Они связаны, но не имеют одинакового значения; они относятся к разным уровням реализации и опыта, поэтому правильное понимание важно, чтобы увидеть, в чем именно заключается проблема или потребность в разработке.

    Что означают эти сокращения

    Что же на самом деле означают эти странные сокращения? Фактически, это аббревиатуры, состоящие из первой и последней буквы слова, а между ними — количество букв.

    • i18n = I nternationalizatio n : i , затем 18 букв, затем n
    • l10n = L ocalizatio n : l , затем 10 букв, затем n

    Разве это не то же самое?

    Итак, вы можете спросить, разве интернационализация и локализация не одно и то же? Вообще-то, нет.

    Много путаницы; отчасти потому, что концепции относительно новые; отчасти также по историческим причинам.Исторически сложилось так, что поддержка компьютеров помимо английского языка осуществлялась, по крайней мере вначале, в виде нескольких специальных решений, которые соответствовали только одному языку. Итак, эта ОС была локализована, скажем, на французский язык, а другая версия — на испанский; и они вполне могут быть несовместимы, даже если оба языка могут иметь общий набор символов (и довольно простой).

    Иначе говоря, исторически l10n делали раньше, чем думали о i18n.

    Но концептуально i18n должен быть первым; поскольку интернационализация — это процесс обеспечения того, чтобы часть программного обеспечения была действительно достаточно гибкой и готовой в первую очередь поддерживать несколько потенциальных локалей.В процессе i18n не задействован реальный язык; приложение вполне может никогда не быть переведено, но если оно правильно интернационализировано, то перевод будет довольно простым (и, что более важно, не требует каких-либо навыков или навыков работы с компьютером, только знание целевого языка). Таким образом, интернационализация делает программное обеспечение совместимым с локальным стандартом .

    С другой стороны, локализация — это (в основном, см. Ниже) перевод на заданный, реальный язык. Локализация, как таковая, не требует выполнения интернационализации , однако, если приложение не было сначала интернационализировано, то это означает, что процесс локализации потребует довольно низкоуровневых модификаций в исходном коде приложения; то есть навыки развития.В старые времена (старые добрые времена, о которых большинство из вас не знает; вам повезло) локализация иногда выполнялась путем «простого» редактирования исходного кода и изменения текстовых строк в исходном коде. Это приводит к двум (или более) различным двоичным файлам ; то есть два (или более) разных продукта для поддержки, с разными версиями, отслеживанием ошибок и т. д. Иногда даже несовместимы друг с другом. И, если вы хотели перенести приложение на другой язык, это нужно было делать заново (и решать, от какой версии отклоняться).Кроме того, никогда не было должного обобщающего обзора проблемы; если была запрошена локализация на новый язык с некоторыми конкретными потребностями, это могло сломать все, потому что это не было запланировано.

    Итак, l10n без i18n — это плохо, очень плохо. Надеюсь, в наши дни, особенно в мире свободного программного обеспечения, это редкость. В нашем мире свободного программного обеспечения у нас есть очень хорошие рамки интернационализации, встроенные в ядро ​​общих наборов инструментов (набор инструментов — это набор инструментов и кирпичиков, из которых разработчики создают приложения).Эти структуры достаточно универсальны, чтобы поддерживать и охватывать все используемые в настоящее время системы письма человека.

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

    И18Н

    Интернационализация — это процесс (или концепция процесса), при котором приложение становится «международным»; то есть сделать его способным поддерживать практически любой язык или местную среду на Земле.

    Это всегда включает в себя изменения в исходном коде , то есть включает разработчиков (которые также должны быть осведомлены о проблемах i18n). I18n имеет различные аспекты, некоторые из которых более сложные, чем другие:

    • возможность отображения / печати текста
      • поддержка любого сложного шрифта
      • поддержка нормализации символов
      • поддерживает замену и рендеринг глифов (нет эквивалентности между символом и глифом; вместо этого некоторые последовательности символов (могут быть последовательностью только одного в простом случае) создают некоторые последовательности глифов (может быть последовательностью одного в простом случае чехол)
      • поддержка переупорядочения глифов (отображение не всегда в том же порядке, что и логически произнесенные / записанные)
      • поддержка двунаправленного рендеринга (слева направо и справа налево)
    • способность манипулировать текстом
      • Поддержка манипуляций с текстовыми строками в программах
      • Поддержка
      • для выделения мышью, вырезания и вставки и т. Д. (Обратите внимание, что вы выбираете глифов на экране, но буфер выбирает текст (символы) => задействована сложная подстановка)
      • Утилиты преобразования набора символов
      • (потому что мы должны справиться с наследием до юникода)
      • поиск текста (grep и т. Д.)
      • сортировка текста в зависимости от правил комплекса
    • возможность ввода текста
      • поддержка определения раскладок клавиатуры
      • поддержка подключения к приложениям ввода для сложных случаев, когда раскладки клавиатуры недостаточно)
    • возможность манипулировать / отображать дату / время
      • Формат отображения / ввода
      • определение первого дня недели
      • определение часовых поясов
      • определение негрегорианских календарей
      • функций для преобразования между различными форматами / календарями
    • возможность определять и обрабатывать локальные настройки
      • различных единиц (км / миль ° C / ° F и т. Д.), денежные и др.
      • различных способов форматирования / отображения чисел

    L10N

    Локализация — это процесс (или концепция процесса), позволяющий сделать приложение «локализованным»; то есть работать для данного локального и конкретного контекста, адаптированного к пользователю.

    Не требует изменения исходного кода; разработчики не участвуют (ну, совсем немного, просто чтобы добавить первую ловушку; когда язык доступен, разработчик должен поместить его в список, предоставить доступ команде l10n и т. д.).

    L10n предоставляет содержимое для заполнения контейнеров, созданных процессом i18n.

    Различные аспекты:

    • перевод переводимых текстовых данных (самый известный)
    • предоставляет уникальные локализованные текстовые данные (не перевод существующего, а независимый), если необходимо
    • средства проверки правописания (см. Ниже)
    • раскладки клавиатуры
    • методы ввода (см. Ниже)
    • правила сортировки

    Как я уже сказал, в них не участвуют разработчики.Ну, в некоторых случаях может быть связано с некоторыми разработками; это для некоторых очень специфических вещей, таких как создание новой проверки орфографии, уникальной для языка или семейства языков, или программы метода ввода (но также существуют универсальные средства проверки орфографии и методы ввода, где вам нужно только предоставить l10n данные).

    Вкратце

    • l10n: l10n проблемы касаются только переводчиков данного языка; никто другой не заботится и ничего не может с этим поделать; только переводчики для этого конкретного языка могут исправить это.
    • i18n: проблемы с i18n — это проблема инфраструктуры i18n; это потенциально может повлиять на многие языки (даже если, возможно, только один действительно обнаружит симптомы), но переводчики не могут ничего сделать для ее решения, только разработчики могут.
    .

    unknwon / i18n: Пакет i18n предназначен для интернационализации и локализации приложений.

    перейти к содержанию Зарегистрироваться
    • Почему именно GitHub? Особенности →
      • Обзор кода
      • Управление проектами
      • Интеграции
      • Действия
      • Пакеты
      • Безопасность
      • Управление командой
      • Хостинг
      • мобильный
      • Истории клиентов →
      • Безопасность →
    • команда
    • предприятие
    • Проводить исследования
      • Изучите GitHub →
      Учитесь и вносите свой вклад
      • Темы
      • Коллекции
      • В тренде
      • Учебная лаборатория
      • Руководства с открытым исходным кодом
      Общайтесь с другими
      • События
      • Форум сообщества
      • GitHub Education
    .

    Что такое i18n в Django?

    Переполнение стека
    1. Около
    2. Товары
    3. Для команд
    1. Переполнение стека Общественные вопросы и ответы
    2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
    3. работы Программирование и связанные с ним технические возможности карьерного роста
    4. Талант Нанимайте технических специалистов и создавайте свой бренд работодателя
    5. реклама Обратитесь к разработчикам и технологам со всего мира
    6. О компании
    .