Převod stránek do UTF-8
Školení, která pořádám
Vzhledem k tomu, že zdejší databáze již podporuje kódování UTF-8, převedl jsem do tohoto kódování i tyto stránky. Databázi jsem převedl již dříve (protože pro způsob porovnávání cp1250_czech
neexistuje varianta nerozlišující velikost písmen), ale vnější podobu stránek jsem převedl až teď.
Kromě samotného převodu textů uložených přímo v souborech (který jsem provedl ve SciTE, protože souborů je jenom pár) bylo potřeba provést následující změny:
- Změnit informaci o kódování v hlavičkách Content-Type (v mém případě direktivou default_charset), XML deklaraci (tu je při použití kódování UTF-8 nebo UTF-16 možné dokonce beztrestně odstranit),
<meta http-equiv="Content-Type">
, odesílaných e-mailech a v SET CHARACTER SET
.
- Pozor je potřeba dát na volání funkce strtr se třemi parametry, nejjednodušší je asi nahradit ho variantou se dvěma parametry, protože žádná vícebajtová náhrada v PHP k dispozici není.
- Problém také může nastat s uloženými cookies – pokud obsahují diakritiku (já do cookie ukládám jméno diskutujícího), tak je prohlížeč bude vracet v původním kódování. Řešit to jde vytvořením nové cookie a postupných převodem starých cookie, já jsem to ale vzhledem k podružnosti způsobených problémů ignoroval. Líbí se mi, jak k podobnému (ale samozřejmě mnohem závažnějšímu) problému přistoupilo Jyxo.
Práce s databází by se měla mírně zrychlit, protože není nutné data na vstupu a výstupu neustále převádět, objem dat přenášených do prohlížeče by díky kompresi prakticky neměl vzrůst. Takhle veliká byla včerejší titulní stránka:
| text | gzip |
Windows-1250 | 40680 B | 13436 B |
UTF-8 | 42451 B | 13684 B |
nárůst | 4.4 % | 1.8 % |
Na co dalšího je podle vašich zkušeností potřeba dát při převodu kódování ještě pozor? Uvítám vaše postřehy v diskusi.
Diskuse
kamil:
Chtěl jsem zeptat, jak je to v mysql s definicí třeba VARCHAR(255) - těch 255 znamená bajtů nebo znaků? Když tam budu chtít uložit 200 znakový text, ve kterém bude 100 českých znaků (takže celkem bude mít 300 bajtů), tak to tam půjde nebo ne?
Pokud jde o verzi MySQL, která podporuje UTF a také je toto kódování pro sloupec zvoleno, jedná se o 255 znaků. Jinak je to 255 bajtů a může se stát, že se znak na hranici přeřízne v půlce.
Václav:
Jakube, někde jste v predchozím článku psal, že je nutno položit dotaz u mysql -> SET CHARACTER SET utf8. Ja když to tam mám, tak to rozbije kódovaní, když ukládám do db. Když tam dam SET NAMES tak to funguje. Jaký je prosím vás mezi tím rozdíl? Jako Collation mám utf_czech_ci. Db je mysql 4.1 a něco
Uvádim príklad:
<?php
public function connect() {
try {
$this->linkid = @ mysql_connect($this->host, $this->user, $this->pswd);
mysql_query("SET CHARACTER SET utf8");
if (!$this->linkid)
throw new Exception("Could not connect to the MySQL server.");
} catch (Exception $e) {
die($e->getMessage());
}
}
?>
lukas:
ja pouzivam
<?php
mysql_query("SET character_set_client=utf8");
mysql_query("SET character_set_connection=utf8");
mysql_query("SET character_set_results=utf8");
?>
a cestina je ok
alsan:
Ty jo.. tohle mi ted dost pomohlo ;) Diky.
Anonym:
Taky ti moc děkuju :D
Jakub Vrána :
Oboje nastavuje kódování vstupu, výstupu a připojení. Vstup a výstup shodně nastavují na předané kódování, kódování připojení nastavuje SET NAMES také na předané, kdyžto SET CHARACTER SET na kódování (a způsob porovnávání) databáze.
Viz http://dev.mysql.com/doc/refman/4.1/en/charset-connection.html.
Z toho usuzuji, že je špatně nastaveno kódování databáze a mohlo by to spravit ALTER DATABASE COLLATE utf8_czech_ci.
MaReK:
Trochu OT: Ale máš někde řešení na konverzi utf-8 do ascii, když potřebuji z titulku článku mít oddiakrizovanou verzi pro name, kvůli mod_rewrite? Začínám s ním, takže nevím ještě co vše je zapotřebí dělat :-(. Díky
Jakub Vrána :
Mám o tom napsaný článek, časem ho tu vystavím.
Fikus:
Nefunkcnost parseru byla v htmlentities(), ktere si pravdepodobne nerozumi s utf8. Jake je reseni? Dvakrat zmenit charset?
Problemy se session a cookie stale pretrvavaji a to POUZE ve Firefoxu(!?) v IE to slape. Mate nekdo podobnou zkusenost?
Fikus:
Tak jsem upgradoval FF a uz to beha asi to byla jen nejaka blbost
Milan:
Zdravím, moc dobře mi v utf-8 nefunguje fce mb_send_mail(). Příchozí emaily vypadají, jako by v utf-8 nebyly ("Přišel" = "PÅ™iÅ¡el"). Nastavení mb_language("uni"); používám. Nevíte tedy někdo, jak správně poslat e-mail s háčky a čárkami? Díky
PS: Jakube, nenašel by se čas o tom napsat článek?
Jakub Vrána :
Já používám běžnou funkci mail() a předám jí tyto hlavičky:
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Ján Koštial:
Diakritika v hlavičke sa musí kódovať podľa RFC2047. Používam na to nasledovnú funkciu:
<?php
//--------------------------------------------------------------------------------------------------
//funkcia zakóduje reťazec do tvaru použiteľného v hlavičke emailu podľa RFC2047
//--------------------------------------------------------------------------------------------------
function RFC2047encode($input, $charset = 'windows-1250')
{
preg_match_all('/(\s?\w*[\x80-\xFF]+\w*\s?)/', $input, $matches);
foreach ($matches[1] as $value) {
$replacement = preg_replace('/([\x20\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value);
$input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input);
}
return $input;
};
?>
Funkcia nie je moja, našiel som to niekde na nete. Patrilo by sa spomenúť autora, ale fakt už neviem...
shuster:
Aj ja sa snažím prejsť na kódovanie UTF-8.
Dump z databázy som prekonvertoval z kódovania 8859-2 do UTF-8
Po pripojení na databázu posielam dopyty:
SET NAMES utf8
SET CHARACTER SET utf8
a pre istotu aj:
SET COLLATION_CONNECTION='utf8_slovak_ci'
Výstup sa mi v browseri zobrazí správne, ale po zobrazení zdroja mám všetky výpisy z DB v paznakoch (t.j. znaky s diakritikou sú viacbajtovo).
Takisto stránka neprejde cez validator.w3.org z dôvodu "line NN, NN, ... it contained one or more bytes that I cannot interpret as utf-8"
SHOW FULL COLUMNS FROM tabulka; vracia collation utf8_general_ci a NULL
Ak si nechám urobiť výpis tejto tabuľky pramo v PMA, tak sa tam aj zdroj zobrazí správne.
Problém je len pri zobrazení zdroja z môjho scriptu...
Napr. táto stránka je v kódovaní UTF-8 a aj zroj zobrazí normálne :)
Poradí mi niekto?
shuster:
Skúšal som nechat aj tabuľku v pôvodnom kódovaní 8859-2 a pomocou iconv impornut data do novej tabulky v UTF-8.
Tentokrát mi už aj browser zobrazoval úplne paznaky ;-(
Ofi:
Jen jeden dotaz: stránky jsem si převed do utf-8 (mimochodem PSPad to nezvlád - děkuji za tip na SCITE. a DB sem si převed na UTF-8 ale když přidám:
mysql_query("SET CHARACTER SET utf8");
tak mi to ty znaky na výstupu rozhází a když to tam nemam vůbec tak vše šlape jak má - jak je to možné_?
Tomáš Urban:
Mám databázi kodovanou ve Windows-1250 a teď bych jí chtěl převést do UTF-8. Když si DB prohlížím přes phpmyadmin tak místo "Přechodové lišty" vydím "PÅ™echodové liÅ¡ty", ale v prohlížeči je vše OK. Pokud bych pro převod použít přávě phpmyadmin potřebuji převést dumpovaný text z DB do "tlamiček" a nebo použít jiný způsob. Můžete mi poradit jak?
Dík za pomoc!!
Jirka:
Když používám:
<?php
mysql_query("SET character_set_client=utf8");
mysql_query("SET character_set_connection=utf8");
mysql_query("SET character_set_results=utf8");
?>
vypíše se mi tohle:
Warning: mysql_query() [function.mysql-query]: Access denied for user 'www-data'@'localhost' (using password: NO) in /home/www/totalweb.cz/www/xxx/aplikace.php on line 66
Warning: mysql_query() [function.mysql-query]: A link to the server could not be established in /home/www/totalweb.cz/www/xxx/aplikace.php on line 66,
nevíte proč?
fotbalcb:
Ahoj, mě s češtinou z mySQL na localhostu pomohl druhý řádek:
$conn = new mysqli("127.0.0.1", "root", "", "");
$conn->set_charset("utf8");
Diskuse je zrušena z důvodu spamu.