Hlavní navigace

Resource soubory a i18n ve wxPythonu

Pavel Šibal

V dnešní části našeho seriálu o programování ve wxPythonu rozvedeme předchozí díl o vytvoření a použití resource souboru a lokalizaci programu s využitím GNU prográmků. Podíváme se především na vkládání ikon a obrázků a lokalizace našich programů.

Vkládání ikon a obrázků

Začneme s trochou praxe – občas při programování GUI vyvstane problém s načítáním různých ikon a obrázků obsažených ve vašem programu. Pokud toto budete řešit otevřením přímo z určeného adresáře, vyvstane problém s cestami. Dejme tomu, že máte ikony uloženy v podadresáři „icons/“. Pokud budete program někam distribuovat, museli byste zkopírovat i všechny obrázky a zajistit, aby byly v adresářové struktuře programu. To by se dalo vyřešit např. pomocí:

import os
icoPath = os.path.join( os.getcwd(), 'icons', '' )
... 

A později přidávat k údajům o jménu souboru i proměnnou icoPath. Výše uvedené řešení sice funguje, ale není moc elegantní. Lepším řešením je vytvořit „resource“ soubor, který přímo obsahuje dané obrázky a ikony. Ve wxPythonu existuje modul wx.tools.img2py, který provádí konverzi obrázků ve formátu PNG do textového souboru, který je pak nahrán do programu místo jednotlivých obrázků pomocí příkazu „import …“.

Nyní si to vyzkoušíme prakticky. Např. pomocí Gimpu vytvořte nějakou ikonu (o velikosti 24×24) a uložíme ji pod názvem „ico01.png“ do adresáře „HelloWorld/i­cons/“. Rovněž ji uložíme jako „ico01.ico“ (použijeme ji později v překladu do binárky pro MS Windows). V adresáři „HelloWorld/ vytvoříme soubor s názvem "code-img.py“ s následujícím obsahem:

#!/usr/bin/env python
import sys, os, glob
from wxPython.tools import img2py

output = 'ui/myImgRes.py'
files = glob.glob('icons/*.png')
dst=open(output, 'w')
dst.write('#Boa:PyImgResource:\n\n#')
for file in files:
    name = os.path.splitext(os.path.basename(file))[0]
    if file == files[0]:
        cmd = "-u -i -n %s %s %s" % (name, file, output)
    else:
        cmd = "-a -u -i -n %s %s %s" % (name, file, output)
    img2py.main(cmd.split()) 

Tento prográmek je mírně poupravenou verzí (pro použití s Boa Constructorem), která byla publikována na stránkách www.koders.com. Pokud se vám nebude chtít jej opisovat, můžete si jej stáhnout (bude se Vám hodit i pro pozdější využití). Po jeho spuštění se vám vytvoří v adresáři „HelloWorld/ui/“ soubor s názvem „myImgRes.py“, který obsahuje jak obrázky z podadresáře „icons/“, tak i funkce potřebné pro jejich načtení ve formátu, který je podporován / vyžadován „Boa Constructorem“ a je kompatibilní s wxPythonem.

Spusťte „Boa Constructor“ a otevřete si příklad z předchozího dílu. V Editoru se přepněte se na záložku „App1“. V podzáložce Application stiskněte klávesu „Insert“ a vyberte soubor „HelloWorld/u­i/myImgRes.py“, čímž soubor s obrázky přidáme k našemu projektu. Nezapomeňte uložit (starší verze Boa Constructoru v linuxu byla poměrně nestabilní;-).

Otevřeme „frmHelloWorld“ a pomocí tlačítka icon spustíme „Designer panel“. V Inspectoru (pravé okno) v záložce „Props“ v položce „Icon“ vybereme náš soubor „myImgRes.py“. Otevře se nám okno „Select resource“ a v něm si vybereme naši ikonu „ico01“.

Boa 2 - 02

a ukončíme pomocí tlačítka icon „Designer panel“. Opět nezapomeňte uložit.

Lokalizace programu

