Short how-to about converting WWW-sites from ISO-8859-2 (known also as Latin-2) to utf-8
Krótkie how-to o konwersji stron WWW z ISO-8859-2 do utf-8
Na początek - co to jest kodowanie, bo jest wiele nieporozumień wokół tego tematu...
Co to jest kodowanie
Komputery operują na liczbach zapisanych w bajtach. Procesory rozumieją i przetwarzają tak naprawdę tylko liczby. Nieważne, czy oglądamy extra grafikę w grze 3D, czy edytujemy dokument w OpenOffice, czy przeglądamy stronę WWW. Dla kompa - to tylko liczby. Liczby są zapisane w bajtach. Bajt składa się bitów i tak dalej... Mniejsza o szczegóły - ważne jest to, że jeden bajt mieści tylko 256 różnych liczb (czyli umownie wartości od 0 do 255). Więcej się po prostu nie da.Jeśli chcemy użyć kompa do pokazywania/edycji tekstu, to wystarczy wymyślić jakieś proste przyporządkowanie. Na przykład, jeśli umówimy się, że:
A to 1 B to 2 C to 3 i tak dalej...
Skoro różnych wartości w bajcie może być 256, to można w ten sposób przyporządkować 256 różnych znaków. Jeśli weźmiemy pod uwagę, że znaków jest cała masa (literki małe, duże, cyferki, plusiki, myślniki, przecinki) i do tego są różne w zależności od języka w którym piszemy tekst (niemcy mają umlauty, norwedzy na przykład przekreślone O, a chińczycy mają kilka tysięcy obrazków), to okazuje się, że trzeba kombinować - na przykład łączyć po kilka bajtów w jeden znak.
W rozumieniu tego artykułu kodowanie to sposób przyporządkowania wartości bajtów (i ich ciągów) do konkretnych liter.
...no i łatwo się domyślić, że takich przyporządkowań powstało mnóóóstwo na początku światowej komputeryzacji - całe mnóóóstwo problemów.
Na szczęście ludzie zaczęli się dogadywać i definiować standardy:
Standardy : ASCII
Podstawą jest ASCII - standard który definiuje pierwsze 127 znaków. Można sobie go obejrzeć na przykład na calculli.ASCII definuje tylko podstawowy zestaw literek, cyferek i znaczków, ograniczając się praktycznie do alfabetu angielskiego (jedyny ogonek to Q).
Standardy : ISO-8859-2 i WINDOWS-1250
Kodowanie ISO-8859-2, znane też jako Latin-2 dodaje do 127 znaków ASCII, dodatkowe 128 - uzupełnia ASCII o różnokrajowe znaczki, między innymi polskie.Kodowanie WINDOWS-1250 - daje mniej więcej to samo.
Problem w tym, że 8859-2 i windows-1250 - robią to w zupełnie inny sposób (tzn, te same literki mają inne odpowiadające im kody).
Oczywiście powodem jest to, że po prostu kto inny definiował 8859-2, a kto inny windows-1250.
Oba kodowania dodają tylko po 128 znaczków, czyli razem z ASCII używają jednego bajtu na znak, potrafiąc rozróżnić 255 różnych znaków.
NIE DA się zapisać w tych kodowaniach innych znaków, bez niestandardowych kombinacji.
Czyli - tak naprawdę nie da się tym zapisać nawet wszystkich tekstów europejskich.
Przez lata wiele polskich tekstów i stron WWW powstawało w edytorach, które najlepiej pracowały używając właśnie jednego z tych kodowań.
Standardy : inne
Przez lata pracy z tekstami w różnych krajach, powstały dziesiątki/setki standardów kodowań, załatwiających jakieś problemy danego języka.Garść przykładów:
- W polsce poza Latin-2, używano też często standardu Mazovia. Poza tym system operacyjny DOS (przed rokiem 95 właściwie nie było innych systemów używanych powszechnie w polsce na PC-ty) definiował także swoje standardy. Dla zainteresowanych szerzej: szukajcie na przykład CP790 CP852
- Chiny - do zapisu języka Traditional Chinese jednym z najpowszechniejszych kodowań stało się Big5. Kod ten zawiera także m.in. znaki używane na Tajwanie (chiński simplified), Hong Kongu czy Makau. Z nie-chińskich alfabetów, Big5 koduje na przykład cyrylice (Rosja), czy japońską Kanę. Big5 jest kodowaniem wielobajtowym - to oczywiste, że potrzebuje więcej niż jednego bajtu, żeby wszystkie znaki przyporządkować.
- Zestawy znaków ISO - kilka tak zwanych stron kodowych, oznaczonych różnymi numerkami (8859-x) - pozwalają zapisać znaki w różnych językach, zdefinowane przez komitet standaryzacyjny.
- Zestawy znaków Windows-xxxx i CPxxxx - generalnie używane w systemach microsoft-u.
- Kodowanie DVB - używane przez telewizję cyfrową. Realnie zawiera (używa) ISO, Big5, utf i paru innych. Jednak ciekawostką jest to, że każdy tekst może zawierać informację o użytym kodowaniu - teoretycznie umożliwia nawet zmiane kodowania w częściach tekstu. W tym celu zdefiniowany jest zestaw prefixów, określających przełączenie kodowania.
Za pomocą jednobajtowych kodowań nie da się stworzyć dokumentu w języku polskim, który zawierałby cytaty z norweskiego i rosyjskiego...
Potrzebne jest więc kodowanie dość mocno uniwersalne, aby potrafiło przedstawić te tysiące znaczków z całego świata. Jako taki standard obecnie przyjęło się UNICODE...
Unicode, utf-7, utf-8, utf-16, utf-32
Często miesza się pojęcia Unicode z kodowaniami utf - a to dlatego, że w praktyce są one mocno powiązane.Unicode (po polsku unikod), jest standardem który z założenia definiuje znaki używane w językach całego świata.
Jest ciągle rozwijany. Unicode w wersji 5.0 koduje 98.884 znaki, definiując ich kształt, ale także cel i kontekst użycia.
Początkowe znaki UNICODE są praktycznie takie same jak te zdefiniowane w ASCII.
utf-7, utf-8, utf-16, utf-32 to sposoby zapisu kodów UNICODE.
Kod oparty na tylu różnych znakach musiałby poświęcać 4 bajty na każdy znak. I tak właśnie jest przy utf-32. Utf-32 to po prostu zapisany w 4 bajtach UNICODE.
Pozostałe - utf-7, utf-8, utf-16 opierają się na założeniu, że najczęściej używanym zestawem jest i tak zestaw łaciński, rzadziej popularne znaki narodowe, a najrzadziej jakieś wynalazki w stylu indiańskich nutek. W tych kodowaniach, na zakodowanie początkowych znaków UNICODE zużywa się mniej bajtów niż na te używane względnie rzadko.
Dla zainteresowanych u-te-ef-ami polecam poczytać choćby wikipedię - ten temat nie będzie rozwijany w tym artykule.
Szczególnym przypadkiem kodowania UNICODE jest utf-8. A to dlatego, że pierwsze 128 znaków jest zakodowanych jako zwykłe ASCII.
Spostrzeżenie: każdy tekst w ASCII jest tekstem w utf-8.
Dodatkowe UNICODE-owe znaki są kodowane większą ilością bajtów w utf-8. Im znak rzadziej używany (statystycznie), tym więcej będzie potrzebował bajtów utf-8 do zakodowania. Znaki z najwyższego zakresu UNICODE wymagają aż 6 bajtów w utf-8.
Na tą chwilę utf-8 stało się chyba najczęściej używanym standardem dla stron internetowych - szczególnie tych wielojęzycznych.
Strona w utf-8 : nagłówek (head)
Aby przeglądarka interpretowała stronę jako utf-8, najlepiej jej to dać znać zgodnie z tym co prerferują normy W3C. Kod jest banalny:<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
Oczywiście dobrze jest upewnić się, że nie została gdzieś inna(stara) definicja
<meta http-equiv=content-type>
Strona w utf-8 : treść
Treść dokumentu strony oczywiście musi być w UTF-8. Jeśli zostawimy inne kodowanie, a w nagłówku wmówimy przeglądarce, że dokument jest w utf-8, to wyświetlą się nam krzaczki.Wskazówki:
- używaj edytora, który natywnie wspiera UTF-8, a do tego daje Ci pełną kontrolę nad kodowaniem - czyli pokazuje jakie kodowanie jest fizycznie w dokumencie, umożliwia konwersję itp. (choćby Eclipse)
- przy ładowaniu stron FTP-em, sprawdź czy program uploadujący wie o UTF-8 albo lepiej przełącz klienta FTP w tryb binarny binary mode.
- jeśli używasz bazy danych (jak MySQL), upewnij się, że baza pracuje w trybie UTF-8. Ewentualnie będziesz musiał przeprowadzić konwersję.
Strona w utf-8 : automatyczna konwersja plików w PHP
Często wystarczy, że przejedziesz wszystkie pliki jakimś automatem zamieniającym ISO-8859-2, czy WINDOWS-1250 na UTF-8.Przykładowy prosty skrypt konwersji z ISO-8859-2 na UTF-8:
function processDir($dir) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { $ext = substr($file, -4); if ( ($file != 'a.php') && ( ($ext == '.php') || ($ext == '.txt') ) ) { $txt = file_get_contents($dir.'/'.$file); $txt = str_replace(chr(0xB1), 'ą', $txt); $txt = str_replace(chr(0xE6), 'ć', $txt); $txt = str_replace(chr(0xEA), 'ę', $txt); $txt = str_replace(chr(0xB3), 'ł', $txt); $txt = str_replace(chr(0xF1), 'ń', $txt); $txt = str_replace(chr(0xF3), 'ó', $txt); $txt = str_replace(chr(0xB6), 'ś', $txt); $txt = str_replace(chr(0xBC), 'ź', $txt); $txt = str_replace(chr(0xBF), 'ż', $txt); $txt = str_replace(chr(0xA1), 'Ą', $txt); $txt = str_replace(chr(0xC6), 'Ć', $txt); $txt = str_replace(chr(0xCA), 'Ę', $txt); $txt = str_replace(chr(0xA3), 'Ł', $txt); $txt = str_replace(chr(0xD1), 'Ń', $txt); $txt = str_replace(chr(0xD3), 'Ó', $txt); $txt = str_replace(chr(0xA6), 'Ś', $txt); $txt = str_replace(chr(0xAC), 'Ź', $txt); $txt = str_replace(chr(0xAF), 'Ż', $txt); file_put_contents($dir.'/'.$file, $txt); } } closedir($dh); } } processDir('/twoj/katalog'); processDir('/twoj/katalog/doc'); processDir('/twoj/katalog/txt'); processDir('/twoj/katalog/blah/bleh');
Skrypt jest banalny - postaraj się go zrozumieć, zanim użyjesz, żebyś sobie nie narobił bałaganu.
I bardzo ważne - kopiując skrypt ze strony, zapisz go jako UTF-8 !
Dla konwersji Windows-1250 na utf-8 musisz tylko wyedytować numerki zamienianych znaków (miłej zabawy z tabelkami !).
Strona w utf-8 : baza w mySQL
Jeśli masz pełną kontrolę nad bazą, a Twoje skrypty korzystają z niej w standardowy sposób - czasami wystarczy ją przełączyć na pracę w UTF-8, zmieniając konfigurację... i już.Jednak pewnie napotkasz takie czy inne problemy, związane z prawami dostępu (serwer mySQL-a dzielony na wielu userów), formatowaniem zapytań przy dostępie do bazy itp.
Nie jestem w stanie podać pełnego zestawu rozwiązań - bo niektóre przypadki wymagają dość indywidualnego podejścia, jeśli trzymane w bazie dane są specyficzne.
Garść podstawowych wskazówek:
- powiedz serwerowi, że preferujesz utf-a. Zaraz po połączeniu (po zawołaniu funkcji mysql_select_db), odpal kod:
mysql_query('SET character_set_connection=utf8') or die('character_set_connection failed'); mysql_query('SET character_set_client=utf8') or die('character_set_client failed'); mysql_query('SET character_set_results=utf8') or die('character_set_results failed');
- tekstowe kolumny w tabelach deklaruj jako utf-owe (już podczas tworzenia tabeli).
W tym celu przy każdym polu w definicji, podczas tworzenia dodajNa przykład:character set utf8
CREATE TABLE properties (path text character set utf8 not null, value text character set utf8, primary key (path(32)))
- pilnuj właściwego kodowania przy dostępie (zapisie/odczycie) do bazy
- aby przeprowadzić konwersję na istniejącej już bazie, często wystarcza export za pomocą phpMyAdmin-a, i ponowny import z właściwymi ustawieniami.
O kopiowaniu
Ten artykuł może być kopiowany w inne miejsca, po uprzednim uzyskaniu zgody autora.Artykuł powinien być kopiowany W CAŁOŚCI (z rysunkami) oraz powinien zawierać link do ke.mu (z dopiskiem, że stąd pochodzi).