sobota, 23. října 2010

Jak začlenit do programu podporu lokalizace

Určitě jste si už v Linuxu všimli skvělého systému na překlad aplikací Gettext. Stáhnete si .po soubor s překladem, přeložíte, co můžete, odešlete zpátky autorovi programu a v nové verzi už je vaše čeština oficiálním překladem. Launchpad.net dokonce umožňuje překládat přímo online. Jednoduché, efektivní. Jak ale podporu pro lokalizaci začlenit do vlastních aplikací napsaných v Pythonu a PyGtk? To jest téma tohoto článku.

Příprava

Pusťme se tedy do toho. Začlenění překladu budu demonstrovat na souborech gui.glade s uživatelským rozhraním a main.py, který načte a zobrazí toto rozhraní a v případě neúspěchu vypíše chybovou hlášku:


  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import gtk
  4. import sys
  5. class LocalizationExample:
  6.     def __init__(self):
  7.         # use GtkBuilder to build our interface from the XML file
  8.         try:
  9.             builder = gtk.Builder()
  10.             builder.add_from_file('gui.glade')
  11.         except:
  12.             self.error_message("Can't load the glade file with user interface: gui.glade")
  13.             sys.exit(1)
  14.        
  15.         # get the widgets which will be referenced in callbacks
  16.         self.window = builder.get_object("window")
  17.         # connect signals
  18.         builder.connect_signals(self)
  19.     def main (self):
  20.         # Run main window of the app
  21.         self.window.show()
  22.         gtk.main()
  23.     def on_window_delete (self, *args):
  24.         gtk.main_quit()
  25. if __name__ == "__main__":
  26.     le = LocalizationExample()
  27.     le.main()

Úprava main.py

Pro začlenění podpory pro lokalizaci je potřeba mírně pozměnit původní soubor main.py. Na začátek souboru přidáme:

  1. import gettext
  2. import locale
  3. APP = "locex"
  4. DIR = 'locale'
  5. locale.setlocale(locale.LC_ALL, '')
  6. gettext.bindtextdomain(APP, DIR)
  7. locale.bindtextdomain(APP, DIR)
  8. gettext.textdomain(APP)
  9. locale.textdomain(APP)
  10. _ = gettext.gettext

Všimněte si konstanty APP = "locex". Nastavuje jakýsi jmenný prostor překladu. Není důležité jakou hodnotu zadáte, každopádně zapamatujte si ji, protože ji za chvíli budeme potřebovat.

Dále také musíme každý řetězec, který chceme přeložit, pozměnit z "řetězec" na _("řetězec"). Náš finální soubor bude tedy po úpravě vypadat takto:

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import gtk
  4. import sys
  5. import gettext
  6. import locale
  7. APP = "locex"
  8. DIR = 'locale'
  9. locale.setlocale(locale.LC_ALL, '')
  10. gettext.bindtextdomain(APP, DIR)
  11. locale.bindtextdomain(APP, DIR)
  12. gettext.textdomain(APP)
  13. locale.textdomain(APP)
  14. _ = gettext.gettext
  15. class LocalizationExample:
  16.     def __init__(self):
  17.         # use GtkBuilder to build our interface from the XML file
  18.         try:
  19.             builder = gtk.Builder()
  20.             builder.add_from_file('gui.glade')
  21.         except:
  22.             self.error_message(_("Can't load the glade file with user interface: gui.glade"))
  23.             sys.exit(1)
  24.        
  25.         # get the widgets which will be referenced in callbacks
  26.         self.window = builder.get_object("window")
  27.         # connect signals
  28.         builder.connect_signals(self)
  29.     def main (self):
  30.         # Run main window of the app
  31.         self.window.show()
  32.         gtk.main()
  33.     def on_window_delete (self, *args):
  34.         gtk.main_quit()
  35. if __name__ == "__main__":
  36.     le = LocalizationExample()
  37.     le.main()

Nyní můžeme soubor uložit a zavřít.

Příprava .pot šablony

Vzhledem k tomu, že gettext neumí pracovat přímo s .glade soubory, použijeme intltool-extract k vygenerování pomocného .glade.h souboru. Otevřeme si Terminál ve složce s programem a zadáme:

intltool-extract --type=gettext/glade gui.glade

Nyní si vytvoříme složku na .po soubory s překlady a necháme do něj vygenerovat .pot šablonu ze souborů main.py a gui.glade.h:

mkdir po
xgettext --language=Python --keyword=_ --keyword=N_ --output=po/template.pot main.py gui.glade.h

Volitelně můžeme přidat také parametry --package-name=NÁZEV a --package-version=VERZE, které se zapíšou do výsledného .pot souboru:

xgettext --language=Python --keyword=_ --keyword=N_ --package-name=LocalizationTest --package-version=0.1 --output=po/template.pot main.py gui.glade.h

Vytvoření souboru pro překlad

Překladový soubor pro konkrétní jazyk vytvoříme zadáním příkazu msginit --input=template.pot --locale=/kód jazyku/ ve složce se šablonou. Pokud chceme vytvořit soubor pro češtinu, bude to:

cd po
msginit --input=template.pot --locale=cs_CZ

Ve složce po se nám vytvoří soubor cs.po, který můžeme otevřít buďto v obyčejném textovém editoru, nebo třeba v Gtranslatoru. Přeložíme tedy všechny řetězce, soubor uložíme a pokračujeme k poslednímu kroku, kterým bude vytvoření .mo souboru.

Binární .mo soubory

.mo soubory jsou v podstatě binární verze .po souborů využívané gettext modulem k lokalizaci. Nejdříve ale musíme pro tyto soubory vytvořit patřičné složky. Přejdeme v terminálu do umístění se souborem main.py a spol. a zadáme:

mkdir -p locale/cs_CZ/LC_MESSAGES

Nakonec vytvoříme .mo soubory příkazem:

msgfmt --output-file=locale/cs_CZ/LC_MESSAGES/locex.mo po/cs.po

Všimněte si, že je .mo soubor pojmenovaný podle konstanty, kterou jsme nastavovali v souboru main.py. Nyní můžeme program vyzkoušet. Měl by být v češtině. Pokud ne, zkuste ho spusit s nastavením proměnné LANG:

LANG=cs_CZ.utf8 ./main.py


Můžete také program spustit v původní anglické verzi:

LANG=en_GB.utf8 ./main.py

Aktualizace překladu

Pokud v budoucnu upravíte zdrojový kód aplikace a přidáte nové řetězce, je potřeba aktualizovat soubory s překlady, abychom nepřišli o již přeložené řetězce.

Pokud máte v aplikaci zatím jenom jeden jazyk, asi bude nejjednodušším řešením ve složce s aplikací vždy spustit tento skript:

  1. #!/bin/bash
  2. intltool-extract --type=gettext/glade gui.glade
  3. xgettext --language=Python --keyword=_ --keyword=N_ --output=po/template.pot main.py gui.glade.h
  4. cd po
  5. msgmerge -U cs.po template.pot
  6. cd ..
  7. mkdir -p locale/cs_CZ/LC_MESSAGES/
  8. msgfmt po/cs.po -o locale/cs_CZ/LC_MESSAGES/locex.mo

U jiných aplikací by bylo samozřejmě nutné skript upravit na odpovídající názvy souborů.

Finální struktura
(main_without_loc.py není potřeba...)

Odkazy

0 komentářů:

Přidat komentář