ugrás a tartalomhoz

Karakterkódolási problémák kiküszöbölése

Hodicska Gergely · 2006. Szep. 3. (V), 04.26
Karakterkódolási problémák kiküszöbölése
Gyakori és visszatérő probléma, hogy valakinek meggyűlik a baja egy oldal készítése során a karakterkódolás témakörével, pedig ha pár apróságot betartunk, akkor nem lesz vele gondunk. A nehézséget valószínűleg az okozza, hogy a helyes működéshez több tényező megfelelő összehangolása szükséges, és ha bármelyikük rossz, akkor csak annyit tapasztalunk, hogy "nem megy jól az oldal". Ez a cikk igazából csak egy válasznak indult, de már korábban is szerettem volna írni erről a témáról, mert fontosnak érzem, hogy tisztázzuk ezt a kérdést, ezért végül úgy döntöttem, hogy egy kicsit jobban körüljárom a témát.

Mint a bevezetőben említettem, a probléma nem bonyolult, csak fontos, hogy kialakítsuk a helyes szemléletmódot. Ennek szerintem egyik fontos eleme, hogy ne csak kövessünk egy ajánlott receptet, hanem játszunk el a lehetőségekkel, jöjjünk tisztába azokkal a mechanizmusokkal, amiknek jelen esetben jelentősége van, különben hiba esetén nehezen fogunk tudni rájönni a megoldás kulcsára.

Először is következzen egy alap forgatókönyv, hogyan járjunk el, ha nulláról indulunk. Tegyük fel, hogy azt szeretnénk, hogy az oldalunk az ISO-8859-2 karakterkódolással működjön. A következő teendőink lesznek:
  • Amennyiben adatbázist használunk, akkor állítsuk be úgy, hogy tábláink a megfelelő karakterkódolást használják. Itt érdemes figyelni arra, hogy pl. MySQL esetén lehetőség van mezőnként meghatározni, ezért ha valamilyen generáló eszközt használunk, akkor ellenőrizzük le, hogy a mezőink tényleg az általunk kívánt beállítással jöttek létre.
  • Legyenek a PHP fájljaink is ilyen kódolásúak, illetve nem is feltétlenül mind, hanem azok a fájlok, amik a kimenetben is megjelenő szövegeket tartalmaznak, és persze ez szintén vonatkozik a template állományainkra.
  • A HTML kódban szerepelhet meta tagként is az adott kódolás, de ez nem annyira fontos, de az igen, hogy az oldal megfelelő Content-Type fejléccel legyen kiszolgálva, annak charset paramétere az általunk választott kódolást tartalmazza. Ezzel lehetne vitatkozni annyiban, hogy elég a meta tag, ha nincs ezzel ellentétes tartalmú fejléc, de ha mi kiadjuk a megfelelőt, akkor nem fogunk kétes szerver beállításoktól függeni.
  • Ezután már csak arra kell figyelnünk, hogy az adatbázissal történő kommunikációnk során biztosítsuk, hogy a szerver a számára küldött parancsokat az általunk használt karakterkódolásnak megfelelően értelmezze. Ezt pl. MySQL használata esetén a SET NAMES latin2 parancs kiadásával érhetjük el.

Ha ezekre figyel az ember, akkor alap esetben nem lesz gondja. Az alap esetet arra értem, hogy nem lesz gond, ha az űrlapjainkba tényleg latin2 kódolású szövegeket írnak be. Ha mégis ez történik, akkor nem árt ha van nálunk egy kevés friss kakas vér, mert ugyan van lehetőségünk befolyásolni (_charset_, accept-charset), hogy a böngészők hogyan reagáljanak erre az esetre, de hogy ténylegesen mi fog történni, az eléggé megvalósítás függő.

A gond akkor szokott kezdődni, amikor az ember azt tapasztalja, hogy nem jól jelennek meg a karakterek az oldalán (mert eredetileg nem a fentieknek megfelelően járt el), és kezdődik a kanosszajárás, ugyanis pl. a fenti leírásnak megfelelően elkezdi a különböző recepteket (ész nélkül) alkalmazni, és probléma mégsem akar megoldódni. ("Én már mindent beállítottam, de ...") Ilyenkor a hiba az, hogy úgy próbálunk meg javítani valamit, hogy nem győződünk meg a hiba okáról. Hiába kezdjük el kiadni mondjuk a megfelelő fejlécet, ha az adatbázisban rossz adatok vannak, vagy éppen a template fájljaink karakterkódolása más, mint amit használni szeretnénk. Hiába változtatjuk meg a tábla karakterkódolását, ha csatlakozáskor nem állítjuk be a megfelelő kliens oldal karakterkódolást, és az adatbázisból a tábla típus ellenére nem a számunkra kívánt formában kapjuk meg az adatokat. És még lehetne folytatni a sort, hogyan tudunk saját magunknak keresztbe tenni, és bosszúságot okozni, hogy ha nem szisztematikusan járunk el a hiba elhárítása érdekében.

Az ilyen esetekben nekem általában az a véleményem, hogy készítsünk egy apró teszt oldalt, ami semmi mást nem csinál, csak a problémás részre koncentrál. Gyakori eset, hogy egy hibakeresés azon bukik el, hogy igazából a hiba egy másik hiba mellékhatásaként jelentkezik, ezért nehezen találjuk meg az eredeti, teljes rendszerben. Fontos hogy ne feltételezésekből induljunk ki, hanem győződjünk meg a tényekről. Nagyon gyakori, amikor menetközben kiderül, hogy az a fránya fájl van rosszul kódolva, az az egy mező valamiért más karakterkódolást kapott, és így tovább.

Mint láttuk, nagyjából három dologra kell figyelni a helyes működés érdekében, ennek megfelelően ha hiba adódik, akkor ezen tényezőknek kell utána járnunk. A legegyszerűbb a megfelelő fejléc küldésének az ellenőrzése, amit könnyedén megtehetünk például a LiveHttpHeaders vagy a(z új kedvenc) TamperData nevű Firefox kiterjesztések használatával. Ha továbbra is fennáll a hiba, akkor mehetünk tovább, de figyeljünk arra, hogy amikor ellenőrizzük, hogy a változtatásaink jó működést eredményeznek-e, akkor "friss" adatokat használjunk, nehogy előforduljon az az eset, hogy már igazából minden jól van konfigurálva, csak az adatbázisban lévő, még a régebbi, rossz konfiguráció alatt felvitt adatok tréfálnak meg minket.

