.[ ČeskéHry.cz ].
Jak připravit hru na snadnou lokalizaci - 1. díl

 
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> Magazín
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
Mnemonic



Založen: 28. 07. 2007
Příspěvky: 93

PříspěvekZaslal: 20. září 2007, 16:00:48    Předmět: Jak připravit hru na snadnou lokalizaci - 1. díl Odpovědět s citátem

Jak připravit hru na snadnou lokalizaci - 1. díl
Žijeme v době, kdy se svět takzvaně zmenšuje. Díky nadnárodním korporacím narazíte na tentýž výrobek v obchodech v mnoha různých zemích a stejný seriál uvidíte v televizi v Čechách i na Islandu. Tento fenomén se samozřejmě nevyhýbá ani počítačovým hrám. Čeští herní distributoři nám přinášejí stále více her v češtině a naopak české hry slaví úspěch v zahraničí. Ovšem než může být hra "exportována" na zahraniční trhy, musí projít procesem, jenž se nazývá lokalizace. A právě přípravě na lokalizaci vaší hry a problémům s ní spojeným se věnuje tento článek.

Úvodem
Lokalizací rozumíme nejčastěji překlad hry do jiného jazyka, ale v obecné rovině jde o přizpůsobení konkrétním kulturním zvyklostem v dané zemi. Možná teď někteří amatérští vývojáři pohrdavě mávli rukou, ale přiznejme si to, český trh není z největších, a každý aspoň trochu ambiciózní projekt by měl disponovat minimálně anglickou verzí, aby bylo možno jej prezentovat za hranicemi naší vlasti. Konec konců, i pravidla populární soutěže Becher Game vyžadují, aby soutěžní hry bylo možné hrát jak v češtině, tak v angličtině.

Na internetu naleznete překvapivě málo materiálů, týkajících se této oblasti vývoje her. Tento článek je proto psán z větší části na základě mých osobních zkušeností a popsané postupy jsou prověřeny praxí. Nicméně, jako nikdo, ani já nemám patent na rozum, a je dost možné, že některé procesy zde popsané by šly optimalizovat či provést úplně jinak a lépe. Pokud budete mít jakékoliv připomínky, návrhy, či upřesnění, neváhejte je napsat do diskuse pod článkem, nebo lépe na fórum ČH.

Článek je psán převážně z pohledu programátora (na platformě Windows), ale popisuje některé obecně platné koncepty, použitelné při lokalizaci.

Aby mohla být hra snadno lokalizována, měla by být na lokalizaci připravena. Projděme si nyní několik nejdůležitějších oblastí, kterých se lokalizace hry dotkne.

Lokalizace herních textů

Tabulka řetězců, její naplnění a údržba
Asi nejvíce na ráně jsou herní texty. Přístupy k lokalizaci textů se různí, ale v ideálním případě by měly být všechny texty soustředěny pěkně pohromadě v jednom velkém textovém souboru (říkejme mu tabulka řetězců - string table), který poté předáte překladateli, a on texty přeloží. Hra by potom měla být schopna načíst a použít texty z toho souboru, takže jeho prostou výměnou dojde k nahrazení všech textů ve hře za jejich přeložené ekvivalenty. Ale jak tohoto ideálu dosáhnout? Předně, každý každičký text ve hře bude muset být vybaven nějakým jednoznačným identifikátorem. Tak dosáhneme toho, že hra se bude interně odkazovat na texty jen pomocí tohoto identifikátoru, a vlastní text bude možné libovolně vyměňovat podle aktuálně zvoleného jazyka. Přiřazení jednoznačných identifikátorů jednotlivým textům je poměrně nepříjemná věc, jelikož je obtížné je spravovat ručně a přitom se vyhnout duplicitám, na žádný text nezapomenout a podobně. Samozřejmě, záleží tu na typu hry a potažmo na množství textů. U akční hry, kde se překládá jen "Spustit hru" a "Zabili tě", udržíte tabulku řetězců snadno i ručně, ale u RPG či adventury nejspíš budete muset vyvinout nějakou utilitku, která udělá špinavou práci za vás.

