Na navigaci | Klávesové zkratky

Translate to English… Ins Deutsche übersetzen…

Převody mezi kódováním

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-1250UTF-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

  1. 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

    před 10 lety
  2. Petr http://tapety.na-mobily.cz #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 :)

    před 10 lety
  3. 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 :)

    před 10 lety
  4. karel #4

    Když už jsme u těch kódování, mrkni se na PDF export tohoto článku :-)

    před 10 lety
  5. mrzout http://www.abclinuxu.cz/blog/mrzutej #5

    Daleko lepsi zkusenosti nez s iconv mam s recode, obzvlaste pri odstranovani te zatracene diakritiky ;)

    před 10 lety
  6. duf http://www.duf.cz #6

    avatar

    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 :-)

    před 10 lety
  7. Slimak #7

    díky za tabulku! .. to php4 bude moje smrt :/

    před 10 lety
  8. Pleva #8

    to není pravda s tím kódováním, Robinson byl v UTF !

    před 10 lety
  9. Urso http://zmsoft.cz/ #9

    avatar

    Mirek je úchyl. Pixy je páprda.
    Na převody (konverze) češtin je nejlepší PREKODÉR.

    před 9 lety

Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.