A hiba kijavítása során mindvégig legyünk nagyon alaposak, ez esetben fokozottan érvényes a "lassan jársz, tovább érsz" mondás. Nézzünk pár tipikus hibát:
  • "A böngészőben jól jelenik meg, de ha a DB-ben nézem, akkor mindenféle kirksz-krakszok vannak." Ez jellemzően akkor fordul elő, amikor nem adunk ki egy űrlap esetén megfelelő fejlécet (pl. egy magyar oldal esetén nincs vagy latin1), ezért a böngésző bizonyos ékezetes karaktereket HTML entity-ként küld el a szervernek, vagy pl. Internet Explorer esetén egy másik, tetszőlegesen választott karakterkódolást használva.
  • "Az adatbázisban biztosan jók az adatok, mert ilyen-olyan kliensben jól jelenik meg." Fontos, hogy meggyőződjünk arról, hogy tényleg milyen formában van letárolva az adat. Például a MySQL automatikusan konvertálja az adatokat a kliens (jelen esetben a PHP) karakterkódolása és az adott mező tényleges karakterkódolása között.
  • "Minden jól be van állítva, a mező is latin2, a fejléc is latin2, mégis eltűnik az ő, ű betű." Na ez itt már egy érdekesebb téma. Amikor a PHP-ból kapcsolódunk a MySQL-hez, akkor alap esetben a kliens oldali karakterkódolás a szerver alapértelmezett karakterkódolása lesz, ami többnyire latin1 szokott lenni, hacsak külön nem állítják át egy másik értékre. Kapcsolódik a PHP, a character_set_client latin1 lesz. Beszúrjuk szépen a böngészőből kapott latin2-es szöveget, de a MySQL úgy tudja, hogy mi latin1-et fogunk neki adni, ezért elcsodálkozik az ő, ű karakteren, és mivel ilyen nincs a latin1-ben, ezért lecseréli őket. Ennek elkerülése végett célszerű kiadni a SET NAMES latin2 parancsot, így alkalmazásunk függetlenné válik az éppen használt MySQL szerver beállításaitól.

_charset_, accept_charset

Fentebb már szóba került, hogy külön kezelnünk kell azt az esetet, amikor a felhasználó az oldalunkon szereplő űrlapba olyan karaktert ír be, amely nem szerepel az oldalunkhoz rendelt kódlapban. Először is lássuk, hogy a különböző böngészők mit is tesznek ebben az esetben. A Firefox és Opera úgy jár el, hogy az adott kódtáblában nem megtalálható karaketereket lecseréli azok NCR megfelelőjére, az Internet Explorer ezzel szemben önkéntesen megváltoztatja az elküldendő adatok karakterkódolását, és abban a formában küldi az adatokat. Ezt követően nézzük, hogy egyáltalán milyen mankókat használhatunk az ilyen esetek elleni védekezéshez.

Az egyik segítség egy _charset_ nevű rejtett input mező elhelyzése az úrlapon, melyben a böngésző (amennyiben támogatja ezt a módszert) jelzi, hogy valójában milyen karakterkódolású is a küldött adat. Jelenleg mindhárom a cikkben már említett böngésző támogtja ezt, valamint ez a megoldás a Web Froms 2.0 ajanlás része is. Ha például Internet Explorer alatt nem határozom meg az oldal karakterkódolását, akkor ha az elküldött adat az "abc" szöveg, akkor a _charset_ értéke ISO-8859-1 lesz, de ha már tartalmaz a szöveg mondjuk egy ő betűt, akkor Windows-1250. A fentiek fényében használhtajuk ezt az értéket arra, hogy a kapott adatot az általunk használt kódtáblára konvertáljuk. Egy több országban futó oldal esetén például az volt a tapasztalat, hogy hiába fért bele az összes érintett nyelv minden karaktere a használt kódlapba, mégis néha előfordult, hogy az Explorer kódlapot váltott (valószínűleg copy-paste szövegek esetén), és ilyenkor nagy segítség volt az _charset_ által nyújtott információ.

A másik mankónk a form tag accept-charset attribútuma. Ebben azt tudjuk jelezni a böngésző számára, hogy szerver oldali űrlap feldolgozó scriptünk milyen karakterkódolásokat képes kezelni. Hmm, miért hasznos ez számunkra? Mindjárt látni fogjuk részletesen, de előzetesen annyit, hogy ha itt megadunk egy karakterkódolást, akkor a böngészőknek ezt kéne használni az adatok küldésekor szemben az oldal számára megadottal. Azért írtam, hogy kéne, mert a vizsgált böngészők közül az Internet Explorer ezúttal is tartogat számunkra némi meglepetést.

Vizsgálódásom alapját a következő kérdések képezték:
  • Mi az adott böngésző esetén az alapértelmezett kódlap?
  • Mi történik, ha olyan karaktert ütök le, amely része az oldal kódlapjának?
  • Mi történik, ha olyan karaktert ütök le, amely nem része az oldal kódlapjának?
  • Mi történik, az előző esetben, ha van accept_charset megadva, és az érintett karakter része az itt megadott kódlapnak?
  • Mi történik, az előző előtti esetben, ha van accept_charset megadva, de az érintett karakter nem része az itt megadott kódlapnak?
A vizsgálat során a következő kis scriptecskét használtam, melyet működés közben is kipróbálhatunk.
<?php
	session_start();
	if (isset($_GET['charset'])) {
		$_SESSION['charset'] = $_GET['charset'];
	}

	if (!empty($_SESSION['charset'])) {
		header('Content-Type: text/html; charset='.$_SESSION['charset']);
		echo 'Current charset: '.$_SESSION['charset'].'<br>';
	}
?>
Set charset to:
<a href="?charset=ISO-8859-1">ISO-8859-1</a>
<a href="?charset=ISO-8859-2">ISO-8859-2</a>
<a href="?charset=UTF-8">UTF-8</a>
<a href="?charset=0">none</a>
<br><br>

accept-charset="UTF-8"
<form method="post" accept-charset="UTF-8">
	<input type="hidden" name="_charset_">
	<input name="text" size="1" maxlength="1">
	<input type="submit">
</form>