Přístup, který se mi osvědčil, je vyvíjet hru (relativně) bez ohledu na budoucí lokalizaci, a teprve když je hra v dostatečně finalizované podobě, se pomocí nějakého nástroje z herních souborů vykousnou všechny texty určené k překladu a vyexportují se do tabulky řetězců. Při tomto procesu se zároveň každému textu přiřadí zmíněný identifikátor, a text v původním souboru je nahrazen tímto identifikátorem.

Tento postup však přináší mnohá úskalí:

1) Jak vytáhnout všechny texty použité ve hře? Na to mám jedinou radu, snažit se navrhnout herní soubory tak, aby to bylo co nejjednodušší. Předně zapomeňte na texty natvrdo zadrátované do programu. Veškeré texty by měly být v datových souborech hry, maximálně ve skriptech. Pro datové soubory je vhodné používat textový formát, nikoliv binární. Nabízí se použití XML, jelikož při vhodně zvolené struktuře budete schopni vytahat texty pomocí obecného nástroje, který vůbec nemusí znát konkrétní strukturu daného datového souboru. Představte si například XML soubor, definující jednotky v real-time strategii:
kód:
<?xml version="1.0"?>
<Units>
  <Unit>
    <Name Localizable="true">Lučištník</Name>
    <Hitpoints>100</Hitpoints>
    <Script>lucistnik.script</Script>
    <Description Localizable="true">Na blízko neefektivní,
    ale na dálku smrtící jednotka.</Description>
  </Unit>
  <Unit>
    <Name Localizable="true">Katapult</Name>
    <Hitpoints>500</Hitpoints>
    <Script>katapult.script</Script>
    <Description Localizable="true">Pomalá, ale velice silná
    jednotka.</Description>
  </Unit>
</Units>

Všimněte si, že entity Name a Description jsou označeny atributem "Localizable". Takže stačí vytvořit obecný nástroj, který načte XML dokument, projede všechny entity (bez ohledu na jejich název), a pokud mají nastaven atribut localizable, vyexportuje jejich hodnotu do tabulky řetězců. Výhodou XML formátu je, že existuje spousta už hotových parserů, takže nemusíte psát vlastní. Nicméně stejný přístup můžete uplatnit i pokud používáte svou vlastní strukturu datových souborů.

V případě, že vaše hra používá nějakou formu skriptování, patrně budete chtít vytáhnout i stringové konstanty ze skriptů. Pro tento účel se mi jeví jako nejschůdnější upravit kompilátor skriptů. Ten totiž během překladu velice přesně ví, že narazil na řetězec, včetně řádku a sloupce v souboru. Pak už není problém řetězec vyextrahovat a nahradit jej identifikátorem.

2) Výsledkem předcházejícího postupu bude, že se všechny herní texty ocitnou v tabulce řetězců a na místo jejich původního umístění bude vložen nějaký jednoznačný identifikátor. To je sice v zásadě cíl, kterého chceme dosáhnout, ale problém je, že původní soubory tímto zásahem poněkud pozbudou na přehlednosti. Představte si následující skript:
kód:
Franta.Talk("Ahoj Pepo, jak se máš?");
Pepa.Talk("Ale jo, ujde to.");
Franta.Talk("Tak já už musím běžet. ");

Po našem zásahu a vyexportování textů se ze skriptu stane něco takového:
kód:
Franta.Talk("STRING0001");
Pepa.Talk("STRING0002");
Franta.Talk("STRING0003");

Zatímco u prvního skriptu vidíme velice dobře, co se v něm děje, druhý skript je díky absenci textů totálně nepřehledný, což může být na obtíž, pokud budeme skript dodatečně upravovat. Elegantní řešení, které jsem okoukal u her od LucasArts, je ponechat v datovém souboru jak původní text, tak identifikátor, v nějaké domluvené syntaxi. Příklad:
kód:
Franta.Talk("STRING0001|Ahoj Pepo, jak se máš?");
Pepa.Talk("STRING0002|Ale jo, ujde to.");
Franta.Talk("STRING0003|Tak já už musím běžet. ");

