Pietrzak Roman
Kemu Studio - yosh.ke.mu
Pierwsza wersja: 2008
Ostatnie zmiany: 2010.11.21
Wszelkie prawa zastrzeżone
All rights reserved

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...
to mamy proste kodowanie.

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.
Typowym problemem jest kodowanie dokumentów, czy aplikacji (także stron internetowych), które używają wielu języków jednocześnie.
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"/>
Wstawiamy to gdzieś w nagłówku (najlepiej wśród innych sekcji meta), czyli pomiędzy tagami <head></head>.

Oczywiście dobrze jest upewnić się, że nie została gdzieś inna(stara) definicja
<meta http-equiv=content-type>
bo zostawienie dwóch (i to sprzecznych) mija się z celem... a zdarzają się i takie kwiatki.

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');
zamienia polskie znaki we wszystkich plikach *.php i *.txt spotkanych w podanych ręcznie katalogach na końcu skryptu.
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 dodaj
    character set utf8
    Na przykład:
    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).

JavaScript failed !
So this is static version of this website.
This website works a lot better in JavaScript enabled browser.
Please enable JavaScript.