accept-charset="iso-8859-2"
<form method="post" accept-charset="iso-8859-2">
	<input type="hidden" name="_charset_">
	<input name="text" size="1" maxlength="1">
	<input type="submit">
</form>

accept-charset=none
<form method="post">
	<input type="hidden" name="_charset_">
	<input name="text" size="1" maxlength="1">
	<input type="submit">
</form>

Latin1: &#x00BB;<br>
Latin2: &#x0165;<br>
Latin3: &#x011F;<br>
<br>

<?php
	if (!empty($_POST)) {
		echo '_charset_: '.$_POST['_charset_'].'<br>';
		echo 'text: '.$_POST['text'].'<br>';
		echo 'text.type: '.(strlen($_POST['text']) == 6 ? 'NCR':'CHAR').'<br>';
	}
?>
A script nagyon egyszerű, lehetőségünk van meghatározni az oldal kódlapját, majd pedig különböző accept-charset beállítások mellett karaktereket küldeni feldolgozásra. Ebben az esetben a script kiírja az _charset_ változó értékét, valamint jelzi, hogy a böngésző karaktert vagy NCR-t küldött-e. Ezenkívül még megjelenít három karaktert, melyeket billentyűzetről nehezen tudnánk bevinni az input mezőbe, de így könnyedén kijelölhetőek és beilleszthetőek. Ezek jelentősége, hogy a mellettük szereplő kódlapban azonos az értékük, és mindegyiküket csak az adott kódlap tartalmazza, így jó alanyai lesznek a tesztelésnek.

A következő táblázatok azt fogják tartalmazni, hogy az egyes böngészők adott beállítások és adott kódlapba tartozó input esetén milyen formátumban és kódlappal küldik a beírt adatokat a szervernek.
                                 Internet Explorer                           
+----------------------------------------------------------------------------+
|                                 |     accept_charset attribútum értéke     |
|                                 |------------------------------------------|
|                                 |    nincs     |  ISO-8859-1  |   UTF-8    |
|---------------------------------+--------------+--------------+------------|
|   |            |   | ISO-8859-1 |     CHAR     |     CHAR     |    CHAR    |
|   |            | i |            |  ISO-8859-1  |  ISO-8859-1  | ISO-8859-1 |
|   |            | n |------------+--------------+--------------+------------|
|   |   nincs    | p | ISO-8859-2 |     CHAR     |     CHAR     |    CHAR    |
|   |            | u |            | Windows-1250 | Windows-1250 |   UTF-8    |
|   |            | t |------------+--------------+--------------+------------|
|   |            |   | ISO-8859-3 |     CHAR     |     CHAR     |    CHAR    |
|   |            |   |            | Windows-1254 | Windows-1254 |   UTF-8    |
|   |------------+---+------------+--------------+--------------+------------|
| K |            |   | ISO-8859-1 |     CHAR     |     CHAR     |    CHAR    |
| a |            | i |            |  ISO-8859-1  |  ISO-8859-1  | ISO-8859-1 |
| r |            | n |------------+--------------+--------------+------------|
| a | ISO-8859-1 | p | ISO-8859-2 |     CHAR     |     CHAR     |    CHAR    |
| k |            | u |            | Windows-1250 | Windows-1250 |   UTF-8    |
| t |            | t |------------+--------------+--------------+------------|
| e |            |   | ISO-8859-3 |     CHAR     |     CHAR     |    CHAR    |
| r |            |   |            | Windows-1254 | Windows-1254 |   UTF-8    |
|   |------------+---+------------+--------------+--------------+------------|
| k |            |   | ISO-8859-1 |     CHAR     |     CHAR     |    CHAR    |
| ó |            | i |            | Windows-1252 | Windows-1252 |   UTF-8    |
| d |            | n |------------+--------------+--------------+------------|
| o | ISO-8859-2 | p | ISO-8859-2 |     CHAR     |     CHAR     |    CHAR    |
| l |            | u |            |  ISO-8859-2  |  ISO-8859-2  | ISO-8859-2 |
| á |            | t |------------+--------------+--------------+------------|
| s |            |   | ISO-8859-3 |     CHAR     |     CHAR     |    CHAR    |
|   |            |   |            | Windows-1254 | Windows-1254 |   UTF-8    |
|   |------------+---+------------+--------------+--------------+------------|
|   |            |   | ISO-8859-1 |     CHAR     |     CHAR     |    CHAR    |
|   |            | i |            |    UTF-8     |    UTF-8     |   UTF-8    |
|   |            | n |------------+--------------+--------------+------------|
|   |   UTF-8    | p | ISO-8859-2 |     CHAR     |     CHAR     |    CHAR    |
|   |            | u |            |    UTF-8     |    UTF-8     |   UTF-8    |
|   |            | t |------------+--------------+--------------+------------|
|   |            |   | ISO-8859-3 |     CHAR     |     CHAR     |    CHAR    |
|   |            |   |            |    UTF-8     |    UTF-8     |   UTF-8    |
+----------------------------------------------------------------------------+
Lássuk, hogy mit tudunk a fentiekből kihámozni. Az Explorer esetében az alapértelmezett kódlap az ISO-8859-1 (pedig a területi beállításom magyar). A küldendő karakterek szempontjából azt a logikát követi, hogy ha az nem fér bele az oldal kódlapjába, akkor megpróbál találni egy olyan kódlapot, amelynek része, és ebben küldi el. Amennyiben nem talál ilyet, akkor elvileg ő is NCR-t küld, de ezt az esetet nem sikerült kikényszeríteni belőle. Az accept_charset kezelése elég sajátos a másik két böngésző viselkedéséhez képest. Egyrészről fura, hogy bizonyos esetekben figyelembe veszi azt, máskor nem. Ha például egy ISO-8859-1-es oldalunk van, amin egy ISO-8859-2-es karaktert próbálunk küldeni, akkor ha megnézzük a táblázatot, azt látjuk, hogy az accept_charset ISO-8859-2-es értéke esetén a Windows-1250-es kódlapot választja, viszont az UTF-8-as értéket már figyelembe veszi, és azt használja. Másrészről azzal a felfogással is lehet vitatkozni, hogy ha a beírt karakter belefér az oldal kódlapjába, akkor teljes mértékben figyelmen kívül hagyja az accept_charset beállítást, hiszen ez azt mondja meg, hogy a fogadó script milyen kódolásokat képes megérteni, és egyáltalán nem biztos, hogy ennek összhangban kell lennie az oldal kódlapjával (pl. egy magyar oldalról adatokat küldünk egy angol oldalnak).
                                  Firefox