Jak vidíte, skript nyní obsahuje texty ve formě "identifikátor | původní text". Tento přístup má dvě výhody. Jednak kód zůstává přehledný a jednak máme možnost se kdykoliv vrátit k původním textům. Například, pokud hra nenajde tabulku řetězců, poběží v klidu dál, ale bude ukazovat z každého textu jen část za "svislítkem". Kromě toho lze pak snadno zopakovat proces exportu textů z herních souborů, jelikož exportní nástroj tak bude schopen přesně určit, které texty již byly vyexportovány do tabulky řetězců, a které byly nově přidány.

Ještě jsme se nepodívali, jak vlastně bude vypadat ta vlastní tabulka řetězců, kterou jsme tak pracně vygenerovali. Rozhodnutí je na vás, mně se osvědčila forma textového souboru, kde na každém řádku je jeden řetězec. Řádek začíná identifikátorem, následuje oddělovač (tabelátor) a pak vlastní text k překladu. Překladateli pak stačí libovolný textový editor a prostě přepíše vše kromě identifikátorů. Tabulka řetězců z našeho příkladu by vypadala takto:
kód:
STRING0001   Ahoj Pepo, jak se máš?
STRING0002   Ale jo, ujde to.
STRING0003   Tak já už musím běžet.

A po čase vám překladatel zpátky pošle něco jako:
kód:
STRING0001   Hi Joe, how are you?
STRING0002   Yeah, I'm okay.
STRING0003   I gotta go.

Tabulku řetězců lze různě vylepšovat, například můžete řádky, začínající středníkem, prohlásit za komentáře (hra je bude při načítání ignorovat), takže si překladatelé budou moci dělat do souboru své poznámky, značky atd.

Další možnosti vám také skýtá identifikátor textu. Můžete do něj kupříkladu zakódovat, která postava text říká, v jaké lokaci je text použit a podobně. Vesměs už pak jde o věci, které zpříjemňují a ulehčují práci lokalizátorů.

U rozsáhlejších her bude muset designér nejspíš do tabulky řetězců vepsat komentáře, upřesňující kontext některých textů, jinak se překladatelé v množství textů ztratí, čímž utrpí kvalita překladu.

Další užitečnou vlastností je možnost, aby se položka tabulky řetězce odkazovala na jinou položku z tabulky. Typicky se ve hře jeden text objevuje víckrát v různých situacích. Pokud umožníte vzájemné odkazy mezi položkami tabulky, překladatel může text přeložit jen jednou, a poté všechny ostatní výskyty téhož textu "přesměrovat" na stejný přeložený termín.

Použití tabulky řetězců v programu
Dobře, ukázali jsme si, jak vytvořit tabulku řetězců, ale jak ji vlastně budeme používat? Předně náš herní engine musí tabulku načíst do paměti. Vzhledem ke struktuře dat (identifikátor, a na něj navázaný text) nejspíše budeme chtít použít nějakou formu hash tabulky. Programujete-li v C++, ideálním řešením je kupříkladu kontejner map z STL.

Načtení textového souboru s tabulkou by měla být triviální záležitost. Prostě čteme řádek po řádku, pokud je řádek prázdný, nebo začíná středníkem (tj. jedná se o komentář), řádek ignorujeme. Jinak rozdělíme řádek na část před tabelátorem (identifikátor) a část za tabelátorem (text) a uložíme do hash tabulky. Opět se nabízí řada vylepšení, jako hlídání duplicitních identifikátorů, oznamování řádků, na kterých chybí tabelátor (překladatel jej omylem nahradil mezerou) atd.

Zvláštní poznámku bych věnoval tomu, zda udržovat všechny texty v paměti. Někomu se to může zdát jako plýtvání pamětí, ale pravdou je, že množství textů u "ukecaných" her se pohybuje řádově ve stovkách kilobytů, málokterá hra se dostane přes megabyte textu. Vzhledem k průměrné velikosti paměti dnešních PC bych s klidným srdcem doporučil udržovat v paměti celou tabulku řetězců.

Nicméně, pokud by se vám to přesto příčilo, nebo pokud míříte na platformu s omezenou pamětí (PocketPC), řešením může být rozdělit tabulku řetězců na víc částí, například na obecné texty a potom na texty specifické pro jednotlivé levely hry a podobně, a ty potom nahrávat do paměti podle potřeby.

