Výběr kódování znaků
Při vytváření českých (nebo jiných ne-ryze anglických) stránek je potřeba vybrat, jaké kódování znaků se bude používat. Pro češtinu se používají hlavně tyto tři:
- UTF-8
- ISO-8859-2
- Windows-1250
Windows-1250 se používá hlavně na Windows, ISO-8859-2 na Unixu, UTF-8 je univerzální kódování, pomocí kterého lze zapsat v podstatě libovolný znak používaný kdekoliv na světě. Naštěstí už jsou pryč doby, kdy prohlížeče dokázaly zobrazit pouze kódování odpovídající operačnímu systému, pod kterým běží, takže není nutné vytvářet skripty, které kódování automaticky převádí, a obvykle stačí kódování prohlížeči pouze vhodně oznámit:
<?php
header("Content-Type: text/html; charset=windows-1250");
?>
K dispozici je také direktiva default_charset. Připomínám, že kvůli případnému uložení stránky na disk je také vhodné stejnou hodnotu uvést i ve značce <meta http-equiv="Content-Type">
. Pokud ale HTTP hlavička poslaná PHP obsahuje jinou hodnotu, tak dostane přednost, takže značka <meta http-equiv="Content-Type">
sama o sobě nestačí.
Které kódování vybrat? Doporučit mohu jednoznačně UTF-8, které má tu hlavní výhodu, že není specifické pro češtinu (nebo pro střední Evropu) a lze v něm tedy zapsat libovolné znaky. Podpora v prohlížečích a editorech je také dobrá. Pokud vytváříte stránky v XHTML a nechcete uvádět XML deklaraci (kvůli problémům s tím spojeným) a zároveň zůstat v souladu s normou, je to také vaše jediná možnost.
UTF-8 je na rozdíl od Windows-1250 nebo ISO-8859-2 vícebajtové kódování – pro uložení jednoho znaku se může použít více bajtů. Znaky ze spodní poloviny ASCII tabulky jsou uloženy do jednoho bajtu, ostatní znaky potom do dvou až čtyř bajtů. Z toho plynou i některé problémy – např. funkce strlen vrací počet bajtů, nikoliv znaků. Pokud chcete vrátit počet znaků, můžete jako náhradu použít funkci iconv_strlen, která použité kódování zohledňuje. Podobný problém na nás číhá i v MySQL – varchar(40)
vyhradí v MySQL až do verze 4.0 místo na 40 bajtů, nikoliv znaků. Ke změně došlo až v MySQL 4.1 (stabilní verze od října 2004), kde je práce s kódováními podstatně vylepšena (používané kódování lze nastavit pro server, databázi, tabulku i sloupec, ve starších verzích to šlo pouze pro server) a UTF-8 se používá i interně např. pro ukládání názvů sloupců.
Neaktuální verze MySQL je i důvod, proč je tento blog publikován ve Windows-1250 a ne v UTF-8. Pokud by se někdo pokusil např. do padesátibajtového sloupce vložit padesátiznakový UTF-8 řetězec s diakritikou (nebo i o něco kratší s hodně speciálními znaky), tak se tento řetězec pochopitelně ořízne. Pokud by se navíc ořízl uprostřed bajtů tvořících jeden znak, mohl by při výstupu dokonce způsobit nevaliditu dokumentu.
Diskuse
skybedy:
Nevzroste při použití UTF-8 nadměrně velikost souboru? Díky.
11.3.2005 11:48:27
Vzroste jen málo, protože více bajtů se používá jen pro ukládání speciálních znaků (pro české znaky s diakritikou vždy dva). Znaky z dolní poloviny ASCII tabulky (a tedy i všechny operátory a např. číslice) zaberou pouze jeden bajt. Např. tato stránka má v jednobajtovém kódování 7820 bajtů, v UTF-8 8146 bajtů, to je nárůst 4%. Při použití komprese by byl nárůst ještě menší.
11.3.2005 11:57:43
xXx:
rek bych ze vyroste
12.7.2006 18:29:03
Ondra:
Nechtel bys nekdy vyjmenovat praci s utf? Mam na mysli nahrazovani, hledani atp.
11.3.2005 13:16:05
na mem blogu bezi vse v utf8. A i na stare databazi. Na mem blogu v tom nevidim problem, protoze do problematickych mist php + mysql + utf8 nemusel vstupovat :)
11.3.2005 14:57:50
Viz např. stále nevyřešená diakritika u jména autora diskusního příspěvku na tvém blogu :-).
11.3.2005 15:01:01
joooo mas pravdu... to je fakt :)))) to musim jeste zpravit :))
11.3.2005 18:56:40
timqui:
ohledne kodovani jsem narazil na jednu zajimavou vec u funkce urlencode()
funkce vrati vzdy prekodovane znaky v kodovani, ve kterem je napsan skript. A to ikdyz pred tim dany retezez rucne prekoduji do pozadovaneho kodovani (treba autoczech).
delo se mi to ve skriptu v UTF a volal jsem pomoci file() stranku (vyhledavace), ktera byla ve win-1250. tedy potreboval jsem do adresy pridat retezec (klicove slovo) we win-1250.
jako reseni me napadolo urlencodovany retezec prepsat pomoci str_replace.
11.3.2005 15:54:26
"urlencode() vrati vzdy prekodovane znaky v kodovani, ve kterem je napsan skript" - to není pravda. urlencode() pracuje podobně jako většina ostatních funkcí s bajty. Pokud mám skript v UTF-8 a chci parametr předat ve Windows-1250, lze použít:
<?php
$q = urlencode(iconv("UTF-8", "Windows-1250", $q));
?>
11.3.2005 16:03:14
skybedy:
Jaký používáte editor, když chcete mít kódování v ISO, popřípadě v UTF ? Díky.
15.3.2005 13:10:56
skybedy:
Já právě teď dva dny stahuju všecko možné, je spousta hezkých editorů, jsou i freeware, ale prostě naše ISO nepodporují.
Jmenovaný SciTE jsem měl také, ale moc se mi nezdál, zkusím ho asi teda stáhnout znovu.
15.3.2005 13:41:06
Chytrex:
Zkus se podívat po PHPeditorIDE.. Je to freeware a poporuje všechny možné kódování..
28.1.2006 14:55:31
skybedy:
Teď jsem přišel na jednu nemilou věc v souvislosti s UTF-8.
IE neumí při tomto k´dování použít font MS Serif, který rád používám, a který by měl být jinak všeobecně kompatibilní.
Při Iso i Winndows to normálně jede.
31.3.2005 12:57:48
abtris:
Ja jsem se dostal prechodem na utf-8 do jinych problemu:
1) zacala se obevovat chybova hlaska:Warning: Cannot modify header information - headers already sent by ...
Pri kodovani iso se to nedeje.
2) dalsi problem mam pri pouziti include('neco.php') kde mam nejaky text, tak to nadela problemy jen v IE.
Problem spociva v prvnich 3 znacich co se podle nich utf-8 rozpoznava, prijde mi ze tam neco zustane co by nemelo, dela mi to apache pod linuxem (1) a to druhe je problem IE (2) v Opere a Mozille/FF to neni problem.
Ma nekdo nejakou radu jak z toho uspesne ven a zustat u UTF-8 ?
25.6.2005 18:54:57
Té trojici znaků se říká BOM (
http://en.wikipedia.org/wiki/Byte_Order_Mark) a vzhledem k tomu, že má jenom informativní charakter, je vhodné její doplňování v textovém editoru vypnout. Třeba ve SciTE se to dělá nastavením kódování na UTF-8 Cookie.
Není to problém Apache, PHP ani IE.
26.6.2005 18:16:38
UTF a české znaky:
Nazdar,
také zkouším přejít z cp1250 na utf-8, ale narazil jsem na potíž v podobě znaků Ď a Č - ani doma, ani na vlastnim serveru, ani na hostingu (Banan.cz) se MySQL (verze 4.1) nechová korektně a místo těchto dvou znaků (malá i velká písmena) vyhodí dvoubajtový nesmysl. Jiná česká písmena, třeba Ř, jsou v pohodě, problém je jen s těmito dvěma. Nějaká elementární chyba je snad vyloučena, všechny ostatní české znaky jsou bez problémů.
Nesetkali jste se s tím už někdo?
24.12.2005 18:52:32
Jarda Antoš:
Jen upozorňuji, že problém s počtem bitů je s UTF-8 i u serializace. Chvíli mi trvalo než jsem přišel na to, že tím pádem serialize nejde použít. Použil jsem na text před serializací base64 a obešel to... no snad napadne někoho něco lepšího :o)
Zdarec Jarda
10.4.2006 13:14:42
V jakém případě nejde serialize() použít? PHP s řetězci pracuje jako s posloupností bajtů a použité kódování by mu tedy mělo být zcela lhostejné.
10.4.2006 13:36:23
Andrew:
Musím jen potvrdit, že při serialize pole v utf-8 dojde k chybě. Řeší se to i v diskusi na php.net pod zmíněnými funkcemi.
12.10.2007 21:22:28
David:
PHP neumím, jenom používám e-mailový formulář (metoda post) a na seznam.cz mi ze serveru chodí špatné kódování: znaky jako ř, č apod. to dokonce bez náhrady vymaže. Dá se to nějak řešit? Používám skript z
http://tvorba-webu.zdarek.com/php/email.php. Díky.
3.1.2007 23:08:09
David:
Díky moc, vyzkouším.
22.1.2007 17:57:47
Zajo:
Pracujem na jednom serveri, kde nie je nainstalovany mysqlAdmin, cize sa v tom pracuje velmi zle a vsetko musim davat cez priamy mysql query . aj tabulky som tak musel nahravat :(
Ale mam iny problem. Nahral som tam vsetko s kodovanim UTF8 a zoradenim utf8_slovak_ci. problem je v tom, ze mi neberie slovensky znak ť(makke t) a namiesto neho pise otazniky. Dalo by sa to nejako vyriesiet? Dakujem vopred
30.10.2007 22:27:22
K prvnímu problému: zkus
http://phpminadmin.sf.net.
Druhá věc: ověř, jestli jsou databáze a tabulky skutečně ve správném kódování (třeba v phpMinAdmin) a jestli po výběru databáze voláš SET CHARACTER SET.
31.10.2007 10:02:31
Zajo:
Pomocou klasickych metod som to nevyriesil .. :(
Ale podarilo sa mi to inak cez str_replace som si pred ulozenim do DB ten znak premenil na kombinaciu inych znakov(napriklad ===) a tie som pri zobrazeni premenil s5. Jednoduche, ale inak som to nevedel vyriesit. Aj tak dakujem za rychlu odpoved :)
3.11.2007 18:53:19
Vojta:
Mám problém s kódováním stránky, nejsem žádný profík a moc se v tom nevyznám, ale v mysql se mi podařilo nastavit české znaky, a když se na moje texty podívám v databázi tak tam všechny české znaky jsou, ale když si to zavolám na stránku pomoci Mysql_Query.... tak mi to vypíše ten text s otaznikama místo českých znaků.
Co s tím??(pokud by byl nekdo ochotny mi poradit muzete mi i napsat na mail: vojta.belovsky@seznam.cz) předem dík
8.3.2008 12:12:09
Megaloman:
Zkus hned po připojení a výběru databáze oznámit klientovi, s jakou znakovou sadou chceš pracovat: "SET NAMES ..."
Ale pokud jsi české znaky nastavil až nad vytvořenými daty, tak ti nepomůže nic, snad jen vymazat a vložit znova (nejlépe přes php).
12.3.2008 12:56:00
pethon:
Při php výpisu z databáze jsem nemohl dosáhnout korektního zobrazení češtiny utf8, nepomohlo ani nastaveni "set names..." etc. Po dotazu SHOW VARIABLES LIKE 'collation%'; jsem zjistil, že chyba bude nejspíš v odlišném nastavení kódování server_collation, takže: pokud máte podobný problém zkuste:
http://czropa.wz.cz/?src=doc/javamysql.phpŘešením bylo nastavit v "my.ini" default-character-set=utf8.
28.4.2008 02:38:00
Rataja:
Chci ořezat řetězec na několik znaků, řekněme zkrátit, ale když se trefím tak, že poslední písmeno je diakritikou, tak se toto písmeno nezobrazuje korektně. Po přečtení příspěvků chápu, že je to tím, že je tento znak rozdělen na vice bytu. Jakym zpusobem pohlidat, spravne zobrazeni posledniho znaku?
$string = vepřové;
echo substr($string, 0, 4);
Diky moc za radu
R.
2.8.2009 23:34:19
Musíš použít funkci, která kódování respektuje, např. iconv_substr(). Dá se použít i taková finta, která nevyžaduje žádnou externí knihovnu:
<?php preg_replace("~(.{0,$length}).*~su", '\\1', $string); ?>.
3.8.2009 12:04:09
Rataja:
Co musím přečíst a nastudovat, abych byl stejný machr? Díky moc, fce zabrala a já dostávám výsledky, které potřebuji.
Opravdu děkuju
3.8.2009 20:49:23
Co se funkcí týče, tak studentům radím přečíst si jednořádkové popisy vestavěných PHP funkcí. Člověk tak získá přehled o tom, co PHP dokáže, takže pak když něco potřebuje udělat, tak ví, že to jde. A najít jak už obvykle nebývá velký problém. Začít můžeš na
http://www.php.net/manual/en/extensions.membership.php.
4.8.2009 10:55:12
Dobrý den, začal jsem se zabývat redakčním systémem, alemé znalosti PHP jsou takřka nulové. Jde o zásahy do přednastavených nadpisů sekcí atp... Používám Joomlu 1.5. Zatím mi běží na lokálním serveru a testuji možnosti.
..............................zpět k problému:
Jde o zásahy do přednastavených nadpisů sekcí atp.
Kódování používám UTF-8 a všechen obsah se v češtině vypisuje správně (česká diakritika) ovšem pokud zasáhnu do PHP kódu a změním např. Modul registration form vypíše místo českých znaků prohlížeč typické znaky pro UTF-8 bez českých znaků. Moduly jsou programovány v angličtině, ale nevím zda je to tím. Pomůže mi někdo?
Podotýkám, že nejsem programátor, nicméně mne tato problematika velmi zajímá.
.....................Ukázka......................
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="
http://www.w3.org/1999/xhtml" xml:lang="en-gb" lang="en-gb" >
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
.................SPÍŠ JDE O TO ZDA STAČÍ ZMĚNIT PARAMETR "XML LANG"................................
...........UKÁZKA SKRIPTU VYPISUJÍCÍHO FORM..............
<?php else : ?>
<?php if(JPluginHelper::isEnabled('authentication', 'openid')) :
$lang->load( 'plg_authentication_openid', JPATH_ADMINISTRATOR );
$langScript = 'var JLanguage = {};'.
' JLanguage.WHAT_IS_OPENID = \''.JText::_( 'WHAT_IS_OPENID' ).'\';'.
' JLanguage.LOGIN_WITH_OPENID = \''.JText::_( 'LOGIN_WITH_OPENID' ).'\';'.
' JLanguage.NORMAL_LOGIN = \''.JText::_( 'NORMAL_LOGIN' ).'\';'.
' var modlogin = 1;';
$document = &JFactory::getDocument();
$document->addScriptDeclaration( $langScript );
JHTML::_('script', 'openid.js');
endif; ?>
<form action="
<?php echo JRoute::_( 'index.php', true, $params->get('usesecure')); ?>" method="post" name="login" id="form-login" >
<?php echo $params->get('pretext'); ?>
<fieldset class="input">
<p id="form-login-username">
<label for="modlgn_username">
<?php echo JText::_('Username') ?></label><br />
<input id="modlgn_username" type="text" name="username" class="inputbox" alt="username" size="18" />
</p>
<p id="form-login-password">
<label for="modlgn_passwd">
<?php echo JText::_('Password') ?></label><br />
<input id="modlgn_passwd" type="password" name="passwd" class="inputbox" size="18" alt="password" />
</p>
<?php if(JPluginHelper::isEnabled('system', 'remember')) : ?>
<p id="form-login-remember">
<label for="modlgn_remember">
<?php echo JText::_('Remember me') ?></label>
<input id="modlgn_remember" type="checkbox" name="remember" class="inputbox" value="yes" alt="Remember Me" />
</p>
<?php endif; ?>
<input type="submit" name="Submit" class="button" value="
<?php echo JText::_('LOGIN') ?>" />
</fieldset>
<ul>
<li>
<a href="
<?php echo JRoute::_( 'index.php?option=com_user&view=reset' ); ?>">
<?php echo JText::_('FORGOT_YOUR_PASSWORD'); ?></a>
</li>
<li>
......................KONEC KÓDU......................
Pokud přepíšu do češtiny submit button a další, vyhodí to klasický ASCII znak pro nerozpoznaný znak "kosočtverec s otazníkem"............Díky
12.10.2009 10:10:39
Ahoj. Chtěl jsem se zeptat, beru data na stránku přes
<? include("nazev_souboru.txt"); ?> a i když mám na webu (v hlavičce) nastavené UTF-8 kódování a v tomhle TXT souboru také (v PSPadu nastaveno v "Formát" -> "UTF-8") tak mi to nebere diakritiku a píše mi to místo toho otazníky. Nevíte jak bych to mohl vyřešit ?
Děkuji, Vlastimil Fišer
30.4.2011 08:36:45
Jak přesně se nastavuje to kódování? Je vkládaný soubor určitě ve správném kódování?
Mimochodem, proč vůbec textový soubor vkládáš pomocí include?
30.4.2011 08:42:43
Děkuji za rychlou reakci.
Formát volím tak, že v PSPadu, nahoře v liště, kliknu na "Formát" a poté zaškrtnu "UTF-8". Zkoušel jsem zaškrtnout i jiné, ale vůbec to nemá vliv nějak, vždy sou tam stejné otazníky a při změně na jiný formát (jakýkoliv) to je pořád stejné. V hlavičce webu mám kódování správně na 100%.
Vkládám ho tam přes include, jelikož to mám do Wordpress šablony kterou jsem vytvořil, ale bohužel dělá mi neplechu když to ukládám přes editor (při opětovné editaci mi to modifikuje kód, podle toho editoru ve WP).
Už si nevím rady. :(
30.4.2011 09:12:55
Tak už jsem to udělal. Stačilo to neukládat do TXT ale do PHP souboru (i když v kódu PHP nemám, myslel jsem si že je to zbytečné). Teď bych se jen chtěl zeptat, zdali nevíte, jak bych mohl udělat to, aby vyhledávače neindexovali ty PHP soubory ze kterých to "tahám".
Děkuji, Vlasta
30.4.2011 09:42:51
Tak s tou PHP hlavickou som sa trapil, lebo mi tiez nefunguje to kodovanie, tak dakujem za tip idem to vyskusat a prerobit.
17.11.2011 11:59:47
Jan Návrat:
Uctivě zdravím a prosím o radu =)
Potřebuji vypisovat řetězce s pevným počtem znaků. Tj např potřebuji aby proměná $out měla při výpise vždy přesně 10 znaků. Co vím, měly by k tomu být určeny funkce řady printf, ale bohužel mi nefungují při použití UTF-8.
$jmeno="Žok";
$out = sprintf("%-10s", $jmeno);
Proměná $out po provedení této části kódu obsahuje řetězec jen s 9 znaky a né 10 (znak Ž sežere dvě místa).
Poradíte prosím jak na to? Moc děkuji =)
27.2.2012 15:51:10
Jirka:
Vkládám php menu do stránky. V souboru menu mám pouze <table>...</table>. Jak mám nastavit kódování stránky, aby se mi háčky a čárky zobrazovaly všude správně? Když zvolím jedno, zobrazuje se blbě obsah menu, když druhé, zobrazí se blbě zbytek stránky.
Děkuji
15.3.2012 22:08:29
Michal:
Rada je jednoduchá a to sjednotit kódování.
15.3.2012 23:16:02
Tomáš Balíček:
Dobrý den,
prosím o radu. Z banky vytahuji data pomocí skriptu a kódování v bance je ISO-8859-2 ale potřebuji vložit data do databáze, kde je použité kódování UTF-8 ale bohužel se mi nedaří převést kódování. Zkoušel jsem následující metodu:
$jmeno2 = mb_convert_encoding($jmeno, 'UTF-8', 'ISO-8859-2' );
//$jmeno = TOMÁŠŠ BALÍČEK
//$jmeno2 = TOMà Š BALĂ ÄŒEK //v zobrazení ISO-8859-2
//$jmeno2 = TOMÁ BALÍČEK //v zobrazení UTF-8
Předem děkuji za odpověď opradu jsem už vyzkoušel všechno možné a nic mě nenapadá.
Tomáš Balíček
8.2.2013 01:32:52
Katka:
Tento soubor .php jsem includovala do jineho souboru....porad to pise kosoctverce s otazniky misto hacek a carek, co s tim???
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Trendymat</title>
</head>
<h2>Vítejte</h2>
<body>
Tato stránka je zaměřena <br />
</body>
</html>
10.8.2016 15:04:12
Kódování je potřeba nastavit také v PHP, např. tímto kódem umístěným na začátek souboru:
<?php
header("Content-Type: text/html; charset=utf-8");
?>
12.8.2016 15:52:05
Dobrý den,
na celých webovkách se mi špatně zobrazuje čeština, v menu prohlížeče si musím nastavit znakovou sadu Středoevropský Windows. Přitom v hlavičce webu to mám definováno. Poraďte prosím jak to zpravit.
20.3.2017 08:20:52
Importuji data ze starého excelu (s příponou xls) a potřebuji je překódovat (php mám v utf-8). Jak to udělám?
4.10.2017 23:45:48