Mnemonic
Založen: 28. 07. 2007 Příspěvky: 93
|
Zaslal: 29. září 2007, 17:25:20 Předmět: Jak připravit hru na snadnou lokalizaci - 2. díl |
|
|
Jak připravit hru na snadnou lokalizaci - 2. díl
V prvním dílu článku jsme se zaměřili na herní texty a jejich připravenost k překladu do jiných jazyků. V druhém dílu si povíme něco o jejich uložení, o fontech, a o ostatních oblastech lokalizace.
Uložení herních textů
ASCII versus Unicode
Další oblast, která stojí za zmínku, je způsob uložení textů. Historicky programy používaly a dodnes používají nejčastěji uložení ve formě osmibitových znaků, čili jeden znak textu zabírá jeden byte v paměti. V důsledku toho je možné použít maximálně 256 různých znaků. ASCII norma, ze které tento způsob uložení vychází, počítala původně jen s uložením základních znaků latinské abecedy (a až z, A až Z), plus číslice, plus symboly. Na to stačilo i pouhých 7 bitů (maximálně 128 znaků). Jak se software postupně rozvíjel, vyvstala potřeba ukládat i různé znaky, specifické pro konkrétní jazyky. Sami to dobře známe, v našem případě šlo o písmena s háčky a čárkami, ale podobné "exotické" znaky používá většina evropských jazyků, mimo angličtiny. Pro tyto znaky bylo nutno použít oněch zbývajících 128 znaků, které ASCII norma nevyužívala. Jelikož ale národních znaků bylo dohromady podstatně více, než 128, byl zaveden koncept tzv. kódových stránek. Bylo definováno několik skupin národních znaků, které je možno přepínat. V praxi to znamená, že oněch 128 rozšiřujících znaků reprezentuje různá písmena podle toho, kterou kódovou stránku právě používáme. Pro evropské jazyky bychom definovali například tyto skupiny: západoevropské znaky, středo- a východoevropské znaky (sem spadají i české znaky s diakritikou), azbuka a řecká abeceda. Stejným způsobem jsou pomocí kódových stránek podporovány i další jazyky, jako hebrejština, arabština a další.
Aby se situace ještě více zkomplikovala, existuje mnoho různých norem pro kódové stránky, které nejsou vzájemně kompatibilní. Jiné kódování používal DOS, jiné Windows, jiné předepisuje ISO norma atd.
Poznámka: Pro zjednodušení budu v následujícím textu používat termín ASCII pro jakékoliv řetězce, používající osmibitové znaky, přestože - čistě technicky - není název ASCII vždy úplně přesný.
Co z toho plyne pro lokalizaci her? Pokud ukládáme texty ve formě osmibitových znaků (jde o klasické céčkovské pole znaků typu char), jsme schopni zobrazit maximálně 256 různých znaků. Chceme-li podporovat více jazyků (což chceme), musíme se nutně zabývat kódovými stránkami. V praxi to znamená jedinou věc: naše hra bude muset používat různé fonty pro jednotlivé kódové stránky. O fontech si ale povíme víc v další kapitole.
Asi je zřejmé, že koncept kódových stránek není úplně ideální řešení, v programátorské hantýrce bych to nazval jako "hack", aneb jak do 256 dostupných buněk nacpat podstatně více znaků cestou nejmenšího odporu. Navíc si všimněte, že jsem se raději vůbec nezmiňoval o asijských jazycích. Jazyky jako čínština či japonština totiž z principu používají mnohem, mnohem více znaků, na které jsou krátké i kódové stránky.
Snaha o konečné řešení problémů s uložením národních znaků vyústila ve standard, jménem Unicode. Cílem Unicode je sjednotit roztříštěnost jednotlivých kódových stránek pro různé jazyky/regiony a definovat množinu všech možných znaků, které lze v kterémkoliv jazyce napsat (nebo alespoň jejich drtivé většiny
Z programátorského pohledu je podstatné, že oproti ASCII již nevystačíme s jedním bytem na uložení jednoho znaku. Momentálně Unicode definuje už přes 90 tisíc různých znaků. Proto existuje několik norem pro uložení Unicode znaků. Dva nejpoužívanější jsou UTF-8 a UTF-16. Zkratka UTF znamená "Unicode Transformation Format", číslo pak udává počet bitů, použitých pro uložení. Jak asi správně namítnete, ani 8 ani 16 bitů nevystačí pro uložení 90 tisíc různých hodnot. Vtip je v tom, že jeden Unicode znak je rozložen do více bytů. Počet bytů je různý, podle konkrétního znaku. V případě UTF-8 může jeden znak zabírat jeden až pět bytů (přičemž "normální" znaky, tj. latinka, vystačí s jedním bytem, takže například anglický text vypadá úplně stejně, ať je uložen v ASCII nebo v UTF-. UTF-16 pak používá na uložení jednoho znaku 16 bitů (neboli word), a ačkoliv to teoreticky také nemusí stačit, prakticky se jeden word rovná jednomu Unicode znaku (pokud nepoužíváte nějaké velice obskurní znaky, jako starobylou japonštinu a podobně).
Tolik stručný úvod do Unicode, ale teď se konečně vrátíme zpět k tématu, kterým je lokalizace her.
Pokud se chcete vyhnout problémům s různými kódovými stránkami, nebo pokud chcete podporovat i asijské jazyky, váš herní engine by měl pracovat s texty v Unicode formátu. Čím dál více moderních her Unicode používá, prostě protože lokalizace je dnes brána za standardní součást vývoje hry a Unicode lokalizaci zjednodušuje.
Výše jsem zmínil dvě možnosti uložení textů, UTF-8 a UTF-16. UTF-8 používá pro uložení normální osmibitové chary, UTF-16 pak používá typ wchar_t, což je šestnáctibitový integer. Obrovská výhoda UTF-8 je v tom, že pokud máte již hotový program, používající všude ASCII znaky, nemusíte pro přechod na UTF-8 vůbec nic měnit na tom, jak jsou texty uloženy. Stejně tak budou i nadále fungovat například standardní céčkovské funkce pro práci s řetězci, jako strcpy, strlen a podobně. Musíte ovšem počítat s tím, že v UTF-8 jeden char nemusí odpovídat jednomu znaku textu (jak jsme si řekli, jeden znak může zabírat více bytů). Takže například funkce strlen vám vrátí počet bytů v řetězci, nikoliv nutně počet znaků! Stejně tak, samozřejmě, pokud přistupujete k jednotlivým prvkům pole pomocí operátoru [], dostanete jednotlivé byty, ne jednotlivé znaky. I přes tyto nevýhody je UTF-8 (téměř) ideálním řešením pro ty, kdo potřebují snadno a rychle doplnit podporu Unicode do rozsáhlého programu, který v původním návrhu s Unicode nepočítal.
Nicméně pokud začínáte navrhovat nový systém, doporučil bych už od začátku používat pro ukládání řetězců UTF-16, resp. pole šestnáctibitových znaků, tedy typu wchar_t ("wide char"). ANSI C norma nyní obsahuje všechny funkce pro práci s řetězci ve dvou variantách: klasické, pro pole hodnot typu char (strcpy, srlen...) a jejich ekvivalenty pro pole hodnot typu wchar_t (wcscpy, wcslen...). Podobně STL vám nabízí kromě typu string také typ wstring.
Samozřejmě, jedna věc je uložení textů, a druhá věc je jejich reprezentace na obrazovce. Tento problém však probereme podrobněji v kapitole o fontech.
Unicode na různých platformách
Problém lokalizace a národních znaků samozřejmě nenechává klidnými ani vývojáře operačních systémů a vývojových platforem. Proto se teď zběžně podívejme, jak se k němu staví nejpoužívanější platformy.
Linux byl historicky postaven na ASCII řetězcích, proto je na této platformě podpora Unicode nejčastěji realizována prostřednictvím UTF-8 kódování, které se zde nyní stalo de facto standardem pro výměnu textů.
V případě Windows je situace zajímavější. Systém Windows byl dlouhou dobu vyvíjen ve dvou paralelních větvích. Na jedné straně to byla řada Win9x (Win95, Win98, WinME), určená pro low-end hardware. Systémy této řady používají klasické osmibitové ASCII řetězce. Naproti tomu řada WinNT (WinNT, Win2000, WinXP, Vista) je od začátku postavena na UTF-16, používá tedy šestnáctibitové znaky. Ovšem kvůli kompatibilitě s programy, psanými pro Win9x, si Windows NT musí poradit i s ASCII řetězci. Prakticky to znamená, že všechny funkce Windows API, které přímo či nepřímo pracují s řetězci, mají dvě varianty. Funkce se jmenují stejně, ale názvy funkcí, pracujících s osmibitovými řetězci, končí písmenem A (jako ANSI), a funkce pro šestnáctibitové řetězce končí písmenem W (jako Wide). Například funkci MessageBox najdeme jako MessageBoxA a MessageBoxW. Funkce typu A slouží jen jako prostředník, který převede řetězec z ASCII do Unicode a zavolá funkci typu W. Na systémech Windows řady Win9x tato konverze částečně funguje také, ale pochopitelně opačným směrem. Unicode varianta je však implementována jen u několika vybraných funkcí. Naštěstí však později vznikla samostatná knihovna "Microsoft Layer for Unicode", která programům umožňuje i na platformě Win9x využívat celou škálu Unicode variant API funkcí.
Platforma Windows CE (Windows Mobile) pro mobilní zařízení se již oprostila od kompatibility se starými programy a používá pouze UTF-16 řetězce. Pokud vyvíjíte hru pro WinCE, můžete sice v programu používat normální ASCII řetězce, ale jakmile potřebujete zavolat nějakou funkci z WinAPI, která očekává řetězec jako parametr, je nutné tento řetězec převést do UTF-16.
Moderní runtime platformy Java a .NET už jsou bezvýhradně postaveny na UTF-16, i když samozřejmě poskytují širokou škálu konverzních funkcí pro jiná kódování textů.
Na závěr této kapitoly ještě letmo zmíním dvě užitečné funkce Windows API, které umožňují konverzi řetězců mezi ASCII a UTF-16. Funkce MultiByteToWideChar převádí osmibitové znaky na šestnáctibitové, a naopak funkci WideCharToMultiByte můžete použít pro převod šestnáctibitových znaků na osmibitové. Podstatné je, že obě tyto funkce dovedou zpracovat i Unicode texty ve formátu UTF-8.
Fonty
V předchozích kapitolách jsme si popsali, jakým způsobem oddělit texty od zbytku hry, a jak je ukládat v paměti při běhu programu. Výsledkem všeho toho snažení by ovšem mělo být, aby se lokalizovaný text objevil hráči na obrazovce. K tomu samozřejmě použijeme fonty, ale možných přístupů je mnoho. Zaměříme se nyní na některé z nich, a to především z pohledu lokalizace.
Tradiční přístup k zobrazení herních textů je ten, že hra nahraje do paměti speciální texturu, ve které jsou vykresleny všechny znaky, a pak na obrazovku renderuje jednotlivá písmena jako čtverce (quady), potažené částí textury s patřičným písmenem. Tento přístup je snadno pochopitelný a jednoduše realizovatelný. Problém je v tom, že textura s fontem obsahuje jen omezenou množinu znaků, typicky 256, tedy jednu kódovou stránku (více o kódových stránkách v minulé kapitole). Aby naše hra byla schopna zobrazovat přeložené texty pro různé jazyky, bude muset umět přepínat různé fonty pro různé kódové stránky (například textura s fontem pro ruštinu bude muset obsahovat úplně jiné znaky, než textura s fontem pro češtinu). Nyní záleží na tom, jak textura s fontem vzniká. Obecně jsou používány dva přístupy. Buďto texturu připravuje ručně grafik, za pomoci programů jako Bitmap Font Builder nebo FONText, a nebo je textura generována automaticky za běhu programu. V prvním případě bude nutno ručně připravit různé fonty pro všechny kódové stránky, které má naše hra podporovat. V druhém případě musí hra vědět, kterou kódovou stránku má použít při generování fontu. Například používáme-li pro vykreslení jednotlivých písmen do textury Win32 API, musíme nejprve vytvořit font pomocí funkce CreateFont, která má jako devátý parametr identifikátor kódové stránky.
Jak vidno, opět se zaplétáme do kódových stránek a omezení ASCII řetězců. Kromě toho tento přístup má několik více či méně fatálních omezení a nedostatků:
- Vykreslováním znak po znaku obcházíme font rendering engine. Ať už používáme Windows API, FreeType, či jinou knihovnu pro vykreslování fontů, tyto knihovny jsou zpravidla stavěny na vypsání souvislého textu. Díky tomu jsou schopny vysázet text s ohledem na typografická pravidla. Například používají tzv. kerning, tedy různě velké mezery mezi různými dvojicemi písmen (kerningovými páry), což podstatně zlepšuje vzhled textu, obzvlášť u větších písmen. Pokud naše hra vykresluje text sama písmeno po písmenu, o tyto výhody přicházíme (nebo je musíme složitě implementovat sami).
- Vykreslováním znak po znaku přicházíme o možnosti pokročilého formátování textu. Tady se dostáváme zpět k lokalizaci. Některé jazyky, jmenovitě hebrejština a arabština, vypisují text zprava doleva (right-to-left, RTL). Zatímco například Win API má pro RTL texty přímou podporu, kterou si vynutíme změnou jediného parametru funkce ExtTextOut, při vykreslování znak po znaku musíme vše obsloužit sami. Možná si řeknete, že upravit rutinu pro vykreslování textu tak, aby psala písmena zprava doleva, není velký problém, situace je ale složitější. Hebrejské a arabské RTL texty totiž v sobě mohou obsahovat části, které je nutno vykreslovat tradičně zleva doprava. Představte si článek v hebrejštině, ve kterém se mluví o prezidentu Georgi Bushovi. Text článku bude psán hebrejsky, zprava doleva, ale kdykoliv se v textu objeví jméno "George Bush", tento text bude psán latinkou a zleva doprava. Toto je takzvaný bidi text (bidi = bi-directional, oboustranný).
- A na závěr jsem si nechal mé oblíbené asijské jazyky. U evropských jazyků si vystačíme s kódovými stránkami, ale není prostě reálné do jedné textury nagenerovat například všechny čínské znaky. Tady musíme chtě-nechtě hledat jiná řešení.
Popsané problémy lze řešit následovně. Místo abychom obcházeli již hotové systémy pro vykreslování fontů a používali je jen k prostému vypsání jednotlivých znaků do textury, můžeme si nechat do textury vypsat už celý finální text, který chceme vytisknout na obrazovku. Tím pádem můžeme prakticky zadarmo využívat všech výhod pokročilého formátování textů. Pochopitelně, tento přístup má také své nevýhody. V závislosti na množství tištěného textu nám může výsledná textura vyjít poměrně velká, tudíž zabere hodně videopaměti, případně bude nutné texturu rozdělit na několik menších, podle schopností dané videokarty.
Oproti statické textuře s fontem má tento přístup také podstatně větší režii při generování textu. Rozhodně není únosné generovat texturu s textem znovu a znovu v každém snímku. Naštěstí ale každý text zůstává na obrazovce po nějaký čas, je tedy možné zavést cache, kde se bude udržovat například posledních deset vygenerovaných textů, takže se textura vygeneruje jen jednou, a v dalších snímcích už se jen opětovně vyrenderuje na obrazovku.
Každopádně, je na vašem posouzení, který z popsaných způsobů bude lépe vyhovovat vašim potřebám. Snažil jsem se jen shrnout některé výhody a nevýhody, které nemusejí být na první pohled zřejmé.
Pro zajímavost, i přímo v DirectX naleznete oba přístupy. Součástí DirectX SDK je pomocná třída CD3DFont, která používá předgenerovanou texturu s jednotlivými znaky. Podpůrná knihovna D3DX naproti tomu obsahuje interface ID3DXFont, který využívá druhého přístupu, tedy vypsání celého textu do textury.
Ostatní aspekty lokalizace her
V předchozích kapitolách jsme se podrobně věnovali lokalizaci her z hlediska uložení herních textů a jejich vykreslování pomocí fontů. To jsou nepochybně ty nejdůležitější oblasti, ale lokalizace zasahuje i do dalších fází vývoje, které si stručně probereme v této závěrečné kapitole.
Grafika
Tady platí jednoduché pravidlo: snažte se používat co nejméně textů přímo v grafice. Pokud to jde, vykreslujte texty pomocí fontů programově. Ušetříte si tak spoustu práce s lokalizací. Uvědomte si, že veškeré textury, obsahující text, bude muset grafik překreslit pro všechny jazykové verze hry. Pokud jste chytří, často se lze použití textů vyhnout úplně, například místo textových tlačítek použijte tlačítka s ikonou, ke které se jen zobrazí textový tooltip po najetí myší.
Uživatelské rozhraní
Uživatelským rozhraním míním různá okna pro uložení pozice, hlavní menu hry, různé potvrzovací dialogy atd. I při návrhu rozložení uživatelského rozhraní je třeba mít na paměti lokalizaci. Na všechny texty nechávejte hodně místa. Uvědomte si, že přeložený text může být mnohem delší, než originál. To platí obzvlášť při překladu z angličtiny. Angličtina je velice strohá, a jiné jazyky zpravidla potřebují více místa pro vyjádření téhož textu. Pamatujte také, že pro asijské jazyky budete zřejmě muset použít větší font, takže si nechte dostatek místa i na výšku.
Perlička: Nejkritičtější v prodlužování textů je asi němčina. Ve hře Oblivion sbíráte léčivé lektvary, které jsou v inventáři popsané jako "Light potion of healing". Němečtí překladatelé to přeložili jako "Schwacher Trank der Lebensenergie-Wiederherstellung", což se jim nevešlo na obrazovku, a proto byli nuceni použít zkratku "Schw.Tr.d.Le.en.-W." Ukázkový příklad špatně navrženého uživatelského rozhraní, ústícího v nekvalitní překlad.
Dabing a videa
Pokud vaše hra obsahuje dabing, udržujte tyto zvukové soubory odděleně od souborů obecných. Organizace souborů s dabingem je hodně závislá na konkrétní hře, ale můžete s úspěchem použít ID textu z tabulky řetězců pro pojmenování souboru s odpovídajícím zvukem. Například bude-li v tabulce řetězců text:
kód: |
STRING0001 Ahoj Pepo, jak se máš? |
Dabing této věty bude uložen v souboru "string0001.mp3". Engine hry pak může snadno sám dohledávat a přehrávat dabing podle toho, jaký text právě zobrazuje na obrazovce. Zároveň, pokud máte v ID textu zakódované jméno postavy, můžete snadno vyfiltrovat jen věty určitého herce a podobně. Při vhodně zvolené struktuře tabulky řetězců z ní můžete dokonce automatizovaně vygenerovat scénář pro jednotlivé dabéry.
Pro videa vždy umožněte zapnout titulky pro případ, že lokalizátoři nebudou chtít nahrávat vlastní dabing. Pro titulky k videím můžete použít standardní formáty, jako je .SUB nebo .SRT. Existují pro ně již hotové editační nástroje.
Vstup z klávesnice
Pokud vaše hra umožňuje vstupy textů z klávesnice, například pro zadání jména hráče, nebo názvu uložené pozice, nepoužívejte pro tyto účely DirectInput, ale klasické zprávy Windows API, jako WM_CHAR. Ty už za vás vyřeší mapování kláves na odpovídající národní znaky, obsluhu "mrtvých kláves" (háčky a čárky) a podobně.
Formáty čísel a dat
Pracujete-li ve hře s čísly a daty, pamatujte, že různé jazyky používají různé formáty (desetinná tečka / čárka, oddělovače řádů, oddělovače dní a měsíců). Umožněte tyto formáty měnit podle jazykové verze hry, případně použijte globální nastavení systému Windows. Windows API vám k tomu nabízí řadu funkcí.
Kulturní odkazy
Při designu hry se vyvarujte nejrůznějších odkazů a vtípků, které jsou specifické jen pro určitý jazyk či národ. Takové odkazy se velice špatně překládají a komplikují lokalizaci. Pokud už musíte něco takového použít, poskytněte překladatelům dostatečné vysvětlení, aby mohli danou situaci korektně "přebásnit" do jiného jazyka nebo přenést do jiného kulturního prostředí.
Snažte se vyhnout herním situacím, které by mohly být potenciálně urážlivé pro některé národy. Například, pokud se váš hlavní hrdina bude v jednom kuse cpát vepřovým, bude se vám hra špatně exportovat do arabských zemí
Závěrem
Tento článek se zaměřil na mnohdy opomíjenou oblast připravenosti herního engine na snadnou lokalizaci. Probrali jsme si nejzásadnější body, odhalili úskalí a pokusili se najít řešení. Pokud se lokalizaci vaší hry teprve chystáte řešit, snad vám tento článek pomůže vyhnout se některým slepým uličkám.
Jan Nedoma (Mnemonic)
Autor se podílel na lokalizaci spousty her, komerčních i freewarových, a to jak v roli vývojáře, tak v roli lokalizátora |
|