Python vnitřně využívá pro zpracování znaků národních abeced „unicode“. Na jednu stranu je to výhoda, ale museli byste všechny zdrojové kódy ukládat rovněž v unicode. A i když neplánujete psát vícejazyčnou verzi programu, je dle mého názoru a zkušeností vhodné napsat program v angličtině a teprve posléze jej lokalizovat. Pro lokalizaci programu, který využívá knihovny wxPython, lze s uspěchem využít standardní GNU prográmky:

  • xgettext – v zadaných souborech vyhledá všechny řetězce určené k přeložení. Vytváří katalog zpráv („.po“)
  • msgfmt – zkompiluje katalog zpráv („.po“) do jeho binární podoby (*.mo")
  • poEdit – slouží ke komfortní úpravě katalogu zpráv.

Všechny tyto prográmky se dají sehnat jak pro Linux (jsou součástí většiny standardních distribucí), tak i pro MS Windows.

A nyní k samotné lokalizaci. Zobrazíme v „Editoru“ „frmHelloWorld“ a v podzáložce „Source“ vložíme za „import wx“ (zhruba 3. řádek shora) následující kód:

from wx import GetTranslation as _ 

Pokud chceme nejaký řetězec lokalizovat, stačí nyní použít _(‚nějaký text k lokalizaci‘). Takto zapsaný řetězec je pak akceptován jak programem „xgettext“, tak i samotnou wx knihovnou. Jako první ve formuláři upravíme nadpis „title=u'Hello World !‚“ na „title=_(‘Hello World !')“

...
        wx.Frame.__init__(self, id=wxID_FRMHELLOWORLD, name=u'frmHelloWorld',
              parent=prnt, pos=wx.Point(359, 140), size=wx.Size(164, 102),
              style=wx.DEFAULT_FRAME_STYLE, title=_('Hello World !'))
... 

rovněž i v tlačítku „btClose“ upravíme nápis a Tool Tip – „label=u'&Close'“ na „label=_(‚&Close‘)“ a „self.btClose­.SetToolTipStrin­g(u'Close me')“ na „self.btClose­.SetToolTipStrin­g(_(‚Close me‘))“.

...
        self.btClose = wx.Button(id=wxID_FRMHELLOWORLDBTCLOSE, label=_('&Close'),
              name=u'btClose', parent=self, pos=wx.Point(40, 49),
              size=wx.Size(75, 23), style=0)
        self.btClose.SetToolTipString(_('Close me'))
... 

Jako poslední upravíme v „stHello“ položku „label=u'Hello world !‚“ na "label=_(‘Hello world !')

...
        self.stHello = wx.StaticText(id=wxID_FRMHELLOWORLDSTHELLO,
              label=_('Hello World !'), name=u'stHello', parent=self,
              pos=wx.Point(0, 18), size=wx.Size(156, 28),
              style=wx.ALIGN_CENTRE)
... 

Aby nám překlady (binární podoba katalogu zpráv – „*.mo“) začaly fungovat, musíme mu nejprve ukázat, co se má vlastně načíst a posléze jej inicializovat. V praxi to znamená, že upravíme v „Editoru“ soubor „App1.py“ zhruba následovně:

...

import wx 
import os, gettext 
...

class BoaApp(wx.App):
    def OnInit(self):
        wx.InitAllImageHandlers()
        path = os.getcwd()
        localedir = os.path.join( path, "i18n" )
        langid = wx.LANGUAGE_DEFAULT
        domain = "helloworld"
        self.mylocale = wx.Locale(langid)
        self.mylocale.AddCatalogLookupPathPrefix(localedir)
        self.mylocale.AddCatalog(domain)
        self.mytranslation = gettext.translation(domain, localedir,
[self.mylocale.GetCanonicalName()], fallback = True)
        self.mytranslation.install()
        self.main = ui.frmHelloWorld.create(None)

        ... 

Samotný katalog zpráv („i18n/hello.po“) vytvoříme pomocí příkazu (předpokládám, že jste v adresáři „HelloWorld/“):

xgettext -d helloworld -s --no-location -o i18n/cs_CZ/helloworld.po
ui/frmHelloWorld.py 