Z hlediska použití v programu je vhodné tabulku řetězců zabalit do třídy, která bude v sobě udržovat všechny texty, a navenek bude poskytovat metodu (nejlépe statickou), které předáme původní text a ona nám vrátí text přeložený. Přičemž originálním textem míním text ve formátu "identifikátor|původní text". Metoda pak provede následující činnost:
Zjistit zda původní text obsahuje identifikátor.
Pokud ne, text není určen k překladu a metoda prostě vrátí zpátky text, který obdržela.
Pokud ano, metoda "vykousne" identifikátor a původní text.
Pomocí identifikátoru se pokusí v tabulce řetězců najít přeložený text.
Pokud identifikátor v tabulce existuje, metoda vrátí přeložený text.
Pokud text s daným identifikátorem není nalezen, metoda vrátí textovou část řetězce, který obdržela.

Tím jsme dosáhli toho, že existuje-li překlad daného textu, je vrácen, jinak se vrátí alespoň původní nepřeložený text.

Tento proces vám opět dává prostor pro různá vylepšení. Ladící verze hry může někam logovat texty, pro které neexistuje překlad, případně může texty vracet včetně identifikátoru, aby se takto ukazovaly na obrazovce. To může být užitečné pro betatestování překladu. Pokud tester narazí na text, ve kterém je hrubka, nebo který je přeložen špatně a nezapadá do kontextu, může překladateli oznámit přímo konkrétní ID textu.

Jediné, co teď zbývá, je vytipovat všechna "koncová" místa v programu, kde se používají texty, a do těchto míst doplnit volání metody naší tabulky řetězců, která původní text nahradí textem přeloženým. Co myslím "koncovými místy"? Jsou to nejčastěji místa, kde se texty nějakým způsobem ukazují uživateli. Ať už jde o zobrazení textu na obrazovku, zápis do nějakého textového souboru a podobně. Těchto míst bývá v herním engine relativně málo.

Ukážeme si jeden (hloupý) příklad, jak náš kód obohatit o podporu lokalizace. Řekněme, že pokud náš program narazí na kritickou chybu, vyhodí na obrazovku message box s hlášením. Původní kód by vypadal takto:
kód:
MessageBox(NULL, "Nastala kritická chyba", "Chyba", MB_ICONERROR);

Pokud chceme hlášení zobrazit v jiném jazyce, upravíme kód takto:
kód:
MessageBox(NULL, CStringTable::Translate("SYSSTR0001|Nastala kritická chyba"),
CStringTable::Translate("SYSSTR0002|Chyba"), MB_ICONERROR);

CStringTable je třída, zapouzdřující naši tabulku řetězců, Translate() je statická metoda, která jako parametr dostane původní text a jako návratovou hodnotu vrací přeložený text (popsáno výše).

Kód se sice o něco zkomplikoval, ale nijak fatálně. Případně můžete použít makro, aby se zápis zkrátil:
kód:
#define LOC(String) (CStringTable::Translate(String))

Výsledný kód by pak vypadal takto:
kód:
MessageBox(NULL, LOC("SYSSTR0001|Nastala kritická chyba"),
LOC("SYSSTR0002|Chyba"), MB_ICONERROR);

Stejným způsobem je třeba upravit všechna místa, kde jsou texty prezentovány uživateli.

Závěrem
Tím končí první část tohoto článku. V druhé části se zaměříme na uložení herních textů, povíme si něco o Unicode. Pak prozkoumáme možnosti výpisu textů na obrazovku v kapitole o fontech a nakonec letmo probereme ostatní aspekty lokalizace her.

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 Smile
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Zobrazit příspěvky z předchozích:   
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> Magazín Časy uváděny v GMT + 1 hodina
Strana 1 z 1

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra
Nemůžete odpovídat na témata v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete hlasovat v tomto fóru


Powered by phpBB © 2001, 2005 phpBB Group


Vzhled udelal powermac
Styl "vykraden" z phpBB stylu MonkiDream - upraveno by rezna