+--------------------------------------------------------------------+
|                                 | accept_charset attribútum értéke |
|                                 |----------------------------------|
|                                 |    nincs    | ISO-8859-1 | UTF-8 |
|---------------------------------+-------------+------------+-------|
|   |            |   | ISO-8859-1 |    CHAR     |    NCR     | CHAR  |
|   |            | i |            | ISO-8859-1  | ISO-8859-2 | UTF-8 |
|   |            | n |------------+-------------+------------+-------|
|   |   nincs    | p | ISO-8859-2 |     NCR     |    CHAR    | CHAR  |
|   |            | u |            | ISO-8859-1  | ISO-8859-2 | UTF-8 |
|   |            | t |------------+-------------+------------+-------|
|   |            |   | ISO-8859-3 |     NCR     |    NCR     | CHAR  |
|   |            |   |            | ISO-8859-1  | ISO-8859-2 | UTF-8 |
|   |------------+---+------------+-------------+------------+-------|
| K |            |   | ISO-8859-1 |    CHAR     |    NCR     | CHAR  |
| a |            | i |            | ISO-8859-1  | ISO-8859-2 | UTF-8 |
| r |            | n |------------+-------------+------------+-------|
| a | ISO-8859-1 | p | ISO-8859-2 |     NCR     |    CHAR    | CHAR  |
| k |            | u |            | ISO-8859-1  | ISO-8859-2 | UTF-8 |
| t |            | t |------------+-------------+------------+-------|
| e |            |   | ISO-8859-3 |     NCR     |    NCR     | CHAR  |
| r |            |   |            | ISO-8859-1  | ISO-8859-2 | UTF-8 |
|   |------------+---+------------+-------------+------------+-------|
| k |            |   | ISO-8859-1 |     NCR     |    NCR     | CHAR  |
| ó |            | i |            | ISO-8859-2  | ISO-8859-2 | UTF-8 |
| d |            | n |------------+-------------+------------+-------|
| o | ISO-8859-2 | p | ISO-8859-2 |    CHAR     |    CHAR    | CHAR  |
| l |            | u |            | ISO-8859-2  | ISO-8859-2 | UTF-8 |
| á |            | t |------------+-------------+------------+-------|
| s |            |   | ISO-8859-3 |     NCR     |    NCR     | CHAR  |
|   |            |   |            | ISO-8859-2  | ISO-8859-2 | UTF-8 |
|   |------------+---+------------+-------------+------------+-------|
|   |            |   | ISO-8859-1 |    CHAR     |    NCR     | CHAR  |
|   |            | i |            |    UTF-8    | ISO-8859-2 | UTF-8 |
|   |            | n |------------+-------------+------------+-------|
|   |   UTF-8    | p | ISO-8859-2 |    CHAR     |    CHAR    | CHAR  |
|   |            | u |            |    UTF-8    | ISO-8859-2 | UTF-8 |
|   |            | t |------------+-------------+------------+-------|
|   |            |   | ISO-8859-3 |    CHAR     |    NCR     | CHAR  |
|   |            |   |            |    UTF-8    | ISO-8859-2 | UTF-8 |
+--------------------------------------------------------------------+
A Firefox esetében is az alapértelmezett kódlap az ISO-8859-1. A karakterek küldésének kezelése letisztultabbnak és logikusabbnak mondható. Ha adtunk meg accept_charset-et, akkor abban a kódlapban próbálja meg elküldeni az adatokat, ha nem akkor az oldaléban. És bármely esetben ha a karakter nem fér bele az érintett kódlapba, akkor helyette a böngésző NCR-t küld.
                                  Opera
+--------------------------------------------------------------------+
|                                 | accept_charset attribútum értéke |
|                                 |----------------------------------|
|                                 |    nincs    | ISO-8859-1 | UTF-8 |
|---------------------------------+-------------+------------+-------|
|   |            |   | ISO-8859-1 |     NCR     |    NCR     | CHAR  |
|   |            | i |            | ISO-8859-2  | ISO-8859-2 | UTF-8 |
|   |            | n |------------+-------------+------------+-------|
|   |   nincs    | p | ISO-8859-2 |    CHAR     |    CHAR    | CHAR  |
|   |            | u |            | ISO-8859-2  | ISO-8859-2 | UTF-8 |
|   |            | t |------------+-------------+------------+-------|
|   |            |   | ISO-8859-3 |     NCR     |    NCR     | CHAR  |
|   |            |   |            | ISO-8859-2  | ISO-8859-2 | UTF-8 |
|   |------------+---+------------+-------------+------------+-------|
| K |            |   | ISO-8859-1 |    CHAR     |    NCR     | CHAR  |
| a |            | i |            | ISO-8859-1  | ISO-8859-2 | UTF-8 |
| r |            | n |------------+-------------+------------+-------|
| a | ISO-8859-1 | p | ISO-8859-2 |     NCR     |    CHAR    | CHAR  |
| k |            | u |            | ISO-8859-1  | ISO-8859-2 | UTF-8 |
| t |            | t |------------+-------------+------------+-------|
| e |            |   | ISO-8859-3 |     NCR     |    NCR     | CHAR  |
| r |            |   |            | ISO-8859-1  | ISO-8859-2 | UTF-8 |
|   |------------+---+------------+-------------+------------+-------|
| k |            |   | ISO-8859-1 |     NCR     |    NCR     | CHAR  |
| ó |            | i |            | ISO-8859-2  | ISO-8859-2 | UTF-8 |
| d |            | n |------------+-------------+------------+-------|
| o | ISO-8859-2 | p | ISO-8859-2 |    CHAR     |    CHAR    | CHAR  |
| l |            | u |            | ISO-8859-2  | ISO-8859-2 | UTF-8 |
| á |            | t |------------+-------------+------------+-------|
| s |            |   | ISO-8859-3 |     NCR     |    NCR     | CHAR  |
|   |            |   |            | ISO-8859-2  | ISO-8859-2 | UTF-8 |
|   |------------+---+------------+-------------+------------+-------|
|   |            |   | ISO-8859-1 |    CHAR     |    NCR     | CHAR  |
|   |            | i |            |    UTF-8    | ISO-8859-2 | UTF-8 |
|   |            | n |------------+-------------+------------+-------|
|   |   UTF-8    | p | ISO-8859-2 |    CHAR     |    CHAR    | CHAR  |
|   |            | u |            |    UTF-8    | ISO-8859-2 | UTF-8 |
|   |            | t |------------+-------------+------------+-------|
|   |            |   | ISO-8859-3 |    CHAR     |    NCR     | CHAR  |
|   |            |   |            |    UTF-8    | ISO-8859-2 | UTF-8 |
+--------------------------------------------------------------------+
Az Opera teljesen úgy működik, mint a Firefox kivéve, hogy az alapértelmezett kódlap az én konfigomon az ISO-8859-2.

