Latin2-es karakterkódolásról UTF-8-ra váltás, UTF-8 kezelése

2005. nov. 06. (vasárnap), 18:00, D. keze nyomán
(Megjegyzés: az írás 2005. nov. 06-án, 18:00-kor kiegészített, második változata olvasható az alábbiakban.) A cikkben a latin-2-es karakterkódolásról UTF-8-as kódolásra történő váltásról, az UTF-8-as kódolással tárolt adatok megjelenítéséről lesz szó. Bevezetőként érdemes elolvasni Joel , az elsőhöz root jogok szükségeseSpolsky cikkét az unicode-ról. Az UTF-8 térhódítása már-már töretlen, azonban mit tegyünk, ha eddig használt Latin 2-es kódolású szövegünket UTF-8 karakterkódolású adatbázisban szeretnénk tárolni? Először tekintsük át, milyen elemek szerepelnek a szöveg felvitelében, tárolásában, megjelenítésében. A tárolás tehát adatbázisban történik, mely MySQL-nél jellemzően 4 beállítási szintet jelent: 1. Szerver alapbeállítás szerinti karakterkódolása Ez általában Latin1 szokott lenni, bővebb felvilágosítást a szolgáltató ad. 2. Adatbázis karakterkódolása Az egész adatbázisra vonatkozóan határoz meg egy irányadó karakterkészletet. 3. Táblázat karakterkódolása Értelemszerűen... ez már komoly befolyással van a tárolás mikéntjére. 4. Mező karakterkódolása Explicit megadás nélkül a táblázatét örökli. Az utolsó hármat jellemzően beállíthatja a felhasználó is. (A "character set" és a "collation" külön fogalmak, melyek túlmutatnak e cikk keretein; érdeklődők a MySQL kézikönyvben részletesen olvashatnak erről is.) A felvitel és a megjelenítés esetében egyazon dolog számít, a lapon megadott karakterkódolás. Akárhogyan adjuk is meg (header, meta tag - lényegében mindegyik ugyanazt állítja, de figyeljünk rá, hogy a header felülírja a meta taget!), a böngésző a megjelölt karakterkészlettel igyekszik megjeleníteni a lap adatait. Ahol nem talál a karakterkészletben megfelelő elemet, ott pedig valami izgalmas dolgot (ismert karaktert, pl kérdőjelet) fog berakni. Mit is jelent ez a gyakorlatban? Mindössze annyit, hogy igyekezzünk ugyanazt a karakterkódolást megadni a lapon, mint amiben az adatokat tároljuk. De mit tehetünk, ha van egy - adott esetben mondjuk - Latin2-es kódolású szövegünk, de UTF-8-ra szeretnénk váltani? 1. Konvertálás manuálisan Dumpoljuk az adatbázist, majd egy erre alkalmas szövegszerkesztővel (Windows alatt akár egy Notepad is jó, Linux alatt pedig például az iconv) más karakterkódolással kell elmenteni az állományt (egyszerűen megnyit, és elment újra, más kódolással). 2. Konvertálás az adatbázisban két táblával Hozzunk létre a konvertálandó tábláknak megfelelő, UTF-8-as táblákat, majd a CONVERT() MySQL függvénnyel töltsük át az egyik táblából a másikba az adatokat. Végezetül a régi táblák törlésével, az újak átnevezésével remélhetőleg a megfelelő eredményt kaptuk. :) A végső táblák (és szöveges mezőik) collationje UTF-8 (pl. utf8_general_ci) legyen. Egyes esetekben probléma lehet a nagy, ékezetes karakterekkel (jellemzően az Ő, Ű, Í "veszélyeztetett"), ilyenkor - MySQL esetén - az adatbázishoz való kapcsolódás után kiadott "SET NAMES utf8" query megoldja a problémát. (Megjegyzés: visszamenőleg ettől nem lesz jó a már tárolt ékezetes karakterek megjelenítése! A SET NAMES a továbbiakban felvitt karakterekhez megfelelő.) Érdemes figyelni arra is, hogy a PHP állományainkat UTF-8 kódolással mentsük el, vagy reguláris kifejezésekben hexadecimálisan adjuk meg az ékezetes karaktereket, ellenkező esetben ugyanis - például - a Latin2-es kódolású PHP állományba beírt ű betű, illetve a mondjuk felhasználói becenévként megadott stringben lévő ű nem fog egyezést adni. A PCRE reguláris kifejezések u módosítója elvileg megoldaná a problémát, de egyrészt innentől már nem Perl-kompatibilis a dolog (ami mondjuk nem egy tragédia), másrészt nekem még nem sikerült működésre bírnom (ez egy kicsivel nagyobb akadályt jelent). Összefoglalva tehát: 1. Figyeljünk, hogy az adatbázis és a lap karakterkódolása egyezzen. 2. Latin2-es (vagy bármilyen) tábla konvertálása UTF-8-ba legegyszerűbben valószínűleg a dump+más kódolással mentés+visszatöltés módon oldható meg. 3. SET NAMES utf8 4. PHP állományainkat (legalábbis azokat, melyekben ennek jelentősége van) UTF-8 kódolással mentsük el, vagy hexa kódokkal adjuk meg a reguláris kifejezésekben az ékezetes karaktereket. Így biztosan nem lesz gond az árvíztűrő tükörfúrógéppel. :) Hasznos lapok: http://www.unicode.org/ http://www.czyborra.com/utf/ http://en.wikipedia.org/wiki/UTF-8 http://hu.php.net/reference.pcre.pattern.modifiers Weblabor.hu: UTF8 fórumterem