Django: Internacionalizace

Pokud webový projekt chcete zpřístupnit co nejširšímu publiku, musíte ho lokalizovat do dalších jazyků, nebo alespoň umožnit, aby byl v případě potřeby lokalizován. Django na tyto účely využívá externí nástroj gettext.

Seriál: Hrajeme si s Djangem (16 dílů)

  1. Django: Úvod a instalace 14.8.2009
  2. Django: Nastavení projektu a první pokusy 21.8.2009
  3. Django: Databázový model 28.8.2009
  4. Django: Databázový model podruhé 4.9.2009
  5. Django: Administrace 11.9.2009
  6. Django: Prezentace dat 18.9.2009
  7. Django: Prezentace dat podruhé 25.9.2009
  8. Django: Zpracovávání formulářů 2.10.2009
  9. Django: Autentizace a autorizace 9.10.2009
  10. Django: Nahrávání souborů 16.10.2009
  11. Django: Zabudované aplikace 23.10.2009
  12. Django: Rozšiřování možností Djanga 30.10.2009
  13. Django: Internacionalizace 6.11.2009
  14. Django: Nasazování projektu 13.11.2009
  15. Django: Kešování a škálování 20.11.2009
  16. Django: Závěr 27.11.2009

Opět si na začátku představíme trochu terminologie: lokalizace znamená přizpůsobení aplikace určitému národnostnímu prostředí. To kromě překladu zahrnuje i kupříkladu správné formátování čísel a časových údajů. Oproti tomu internacionalizace znamená zmezinárodnění, tedy úprava našeho jednojazyčného produktu, abychom mohli přidávat další jazyky. Tyto termíny se v anglickém IT žargonu často zkracují na výrazy l10n a i18n — čísla zde znázorňují počet vynechaných znaků v původních slovech.

Nastavení projektu

Abychom umožnili lokalizaci, musíme mít v konfiguračním souboru settings.py povoleno několik nastavení. První je konstanta LANGUAGE_CODE, jež znázorňuje výchozí jazyk projektu. Podle této konstanty se mimo jiné nastaví jazyk administračního rozhraní. Jazykový kód pro češtinu je 'cs', pro slovenštinu 'sk', kódy dalších jazyků naleznete v seznamu identifikátorů. Další důležitou konstantou je LANGUAGES. Ta pomocí n-tic zapisuje použité jazyky v projektu a jejich názvy. A konečně, pomocí konstanty USE_I18N máme možnost úplně vypnout internacionalizaci, v případě, že se bez ní obejdeme.

Jestliže bychom chtěli náš projekt přeložit do angličtiny, nastavení by vypadalo takto:

LANGUAGE_CODE = 'cs'

LANGUAGES = (
    ('cs', u'Čeština'),
    ('en', u'English'),
)

USE_I18N = True

Dalším krokem je vytvoření adresáře, do kterého se budou ukládat překlady do jednotlivých jazyků. Konvence nám stanovuje ho vytvořit přímo v adresáři projektu a pojmenovat ho locale. Jakmile ho vytvoříte, můžeme se vrhnout na zadávání lokalizačních řetězců. Pomocí nich určíme, které kusy kódu mají být přeloženy.

Vyznačení textu k překladu

Před započetím práce na každém novém projektu bychom se měli vždy nejprve rozmyslet, jestli daný projekt bude potřeba někdy přeložit do dalšího jazyka. Ne, že by nebylo možné projekt internacionalizovat později. Je jenom mnohem otravnější procházet již hotovou aplikaci a vyznačovat lokalizační řetězce, než to dělat průběžně. Také je vhodné určit, zda je lepší psát texty v mateřském jazyce nebo v angličtině. Pokud na projektu pracují (nebo budou výhledově pracovat) vývojáři různých národností, angličtina by měla být samozřejmostí.

Lokalizačních řetězce se mohou vyskytnout na dvou různých místech — v šablonách a v aplikačním kódu (tedy např. v modelech nebo v pohledech).

Lokalizace šablon

Na začátku každé šablony obsahující lokalizační řetězce musí být uveden kód pro načtení internacionalizačního modulu {% load i18n %}. Poté jenom stačí řetězce označovat pomocí značky {% trans "řetězec k překladu" %}. Pro delší texty lze použít párovou značku {% blocktrans %}řetězec k překladu{% endblocktrans %}.

Lokalizace pythonového kódu

V modulu django.utils.translation máme k dispozici několik lokalizačních funkcí, nás budou zajímat pouze tyto: ugettext, ugettext_lazy a string_concat. První dvě mají stejnou funkci, vyznačí daný text k překladu, liší se jenom v době překladu řetězce. Funkce ugettext přeloží řetězec do daného jazyka řetězec ihned, kdežto funkce ugettext_lazy až když je to potřeba. Proto je úspornější používat funkci ugettext_lazy. Obě funkce jsou často používané, takže bývá zvykem je při importování zkracovat na pouhou pomlčku:

from django.utils.translation import ugettext as _

Parametrem těchto dvou funkcí je unikódový řetězec:

translated = _(u'řetězec k překladu')

Další zajímavou funkcí je string_concat, jež slouží ke spojování překladových řetězců. Protože funkce ugettext_lazy vrací objekt, který se přeloží na řetězec, až bude třeba, běžné spojování řetězců pomocí operátoru plus nefunguje. Proto musíme požadované řetězce vložit do seznamu a ten předat jako parametr funkci string_concat. V tomto seznamu můžeme libovolně míchat obyčejné řetězce s překladovými:

concated = string_concat([_(u'řetězec'), ' k ', _(u'překladu')])

Když už teď víme, jak v projektu vyznačit lokalizační řetězce, ukážeme si, jak z nich vytvořit překladové soubory.

