Pokud potřebujete v PHP převádět řetězce z jednoho do druhého
kódování, je nejlepší použít funkci iconv. Ta podporuje
obrovské množství kódových stránek. Narozdíl od rozšíření Multibyte String
Functions zná i WINDOWS-1250
(neboli
CP-1250
).
Pokud nelze některé znaky převést, můžeme je buď ignorovat:
$s = iconv('WINDOWS-1250', 'ISO-8859-2//IGNORE', $s);
nebo převyprávět: (to udělal třeba Pleva s Robinsonem)
$s = iconv('WINDOWS-1250', 'ISO-8859-2//TRANSLIT', $s);
Což například znak €, který není v cílovém kódování
k dispozici, převede na řetězec EUR
.
Co když není iconv?
Rozšíření iconv
je nativní součástí PHP5 (naštěstí!),
takže obavy se týkají jen verze PHP4. Tady je možné si vypomoci funkcí strtr a připravit si
podle potřeby převodní tabulky.
Upozornění: V žádném případě nepoužívejte
str_replace()
!
WINDOWS-1250 → ISO-8859–2
Jelikož zdrojová sada má širší pokrytí než cílová, použijeme převyprávění:
// windows-1250 to iso-8859-2 (translit) by dgx
function win2iso($s)
{
static $tbl = array("\x80"=>"EUR","\x81"=>"","\x82"=>"`","\x83"=>"","\x84"=>"\"","\x85"=>"...","\x86"=>"+","\x87"=>"","\x88"=>"",
"\x89"=>"o/oo","\x8a"=>"\xa9","\x8b"=>"<","\x8c"=>"\xa6","\x8d"=>"\xab","\x8e"=>"\xae","\x8f"=>"\xac","\x90"=>"","\x91"=>"`",
"\x92"=>"\xb4","\x93"=>"\"","\x94"=>"\"","\x95"=>"o","\x96"=>"-","\x97"=>"-","\x98"=>"","\x99"=>"TM","\x9a"=>"\xb9","\x9b"=>">",
"\x9c"=>"\xb6","\x9d"=>"\xbb","\x9e"=>"\xbe","\x9f"=>"\xbc","\xa1"=>"\xb7","\xa5"=>"\xa1","\xa6"=>"|","\xa9"=>"(c)","\xab"=>"<<","\xac"=>"not",
"\xae"=>"(R)","\xb1"=>"+/-","\xb5"=>"u","\xb6"=>"P","\xb7"=>".","\xb9"=>"\xb1","\xbb"=>">>","\xbc"=>"\xa5","\xbe"=>"\xb5");
return strtr($s, $tbl);
}
Použití statické proměnné pro uložení tabulky je trik, který vede ke zrychlení aplikace. Pole totiž není nutné při každém volání funkce znovu vytvářet. Dále si všimněte, že znaky jsou zapsány pomocí hexadecimálních sekvencí. Nehrozí tedy znehodnocení skriptu při uložení v jiném kódování – vřele doporučuji toto používat.
Poznámka: uvedená funkce je pomalejší než odpovídající volání iconv.
ISO-8859–2 → WINDOWS-1250
V tomto případě bude vždy jednomu znaku ze vstupního kódování
odpovídat jeden znak na výstupu. Proto jako parametry funkce
strtr
použijeme řetězce, namísto pole. Vykonávání se tím
dramaticky zrychlí a tato funkce je dokonce mnohem rychlejší, než
odpovídající volání iconv.
// iso-8859-2 to windows-1250 by dgx
function iso2win($s)
{
return strtr($s,
"\xa1\xa5\xa6\xa9\xab\xac\xae\xb1\xb5\xb6\xb7\xb9\xbb\xbc\xbe",
"\xa5\xbc\x8c\x8a\x8d\x8f\x8e\xb9\xbe\x9c\xa1\x9a\x9d\x9f\x9e");
}
ISO-8859–2, WINDOWS-1250 → UTF-8
Opět budeme volat strtr(), jen s jinou převodní tabulkou. Funkce si můžete stáhnout, viz níže.
ISO-8859–1 → UTF-8
Přímo pro tento účel má PHP funkci utf8-encode.
Existuje i reverzní utf8-decode
. Jsou (samozřejmě) rychlejší
než adekvátní volání iconv.
UTF-8 ⇒ WINDOWS-1250 nebo ISO-8859–2
Pokud si teď říkáte, že vlastně stačí text prohnat inverzní
tabulkou, než která byla použita při převodu WINDOWS-1250
⇒
UTF-8
, není to tak docela pravda. Tabulka sice převede všechny
znaky patřící do cílového kódování, ale v textu zůstanou ostatní
unicode znaky. Ty je nutné odstranit regulárním výrazem. Důležité je
dodržet pořadí, nejprve regulární výraz a poté strtr()
.
Tyto funkce už jsou značně pomalejší než ekvivalentní volání iconv.
Navíc přicházíme o možnosti převyprávění //TRANSLIT
.
Závěrem
Úspěch takovýchto funkcí stojí a padá s přesností použitých tabulek. Tak věřím, že jsem se dopracoval k těm správným.
Download charset-2-charset
Související:
Komentáře
Non_E #1
Tohle vypadá užitečně. Jen co bude čas, tak to zkusím, protože iconv se mi nějak nechce kamarádit s glibc. Díky
Petr #2
Iconv je sice rychla a celkem efektivni, nicmene prave na PHP4 nekdy trochu zlobi. Pri prevodu napr. z utf8 na cp1250 jsem si nekdy vsiml zvlastniho chovani… V kombinaci s glibc mi taky nekdy blbne. V kazdem pripade na php5 je vse v pohode :)
uzivatel #3
urobil som si da sa povedat podobnu prevodovu tabulku. len som nevedel o moznosti static ktoru velmi rad zakomponujem do mojho srciptu. dik za doplnenie :)
karel #4
Když už jsme u těch kódování, mrkni se na PDF export tohoto článku 🙂
mrzout #5
Daleko lepsi zkusenosti nez s iconv mam s recode, obzvlaste pri odstranovani te zatracene diakritiky ;)
duf #6
ahoj davide, chtel jsem se jenom ciste ze zvedavosti zeptat? proc se ty komentare tady chovaji natolik rozdilne v prohlizecich IE a Firefox? ja jsem si tu ve FF klikal na komentaricky jak ***** a ono nic. tak jsem se podival v IE a tam jsou zase ty komentare hnusne 🙂
Slimak #7
díky za tabulku! .. to php4 bude moje smrt :/
Pleva #8
to není pravda s tím kódováním, Robinson byl v UTF !
Urso #9
Mirek je úchyl. Pixy je páprda.
Na převody (konverze) češtin je nejlepší PREKODÉR.
Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.