A fentiek alapján láthatjuk, hogy ha az oldalunk UTF-8 kódolást használ, akkor sok gondunk nincs, ellenkező esetben viszont érdemes valamilyen stratégiát kialakítanunk a problémás esetek kezelésére. Döntésünk meghozatalakor még azt vegyük figyelembe, hogy lehetőleg kerüljük azokat az eseteket, amikor NCR-eket kaphatunk vissza, ugyanis ezekkel van egy komoly gond: nem tudjuk eldönteni, hogy egy NCR azért szerepel a szövegben, mert a böngésző helyezte el benne egy problémás karaktert lecserélve, vagy pedig ténylegesen része kéne legyen a szövegnek. Hogy ez jobban érthető legyen: mind az "őő", mind az "ő&#337;" input alapján a szerverre "&#337;&#337;" fog megérkezni, és nem tudjuk eldönteni, hogy a felhasználó mit is gépelt be. Ezen információk fényében én azt javaslom, hogy amennyiben nem UTF-8 az oldalunk kódolása, akkor helyezzünk el egy _charset_ nevű rejtett input elemet űrlapjainkon, és állítsuk be az accept_charset attribútumot UTF-8-ra, és a bejövő adatokon a kapott _charset_ érték alapján szükség esetén végezzük el a számunkra megfelelő konverziót (például az iconv PHP kiterjesztés segítségével).
 
1

hibás cím

Joó Ádám · 2006. Szep. 3. (V), 10.34
Olvasatlanban csak annyit, hogy a karakterkódolás az egy szó!

Szerk.: meg a kanosszajárás is.
2

köszi, javítva

Hodicska Gergely · 2006. Szep. 3. (V), 15.59
Felhő
34

IE és az UTF-8 oldal esete

provizozo · 2008. Júl. 23. (Sze), 08.15
Hallihó

Lenne egy kis gondom egy weblappal kapcsolatban, amit sehogyan sem tudtam eddig megoldani ...

Van egy html oldalam és van három különböző teszt számítógépem IE-vel, az egyiken Firefoxszal is.

A weblap a három gép közül az egyiken (IE6) azt csinálja, hogy letöltődik, és a utf-8 header (elmentve is így van persze) ellenére rossz kódlappal jelenik meg. Megnyomom a Refresh-t a böngészőn, akkor helyreáll és jó egészen addig, míg ki nem törlöm a helyben tárolt tartalmat. Akkor legközelebb elsőre megint rosszul töltődik le....a másik kettő gépen viszont ezt nem csinálja, mindenképpen jó.

Mivel a három gép közül csak az egyiken csinálja ezt, ezért gondolom hogy az alapvető hiba nem weblappal lehet.

Hanem azt lenne jó tudni, hogy akkor hol lehet a gubanc, ha élesben fog menni a weboldal akkor vajon a felhasználók mekkora része fogja úgy látni, hogy egy ócska, olvashatatlan oldalra tévedt?....Milyen beállítástól vagy komponenstől függhet, amit talán ellenőrizni is tudnék hogy megvan-e, megfelelő-e, mint ahogyan most pl. a Javascripttel is teszem...

Ha volna valakinek ötlete, hogy hol kellene keresgélni, annak örülnék...
35

Közben sikerült kitalálnom !

provizozo · 2008. Júl. 23. (Sze), 08.54
Hallihó,


Rájöttem közben!
Nálam akkor jelentkezik ez a hiba, ha az oldal HEAD-jében nincs Language META tag ÉS az Explorerben a Jobb gomb->Kódolás menüben be van pipálva az Automatikus választás.



Ha a pipa nincs ott, akkor az oldal elsőre is jól jön le.

Illetve én beletettem az oldalba eg ilyen TAG-et:



<META HTTP-EQUIV="Content-Language" CONTENT="en-GB">


és ezután már jól műxik ha van pipa ha nincs. Magyar lang beállítással nem próbáltam az még hátra van.



Üdv !
3

3 apróság

vince · 2006. Szep. 3. (V), 21.28
1. az idézet mondás tudomásom szerint egy jótanács, vagyis helyesen "Lassan járj, tovább érsz!"
2. IE "táblázat" után a kikényszeríteni szóból kimaradt egy karakter
3. a "táblázatokat" lehetne rendes táblázatként beszúrni a szövegbe? Nagyon átláthatlannak és csúnyának találom őket így...
4

re: 3 apróság

Hodicska Gergely · 2006. Szep. 3. (V), 22.11
1. az idézet mondás tudomásom szerint egy jótanács, vagyis helyesen "Lassan járj, tovább érsz!"

Véleményes, láttam elég gyakran mindkét formában.

2. IE "táblázat" után a kikényszeríteni szóból kimaradt egy karakter

Köszi, javítva.

3. a "táblázatokat" lehetne rendes táblázatként beszúrni a szövegbe? Nagyon átláthatlannak és csúnyának találom őket így...

Ezek kicsit komplex táblázatok, nem sikerült bbcode-dal rowspant és colspant megadni, ezért jött a lynx feeling, de simán weboldalon is szinte teljesen így néz ki.
Az értelmezése meg szerintem adja magát (bár lehet, hogy csak azért, mert sokat bíbelődtem vele ;)), szinte olvashatod balról jobbra: x karakterkódolású oldalon jön inputként egy x kódlapban lévő karakter, aminek a hatására a böngésző az űrlap accept-charset beállítása függvényében adott formában küldi az adatot.


Felhő
8

Gratula a cikkhez!

Balogh Tibor · 2006. Szep. 4. (H), 23.49
Gratula a cikkhez!

Úgy látom érdemes volt kikönyörögnöm ezt a parancssoros "színezést", ha ti is szívesen használjátok. Szerintem semmi baj ezekkel a táblázatokkal. Nem szép színes, de legalább átlátható.
5