Překladové soubory

Unixový nástroj gettext, který je v Djangu využíván pro překlad, pracuje se dvěma druhy souborů: jedny jsou textové a mají příponu .po a ty druhé, s příponou .mo, jsou binární. V textovém souboru budeme udržovat překlad, který je potřeba při každé změně převést do binárního souboru.

Vytváření a aktualizace se dělá pomocí příkazu django-admin.py makemessages. Je potřeba ho napsat do příkazové řádky v adresáři projektu a připojit k němu parametr -l se specifikací jazyka. Tedy například řetězce pro angličtinu vygenerujeme takto:

$ django-admin.py makemessages -l en
processing language en

Abyste nemuseli při aktualizaci mnoha jazyků psát tento příkaz vícekrát, můžete použít parametr -a, ten aktualizuje řetězce pro všechny jazyky. Každopádně, po provedení příkazu se nám vytvořil nový soubor locale/en/LC_MESSAGES/django.po, který má zhruba takovýto obsah:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSIONn"
"Report-Msgid-Bugs-To: n"
"POT-Creation-Date: 2009-11-04 20:01+0100n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONEn"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>n"
"Language-Team: LANGUAGE <LL@li.org>n"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=UTF-8n"
"Content-Transfer-Encoding: 8bitn"

#: templates/base.html:20
msgid "Titulní strana"
msgstr ""

Prvních sedmnáct řádků souboru jsou metainformace o souboru, např. údaje o autorovi a překladateli. Je vhodné přepsat předvyplněné údaje svými, zvláště když pracujete na větším projektu. Lokalizační řetězce uvozuje klíčové slovo msgid (dvacátý řádek) a překlad je potřeba napsat do uvozovek za klíčové slovo msgstr (dvacátý první řádek). V případě, že se jedná o delší překlad, můžeme nechat uvozovky za klíčovým slovem prázdné a text rozepsat do uvozovek na další řádky. Django mimochodem automaticky do komentáře vypisuje umístění řetězce, což považuji za užitečné. Za povšimnutí také stojí, že poznámka začínající čárkou a slovem fuzzy (šestý řádek) značí, že následující překlad bude ignorován.

Když doplníme překlady do příslušných polí, je potřeba soubory převést do binární podoby. Toho docílíme napsáním příkazu django-admin.py compilemessages:

$ django-admin.py compilemessages
processing file django.po in /home/dqd/hrajeme_si/locale/en/LC_MESSAGES

Tím se nám vytvoří soubory s příponou .mo, jež se používají při generování stránek.

Přepínání jazyků

Jakmile máme všechno přeloženo, potřebujeme dát návštěvníkovi možnost zvolit si jazykovou verzi webu. Tuto funkci zajišťuje kontextový procesor django.core.context_processors.i18n. Je potřeba ho tedy mít zařazený v konfigurační konstantě TEMPLATE_CONTEXT_PROCESSORS. (O kontextových procesorech jsme se zmiňovali v minulém dílu.) Kromě toho musíme v souboru settings.py do konstanty MIDDLEWARE_CLASSES přidat položku 'django.middleware.locale.LocaleMiddleware':

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
    'django.middleware.locale.LocaleMiddleware',
)

Pomocí tohoto nastavení se uživateli do prohlížeče ukládá cookie s aktuálně zvoleným jazykem. Kontextový procesor nám poskytuje několik proměnných pro výběr jazyka. Přidáme si proto do hlavní šablony templates/base.html tento kód:

{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}

<form action="/i18n/setlang/" method="POST" id="lang">
<select name="language" onchange="this.form.submit();">
{% for lang in LANGUAGES %}
<option value="{{ lang.0 }}"{% ifequal lang.0 LANGUAGE_CODE %} selected{% endifequal %}>{{ lang.1 }}</option>
{% endfor %}
</select>
<noscript><input type="submit"></noscript>
</form>

Na prvních dvou řádcích načteme aktuálně vybraný jazyk do proměnné LANGUAGE_CODE a seznam všech dostupných jazyků do proměnné LANGUAGES. Poté zobrazíme formulář pro změnu jazyka se všemi možnostmi. Uživatel je po výběru jazyka pomocí JavaScriptu přesměrován na stránku, která mu nastaví správný jazyk. Tu jsme si zatím nedefinovali, proto otevřeme soubor urls.py a na jeho konec připíšeme následující kód:

urlpatterns += patterns('',
    # ...
    (r'^i18n/', include('django.conf.urls.i18n')),
)

A takto vypadá výsledek:

Django 13 - internationalization

Související odkazy

V následujícím dílu si konečně ukážeme přemístění projektu na ostrý server.

Autor je dlouhodobým studentem Fakulty informatiky, webový nadšenec a programátor — nejraději programuje v jazycích Haskell a Python.

Komentáře: 17

Přehled komentářů

Mintaka Po Editory
Jakub Vrána Zásadní chyba
Pavel Dvořák Re: Zásadní chyba
Jakub Vrána Re: Zásadní chyba
os.path Re: Zásadní chyba
calyx Re: Zásadní chyba
Pavel Dvořák Re: Zásadní chyba
calyx Re: Zásadní chyba
PMD Re: Zásadní chyba
. Re: Zásadní chyba
Pavel Dvořák Re: Zásadní chyba
kiot Jak udelat jen a pouze CZ verzi?
Pavel Dvořák Re: Jak udelat jen a pouze CZ verzi?
kiot Re: Jak udelat jen a pouze CZ verzi?
Pavel Dvořák Re: Jak udelat jen a pouze CZ verzi?
kiot Re: Jak udelat jen a pouze CZ verzi?
Mintaka Re: Jak udelat jen a pouze CZ verzi?
Zdroj: https://www.zdrojak.cz/?p=3114