Převod stránek do UTF-8
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?
19.12.2005 13:16:46
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.
19.12.2005 13:38:50
MySQL < 4.1 pracuje s bajty, vyšší verze se znaky.
19.12.2005 13:55:17
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());
}
}
?>
19.12.2005 19:10:14
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
19.12.2005 20:50:49
alsan:
Ty jo.. tohle mi ted dost pomohlo ;) Diky.
13.10.2008 05:09:14
Anonym:
Taky ti moc děkuju :D
13.11.2011 18:22:14
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.
20.12.2005 01:42:00
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
21.12.2005 10:03:02
Mám o tom napsaný článek, časem ho tu vystavím.
21.12.2005 10:26:48
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?
3.5.2006 20:12:31
Fikus:
Tak jsem upgradoval FF a uz to beha asi to byla jen nejaka blbost
3.5.2006 21:32:50
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?
21.10.2006 13:24:22
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
23.10.2006 14:25:45
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...
24.10.2006 23:36:42
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?
13.3.2007 01:21:30
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 ;-(
13.3.2007 10:45:25
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é_?
4.7.2009 05:50:35
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!!
20.11.2009 06:14:01
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č?
24.1.2011 00:57:19
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");
25.12.2016 21:41:31