Tento soubor otevřeme např. pomocí programu poEdit a lokalizujeme jej. Obsluha tohoto programu je naprosto triviální, pouze nezapomeňte vyplnit údaje z menu „Katalog ->Nastavení“ – předejdete následným chybám.

Boa 2 - 03

Nyní nastal čas na přeložení souboru „i18n/hello.po“ na „i18n/cz_CZ/h­ello.mo“. K tomu slouží prográmekmsgfmt. Překlad provedeme pomocí:

msgfmt -v -o ./i18n/cs_CZ/helloworld.mo ./i18n/cs_CZ/helloworld.po 

Pro dnešek snad stačí. Původně jsem chtěl ještě probrat vytvoření spustitelných binárek jak pro Linux tak i pro MS Windows, ale nechám to do příštího dílu seriálu. I dneska máte k dispozici zdrojové kódy.

Našli jste v článku chybu?

28. 6. 2006 7:11

sidlo (neregistrovaný)

Musím uvést předchozí informace na správnou míru. Nefunkčnost programu byla způsobena překlepem ve zdrojáku. Program funguje s balíkem wxPython2.6-gtk2-unicode-2.6.3.2 z www.wxpython.org, ale nefunguje boa-constructor. S balíkem wxPython2.6-gtk2-ansi-2.6.3.2 z www.wxpython.org funguje program a boa-constructor funguje s varováním, že má problémy s HTML soubory s kódováním iso-88598-1. Vrátil jsem původní balíky Mandriva wxPython2.6-gtk2-ansi-2.6.1.0 a všechno funguje jak má - program i boa-const…

27. 6. 2006 13:14

sidlo (neregistrovaný)
děkuji, Vaše diagnóza byla správná, používám Mandrivu, naistaloval jsem poslední verzi wxPython pro unicode, opravil překlep z malocale na mylocale a funguje
Vitalia.cz: To nejhorší při horečce u dětí: Febrilní křeče

To nejhorší při horečce u dětí: Febrilní křeče

DigiZone.cz: R2B2 a Hybrid uzavřely partnerství

R2B2 a Hybrid uzavřely partnerství

Měšec.cz: Exekuční poradna: ptejte se online

Exekuční poradna: ptejte se online

Lupa.cz: Levný tarif pro Brno nebude, je to kartel

Levný tarif pro Brno nebude, je to kartel

120na80.cz: Rovnátka, která nejsou vidět

Rovnátka, která nejsou vidět

Podnikatel.cz: Podnikatelům dorazí varování od BSA

Podnikatelům dorazí varování od BSA

Podnikatel.cz: Chaos u EET pokračuje. Jsou tu další návrhy

Chaos u EET pokračuje. Jsou tu další návrhy

120na80.cz: Co všechno ovlivňuje ženskou plodnost?

Co všechno ovlivňuje ženskou plodnost?

Vitalia.cz: Nejlepší obranou při nachlazení je útok

Nejlepší obranou při nachlazení je útok

Vitalia.cz: Test na HIV je zdarma i za pět set

Test na HIV je zdarma i za pět set

Lupa.cz: Obchod budoucnosti je bez front, košíků i pokladen

Obchod budoucnosti je bez front, košíků i pokladen

Vitalia.cz: Proč vás každý zubař posílá na dentální hygienu

Proč vás každý zubař posílá na dentální hygienu

Vitalia.cz: Jak vybrat ořechy do cukroví a kde mají levné

Jak vybrat ořechy do cukroví a kde mají levné

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Podnikatel.cz: Udávání a účtenková loterie, hloupá komedie

Udávání a účtenková loterie, hloupá komedie

Lupa.cz: Insolvenční řízení kvůli cookies? Vítejte v ČR

Insolvenční řízení kvůli cookies? Vítejte v ČR

120na80.cz: 5 nejčastějších mýtů o kondomech

5 nejčastějších mýtů o kondomech

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Root.cz: Certifikáty zadarmo jsou horší než za peníze?

Certifikáty zadarmo jsou horší než za peníze?