Lokalizace programu v jazyce C

Z Milan Kerslager
Přejít na: navigace, hledání

Lokalizace do národního prostředí má za úkol nahradit chování programu a anglická hlášení jejich českými ekvivalenty. Některé části jsou společně definované pro celý systém (například tvar zápisu datumu, rozměr používaného papíru, používaná měna a podobně), překlad hlášení programu je pak specifické pro každý program zvlášť.

Popis národních odlišností

Popis národních odlišností je umístěn do adresáře /usr/share/locale/jazyk. V případě, že ve státě je více oficiálních jazyků, používá se adresář /usr/share/locale/jazyk_STÁT. Dvoupísmenný kód jazyka je určen normou ISO-639 a kód státu je určen normou ISO-3166.

cs             čeština (implicitní stát, implicitní kódování ISO-8859-2)
cs_CZ          čeština v České republice (implicitní kódování ISO-8859-2)
cs_CZ.UTF-8    čeština v České republice s kódováním UTF-8
sk_SK.UFT-8    slovenština ve Slovensku s kódováním UTF-8

I18N

Zkratka I18N odkazuje na slovo internationalisation (první a poslední písmeno a 18 znaků mezi nimi). Označuje postup, který zajistí, že program je ve tvaru, který lze lokalizovat (jde tedy o programátorskou část).

L10N

Zkratka L10N odkazuje na slovo localisation (první a poslední písmeno a 10 znaků mezi nimi). Označuje postup, který změní chování programu tak, aby vyhovoval národním zvyklostem (překlad hlášení programu, použití správných jednotek atp).

Nastavení prostředí

Nastavené prostředí lze zjistit spuštěním příkazu locale. Tento příkaz vypíše sadu proměnných prostředí, které se dědí na další spouštěné programy a ty se pak podle nich mohou zachovat. Prohlédněte si příklad výstupu tohoto programu:

LANG=cs_CZ.UTF-8
LC_CTYPE="cs_CZ.UTF-8"
LC_NUMERIC="cs_CZ.UTF-8"
LC_TIME="cs_CZ.UTF-8"
LC_COLLATE="cs_CZ.UTF-8"
LC_MONETARY="cs_CZ.UTF-8"
LC_MESSAGES="cs_CZ.UTF-8"
LC_PAPER="cs_CZ.UTF-8"
LC_NAME="cs_CZ.UTF-8"
LC_ADDRESS="cs_CZ.UTF-8"
LC_TELEPHONE="cs_CZ.UTF-8"
LC_MEASUREMENT="cs_CZ.UTF-8"
LC_IDENTIFICATION="cs_CZ.UTF-8"
LC_ALL=

Čím dříve je proměnná vypsána, tím má nižší váhu a proměnné umístěné níže mohou její nastavení změnit. Proto se obvykle národní prostředí celého počítače nastavuje pomocí proměnné LANG. Uživatel pak má možnost jednoduchým způsobem ovlivnit zbývající nastavení (zápis čísel, měny, používaný rozměr papíru atd) – jen nastaví další proměnnou prostředí. Tímto způsobem si můžeme nechat psát program česky, ale čísla například vypisovat s desetinnou tečkou, jako v některých západních státech. Logicky nastavení proměnné LC_ALL překryje všechna ostatní nastavení.

V proměnné je nejprve kód jazyka, za podtržítkem může být upřesněn kód státu a za tečkou pak eventuálně i kódování (zde UTF-8). Implicitní kódování pro nastavení cs a cs_CZ je ISO-8859-2. Avšak pro současné systémy je výhodnější používat unikód, protože pak lze používat všechna písmena nejrůznějších jazyků zároveň (tj. např. v poštovním programu můžeme snadno číst francouzské, ruské i čínské texty – samozřejmě pokud používáme unikódový font, který požadované znaky obsahuje).

Lokalizace programu

Příklad lokalizovaného programu si můžete prohlédnout níže. Na začátku je potřeba zavolat trojici knihovních funkcí: setlocale (přebírá nastavení proměnných prostředí na dané locale), bindtextdomain (určuje adresář, kde se nacházejí katalogy s přeloženými zprávami) a textdomain (určuje název souboru s katalogem, ve kterém se budou nacházet přeložená hlášení).

#include <locale.h>
#include <stdio.h>
main ()
{
  setlocale(LC_ALL, "");
  bindtextdomain("priklad", "");
  textdomain("priklad");
  printf("%s\n", gettext("Hello world!"));
}

Řetězec, který má program vytisknout, je obalen voláním knihovní funkce gettext. Za normálních okolností (tj. není-li locale nastaveno nebo v případě, že katalogy na disku chybí), bude funkce vracet stejný řetězec, který dostala jako parametr. V případě, že je nastaveno locale a je nalezen katalog a v katalogu bude příslušný řetězec přeložen, vrátí funkce gettext příslušný překlad. Proto program s českými locale může vypsat Nazdar světe! místo Hello world!.

