Přejít k navigační liště

Zdroják » Různé » Alternativa k Django Rosetta: Django Translation Manager

Alternativa k Django Rosetta: Django Translation Manager

Články Různé

Translation Manager je Django aplikace, která zjednodušuje práci se statickými překlady (uchovanými v *.po souborech) ve vašem Django projektu. Na rozdíl od django-rosetta překlady z *.po souborů uchovává ve vlastní databázové struktuře.

Vývoj webových aplikací je pro nás řadu let denním chlebem, vedle PHP pro běžné webové projekty stavíme rozsáhlejší systémy v Pythonu na frameworku Django. Každodenní práci nám usnadňuje open-source software, což nás motivuje do open-source komunity také něčím přispět. Jedním z takových projektů je náš Translation Manager.

6a962563e235e1789e663e356ac8d9e4

Pro desítky multijazyčných projektů jsme dosud na překlady používali balíček Django Rosetta. Přestože je to nepochybně velmi populární a užitečný balíček, postupem času jsme začali narážet na některé jeho limity, a to zejména:

  • Nenabízí možnost vypnutí tzv. fuzzy překladů (jedná se o automatické návrhy překladů na základě podobnosti překladových řetězců).
  • Neumožňuje použití pokročilých filtrů nebo seskupování překladů do kategorií.
  • Není možné jej zcela ovládat z administračního prostředí Djanga.
  • Neumožňuje automatické zálohování existujících překladů.

Omezení Rosetty – a také jistý diskomfort signalizovaný od koncových klientů – nás nakonec dovedly k rozhodnutí vyvinout vlastní řešení. Pojmenovali jsme ho Django Translation Manager a kromě eliminace uvedených potíží má další, snad užitečné, vlastnosti jako například ukládání překladů v databázi místo v souborech.

Pojďme se podívat na to, jak Translation Manager funguje, a jak jej můžete jednoduše implementovat do vašeho Django projektu.

1. Vytvoření překladových řetězců

Translation Manager je nadstavbou nad zabudovanými Django překlady označovanými jako i18n. Ty jsou velmi dobře popsány v oficiální Django dokumentaci, a tak se jimi zde nebudeme zabývat do přílišného detailu.

Aby byl projekt multijazyčný, je třeba do zdrojového kódu vložit speciální značky, tedy překladové řetězce. Rozhodně doporučujeme vkládat tyto značky od samotného počátku projektu – nahrazování běžných řetězců až v průběhu projektu či na jeho konci je o poznání bolestnější záležitost.

Překladové řetězce tedy jednoduše říkají Djangu, že mají být před načtením webové stránky přeloženy do příslušného jazyka.

K označení překladových řetězců v Python kódu použijte Django modul ugettext() nebo ugettext_lazy().

from django.utils.translation import ugettext_lazy

ugettext_lazy(“your-translation-string”)

Přestože Django dokumentace od takových praktik odrazuje, je celkem běžnou a užitečnou praxí importovat tyto moduly jako _ alias. Pokud je obsahu více, ušetří se tím spoustu času.

from django.utils.translation import ugettext_lazy as _

_(“your-translation-string”)

Co se týče překladových řetězců v šablonách, tak používáme dva standardní Django tagy – {% trans %} a {% blocktrans %}. Abyste ovšem bylo možné je používat, musí se v šalboně načíst modul překladů pomocí {% load i18n %}.

{% load i18n %}
{% trans “your-translation-string” %}

nebo

{% load i18n %}
{% blocktrans %}your-translation-string{% endblocktrans %}

2. Instalace Translation Manageru

Instalace se provádí pomocí  pip:

pip install django-translation-manager

Do instalovaných aplikací v settings.py je třeba přidat 'translation_manager':

INSTALLED_APPS = (
    ...
    'translation_manager',
)

Dále je třeba přidat požadované jazky do proměnné LANGUAGES umístěné v settings.py:

LANGUAGES = (
    ('cs', _('czech')),
    ('en', _('english')),
)

V souladu s proměnnou LANGUAGES vytvoříme následující adresáře v kořenovém adresáři vašeho projektu:

locale/cs/LC_messages
locale/en/LC_messages

Na závěr synchronizujeme databázi použitím python manage.py syncdb nebo python manage.py migrate, a to v závislosti na používané verzi Djanga.

3. Vytvoření překladových souborů z Django administrace

Translation Manager využívá základních funkcionalit Djanga k extrakci všech překladových řetězců ze zdrojového kódu a jejich uložení do překladových souborů. Překladový soubor není nic jiného než soubor obsahující všechny překladové řetězce spolu s jejich odpovídajícími překlady v daném jazyce. Překladový soubor má koncovku .po a je tvořen prostým textem.

Výchozí překladová funkcionalita Djanga používá k vytvoření nebo aktualizaci překladových souborů následující příkaz:

python manage.py makemessages

