Локали и кодировки

При разработването на уеб приложения има три важни момента, свързани с кодирането: информация в скриптовите файлове, информация в базата данни и браузъра на потребителя. Ако поне едно кодиране е зададено неправилно, тогава в най-добрия случай данните ще се показват неправилно, в най-лошия случай ще бъдат безвъзвратно загубени. За да предотвратите това да се случи и приложението да работи правилно с всякакви настройки на сървъра, трябва да зададете правилно кодировките.

Работа с локали в PHP

Локали в Windows

За да разберете какви локали са налични в Windows, трябва да отидете в контролния панел, „Регионални и езикови опции“.

базата

Разделът „Разширени“, раздел „Кодови страници на таблица за преобразуване“, показва списък с всички възможни локали на Windows, които могат да се използват в PHP.

Кодовите страници, които са маркирани в списъка от PHP, могат да се използват по техния номер.

Най-общо използването изглежда така: Language_Region.Code_page номер

За България това може да изглежда като Russian_Russia.1251 (cp1251) или Russian_Russia.20866 (KOI8-R).

За Украйна - Ukrainian_Ukraine.1251 (cp1251).

Вместо дълги имена можете да използвате съкратени руски, американски, украински и т.н. В този случай кодовата страница ще бъде зададена, като се вземат предвид регионалните настройки, за България и Украйна - 1251, за Америка - 1252.

Засега това може да се отдаде на вътрешния механизъм на PHP за работа с низове. От PHP 6 цялата обработка на низове ще трябва да бъде в UTF-8, но дотогава просто трябва да сте наясно с това и да правите корекции.

Като цяло, това може да е краят на разговора за локалите на Windows. Основното нещо, което трябва да запомните е, че локалите, които са пренесени от UNIX, работят под WIndows само за показ. стъпканаляво, стъпете надясно и резултатът ще бъде непредвидим. Само cp1251 (windows-1251) и KOI8-R могат да се използват безопасно и само за LC_ALL.

Локали в UNIX

По-горе описах работата с локали в Windows, сега можете да се съсредоточите върху UNIX-подобни системи. За простота ще ги нарека UNIX и ще имам предвид FreeBSD :). В контекста на тази статия това не е особено важно.

И така, дистрибуциите на UNIX се доставят в една форма за всички и работата е предназначена за многопотребителски режим, така че самият потребител трябва да се погрижи за правилната настройка на локала, например:

Ето как може да изглежда системната команда за локализация, която показва текущите настройки за локализация за потребителя. И така, обикновено локалните настройки за потребителя, под който работи PHP, изглеждат така:

Функцията ucwords() трябваше да изписва с главни букви първите букви на всички думи. А преди това strtolower() трябваше първо да направи всички главни букви малки. Но нищо не се случи. Следният код също няма да работи:

Въпреки че \w е набор от знаци, от които може да се състои една дума (азбука, цифри и _), регулярният израз не работи. Причината е просто, че когато работихме с cp1251, не казахме на php за това. За да коригирате ситуацията, достатъчно е да използвате функцията setlocale() и да посочите правилния локал, например по следния начин:

С командата grep избрах локалите, които поддържат български език. Всеки от тях може да се използва, но трябва да се разбере, че данните трябва да бъдат в кодирането, за което е проектиран локалът. Ако това правило не се спазва, тогава резултатът може да бъде доста неочакван:

Като се има предвид, че koi8-r е доста популярно кодиране за UNIX сървъри, а windows-1251 за сайтове на български език, тогава нещо подобно„Необичайното“ поведение не е необичайно. Веднъж аз самият се сблъсках с този проблем, когато пренасях проект към истински хостинг.

След като зададете правилния локал, всички примери, които не са работили по-горе, ще работят както трябва!

Функцията strftime(), която работи коректно с локали, също ще говори български, както и всичко останало, което зависи от локала.

MySQL кодировки

Позволете ми да ви напомня, че възможността за задаване на кодировки се появи само в MySQL 4.1.11 и по-нови.

Първото нещо, което трябва да научите, е да погледнете текущите настройки на mysql връзката:

Критични за потребителя са character_set_client и character_set_results, които отговарят за кодирането, в което данните влизат в базата данни, и кодирането, в което данните идват от базата данни до потребителя. Ако тези две кодировки се различават от тази, в която работи клиентът, в нашия случай php скриптове, тогава неизбежно ще има "странности", например при сортиране на селекция или въвеждане на данни в базата данни.

Второто нещо, което трябва да знаете, е как правилно да кажете на mysql за кодировките. Най-простият и правилен начин е да използвате заявката за имена на набори:

След това трите променливи 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:

Надписът "Hello world!" ще се показва в unicode, докато браузърът ще получи информация за кодирането чрез заглавките и ще покаже страницата правилно. Но е важно да разберете, че вътре в скрипта и когато се свързвате с базата данни, трябва да използвате windows-1251 (cp1251), тъй като страницата трябва да се формира в едно кодиране.

Важно е да запомните, че функциите iconv не винаги са налични и проверката за наличността на тези функции няма да бъде излишна.

Заключение

За безопасното разработване на уеб проекти на български език във файла с общи настройки трябва да има следните команди:

Колкото и да е странно, тези три реда код значително увеличават преносимостта на уеб проектите.