Köszönöm

Anonymous · 2006. Szep. 4. (H), 10.16
Nagyon hasznos írás, csak szeretném megköszönni.

üdv,
Feri
6

Internet Explorer 7 Release Candidate 1 in standalone mode

toxin · 2006. Szep. 4. (H), 12.03
-ben nincs változás a fenti táblázathoz képest, a nem standalone mode-ban nemtudom :S

ui: persze köszönet a cikkért :) (crossForm-om nevében is :)) )
7

Köszönjük!

TeeCee · 2006. Szep. 4. (H), 18.18
Köszönjük a hasznos cikket és a hasznos scriptecskét, ami jó példaként szolgál!
(nemrég sokat szenvedtem latin2 <-> UTF-8 vegyesfelvágottban írt egész nagy rendszeren, aminek UTF-8at kellett kiadnia. Mennyivel egyszerűbb most dolgozni vele, hogy minden UTF-8as. DE igazából mindegy, hogy UTF8, avagy Latin2, csak egyforma legyen)
9

UTF-8 Rulez!

Anonymous · 2006. Szep. 5. (K), 12.38
Hát egen, ez nem egyszerű kérdés. A tapasztalat persze azt mondja, mindent mindig UTF-8 kódolással használj, akkor nem írhatank be olyan karaktert ami nincs benne a kódlapban. Sosem tudhatod előre, hogy egy latin2-re megírt rendszernek mikor kell befogadnia egy a kódlapban nem szereplő karaktert. Sok hosszú éjszakát és keserves újraírást spórolhatsz meg ha a fent leírt beállításokat eleve Unicode-ra alkalmazod. Végülis kinek fáj az, ha egy magyar közönség számára készült oldal gond nélkül lekezeli a hagyományos kínai karaktereket is. Bár a php még nem teljesen alkalmas az UTF-8 kezelésére, azért ez nem megkerülhetetlen probléma. Azért várom már a php6-ot, amiben zend-ék végre megvalósítják a teljes UTF-8 támogatást.

rage
18

utöfö nyóc

Anonymous · 2006. Okt. 4. (Sze), 20.19
Azért az picit szánalmas, hogy az UTF-et ennyi idő után még mindig nem támogatja rendesen egy olyan elterjedt prog. nyelv mint pl. a PHP, de pl. a Delphi-vel is vannak hasonló gondok, meg szinte mindennel...szép, mosolygós dolog az UTF, de valahogy nem törekednek a fejlesztők a teljes átláthatóságra és hazsnálhatóságra. Idő kérdése...remélem.

v.jani
19

he?

amonrpg · 2006. Okt. 5. (Cs), 06.18
Nem igazán értem, szerintem, amit írsz.
Vagy ha igen:
Ha nem nagyon vigéckedsz a PHP fájlodban a speciális karakterekkel, akkor az esetek 99%-ban nincs gondod az UTF kódolással. A maradékra meg ott vannak az mb_* fgv-nyek.
A másik esetben nem a delphivel van a probléma. :D Hanem a windows-zal és azokkal a kontrollokkal, komponensekkel, amiket a Microsoft csinált. Ugyanis a windows alapállapotban nem nagyon kezeli az unicode-ot, csak kiegészítőkkel, vérrel és verítékkel. Amúgy is az MS nyelv- és kódolástámogatása egy szép nagy vicc.
De a delphi-hez is le tudsz tölteni kontrol-okat, amik unicode-osak, keress rá a TNT csomagra. Egész jó cucc, én használom. :)

Ráadásként: az UTF és az Unicode szép és átlátható. Semmi mágia nincs benne. Az, hogy a megvalósításokkal sok helyen gond van, nos az informatika mindig is ilyen volt. :D Sosem ment semmi elsőre flottul. :) Csak idő kérdése, már nincs olyan messze az UTF-es, register_globals-mentes PHP6. Addig meg igyunk meg még egy sört.... :D
10

Segítséget szeretnék

zuzda · 2006. Szep. 6. (Sze), 18.18
Szevasztok!

Nekem az a problémám, hogy localhost-on az "ő" betűt nem jeleníti meg. Egyenlőre csak adatbázisból jelenít meg adatokat. Próbáltam utf-8-ban is, iso-8859-2-ben is, MySQL-ben és a meta információknál is ugyanarra állítottam, de nem akarja az igazságot. Próbáltam Firefoxban is állítani a karakterkódolást.
Felraktam az oldalt uw-ra, onnan tökéletesen megy.
Van valami tippetek?
11

szisztematikus hibakeresés

Hodicska Gergely · 2006. Szep. 6. (Sze), 22.48
Szia!


El kéne olvasd még egyszer figyelmesen a cikket. Pont ezt próbáltam meg kiemelni, hogy ne csak nekiálljunk állítgatni a dolgokat, hanem előbb győződjünk meg a tényekről. Másodsorban kód nélkül semmit sem tudunk csinálni. Mielőtt elkéred a DB-ből az adatokat, kérdezd le, hogy mi a kliens oldali karakterkódolás. Ellenőrizd a böngészőben, hogy a megfelelő fejlécet adod-e ki, hogy nem a szövegek a DB-ben hibásak (lásd a cikkben a friss adatok használatára történő utalást).


Felhő
12

thx

zuzda · 2006. Szep. 7. (Cs), 13.08
Akkor átrágom mégegyszer.
Azért kössz.
13

sikerült

zuzda · 2006. Szep. 7. (Cs), 13.53
Kipróbáltam a "set names 'latin2'" beállítást, így működik. Az lehetett talán a probléma, hogy az adatokat más kódolással vittem fel adatbázisba, és utána állítottam át latin2-re.

Kicsit nehezen értelmeztem elsőre a cikkben írtakat, az lehetett a probléma :)
14

UTF-8

mdesign · 2006. Szep. 21. (Cs), 13.10
A set names lefuttatását nem lehet sehogy kikerülni?

Jelenleg minden fájlom UTF-8
Az adatbázisban is minden utf8/utf8_hungarian_ci
my.ini: default-character-set=utf8
php.ini: default-charset: kikommentezve

Mégis kérdőjelek jelennek meg az ékezetek helyett:(
Csak PHP-ban. MySql managerben jól jeleníti meg.
15

meg van a megoldás:)