Tento příkaz spustí skript, který projde celou strukturu projektu a extrahuje všechny překladové řetězce (viz krok 1). Následně vytvoří nebo aktualizuje překladové *.po soubory v příslušných ‘LC_messages’ adresářích (krok 2).

V této fázi přichází na scénu výhody Translation Manageru. Vzhledem k tomu, že je Translation Manager instalován jako samostatná aplikace, můžete jej jednoduše spravovat přímo z prostředí Django administrace.

Není tedy nutné spouštět příkaz makemessages z příkazového řádku (přesto stále můžete, pokud chcete). Namísto toho můžete v administraci kliknout na tlačítko v pravém horním rohu s označením “Aktualizovat seznam překladů” a příkaz se automaticky provede.

Jakmile příkaz proběhne, v administraci se zobrazí všechny překladové řetězce. Je důležité zmínit, že kromě vygenerování nebo aktualizace překladových *.po souborů dojde k uložení jejich obsahu do databáze.

4. Přeložení překladovových řetězců

Aby byl celý proces co nejjednodušší, Translation Manager umožňuje spravovat všechny překlady přímo z prostředí Django administrace.

Translation Manager zároveň umožňuje filtrování překladových řetězců. Aby bylo možné této funkce naplno využít, doporučujeme od začátku vytváření překladových řetězců dodržovat přesný styl či metodiku pojmenování.

Celá záležitost je jednodušší, než se může na první pohled zdát. Pouze je třeba setřídit překladové řetězce do předem definovaných kategorií podle jejich účelu nebo místa zobrazení. V COEXu např. používáme ustálené předpony ‘front-’ pro frontendové záležitosti, ‘admin-’ pro backendové řetězce a ‘email-’ pro všechny e-mailové šablony.

Tato část rovněž úzce souvisí s nastavením – v proměnné TRANSLATION_QUERYSET_FORCE_FILTERS totiž můžete používané předpony specifikovat a na jejich základě potom jednoduše filtrovat. Více se o tomto nastavení dočtete v bodě 6.

Jak už jsme zmínili dříve, Translation Manager vytváří svoji vlastní databázovou strukturu, kde uchovává všechny překlady. Díky tomu je možné sledovat všechny provedené změny a zálohovat všechny dřívější verze.

06e2304a6a200a54d7729ed6fcdc5cb4

5. Publikování překladů

Jakmile jsou překlady dokončeny, nastává čas ukázat vícejazyčný web světu. K tomu je třeba překladové *.po soubory zkompilovat do podoby použitelné pro moduly ugettext() nebo ugettext_lazy().

Kompilaci lze provést spuštěním následujícího příkazu:

python manage.py compilemessages

Situace je obdobná jako u příkazu makemessages v kroku 3. Translation Manager tento příkaz provede po kliknutí na tlačítko “Publikovat překlady” v Django administraci. Výsledkem budou kompilované *.mo soubory v adresářích ‘LC_messages’ vytvořených v kroku 2.

6. Restart webserveru

Posledním krokem k tomu, aby se překlady objevily na webu, je restartování webserveru.

Lze to udělat ručně, nicméně Translation Manager umožňuje proces automatizovat. Po úspěšném zkompilování překladových souborů je vyslán Djangu signál, na jehož základě může být spuštěn skript pro restart webserveru.

from translation_manager.signals import post_save as translation_post_save

translation_post_save.connect(restart_server, sender=None)

Funkce restart_server pak může vypadat  například následovně:

def restart_server(sender, **kwargs):
        request = kwargs.pop('request', {"META": {}})
        gunicorn_served = bool(re.match(r"gunicorn", 
                request.META.get("SERVER_SOFTWARE", u"")))
        if gunicorn_served:
                management.call_command('hup', verbosity=0, 
                        interactive=False)

7. Úprava Translation Manageru k obrazu svému

Tento krok je samozřejmě zcela volitelný. Translation Manager může být jednoduše nastaven přetížením následujících proměnných v settings.py.

LOCALE_PATHS (list)
Seznam cest do složek
‘locale’. Pokud není nastaveno, je vybrána složka ‘locale’ v kořenovém adresáři vašeho projektu.

TRANSLATIONS_BASE_DIR (string)
Řetězec označující úroveň v adresářové struktuře projektu, od které bude Translation Manager hledat překladové řetězce. Výchozí hodnotou je kořenový adresář projektu.

TRANSLATIONS_IGNORED_PATHS (list)
Seznam cest, které Translation Manager nebude prohledávat pro výskyt překladových *.po souborů, jako je např. [‘env’, ‘media’]

TRANSLATIONS_MAKE_BACKUPS (boolean)
Boolean hodnota, která určuje, jestli se budou vytvářet automatické zálohy v případě aktualizace databáze novými překlady.

TRANSLATIONS_CLEAN_PO_AFTER_BACKUP (boolean)
Boolean hodnota, která určuje, jestli budou překladové *.po soubory smazány po vytvoření záloh.

Následující nastavení ovlivňují vzhled a chování Django administrace:

