×
Namespaces

Variants
Actions
Revision as of 14:57, 26 January 2009 by marcelobarrosalmeida (Talk | contribs)

Archived:Localization Example for PySymbian

From Nokia Developer Wiki
Jump to: navigation, search


Article Metadata
Tested with
Devices(s): E71
Compatibility
Platform(s): S60 3rd Ed
S60 3rd Edition (initial release)
Article
Keywords: locale, localization
Created: (26 Jan 2009)
Last edited: marcelobarrosalmeida (26 Jan 2009)

Introduction

In this article is presented a strategy for supporting multiple languages in your Python application for S60 devices. Since the default language is defined, additional translations may be added at any time. Moreover, missing translations are replaced by the default translation, allowing incremental translations without breaking the code.

The strategy is composed of a main script file (wm_locale.py), used for loading dynamically the language desired, and for localization files, with translations inside. The localization files are python files as well and they are imported as modules. Using python introspection, translation may be loaded and missing translations are replaced by the default language.

Show me the code

The main script is below.

wm_locale.py

# -*- coding: utf-8 -*-
#
# Marcelo Barros de Almeida
# marcelobarrosalmeida (at) gmail.com
#
 
__all__ = [ "Locale" ]
 
class Loc_Data(object):
"Translation data holder"
pass
 
class Default(object):
"Default language support"
def __init__(self):
self.loc = Loc_Data()
self.loc.zero = u'Zero'
self.loc.one = u'One'
self.loc.two = u'Two'
self.loc.three = u'Three'
self.loc.four = u'Four'
self.loc.five = u'Five'
self.loc.six = u'Six'
self.loc.seven = u'Seven'
self.loc.eight = u'Eight'
self.loc.nine = u'Nine'
self.loc.change_language = u'Change Language'
self.loc.english_us = u'English (USA)'
self.loc.finnish = u'Finnish'
self.loc.hungarian = u'Hungarian'
self.loc.portuguese_br = u'Portuguese (Brazil)'
self.loc.about = u'About'
self.loc.exit = u'Exit'
 
class Locale(Default):
"Multiple language support class"
 
LOC_MODULE = "wm_locale_%s"
 
def __init__(self,lang = ""):
"Load all locale strings for one specific language or default if empty"
self.set_locale(lang)
 
def set_locale(self,lang = ""):
"Load all locale strings for one specific language or default if empty"
Default.__init__(self)
 
try:
lang_mod = __import__( self.LOC_MODULE % ( lang ) )
except ImportError:
pass
else:
self.merge_locale(lang_mod)
 
def merge_locale(self, lang_mod):
"Merge new location string into default locale"
 
# replace existing strings and keep old ones
# if it is missing in the locale module
for k,v in self.loc.__dict__.iteritems():
if hasattr(lang_mod,k):
nv = lang_mod.__getattribute__(k)
self.loc.__setattr__(k,nv)

All default translations are defined in class Default() using attribute self.loc. Each string in your program should be represented by a different attribute in self.loc.

Localization modules are loaded dynamically and there is a convention for file name used. This is represented by the following expression:

LOC_MODULE = "wm_locale_%s"

So, if you have a pt_BR translation, create a file called wm_locale_pt_BR.py. Inside this module, translate all string in class Default(), removing any class or self.loc reference. For instance, pt_BR translation would be:

wm_locale_pt_BR.py

# -*- coding: utf-8 -*-
#
# Marcelo Barros de Almeida
# marcelobarrosalmeida (at) gmail.com
#
zero = u'Zero'
one = u'Um'
two = u'Dois'
three = u'Três'
four = u'Quatro'
five = u'Cinco'
six = u'Seis'
seven = u'Sete'
eight = u'Oito'
nine = u'Nove'
change_language = u'Mudar idioma'
english_us = u'Inglês (EUA)'
finnish = u'Finlandês'
hungarian = u'Húngaro'
portuguese_br = u'Português (Brasil)'
about = u'Sobre'
exit = u'Sair'

Finally, in the next program is demonstrated how locale class can be used.

wm_locale_demo.py

# -*- coding: utf-8 -*-
#
# Marcelo Barros de Almeida
# marcelobarrosalmeida (at) gmail.com
#
 
import sys
sys.path.append(r'e:\python')
 
import appuifw
import e32
import wm_locale
 
class Locale_Demo(object):
def __init__(self):
appuifw.app.exit_key_handler = self.close
appuifw.app.title = u"Locale Demo"
self.update_locale()
self.app_lock = e32.Ao_lock()
 
def close(self):
self.app_lock.signal()
 
def about(self):
appuifw.note( u"Locale Demo by Marcelo Barros", "info" )
 
def update_locale(self,lang=""):
self.labels = wm_locale.Locale(lang)
self.refresh()
 
def refresh(self):
entries = [
self.labels.loc.zero,
self.labels.loc.one,
self.labels.loc.two,
self.labels.loc.three,
self.labels.loc.four,
self.labels.loc.five,
self.labels.loc.six,
self.labels.loc.seven,
self.labels.loc.eight,
self.labels.loc.nine
]
 
self.body = appuifw.Listbox(entries)
 
self.menu = [
(self.labels.loc.change_language, (
(self.labels.loc.english_us, lambda: self.update_locale("en_US")),
(self.labels.loc.finnish, lambda: self.update_locale("fi")),
(self.labels.loc.hungarian, lambda: self.update_locale("hu")),
(self.labels.loc.portuguese_br, lambda: self.update_locale("pt_BR"))
)
),
(self.labels.loc.about, self.about),
(self.labels.loc.exit, self.close)
]
 
appuifw.app.menu = self.menu
appuifw.app.body = self.body
 
def run(self):
self.app_lock.wait()
appuifw.app.menu = []
appuifw.app.body = None
appuifw.app.set_exit()
 
if __name__ == "__main__":
 
ld = Locale_Demo()
ld.run()

If you have more translation files, just add them to your project. Translations below were provided by [1] and you can see that there are missing translation.

wm_locale_en_US.py

zero = u'Zero'
one = u'One'
two = u'Two'
three = u'Three'
four = u'Four'
five = u'Five'
six = u'Six'
seven = u'Seven'
eight = u'Eight'
nine = u'Nine'
change_language = u'Change Language'
english_us = u'English (USA)'
finnish = u'Finnish'
hungarian = u'Hungarian'
portuguese_br = u'Portuguese (Brazil)'
about = u'About'
exit = u'Exit'

wm_locale_fi.py

zero = u'nolla'
one = u'yksi'
two = u'kaksi'
three = u'kolme'
four = u'neljä'
five = u'viisi'
six = u'kuusi'
seven = u'seitsemän'
eight = u'kandeksan'
nine = u'yhdeksän'
change_language = u'Vaihda kieli'
english_us = u'englanti'
finnish = u'suomi'
hungarian = u'unkari'
about = u'Tietoja'
exit = u'Poistu'

wm_locale_hu.py

zero = u'nulla'
one = u'egy'
two = u'kett\u0151'
three = u'három'
four = u'négy'
five = u'öt'
six = u'hat'
seven = u'hét'
eight = u'nyolc'
nine = u'kilenc'
change_language = u'Nyelv változtatás'
english_us = u'angol'
finnish = u'finn'
hungarian = u'magyar'
about = u'Információ'
exit = u'Kijárat'

References

Thanks to Rafael T. and JOM for fruitful discussions at Nokia Forum.

101 page views in the last 30 days.