Функционал готов к использованию во всём мире, когда он работает на любом языке и соответствует нормам каждого читателя без изменений в коде. Эта страница следует рекомендациям Microsoft. Контрольный список интернационализации: в каждом разделе описаны различия между рынками, правила написания корректного кода и Проверка Глобализации код, который отмечает неверный подход.
В основном всё сводится к одному правилу: пусть локаль читателя определяет параметры. Браузерная
Intl API, средства форматирования вашего фреймворка и используемые данные
Культура учитывает нормы каждого рынка; код с жёстко заданными параметрами для одного рынка такого не делает.
Текст и предложения
Любой текст, который видит пользователь, должен быть добавлен в каталог источников под соответствующим ключом и отображаться через функцию перевода проекта. Сюда относятся метки, заголовки, кнопки, сообщения, ошибки, плейсхолдеры alt текст и метки ARIA. Коды: hardcoded_text.
Одно предложение — это одно сообщение. Порядок слов различается в разных языках, поэтому предложение, собранное из частей, перевести нельзя. Передавайте значения через плейсхолдеры, а счётчики — через формы множественного числа. Коды: concatenated_text.
// Not world-ready: English word order and English plurals
'You have ' + count + ' new ' + (count === 1 ? 'message' : 'messages');
// World-ready: one ICU message
t('inbox.new', { count });
// "inbox.new": "{count, plural, one {You have # new message} other {You have # new messages}}"Для разных языков нужны разные формы множественного числа: в английском их два, в арабском — шесть, в японском — одна. Записывайте исходное сообщение с использованием ICU-плагинов, а движок сам добавит нужные формы для каждого языка.
Числа
На разных рынках одно и то же число записывается по-разному: в США — 1,234.5, в Германии — 1.234,5, в Швеции и Франции — 1 234,5, а в некоторых арабских странах — иначе. Форматируйте числа с учётом локали читателя. Коды: locale_number.
new Intl.NumberFormat(locale).format(1234.5);
new Intl.NumberFormat(locale, { style: 'percent' }).format(0.25);Считывайте число, введённое пользователем, с учётом той же локали, или используйте поле ввода чисел, значение которого нормализует браузер. parseFloat('1,5') равно 1, а не «одна с половиной». Коды: locale_parsing.
Даты, время и часовые пояса
Порядок дат, разделители, названия месяцев, 12- или 24-часовой формат и календарь — всё это различается. Форматируйте данные с учётом локали читателя и никогда не используйте фиксированный шаблон вроде MM/dd/yyyy. Коды: locale_date.
new Intl.DateTimeFormat(locale, { dateStyle: 'medium', timeStyle: 'short', timeZone }).format(when);- Храните моменты времени в формате UTC, в виде строки ISO 8601 с указанием смещения, и форматируйте их в часовом поясе читателя. Рассчитывайте «сегодня» и границы дней именно в этом часовом поясе, а не в часовом поясе сервера.
- Неделя начинается в разные дни: в США — в воскресенье, в большинстве стран Европы — в понедельник, в некоторых странах Ближнего Востока — в субботу. Выходные тоже различаются. Учитывайте эти параметры из локали (
new Intl.Locale(locale).getWeekInfo()при наличии или из данных локали вашей библиотеки для работы с датами), а не используйте постоянные значения. Коды:calendar_names. - Названия дней недели и месяцев берутся из локали
Intl.DateTimeFormat(locale, { weekday: 'long' })), а не из списка в коде. Коды:calendar_names. - Календари. В Саудовской Аравии, Израиле и Японии григорианский календарь используется наряду с календарями Умм аль-Кура, еврейским и японским; в Таиланде и Иране по умолчанию применяются буддийский и персидский календари. Культура указывает, какой календарь используется на конкретном рынке.
Валюта
Форматируйте суммы с учётом валюты и локали читателя, никогда не ставьте символ рядом с числом. Одна и та же сумма будет выглядеть $1,234.50, 1.234,50 $ или US$1,234.50
в зависимости от читателя, причём во многих странах используется один и тот же символ. Коды:
hardcoded_currency.
new Intl.NumberFormat(locale, { style: 'currency', currency }).format(1234.5);Выбор валюты — это коммерческое решение, а не вопрос форматирования: изменение локали читателя не должно приводить к пересчёту цен. Культура указывает валюту, принятую на каждом рынке.
Сортировка, сравнение и регистр
Каждый язык имеет свои правила сортировки: в шведском языке буквы å, ä и ö идут после z, в немецком ä сортируется как a, а в китайском — по пиньиню или количеству черт. Сортируйте текст для пользователей с учётом локали читателя. Коды: ordinal_sort.
names.sort(new Intl.Collator(locale).compare);Сопоставление регистра также зависит от языка: в турецком языке заглавная буква i — это İ. Используйте toLocaleUpperCase(locale) для текста, который видит пользователь. Коды: case_mapping.
Списки
«Анна, Бен и Чен» пишется по-разному в разных языках. Объединяйте элементы списка с учётом локали. Коды: joined_list.
new Intl.ListFormat(locale, { style: 'long', type: 'conjunction' }).format(names);Имена, адреса, почтовые индексы и номера телефонов
- Имена. Во многих странах фамилия стоит первой, а у многих людей одно имя или более двух. Вводите имя человека в одно поле, если для конкретного рынка не требуется разделять его части. Принимайте любые алфавиты: Åsa, José, 王 и Мария — все это имена. Коды:
latin_only_input. - Адреса. Поля, их порядок и названия различаются: в США это штат и почтовый индекс, в Японии — префектура, в некоторых странах почтового индекса вообще нет. Культура показывает, как оформляется адрес в каждой стране. Не требуйте заполнения полей, которые не используются на конкретном рынке.
- Почтовые индексы. Оставляйте их как текст и проверяйте по правилам конкретной страны или вообще не проверяйте. Шаблон из пяти цифр не подойдёт для большинства стран мира. Коды:
postal_code_format. - Номера телефонов. Храните их в формате E.164 (
+46 8 123 456 78), форматируйте и проверяйте с помощью библиотеки, знающей планы нумерации каждой страны, например libphonenumber. Шаблон вроде(555) 555-1234Отклоняет любые числа, не относящиеся к Северной Америке. Коды:phone_number_format.
Единицы измерения и бумага
В большинстве стран используются километры, килограммы и градусы Цельсия; в США — мили, фунты и градусы Фаренгейта; в Великобритании применяются оба варианта. Берите единицу измерения из региона читателя и форматируйте её с учётом локали. Коды: fixed_unit.
new Intl.NumberFormat(locale, { style: 'unit', unit: 'kilometer' }).format(12);Печатный и PDF-формат вывода соответствует стандартам бумаги на рынке: в Северной Америке — формат Letter, почти повсюду — формат A4. Коды: paper_size.
Методы ввода и шрифты
Для ввода текста на китайском, японском и корейском языках используется редактор методов ввода: для выбора слова нажимают Enter, а не для отправки данных. Обработчик, отправляющий данные по нажатию Enter, должен игнорировать этот сигнал во время формирования слова. Коды: ime_composition.
onKeyDown={event => {
if (event.key === 'Enter' && !event.nativeEvent.isComposing) submit();
}}Выбирайте шрифты, охватывающие все используемые скрипты, или используйте системные шрифты, которые это обеспечивают; для арабского, китайского, иврита, японского, корейского и тайского языков требуются отдельные шрифты. Оставляйте в межстрочном интервале место для скриптов с высокими символами, не полагайтесь на курсив (для китайского и японского языков он отсутствует), и никогда не размещайте текст в изображениях — их невозможно перевести.
Направление справа налево
Арабский и иврит пишутся справа налево, при этом вся верстка также отражается: навигация, выравнивание, значки, указывающие направление, и порядок колонок.
- Установите
dir="rtl"на корневой элемент для этих языков, а такжеlangдля каждого языка. - Используйте логические свойства:
margin-inline-startвместоmargin-left,padding-inline-end,inset-inline-start,text-align: start,float: inline-start, а также логические вспомогательные классы вашей CSS-системы (ms-4,pe-2,text-start). Коды:physical_direction,unmirrored_layout. - Зеркально отображайте значки, указывающие направление, такие как стрелки и шевроны, но не другие, например часы или кнопку воспроизведения.
- Числа, код, URL и имена латинского алфавита остаются слева направо внутри текста, написанного справа налево. Изолируйте такой текст от людей или данных в
<bdi>, чтобы он не нарушал порядок окружающих элементов.
Пространство для расширения
Тексты переводов часто длиннее английских версий, причём самые короткие метки увеличиваются больше всего: немецкое слово «OK» может превратиться в целое слово, а метка из десяти символов — удвоиться. Оставляйте тексту пространство: позволяйте ему переноситься, давайте кнопкам и вкладкам увеличиваться вслед за метками, избегайте фиксированных ширины и высоты для текста. Не сокращайте метки, необходимые пользователям для выполнения действий. Коды: clipped_text.
Режим псевдоперевод удлиняет каждую строку на указанные значения, чтобы вы могли увидеть проблему до того, как её заметит переводчик:
| Исходная длина | Добавлено |
|---|---|
| До 10 символов | 100% |
| От 11 до 20 | 80% |
| От 21 до 30 | 60% |
| От 31 до 50 | 40% |
| От 51 до 70 | 31% |
| Более 70 | 30% |
Китайский, японский и корейский текст обычно короче, но требует более высоких строк.
Чек-лист для каждого изменения.
- Текст, который читают пользователи, берётся из каталога, а каждое предложение — это одно сообщение.
- Числа, даты, время, валюта, единицы измерения и списки адаптируются под локаль читателя.
- Сортировка и сопоставление регистра букв осуществляются с учётом локали читателя.
- Имена, адреса, почтовые индексы и номера телефонов поддерживают все рынки.
- Нажатие клавиши Enter не отправляет данные, пока идет набор слова.
- Макет использует логические свойства и предусматривает место для более длинных текстов.