TRANSLATIONS_QUERYSET_FORCE_FILTERS (list)
Seznam předpon použitých v překladových řetězcích. Na jejich základě Django administrace umožní filtrování. Více se o nich dočtete v kroku 4.

TRANSLATIONS_QUERYSET_FORCE_FILTERS = ['admin-', 'front-', 'email-']

TRANSLATIONS_HINT_LANGUAGE (string)
Řetězec označující výchozí jazyk nápovědy. Nápověda se zobrazuje přímo v Django administraci vedle překladových řetězců. Při dalších překladech lze snadno poznat, jak má výsledný text vypadat.

TRANSLATIONS_ADMIN_EXCLUDE_FIELDS (list)
Seznam řetězců určujících položky, které budou vyřazeny z Django administrace (sloupce).

TRANSLATIONS_ADMIN_FIELDS (list)
Jedná se o opak předchozí proměnné. Určuje seznam položek, které mají být zobrazeny v Django administraci jako sloupce.

TRANSLATIONS_CUSTOM_FILTERS (list)
Umožňuje vytvoření jednoho vlastního filtru. Proměnná musí obsahovat seznam, kde první hodnota je řetězec určující zobrazený název filtru. Druhá hodnota musí být seznam tuplů obsahujících regulární výraz vašeho filtru a zobrazený název filtru.

TRANSLATIONS_CUSTOM_FILTER = [
        gettext_noop(‘admin-translation_manager-filter-title’),
        [
                (‘^admin-',gettext_noop(‘admin-translation_manager-filter-admin’)), 
                (‘^front-',gettext_noop(‘admin-translation_manager-filter-front’)),
                (‘^email-',gettext_noop(‘admin-translation_manager-filter-email’))
        ]
]

Závěrečné slovo

První verze Translation Manageru byla vypuštěna do světa koncem roku 2014. Projekt je pod licencí Mozilla Public License 2.0, což v praxi znamená, že jej lze použít zdarma i v komerčních projektech. Kompatibilita se staršími verzemi Djanga (1.4 – 1.7) je udržována ve verzi 0.2.7. Pro Django 1.8+ je určena verze 0.3.0+, kde je počítáno i s novými funkcemi.

Jak bylo popsáno na začátku dnešního článku, Django Rosetta je velmi populární Django balíček a rozhodně si vážíme úsilí vývojářů, kteří za ním stojí. Přesto pro nás mnohdy představoval značná omezení při tvorbě multijazyčných projektů, a proto jsme se rozhodli vytvořit alternativu.

Budeme rádi pokud Translation Manager vyzkoušíte a také uvítáme samozřejmě jakékoliv komentáře, připomínky a nápady na zlepšení.

Text vzniknul v rámci COEX Python týmu, speciální dík patří Oldřichu Kučinovi a Jakubovi Ladrovi.

Zdrojový kód je k nalezení na adrese:
https://github.com/COEXCZ/django-translation-manager

Anglická verze článku na našem blogu:
https://www.coex.cz/blog/translation-manager

Komentáře

Subscribe
Upozornit na
guest
6 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
pavels

Jen mala poznamka, ugettext() neni modul ale funkce. Take pises o ugettext_lazy() a pozdeji o lazy_ugettext().

snakeyyy

Z tohoto článku to vypadá opravdu dobře, ale dokumentace na githubu je o poznání stručnější a kdybych přečetl jen tu, nepochopil bych jak to funguje a jak to použít. Tudíž doporučuji ji doplnit.

David Klouček

vedle PHP pro běžné webové projekty stavíme rozsáhlejší systémy v Pythonu na frameworku Django

Proč ne taky v PHP?

Jan Češpivo

Ahoj,
u nás (v COEXu) je toto dáno hlavně historickým vývojem. Rozhodnutí bylo zcela pragmatické. Před cca 10 lety jsme používali pro vývoj webových aplikací téměř výhradně PHP. Postupně jsme ale naráželi na limity udržovatelnosti našich už tehdy poměrně velkých aplikací. V té době ale v PHP neexistoval žádný skutečně použitelný webový framework, dokonce i Zend framework byl teprve v plenkách a OOP v PHP teprve nastupovalo spolu s pětkovou verzí. Po několika pokusech napsat vlastní framework a zjištění, že to není ta správná cesta, jsme začali pokukovat i po alternativách v podobě jiných programovacích jazyků a jejich frameworcích. Zaujalo nás už tehdy velmi slibně se rozvíjející Ruby on Rails a konkurenční Django. Ruby i Python byly oproti PHP mnohem vyspělejší jazyky s plnou podporou OOP. Oba frameworky měly podobné vlastnosti. Nakonec vyhrála čitelnost syntaxe, tedy Python a s ním i Django.

Nechci tak říkat, že se v PHP nedají realizovat velké projekty. V PHP se v posledních letech vyrojilo velké množství dobrých frameworků a hlavně jazyk jako takový se hodně posunul.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.