Katalog hlášení

Pro vytvoření katalogu hlášení použijeme nástroj, který vyrobí soubor pro překlad tak, že vyzobe ze zdrojového textu všechna hlášení připravená k lokalizaci:

xgettext --default-domain=priklad --output-dir=. --add-comments --keyword=_ priklad.c

V aktuálním adresáři nám vznikne soubor priklad.po, do kterého doplníme chybějící údaje a smažeme případné slovo fuzzy (označuje nepřesný překlad, např. když se v anglickém vzoru opraví překlep).

# Czech translation for our priklad.
# Copyright (C) 2007
# This file is distributed under the same license as the priklad package.
# Milan Kerslager <milan.kerslager@tul.cz>, 2007.
#
msgid ""
msgstr ""
"Project-Id-Version: priklad 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-04-11 18:29+0200\n"
"PO-Revision-Date: 2007-04-11 18:31+0200\n"
"Last-Translator: Milan Kerslager <milan.kerslager@tul.cz>\n"
"Language-Team: Czech <cs@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-2\n"
"Content-Transfer-Encoding: 8bit\n"

#: priklad.c:9
msgid "Hello world!"
msgstr "Nazdar světe!"

Umístění katalogu v systému

Katalogy s překlady jsou pro češtinu soustředěny obvykle do adresáře /usr/share/locale/cs/LC_MESSAGES. Ostatní jazyky mají dle výše zmíněné normy své vlastní adresáře. Protože se v některých státech mluví více jazyky, je možné jazyk upřesnit, např. cs_CZ (čeština v České republice), pt_BR (portugalština v Brazílii) a pt_PT (portugalština v Portugalsku).

Soubor s překlady je potřeba překompilovat do kompaktního formátu, ze kterého si už knihovní funkce gettext bude umět český ekvivalent převzít a umístit jej do adresáře cs/LC_MESSAGES. V programu je u funkce bindtextdomain použit prázdný řetězec, takže se hlášení budou hledat v aktuálním adresáři (obvykle je to adresář /usr/share/locale, ale tam nemůžeme v rámci experimentů jen tak zapisovat).

mkdir -p cs/LC_MESSAGES
msgfmt -v -o cs/LC_MESSAGES/priklad.mo priklad.po

Po nastavení locale by měl program po spuštění vypsat české hlášení převzaté z katalogu. Použijte nastavení vhodné pro vaše prostředí (jeden z uvedených řádků):

LANG=cs_CZ.UTF-8
LANG=cs
LC_ALL=cs_CZ.UTF-8
LC_ALL=cs

Speciality v PO souborech

Fuzzy

Překlad je v PO souboru označen jako fuzzy, pokud se v anglické verzi například opraví překlep a starý překlad je sloučen s novou verzí (programem msgmerge). Slovo fuzzy tak označuje místa, která musí překladatel projít a překlad opravit tím, že slovo fuzzy ze zadaného řádku odstraní:

#, fuzzy
msgid "Hello World!!!"
msgfmt "Nazdar světe!"

V tomto případě tvůrce programu zřejmě přidal vykřičníky. POZOR: pokud je v PO souboru uvedena i formátovací poznámka, je potřeba ji zachovat a smazat jen slovo fuzzy, např:

#, c-format, fuzzy
msgid "Number of pages: %d"
msgfmt "Počet stránek je %d"

Znak \n

Znak \n označuje přechod na nový řádek. V překladu nemusí být stejný počet těchto znaků, avšak je-li umístěn znak nového řádku na začátku (nebo na konci) vzorového řetězce, musí překlad též mít znak přechodu na nový řádek na začátku (nebo na konci) překladu.

Znaky >, < a &

Znaky >, < a & jsou (stejně jako v HTML) speciální a chcete-li je v překladu použít, musíte je nahradit jejich entitami:

Znak "

Znak uvozovek je také speciální. Chcete-li ho v překladu použít, dejte před něj znak zpětného lomítka: \"

Změna pořadí parametrů

Je-li překladu uvedeno více parametrů, je jejich pořadí zachováno, i když jsou uvedeny pod stejnými formátovacími znaky:

#, c-format
msgid "%n out of %n"

Výše uvedený zápis vrátí například: 3 out of 10. Chcete-li, aby v překladu byly uvedeny obráceně (Z 10 zbyly jen 3), použijte speciální zápis:

#, c-format
msgid "%n out of %n"
msgstr "Z %2$d zbyly jen %1$d"

Cvičení

Příklad 1
Napište program, který bude kromě českého jazyka schopen komunikovat v dalších 2 jazycích. Lokalizovaná bude nápověda programu i všechna běhová hlášení.

Externí odkazy