mdesign · 2006. Szep. 21. (Cs), 16.09
Ahhoz, hogy alapértelmezetten UTF-8-al kapjuk a karaktereket, a következő beállítást kell elmenteni a my.ini-ben:

#Command(s) that are executed for each new connection
init-connect=SET NAMES utf8;
Ez viszont önmagában még nem elég. Mivel ha SUPER privilégium van rendelve a userhez amivel csatlakozunk, akkor nem fut le az init-connect!
Ezért a mysql user-től vonjuk meg ezt a jogosultságot, és már megy is!

Üdv Karesz
24

utf8_general_ci / ut8_hungarian_ci

rrd · 2007. Jan. 3. (Sze), 15.34
Igazából mi a különbség a utf8_general_ci és a ut8_hungarian_ci között?
31

general vs. hungarian

ralesk · 2007. Már. 21. (Sze), 16.01
A rendezés (collation).

A general az csak simán kód szerint (így a–z elébb jön, mint á, å, ð, ő, azok pedig előbb, mint б, ц, ก, น…), a hungarian pedig a magyar rendezési elvek szerint: aá b c cs d dz dzs eé f g gy h ií j k l ly m n ny oó öő p q r s sz t ty uú üű v w x y z zs
16

ismeretlen kodolas identifikacio

Anonymous · 2006. Okt. 4. (Sze), 15.38
Jo a cikk,gratula. kicsit offtopic lesz a kerdesem,de eddig nem igazan talaltam megoldast.:( Php-bol kell kulso weboldalak tartalmat beolvasnom, es a Content-Type fejléc charset paramétere alapjan konvertalnom a szoveget a sajat kodolasomba. Szuperul mukodik a dolog, amig nem akadok olyan oldalra, ahol hianyzik ez a parameter a html fejlecbol. A kerdesem az lenne, letezik e valamilyen modszer, hogy biztonsagosan meghatarozzam milyen kodolasu az adott oldal?Tehat tkp. ismeretlen kodolasu szoveget kell sajat kodolasba konvertalni. Koszonom, jalso
17

dekodolasnal nincs biztonsag

amonrpg · 2006. Okt. 4. (Sze), 17.15
Ismeretlen kódolású szöveg átalakítása sosem biztonságos.
Ez az alap.
De, elég jó hatásfokot lehet elérni ezekkel a fgv-ekkel (http://php.net):
iconv vagy mb_convert_encoding. Nézz utána.
20

MyAdmin vicces kedvű

Joó Ádám · 2006. Okt. 7. (Szo), 18.06
Tipp: ha a phpMyAdminban kriksz-krakszok jelennek meg, akkor ne essünk neki egyből őrült módon debuggolni, hanem ne legyünk restek és írjunk egy szkriptet az adatok kiolvasására. Az imént kb egy órám ment veszendőbe úgy, hogy a szöveggel minden rendben volt, csak a MyAdminnak nem tetszett (pedig a headerje is utf-8 volt).
21

Köszönet

Anonymous · 2006. Okt. 26. (Cs), 18.29
Gratula a szerzőnek. Mind a cikk, mind pedig a hozzászólások nagyon hasznosak (már amelyikek nem a helyesírási hibákkal bíbelődnek...)

Z
22

ISO-8859-1

Anonymous · 2006. Nov. 7. (K), 16.52
janoszen.hu - egy példa ISO-8859-1-re
23

LOL

janoszen · 2006. Dec. 20. (Sze), 00.46
Na, ez a kb 5 perc alatt földobott... :D
25

kérdés

TIV · 2007. Jan. 17. (Sze), 20.40
na valamit nem értek...

<?
header("Content-Type: text/html; charset=latin2");
$kapcsolat = mysql_connect('localhost', 'atjaro', 'haz')
or die('Nem tudok csatlakozni: ' . mysql_error());
mysql_select_db("test")
or die ("<br />Nem lehet megnyitni az adatbazist!");

mysql_query("SET NAMES latin2");

$sql = "INSERT INTO nevek (nev) VALUES ('hegedűs');";
mysql_query($sql,$kapcsolat) or die("nem tudtam hozzáadni!");
?>
headerben is latin2, set names is latin2, sőt livehttpheadersben megnéztem, ott is latin2, és a mysql def.charset is latin2...mégis, ha megnézem mysql query toolal, akkor 'hegedus' lesz belőle...kiolvastatom PHPval, akkor is..

miért? valamit nem olvastam el? köszönöm!
26

mivel mented el?

Hojtsy Gábor · 2007. Jan. 17. (Sze), 21.38
Ezt a fájlt latin2 kódolással mentetted el a szerkesztőprogramodban? Nem mindegy ám, hogy milyen bájtok vannak ott az ű betű helyén a fájlban.
27

iso-8859-2

Hodicska Gergely · 2007. Jan. 19. (P), 16.55
Szia!


Biztosra nem mondanám, hogy nem lehet itt "header("Content-Type: text/html; charset=latin2");" latin2-t mondani, de az biztos, hogy mindig azt láttam, hogy itt ilyen formában adják meg: iso-8859-2. Meg kéne próbálnod kicserélni. Plusz amikor az oldal bejön a böngészőbe, akkor a böngésző milyen encodingot választ?


Üdv,
Felhő
28

jeje:)

TIV · 2007. Jan. 19. (P), 18.30
nah, csinálgattam dolgokat és most az a baj nem tudom miért jó:D

1. headerben elfogadja a latin2-t, és a iso-8859-2-vel is műxik.
2. megnéztem a lap encodingját, Középeurópai ISOra raktam de ha jól emléxem DWben ez az alap beállítás és most nem emlékszem de szerintem ezen volt:S
3. most viszont ezt írta ki: Data too long for column 'nev' at row 1
kiszedtem belőle a mysql_query("SET NAMES latin2"); sort és most megy rendesen.

A MySQL query browserben most 'hegedus'-ből 'heged|s' lett. jó ez így? lekérdezésnél szépen kiírja a lapra az ékezeteket, szóval csak a progi nem kezeli ezeket az ékezeteket megfelelően?

Köszönöm mindkettőtöknek a segítséget, tanultam vmit!:)

Szerk: 5 db most szót használtam!:)))

