- Локали и кодировки
- Введение
- Работа с локалями в PHP
- Локали в Windows
- Локали в UNIX
- Кодировки в MySQL
- Кодировка HTML-страниц
- Заключение
- Как в Windows 10 определить системный язык
- С помощью консольной утилиты DISM
- С помощью консоли PowerShell
- С помощью редактора реестра и таблицы декодирования
- Настройка локализации Windows
- Как настроить локализацию Windows
- Где находится список доступных локалей Windows?
- 2 ответов
Локали и кодировки
Введение
При разработке веб-приложений есть три важных момента, связанных с кодировками: информация в файлах-сценариях, информация в базе данных и браузер пользователя. Если выставить хотя бы одну кодировку неверно, то, в лучшем случае, данные отобразятся неверно, в худшем, безвозвратно потеряются. Чтобы этого не произошло, а приложение работало корректно при любых настройках сервера, нужно правильно выставить кодировки.
Работа с локалями в PHP
Работа с локалями в PHP выглядит одинаково и в UNIX, и в Windows, и в любой другой платформе. Для установки значений локали служит всего одна функция setlocale() . Чтобы выставить локаль, нужно передать функции первым аргументом категорию, на которую эта локаль распространяется, последующими список возможных локалей. Результатом будет название первой подходящей локали, которая и была установлена.
Локали в Windows
Для того, чтобы узнать, какие локали доступны в Windows, нужно зайти в панель управления, «Язык и региональные стандарты».
На вкладке «Дополнительно», в разделе «Кодовые страницы таблиц преобразования» показан список всех возможных локалей для Windows, которые можно использовать в PHP. Кодовые страницы, которые отмечены в списке, из PHP могут быть использованы по их номеру. В общем случае, использование выглядит по следующей схеме: Язык_Регион.Номер_кодовой_страницы Для России это может выглядеть как Russian_Russia.1251 (cp1251) или Russian_Russia.20866 (KOI8-R). Для Украины — Ukrainian_Ukraine.1251 (cp1251). Вместо длинных названий можно использовать сокращённые russian , american , ukrainian и так далее. При этом кодовая страница выставится с учётом региональных настроек, для России и Украины — 1251, для Америки — 1252. Единственная кодировка, с которой у меня возникли проблемы, как ни странно, оказалась UTF-8. При попытке выставить эту кодировку, выставляются все категории локалей, кроме основной. Вывод локализованных сообщений при этом идёт в cp1251. Пока это можно списать на внутренний механизм PHP работы со строками. С шестой версии PHP вся обработка строк должна будет вестись в UTF-8, но до тех пор надо просто знать об этом и делать поправку. Ещё одной странностью при работе с локалями в PHP на Windows является неправильная работа с категориями локалей. Так, например, я выставляю локаль на функции времени KOI8-R, setlocale(LC_TIME, ‘Russian_Russia.20866’) , но почему-то выставляется cp1251 на все категории. Суть проблемы я так и не понял, возможно, это просто баг (проверялось на PHP 5.2.3), а возможно, что внутренний механизм Windows просто не позволяет этого делать. Хотя по мне, так это чистой воды баг. В общем-то, на этом можно и закончить разговор о локалях на Windows. Главное, запомнить, что локали, которые портированы из UNIX, под WIndows работают только для «галочки». Шаг влево, шаг вправо и результат будет непредсказуемым. Безопасно можно использовать только cp1251 (windows-1251) и KOI8-R, и только для LC_ALL . Локали в UNIXВыше я описал работу с локалями в Windows, теперь можно заострить внимание на UNIX-like системах. Для простоты, я буду их называть UNIX, а подразумевать FreeBSD :). В контексте данной статьи это не особо важно. Итак, дистрибутивы UNIX поставляются в одном виде для всех, и работа рассчитана на многопользовательский режим, поэтому о правильной настройке локали должен заботиться сам пользователь, например: Так может выглядеть работа системной команды locale , которая выводит текущие настройки локали для пользователя. А так, обычно, выглядят настройки локали для пользователя, под которым работает PHP: Функция ucwords() должна была сделать заглавными первые буквы всех слов. А перед этим strtolower() должна была предварительно все заглавные буквы сделать строчными. Но ничего не произошло. Так же не будет работать следующий код: Хотя \w является множеством знаков, из которых может состоять слово (алфавит, цифры и _), регулярное выражение не срабатывает. Причина как раз в том, что, работая с cp1251, мы не сказали об этом php. Чтобы исправить положение, достаточно воспользоваться функцией setlocale() и указать правильную локаль, например, так: Здесь первый аргумент — это категория, на которую будет распространяться локаль (константа LC_*), второй — название локали. Начиная с версии 4.3.0 можно указывать несколько имён локалей в виде массива или в качестве дополнительных аргументов. После вызова функция установит первую подходящую локаль и вернёт её имя: С помощью команды grep я отобрал локали, которые поддерживают русский язык. Любую из них можно использовать, однако следует понимать, что данные должны быть в кодировке, на которую рассчитана локаль. Если же это правило не будет соблюдено, то результат может оказаться весьма неожиданным: Если учесть, что koi8-r достаточно популярная кодировка для UNIX-севреров, а windows-1251 для русскоязычных сайтов, то подобное «необычное» поведение не такая уж и редкость. Когда-то я и сам столкнулся с этой проблемой при портировании проекта на реальный хостинг. После установки правильной локали все примеры, которые не работали выше, будут работать как нужно! По-русски заговорит и функция strftime(), которая корректно работает с локалями, а также и всё остальное, что зависит от локали. Кодировки в MySQLНапомню, что возможность задавать кодировки появилась только в MySQL 4.1.11 и выше. В отличие от php, проблемы с кодировками базы данных проявляют себя гораздо быстрее, чем проблемы с локалью. И связано это прежде всего с хранением и выборкой данных, поскольку от этого зависит информация на сайте. Я не буду подробно расписывать все тонкости, поскольку есть отдельная статья, остановлюсь на самых важных моментах. Первое, чему необходимо научиться, смотреть текущие настройки соединения с mysql: Критичными для пользователя являются character_set_client и character_set_results, которые отвечают за кодировку, в которой данные поступают в базу, и кодировку, в которой данные поступают из базы к пользователю. Если эти две кодировки отличаются от той, в которой работает клиент, в нашем случае php-скрипты, то неминуемо будут «странности», например, при сортировке выборки или внесении данных в базу. Второе, что необходимо знать, как правильно сообщить mysql о кодировках. Самый простой и правильный способ, это использовать запрос set names: После этого три переменные character_set_client, character_set_connection и character_set_results примут значение cp1251. Это будет означать — клиент работает в кодировке windows-1251 (cp1251). Помимо этого можно устанавливать непосредственно серверные переменные: Теперь данные поступают и извлекаются в разных кодировках. Список доступных кодировок можно просмотреть так: И третье, что необходимо знать, — правила создания таблиц для хранения данных в нужной кодировке. К слову, данные можно хранить в любой кодировке, а работать с ними в кодировке клиента. Однако, важно понимать, что кодировки носят национальный характер и должны соответствовать вносимым данным. Иначе будут потери. Для русского языка есть три национальных кодировки koi8r, cp866, cp1251, которые могут конвертироваться друг в друга без потерь. Также можно использовать интернациональную кодировку UTF8. Кодировку можно выставить на базу данных, таблицу и поле таблицы. Так, например, можно создать базу данных в кодировке koi8r: Следует отметить, что кодировка базы данных влияет только на дефолтные значения кодировок при создании таблиц. Это значит, что неважно в какой кодировке была создана база, если кодировка таблицы была задана явно. Это же правило относится и к полям таблицы. Следующим шагом я создам таблицу в cp1251 и одним полем в utf8: После того, как таблица создана с нужными параметрами кодировки, mysql автоматически начинает переводить данные при внесении и выборке. Данные хранятся в разном виде, но поступают к пользователю именно так, как надо! Подробнее с кодировками и проблемами их использования можно ознакомиться на http://dev.mysql.com/doc/refman/5.1/en/charset.html. Кодировка HTML-страницОбъявить кодировку html-страницы можно двумя способами: через заголовки и мета-тег в самой странице. Мета-тег используется только в статичных страницах. Я не буду его разбирать, это проблемы html. Во всех остальных случаях предпочтительней использовать HTTP-заголовок Content-Type. PHP позволяет работать с HTTP-заголовками посредством функции header(): Но браузер отобразит страницу корректно только в том случае, когда php-файлы сами были созданы в кодировке cp1251. Также нужно понимать, что заголовки должны быть отправлены до любого вывода на экран. При необходимости перекодировать страницы «на лету», достаточно воспользоваться буферизацией и iconv: Надпись «Привет, мир!» будет выведена в юникоде, при этом браузер получит информацию о кодировке через заголовки и правильно отобразит страницу. Но важно понимать, что внутри скрипта и при соединении с базой данных надо использовать windows-1251 (cp1251), поскольку страница должна быть сформирована в одной кодировке. Важно помнить, что функции iconv доступны не всегда, и проверка на доступность этих функций не будет лишней. ЗаключениеДля безопасной разработки русскоязычных веб-проектов необходимо включать в файл с общими настройками следующие команды: Как ни странно, но эти три строчки кода значительно повышают портируемость веб-проектов. © 2021 Антон Прибора. При копировании материалов с сайта, пожалуйста, указывайте ссылку на источник. Как в Windows 10 определить системный языкКак известно, Windows 10 поддерживает установку языковых пакетов, с помощью которых можно изменять локализацию интерфейса операционной системы. С этим очень близко связано понятие системного языка. Системный язык это не тот, который был добавлен с помощью языкового пакета, а тот, который был выбран при установке самой системы. Если вы работаете на корпоративном компьютере, язык которого менялся посредством установки MUI -пакетов, возможно, вы захотите узнать, какой язык использовался в системе изначально. Способов определить системный язык несколько. Рассмотрим их по порядку. С помощью консольной утилиты DISMЗапустите от имени администратора командную строку и выполните в ней команду dism /online /get-intl . Через несколько секунд получите результат. Обратите внимание на параметр «Язык пользовательского интерфейса по умолчанию». Его значение и будет системным языком. С помощью консоли PowerShellЗапустите консоль PowerShell от имени администратора и выполните команду [CultureInfo]::InstalleduICulture . Значение параметра DisplayName будет указывать на системный язык. Обратите также внимание на параметр LCID, он содержит код языка, прописанный в реестре Windows (смотрите ниже). С помощью редактора реестра и таблицы декодированияКомандой regedit откройте редактор реестра и разверните ветку HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Language В правой колонке окна редактора найдите строковый параметр InstallLanguage (он в самом низу) и посмотрите его значение. Оно представлено четырёхзначным кодом, для расшифровки которого следует воспользоваться таблицей декодирования на сайте MSDN. В нашем примере код 0419 соответствует русскому языку. Настройка локализации WindowsЧасто требуется автоматизированным способом для группы компьютеров настроить раскладку клавиатуры, язык интерфейса системы, отображение локальной атомизации (времени, денежных единиц). Всего существует 4 основных настройки (локали):
Помимо этого отдельно настраиваются:
Чтобы иметь возможность изменять эти настройки массово и автоматизированно, вам необходимо воспользоваться таблицами, в которых представлены возможные и допустимые значения для каждой настройки. К счастью, необходимые таблицы приводит Microsoft в своей документации: Как настроить локализацию WindowsЕсть несколько способов и команд для этой задачи. Проще всего воспользоваться командами Powershell или DISM с указанием идентификатора локали. Например (в квадратных скобках указан параметр): Set-WinSystemLocale ja-JP Также вы можете использовать команды DISM: Dism /image:C:\mount\windows /set-allIntl:fr-fr Еще один вариант, применимый только при развертывании новой операционной системы — использование файла ответов xml. Более подробные сведения об использовании этих команд вы найдете в документации. Был ли наш пост полезен? Нажмите на звезду, чтобы оценить мои труды! Средний рейтинг: 0 / 5. Количество голосов: 0 Где находится список доступных локалей Windows?если открыть Regional and Language Options (via Control Panel ), и нажмите на кнопку Regional Options tab, то есть выпадающий список всех доступных локалей. откуда этот список заполняется? (Я хочу сравнить настройки для каждой локали; я в порядке с тем, как это сделать, но мне нужен список имен локалей для цикла.) EDIT: после просмотра моего каталога windows (вероятно, следует упомянуть, что я использую XP) , файл выглядит вероятным, но это двоичный файл. Это то, на что я должен смотреть, и если да, то как я его читаю? 2 ответовМайкрософт не делает его легким для вас. Файл NLS упоминается в дозе содержат сведения о языке, но это в hex. Даже HEX-редактор, содержание далеко от удобочитаемое. Я решил взять альтернативную стратегию, вдохновленную ответом r0ca. есть более точный список доступных локалей опубликовано Microsoft. К сожалению, даже этот список не совсем верно. (Я установил все доступные локали, и у меня ничего нет Сото, которого нет в списке Microsoft, но нет в традиционном испанском, современном испанском или македонском. Украинский в списке дважды.) имена не совсем правильно в списке Microsoft либо. В общем случае имена должны иметь вид «Language» или «Language_Country Name», например «English»или» English_United Kindom» это означает, что подчеркивания после первого должны быть заменены пробелами и что имена людей должны быть заменены именами стран, например «Malay_Brunei_Darussalam» становится » Malay_Brunei Даруссалам» «Dutch_Belgian» становится «Dutch_Belgium» есть много других странностей. Латиница, кириллица и некоторые другие слова должны быть bracketted, например «Serbian_Cyrillic_Bosnia_Herzegovina» становится «сербский (кириллица)_Bosnia And Herzegovina» дополнительно «Sami_Inari» становится «Sami (Inari)_Finland» есть еще много примеров того, чтобы угадать имена собственных стран «English_Philippines» становится «English_Republic Филиппин» Я понял большинство из этих исключений, изменив локаль Windows с панели управления, затем загрузив R и набрав к сожалению, этот метод в настоящее время не работает с индийских языков (плюс несколько других). См. раздел отчет об ошибке здесь. |