**This is a short recipe how to make a multi-language site** First of all, I load all my languages during the WebKit start-up into a variable, which is visible from any place, i.e. I create this variable in *__builtin__* dictionary. So, in my *contextInitialize()* method is:: __builtin__.__dict__['LANGUAGES'] = Languages() where *Languages()* is a dictionary-like object, where keys are language codes and items are *gettext.translation()* objects:: import gettext import os class Languages: def __init__(self): self._langs = {} self.load() def __getitem__(self, lang): return self._langs[lang] def load(self): localeDir = 'yourLocaleDirectory' dirItems = os.listdir(localeDir) for dirItem in dirItems: if os.path.isdir(os.path.join(localeDir, dirItem)): try: self._langs[dirItem] = gettext.translation('yourDomain', localeDir, [dirItem]) except Exception, e: print 'Error: Loading language: "%s"' % dirItem def gettextFunc(self, lang): if self._langs.has_key(lang): return self._langs[lang].gettext else: return lambda x: x So. I have all the translations in memory and now I need to use them. I need to know, which language to choose. Because my site is also for registered users, there are two ways: - If the user is logged in, language code is read from his profile. - If the user is not logged in, I pass choosen language code via GET method from page to page, but if the user did not choose language, some default one is used. In *awake()* method of a servlet I set right gettext function: :: awake(self, transaction): ... self._ = LANGUAGES.gettextFunc('languageCode') ... Every string, that needs to be translated, I mark as usually *\_('stringToTranslate')* and in the beginig of every method Where I need it, I just do:: someMethod(self): _ = self._ That's it. :-) One last thing. Strings that needs to be translated are not just in servlets, but on other places too (for example in some modules), so I need some *\_()* function there. At the begining of such a place I have:: _ = lambda x: x -------------------- If you have lots of situations where you need to internationalize code that won't have access to your context (i.e., to ``self._``), then you might want to try keeping track of language on a per-thread manner. (If you are using that last recipe, ``_ = lambda x: x``, then you might want to try this instead.) An **untested** example of this:: def awake(self, trans): self._ = LANGUAGES.gettextFunc('languageCode') languagecontext.register(self._) def sleep(self, trans): languagecontext.deregister() # then in languagecontext: import threading class LanguageContextTracker: def __init__(self): self._threads = {} def curName(self): return threading.currentThread().getName() def register(self, obj): self._threads[self.curName()] = obj def deregister(self): try: del self._threads[self.curName()] except KeyError: pass def language(self): return self._threads[self.curName()] TheLanguageContextTracker = LanguageContextTracker() register = TheLanguageContextTracker.register deregister = TheLanguageContextTracker.deregister language = TheLanguageContextTracker.language Then use ``languagecontext.language()`` to get your ``_`` object, even after you've lost track of the servlet you are associated with. (If someone implements this, please correct this code as necessary) -- `Ian Bicking`_ -------------------- Based on **very light testing** the above approach seems to work. Although I implemented it slightly differently. Instead of gettext -functions TheLanguageContextTracker keeps track of preferred translation languages (as strings like 'en', 'fi',...). My LangUtil.py looks like this:: import threading import gettext class LanguageContextTracker: def __init__(self): self._threads = {} def curName(self): return threading.currentThread().getName() def register(self, obj): self._threads[self.curName()] = obj def deregister(self): try: del self._threads[self.curName()] except KeyError: pass def language(self): return self._threads[self.curName()] TheLanguageContextTracker = LanguageContextTracker() register = TheLanguageContextTracker.register deregister = TheLanguageContextTracker.deregister language = TheLanguageContextTracker.language _translations = {} def initialize(): "Load translations and put them to a dictionary. ADD ERROR HANDLING HERE" _translations['fi'] = gettext.translation("mydomain","C:/mywebkitproject/locale",["fi"]) _translations['en'] = gettext.translation("mydomain","C:/mywebkitproject/locale",["en"]) def mygettext(s): "Look up the preferred translation and return the translated string" try: return _translations[language()].lgettext(s) except: return s In a Page -class from which all other Page -classes in the site inherit I have the following:: def awake(self,trans): if trans.request().hasField("lang"): trans.session().setValue("lang",trans.request().field("lang")) LangUtil.register(trans.session().value('lang','en')) SiteTemplate.awake(self,trans) # I've got a Cheetah template at the top of my Page-class hierarcy def sleep(self,trans): SiteTemplate.sleep(self,trans) LangUtil.deregister() And into Launch.py I've added the following:: # Initialize translations and have _ point to LangUtil.mygettext import LangUtil LangUtil.initialize() __builtins__.__dict__['_'] = LangUtil.mygettext -- jranki