UI: JAJJ lenne még egy kérdésem!! MySQL! MySQL ADMIN toolsban létrehoztam egy felhasználót, de hogy tudok neki adatbázis létrehozó jogot adni? Nem adatbázison belül táblát! Adatbázist! Azt csak root tud? Mert a jogokkal kapcsolatos részt megtaláltam, szépen rá kell húzni a jogosultságokat az adatbázisokra, nade adatbázis létrehozás jog nincs és azt hova is húznám ugye... előre is köszi!
29

Sehogy se akarja...

Joó Ádám · 2007. Jan. 21. (V), 17.53
Estére működnie kéne az oldalnak, mégsem sikerül belőni a kódolást.

Adott egy excel tábla, ebből utf-8-cal exportáltam csv-be a tartalmat. Ezt a csv-t egy saját szkripttel (utf-8) átírtam sql insertekké.
Létrehoztam a táblát MySql-ben (MySQL alap karakterkészlet utf-8, MySql kapcsolat egyeztetés utf-8_unicode_ci), itt a tábla egybevetése utf-8_hungarian_ci és a mezőké is. Mind a http fejléc, mind a meta tag phpMyAdminban utf-8-as, itt rendesen is jelenik meg.
Az oldalon kiolvasom a tábla tartalmát (a szkript utf-8-as itt is), utf-8-as Content-type-pal kiküldöm. Meghívok egy mysql_query("SET NAMES utf-8");-at , Firefox>Nézet>Karakterkódolás>UNICODE(UTF-8).
Az adatbázisból kiolvasott szöveg pedig rombuszos kérdőjelekkel jelenik meg. A rókában való kísérletezés után kiderül, hogy ezek a szövegek latin2-esek.

Bocs a terjengősségért, igyekeztem minden körülményt megadni. Van bárkinek ötlete, mit nem állítottam be?

Szerk.: Érdekes, az IE (UTF-8-as beállítással) jól jeleníti meg (Opera megint csak hibás.)
30

SET NAMES 'utf8' !

Bitman · 2007. Jan. 25. (Cs), 11.50
Helló!

Szerintem az a hiba, hogy itt ha jól tudom nem kötőjellel, hanem anélkül kell megadni, hogy utf8:
mysql_query("SET NAMES 'utf8'");
37

Re: SET NAMES 'utf8' !

foszto · 2010. Feb. 1. (H), 13.12
Tapasztalataim szerint szerverfüggő, hogy a "SET NAMES 'utf8'", "SET CHARACTER SET utf8" stb. esetében a UTF8 vagy UTF-8 -at kell használni. Mivel többnyire egy szerverre dolgozok most már nem vagyok biztos benne de javítsatok ki ha tévedek, Wines szerveren UTF-8-at Linuxos szervereken UTF8-at kell használni.
32

kösz

new-g · 2007. Már. 28. (Sze), 09.40
Csak meg szeretném köszönni ezt a cikket. Pont egy ilyen problémával álltam szemben már napok óta és nem tudtam megoldani, de most már minden működik. Thx.
33

SET NAMES latin2

ada · 2007. Ápr. 3. (K), 01.29
Ezt pl. MySQL használata esetén a SET NAMES latin2 parancs kiadásával érhetjük el.


Habár még nem volt időm végigolvasni az egész cikket, egy évvel ezelőtti emlékeim szerint ez a parancs csak és kizárólag az új MySQL-eken ment (új alatt értsd, hogy akkoriban még elterjedt volt az a verzió amin nem ment), ami nem teljesen elhanyagolható szerintem.
36

Nekem ez jött be,amikor

Balogh László · 2010. Jan. 21. (Cs), 05.54
Nekem ez jött be,amikor Post-al elküldöm akkor adatbázisba mentés előtt átalakítom az ékezetes betőket.

$karakter_mit= array('á','Á','é','É','ö','Ö','ő','Ő','ü','Ü','ű','Ű','í','Í','ó','Ó');
$karakter_mire = array("&aacute;","&Aacute;","&eacute;","&Eacute;","&ouml;","&Ouml;","&otilde;","&Otilde;",
"&uuml;","&Uuml;","&ucirc;","&Ucirc;","&iacute;","&Iacute;","&oacute;","&Oacute;");

$_POST['szoveg']=str_replace($karakter_mit, $karakter_mire,$_POST['szoveg'] );

38

Sziasztok!Hozzászólások elég

acoliver · 2014. Dec. 8. (H), 19.29
Sziasztok!
Hozzászólások elég régiek, de nekem most aktuális ez a téma. Reménykedek benne, hogy kapok segítséget.
A tudásom nem tökéletes, ellenben nagy a szorgalmam.
Ha jól értem három dologra kell odafigyelni egy egyszerű /adatbázis használata nélküli/oldal elkészítéséhez:

  • valami.php fájlt utf-8 kódolással írjam

  • meta tageknél a charset-et is utf-8-ra állítani

  • header('Content-type: text/html; charset=utf-8');
    header() fgv-nél is ugyan így járok el. Erről tudom, hogy még akkor kell meghívni mielőtt bármi is történne a honlapunkkal.

A következő php kód, amiben szeretném, ha tanácsod adnátok:
index.php

<?php
header('Content-type: text/html; charset=utf-8');
require 'Side.class.php';
	$index = new Side(); 
	$index->show(  );
?>
side.class.php

<?php
class Side {
	public $title = "Oldal";
	public $keyword = "ékezetes betűk"; 
	
	public function showMeta(){
		echo "
		<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\" >
		<meta name=\"keywords\" content=\"" .$this->keyword. "\" >
		<meta name=\"language\" content=\"HU\" >"; 
	}
	public function showBody(){
		echo	"
			<header >
				<p>Ide a honlapon megjelenítendő szöveg...</p>
				<p>	í é á ű ő ú ó ü ö stb.</p>
			</header>";
	}
	public function show(){
		echo "<!DOCTYPE html><html><head>"; 
		$this->showMeta();
		echo "<head><body>"; 
		$this->showBody();
		echo "</body></html>"; 
	}
}
?>
A problémám, hogy csak azoknál az oldalnál működik jól, amelyiknél vagy automatikusra van beállítva a kódolás vagy egyszerűen unicode utf-8-ra.
Már megy az oldal és pont a főnök szembesült elsőnek a problémámmal.
Kérlek segítsetek!
39

uj tema

Pepita · 2014. Dec. 8. (H), 20.28
Legyszi nyiss uj forumtemat es hasznald helyesen a colorer-t.