Hlavní navigace

Ruby a unicode: bratři nebo nepřátelé?

Jakub Šťastný

Unicode je jedna z nejdůležitějších dnešních technologií, přesto je jeho podpora v Ruby stejně jako v mnoha dalších programovacích jazycích problematická. Pomoc však existuje, možností pomoci je dokonce více. Jak tedy nepodporu unicode elegantně vyřešit?

Co je míněno podporou unicode?

Když říkám, že Ruby neumí unicode, ani v nejmenším to neznamená, že nemůžete psát své skripty v UTF-8, UTF-16 nebo podobném kódování, s tím samozřejmě problém není. Problém je v tom, že string v Ruby je implementovaný jako sekvence bytů bez ohledu na délku znaku. Důsledkem toho nefungují správně metody jako například length, reverse, upcase, each_char a podobné.

Řešení?

Hackujeme přes regulární výrazy

Pointa jednoho z možných způsobů řešení spočívá v tom, že regulární výrazy unicode de facto podporují, jenom je třeba jim pomoci, aby si to „uvědomily“. Od toho slouží přepínač u. Ukázka napoví více:

# špatně - bez přepínače "u"
"čeština".gsub(/./, '\& ').each { |match| puts match }
=> ? ? e ? ? t i n a

# správně - s přepínačem "u"
"čeština".gsub(/./u, '\& ').each { |match| puts match }
=> č e š t i n a

Užitečné, že? Pokud se vám parametr „ u“ nechce u každého regulárního výrazu uvádět, je možné jej nastavit globálně pomocí proměnné $KCODE:

$KCODE = "u"

"čeština".gsub(/./, '\& ').each { |match| puts match }
=> č e š t i n a

To je sice hezké a bezesporu také velmi užitečné, ale naši potřebu fungujících metod reverse a podobně to neřeší. Budeme si muset pomoci sami, ale nebojte, není to těžké – stačí prostě předefinovat metodu reverse:

$KCODE = "u"

class String

  def reverse
    self.scan(/./).reverse.join
  end

end

Nyní bude metoda reverse fungovat bezproblémově. Stejným způsobem lze velmi snadno a přitom maximálně elegantně předefinovat další metody jako například first, last nebo length a na několika málo řádcích změnit chování Ruby tak, že po načtení této vaší knihovny již nebude k poznání, že Ruby vůbec někdy unicode nepodporovalo. To je důsledek čistého objektového návrhu.

Sluší se poznamenat, že binárka Ruby umožňuje použití parametru -Ku (resp. parametru -K s volbou u), který umožňuje nastavení proměnné $KCODE při spouštění programu bez přímého zásahu do něj.

Tímto způsobem je možno předefinovat i ostatní metody Stringu:

$KCODE = "u"

class String

  def reverse
    self.scan(/./).reverse.join
  end

  def first
    self.scan(/^./).join
  end

  def last
    self.scan(/.$/).join
  end

  def length
    self.scan(/./).length
  end

  ...

end

Problémy

Pokud bychom chtěli opravdu důkladnou podporu unicode, bylo by patrně též záhodno předefinovat pár metod třídy Range, protože ("a".."z") bude samozřejmě zacházet pouze s ASCII sadou. Je ovšem otázka, zda je moudré něco takového dělat a když už, tak alespoň musíme brát ohled na systémové locales. Pokud bychom chtěli, aby správně fungovalo porovnávání, bylo by též třeba předefinovat metodu <=> z modulu Comparable.

Nejsem si příliš jistý ohledně metod upcase, downcase a swapcase. Osobně používám metodu tr, ale to předpokládá vypsání všech unicode znaků jako její parametr. Pro ty české to samozřejmě není problém, ale obecné řešení to není. Pokud někdo máte lepší řešení, budu rád, když se podělíte v diskusi.

Příště

V příštím díle se podíváme na různé knihovny, které nám při naší práci s unicode mohou přijít vhod – unicode, ICU4R a z Ruby on Rails známý ActiveSupport::Multibyte. Řeč přijde též na podporu unicode v chystaném Ruby 1.9.1 a dozvíte se také, jak podporují unicode ostatní implementace Ruby, především JRuby.

Odkazy

Našli jste v článku chybu?

29. 10. 2007 10:57

Jirka Kosek (neregistrovaný)
Pravda to samozřejmě není. Jádro problému je v tom, že východoasijské znaky byly do Unicode unfikovány -- tj. pokud např. v čínštině a japonštině byly znaky se stejným významem (ale trošku odlišným vzhledem), jsou v Unicode jako jeden znak. Je to logické, protože Unicode se ve většině případů stará o význam znaku ne o jeho kresbu/vzhled.

Pro korektní zobrazení textu pak tedy ještě potřebujete znalost jazyka (a někdy i skriptu a regionu). Tyto věci neumí Unicode zrovna dobře reprezentovat, takže…

9. 1. 2008 1:13

Mám české 2000ky. Nepodařilo se mi. Existuje k tomu nějaká dokumentace? V případě MSDN prosím bližší odkaz. Přeci jen tato knihovna je jako sám internet před vynalezením vyhledávačů.
Podnikatel.cz: Podnikatelům dorazí varování od BSA

Podnikatelům dorazí varování od BSA

DigiZone.cz: Velká cena v Abú Dhabí: 131 ti­síc diváků

Velká cena v Abú Dhabí: 131 ti­síc diváků

120na80.cz: 5 nejčastějších mýtů o kondomech

5 nejčastějších mýtů o kondomech

Lupa.cz: Kdo pochopí vtip, může jít do ČT vyvíjet weby

Kdo pochopí vtip, může jít do ČT vyvíjet weby

Vitalia.cz: Proč vás každý zubař posílá na dentální hygienu

Proč vás každý zubař posílá na dentální hygienu

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Podnikatel.cz: Snížení DPH na 15 % se netýká všech

Snížení DPH na 15 % se netýká všech

Vitalia.cz: Spor o mortadelu: podle Lidlu falšovaná nebyla

Spor o mortadelu: podle Lidlu falšovaná nebyla

Vitalia.cz: Když přijdete o oko, přijdete na rok o řidičák

Když přijdete o oko, přijdete na rok o řidičák

Měšec.cz: Stavební spoření: alternativa i pro seniory

Stavební spoření: alternativa i pro seniory

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

120na80.cz: Horní cesty dýchací. Zkuste fytofarmaka

Horní cesty dýchací. Zkuste fytofarmaka

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Root.cz: Certifikáty zadarmo jsou horší než za peníze?

Certifikáty zadarmo jsou horší než za peníze?

Podnikatel.cz: Udávání kvůli EET začalo

Udávání kvůli EET začalo

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Podnikatel.cz: Chtějte údaje k dani z nemovitostí do mailu

Chtějte údaje k dani z nemovitostí do mailu

Vitalia.cz: Pamlsková vyhláška bude platit jen na základkách

Pamlsková vyhláška bude platit jen na základkách