| 1 |
# -*- coding: utf-8 -*- |
|---|
| 2 |
import gettext |
|---|
| 3 |
import locale |
|---|
| 4 |
import os |
|---|
| 5 |
import dabo |
|---|
| 6 |
|
|---|
| 7 |
__app_initialized = False |
|---|
| 8 |
__app_has_locale = False |
|---|
| 9 |
__dabo_trans = None |
|---|
| 10 |
__app_trans = None |
|---|
| 11 |
_localedir = "locale" |
|---|
| 12 |
_frozenlocaledir = "dabo.locale" |
|---|
| 13 |
|
|---|
| 14 |
""" |
|---|
| 15 |
Beware: if you are using 8-bit (non-Unicode) locales, you could encounter errors like |
|---|
| 16 |
"UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-7: ordinal not in range(128)" |
|---|
| 17 |
Such error could appear, for example, when comparing non-Unicode string with Unicode string, |
|---|
| 18 |
or when printing Unicode string on non-Unicode console. |
|---|
| 19 |
|
|---|
| 20 |
Unfortunately, this is a Python specifics, not a Dabo framework error. |
|---|
| 21 |
This is because Python by default use only 7-bit ascii <-> Unicode conversion. |
|---|
| 22 |
e.g. look at http://mail.python.org/pipermail/python-list/2007-March/433232.html |
|---|
| 23 |
|
|---|
| 24 |
Suggested solutions are: |
|---|
| 25 |
1) Use unicode locale |
|---|
| 26 |
2) Modify the site.py, so that locale-aware encoding will be set up (site-wide effect) |
|---|
| 27 |
3) Insert following code at the top of app, does the same thing as above (inspired by site.py) |
|---|
| 28 |
|
|---|
| 29 |
import sys |
|---|
| 30 |
import locale |
|---|
| 31 |
reload(sys) |
|---|
| 32 |
sys.setdefaultencoding(locale.getdefaultlocale()[1]) |
|---|
| 33 |
|
|---|
| 34 |
""" |
|---|
| 35 |
#TODO: Maybe, this code should go to the beginning of this file ??? then everything will be ok |
|---|
| 36 |
|
|---|
| 37 |
def _(s): |
|---|
| 38 |
""" Use it to get translated strings. |
|---|
| 39 |
Localization files of app should be in under its locale directory. |
|---|
| 40 |
Localization files of dabo framework should be under dabo's locale directory. |
|---|
| 41 |
""" |
|---|
| 42 |
|
|---|
| 43 |
global defLang, __app_initialized, __app_has_locale |
|---|
| 44 |
|
|---|
| 45 |
if not __app_initialized: |
|---|
| 46 |
try: |
|---|
| 47 |
app = dabo.dAppRef |
|---|
| 48 |
except AttributeError: |
|---|
| 49 |
app = None |
|---|
| 50 |
|
|---|
| 51 |
if app: |
|---|
| 52 |
__app_initialized = True |
|---|
| 53 |
|
|---|
| 54 |
appShortName = app.getAppInfo("appShortName").lower() |
|---|
| 55 |
# if not changed in user app, defaults to "daboapplication" |
|---|
| 56 |
localedir = os.path.join(app.HomeDirectory, _localedir) |
|---|
| 57 |
|
|---|
| 58 |
if gettext.find(appShortName, localedir, [defLang,"en"], all = True): |
|---|
| 59 |
# application really has some localization file, "en" at least |
|---|
| 60 |
|
|---|
| 61 |
__app_has_locale = True |
|---|
| 62 |
setLanguage(domain = appShortName, localedir = localedir) |
|---|
| 63 |
__app_trans.add_fallback(__dabo_trans) |
|---|
| 64 |
# application's localization is inplace now, dabo's localization is a fallback |
|---|
| 65 |
else: |
|---|
| 66 |
# app doesn't appear to have a locale directory set up. |
|---|
| 67 |
pass |
|---|
| 68 |
|
|---|
| 69 |
# as it looks like the default is to use Unicode, then we return Unicode strings |
|---|
| 70 |
if __app_initialized and __app_has_locale: |
|---|
| 71 |
return __app_trans.ugettext(s) |
|---|
| 72 |
else: |
|---|
| 73 |
# application's localization is not ready for now, use only dabo's localization |
|---|
| 74 |
return __dabo_trans.ugettext(s) |
|---|
| 75 |
|
|---|
| 76 |
def n_(s): |
|---|
| 77 |
""" Use it if you want to tell translation service about string |
|---|
| 78 |
but don't want to translate it inplace. |
|---|
| 79 |
""" |
|---|
| 80 |
return s |
|---|
| 81 |
#TODO: wouldn't it be better, if we will use something like _("string",False) in _ function ??? |
|---|
| 82 |
# i.e. one more argument for _function, telling by default to translate strings ? |
|---|
| 83 |
# def _(s, translate=True): |
|---|
| 84 |
# pkm: Agree. Actually, can someone give an example of when you'd even want this? |
|---|
| 85 |
# Do we use it even? |
|---|
| 86 |
|
|---|
| 87 |
def setLanguage(lang=None, charset=None, domain="dabo", localedir=None): |
|---|
| 88 |
"""Use it if you want to switch to another localizations than your default. |
|---|
| 89 |
You should call it twice - once for dabo framework, and once for app. |
|---|
| 90 |
""" |
|---|
| 91 |
global defLang, defCharset, __dabo_trans, __app_trans |
|---|
| 92 |
|
|---|
| 93 |
#TODO: we should search system localizations directory as well |
|---|
| 94 |
|
|---|
| 95 |
if localedir is None: |
|---|
| 96 |
localedir = os.path.join(os.path.split(dabo.__file__)[0], _localedir) |
|---|
| 97 |
if not os.path.exists(localedir): |
|---|
| 98 |
localedir = os.path.join(os.getcwd(), _frozenlocaledir) |
|---|
| 99 |
|
|---|
| 100 |
if charset is None: |
|---|
| 101 |
charset = defCharset |
|---|
| 102 |
|
|---|
| 103 |
if lang is None: |
|---|
| 104 |
lang = defLang |
|---|
| 105 |
else: |
|---|
| 106 |
lang = lang.lower() |
|---|
| 107 |
# It might be the full name instead of the two-letter abbreviation |
|---|
| 108 |
if lang not in getLanguages(): |
|---|
| 109 |
try: |
|---|
| 110 |
lang = {"english": "en", |
|---|
| 111 |
"spanish": "es", "espanol": "es", "español": "es", |
|---|
| 112 |
"french": "fr", "francais": "fr", "français": "fr", |
|---|
| 113 |
"german": "de", "deutsch": "de", |
|---|
| 114 |
"italian": "it", "italiano": "it", |
|---|
| 115 |
"portuguese": "pt", "portuguése": "pt", |
|---|
| 116 |
"russian": "ru"}[lang] |
|---|
| 117 |
except KeyError: |
|---|
| 118 |
pass |
|---|
| 119 |
|
|---|
| 120 |
dabolocalefile = gettext.find(domain, localedir, languages=[lang], all=True) |
|---|
| 121 |
print dabolocalefile |
|---|
| 122 |
|
|---|
| 123 |
if not dabolocalefile: |
|---|
| 124 |
print "Gettext file for language %s was not found , falling back to english" % lang |
|---|
| 125 |
|
|---|
| 126 |
dabolocalefile = gettext.find(domain, localedir, languages = ['en'], all=True) |
|---|
| 127 |
|
|---|
| 128 |
if not dabolocalefile: |
|---|
| 129 |
raise IOError, "Neither english nor '%s' language was found " % lang |
|---|
| 130 |
|
|---|
| 131 |
defLang = "en" |
|---|
| 132 |
defCharset = "UTF-8" |
|---|
| 133 |
|
|---|
| 134 |
if domain == "dabo": |
|---|
| 135 |
__dabo_trans = gettext.translation(domain, localedir, languages=[lang], codeset=charset) |
|---|
| 136 |
defLang = lang |
|---|
| 137 |
else: |
|---|
| 138 |
__app_trans = gettext.translation(domain, localedir, languages=[lang], codeset=charset) |
|---|
| 139 |
|
|---|
| 140 |
defLang, defCharset = locale.getdefaultlocale() |
|---|
| 141 |
|
|---|
| 142 |
if defLang is None: |
|---|
| 143 |
defLang = "en" |
|---|
| 144 |
else: |
|---|
| 145 |
defLang = defLang[:2] |
|---|
| 146 |
if defCharset is None: |
|---|
| 147 |
defCharset = "UTF-8" |
|---|
| 148 |
|
|---|
| 149 |
setLanguage() |
|---|
| 150 |
|
|---|
| 151 |
if __name__ == "__main__": |
|---|
| 152 |
# this code is important for every non-unicode locale |
|---|
| 153 |
import sys |
|---|
| 154 |
import locale |
|---|
| 155 |
reload(sys) |
|---|
| 156 |
sys.setdefaultencoding(locale.getdefaultlocale()[1]) |
|---|
| 157 |
|
|---|
| 158 |
print 'user locale is ', locale.getdefaultlocale() |
|---|
| 159 |
print 'framework locale is ', defLang, defCharset |
|---|
| 160 |
print _("Framework localization test") |
|---|