1
# ln_text.py: localisation support for IDJC
2
# Copyright (C) 2010 Stephen Fairchild (s-fairchild@users.sourceforge.net)
4
# This program is free software: you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation, either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program in the file entitled COPYING.
16
# If not, see <http://www.gnu.org/licenses/>.
22
def _get_modulename(cls):
23
return cls.__name__ + "_text"
26
def __getattr__(self, name):
27
"""Setting the LANG environment variable to xx_XX will result in all the item labels handled by this module being set by this method. This feature provides the language translator with a context for the item lables themselves."""
29
print "*** ln_text.py: warning, missing attribute '%s'" % name
30
if self._warning == False:
31
print "this and other missing attribute warnings will only appear once"
33
setattr(self, name, "((%s))" % name) # prevent duplicate warnings
34
return getattr(self, name)
35
def _load_text(self, cls):
36
"""The regular __import__ function will not dump multiple references from a module into a class necessitating the following code."""
37
modulename = _get_modulename(cls)
38
#print "loading attributes from %s for %s" % (modulename, cls.__name__)
39
mod = __import__(modulename)
42
setattr(cls, item, getattr(mod, item))
43
def _detect_mismatched_references(self, cls):
47
for reference in filter(no_underscore, dir(self)):
48
if not reference in cls_vars:
49
print "### ln_text.py: warning, attribute %s does not appear in the canonical list %s" % (reference, cls.__name__)
51
return "Language translation: " + self.__class__.__name__
54
for cls in self.__class__.mro():
58
if cls.__base__ is xx_XX:
59
self._detect_mismatched_references(cls)
62
if os.getenv("LANG") == "xx_XX": # convert to a valid locale
63
os.environ["LANG"] = "en_GB"
74
def _set(): # choose which translation to use
75
lev = os.getenv("LANG")
77
language = lev[0:2].lower()
78
country = lev[3:5].upper()
81
except (IndexError,TypeError):
82
print "Selecting language en_US. Change environment variable LANG to override."
85
lev = "_".join((language, country))
87
gns = sys.modules[__name__] # the global name space
88
# make sure lev matches one of the available languages
89
if not lev in dir(gns):
91
if each[:2] == language:
92
print "Compromise language match found", each
96
print "Could not find a suitable language match - will use en_US"
99
# find the class whose name matches the lev variable and instantiate it
100
return getattr(gns, lev)()
102
# set the ln (localisation) variable which is what the calling module should import
105
if __name__ == "__main__":
106
def _cleanlist(module):
107
return [ l for l in dir(module) if l[0] != "_" ]
109
def sort(cls, basecls = en_GB):
111
"""# -*- encoding: utf-8 -*-
112
# Set your text editor to UTF-8 before modifying this file
114
# %s: IDJC language localisation file for %s
117
# This program is free software: you can redistribute it and/or modify
118
# it under the terms of the GNU General Public License as published by
119
# the Free Software Foundation, either version 2 of the License, or
120
# (at your option) any later version.
122
# This program is distributed in the hope that it will be useful,
123
# but WITHOUT ANY WARRANTY; without even the implied warranty of
124
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
125
# GNU General Public License for more details.
127
# You should have received a copy of the GNU General Public License
128
# along with this program in the file entitled COPYING.
129
# If not, see <http://www.gnu.org/licenses/>\n\n""")
132
trans = __import__(_get_modulename(cls))
134
print "Import failed. Try creating the empty file %s and try again." % (_get_modulename(cls) + ".py")
136
base = __import__(_get_modulename(basecls))
137
translist = _cleanlist(trans)
140
return getattr(trans, item) == getattr(base, item)
142
def write_items(file, module, attrlist, prepend = ""):
143
for attr in attrlist:
144
file.write("".join((prepend, attr, " = ")))
145
data = getattr(module, attr)
146
if type(data) == tuple:
147
file.write(str(data))
148
if type(data) == str:
149
escdata = data.replace('"', '\"')
152
escdata = escdata.replace('\n', '\n#')
153
file.write(escdata.join(('"""', '"""')))
155
file.write(escdata.join(('"', '"')))
159
return " ".join(text)
161
baselist = _cleanlist(base)
162
unmatched = [ r for r in translist if not r in baselist ]
165
for baseitem in baselist:
166
if trans != base and (not baseitem in translist or matching(baseitem)):
167
untranslated.append(baseitem)
169
regular.append(baseitem)
170
if "translationcopyright" in translist:
171
transcopyright = getattr(trans, "translationcopyright")
172
if type(transcopyright) == str:
173
transcopyright = (transcopyright, )
175
transcopyright = ("Copyright (C) 2008 Stephen Fairchild (s-fairchild@users.sourceforge.net)", )
176
copyrights = "# " + "\n# ".join(transcopyright)
177
filename = _get_modulename(cls) + ".py"
178
file = open(filename, "w")
179
file.write(header % (filename, cls.__name__, copyrights))
181
file.write(stretch("# Items with no match in %s\n\n" % (_get_modulename(basecls) + ".py")))
182
write_items(file, trans, unmatched)
185
file.write(stretch("# The following are regular translations\n\n"))
186
write_items(file, trans, regular)
188
file.write(stretch("# Untranslated items -- same as %s\n\n" % basecls.__name__))
189
write_items(file, base, untranslated, "#")
190
print "Sort of %s complete." % filename
192
print "Use the sort() function to neatly arrange the translatable items.\n"
193
print "Example usage:\n"
194
print ">>> sort(fr_FR)"
195
print "Untranslated items will be in British English for translation into French"
196
print "The file fr_FR_text.py file needs to exist beforehand even if empty.\n"
197
print ">>> sort(de_DE, fr_FR)"
198
print "Untranslated items will be in French for translation into German."
199
print "This assumes there is a French translation in the first place.\n"
200
print "Choose one or two of:", [ s[1].__name__ for s in locals().items() if type(s[1]) == type and s[1] is not xx_XX and issubclass(s[1], xx_XX) ]
201
print "To add a language/country code you'll need to edit ln_text.py"
202
print "\nIt is quite safe to run this over files that have already been translated.\nCtrl+D quits."