Hi everyone I post a reply in the web3py thread in this mailing list asking for a site where make a wishlist, but thinking about what I would want in web3py, I realized that I needed in web2py already so I have make a patch for the actual translation system in the gluon/languages.py file.
One of the lacks that I see in the translation system is that is a little difficult to maintain the language file in large applications like the one I am developing at this moment. Think about modules that you can plug or unplug of your application, and each have their own strings, or something more common, the pluggin system. Actually if you want to install a plugin like plugin_wiki you have to do your own translation because you cannot insert translation files (if actually web2py supports this... do it I don't know how to make it xD). It would be great to have a community where you can make plugins and add the language files inside. This is what makes the patch: Allows to use a "namespace" parameter in the T() like this T("Hello World", namespace="plugin_wiki") So in the languages/ folder will appear this: - languages/ - en_en.py - plugin_wiki/ - en_en.py so if you use T("Hello World", namespace="plugin_wiki") it will go to find the string into languates/plugin_wiki/*your_lang*.py and if you use the common way T("Hello World") it will go as always to languages/*your_lang*.py I haven't tested it enough but it works for me at now, and I haven't written the part for the admin interface where you can push the button for refreshing the lang files (I don't get on wiht the RegExp at all) My 2 cents I hope that I can send the patch to the list --
--- languages.py_orig_bkp 2012-11-29 12:41:39.377540956 +0100 +++ languages.py 2012-11-29 12:48:52.881536524 +0100 @@ -49,7 +49,7 @@ logging.error('Syntax error in %s' % filename) return {} -def read_dict(filename): +def read_dict(filename): return getcfs('language:%s'%filename,filename, lambda filename=filename:read_dict_aux(filename)) @@ -110,28 +110,30 @@ m = None s = None T = None - + n = None def __init__( self, message, symbols = {}, T = None, + namespace="app_base" ): self.m = message self.s = symbols self.T = T + self.n = namespace def __repr__(self): return "<lazyT %s>" % (repr(str(self.m)), ) def __str__(self): - return self.T.translate(self.m, self.s) + return self.T.translate(self.m, self.s, self.n) def __eq__(self, other): - return self.T.translate(self.m, self.s) == other + return self.T.translate(self.m, self.s, self.n) == other def __ne__(self, other): - return self.T.translate(self.m, self.s) != other + return self.T.translate(self.m, self.s, self.n) != other def __add__(self, other): return '%s%s' % (self, other) @@ -173,7 +175,7 @@ return str(self) def __mod__(self, symbols): - return self.T.translate(self.m, symbols) + return self.T.translate(self.m, symbols, self.n) class translator(object): @@ -194,16 +196,21 @@ notice 2: en and en-en are considered different languages! """ - + t={} + def __init__(self, request): self.request = request self.folder = request.folder self.current_languages = ['en'] self.accepted_language = None - self.language_file = None + self.language_file = {} + self.language_file['app_base'] = None + self.t = {} + self.t['app_base'] = {} self.http_accept_language = request.env.http_accept_language self.requested_languages = self.force(self.http_accept_language) self.lazy = True + self.namespace = 'app_base' self.otherTs = {} def get_possible_languages(self): @@ -221,6 +228,7 @@ self.force(self.http_accept_language) def force(self, *languages): + ret_langs = False if not languages or languages[0] is None: languages = [] if len(languages) == 1 and isinstance(languages[0], (str, unicode)): @@ -238,23 +246,45 @@ self.accepted_language = language break filename = os.path.join(self.folder, 'languages/', language + '.py') - if os.path.exists(filename): + if os.path.exists(filename): self.accepted_language = language - self.language_file = filename - self.t = read_dict(filename) + self.language_file['app_base'] = filename + self.t['app_base'] = read_dict(filename) + ret_langs = True + #return languages + + root_dir = os.path.join(self.folder, 'languages/') + #for root, dirs, files in os.walk(root_dir): + for namespace in os.listdir(root_dir): + if namespace.startswith("."): + continue + if os.path.isdir(root_dir+namespace): + filename = os.path.join(self.folder, 'languages/', namespace + os.sep, language + '.py') + if os.path.exists(filename): + self.language_file[namespace] = filename + self.t[namespace] = read_dict(filename) + if ret_langs == True: return languages - self.language_file = None - self.t = {} # ## no language by default + for key, value in self.language_file.items(): + self.language_file[key] = None + for key, value in self.t.items(): + self.t[key] = {} # ## no language by default return languages - def __call__(self, message, symbols={}, language=None, lazy=None): + def __call__(self, message, symbols={}, language=None, lazy=None, namespace=None): + if namespace is None: + namespace = 'app_base' + if namespace != 'app_base': + namespace_folder =os.path.join(self.folder, 'languages/', namespace) + if not os.path.exists(namespace_folder): + os.makedirs(namespace_folder) if lazy is None: lazy = self.lazy if not language: if lazy: - return lazyT(message, symbols, self) + return lazyT(message, symbols, self, namespace) else: - return self.translate(message, symbols) + return self.translate(message, symbols, namespace) else: try: otherT = self.otherTs[language] @@ -263,7 +293,7 @@ otherT.force(language) return otherT(message, symbols, lazy=lazy) - def translate(self, message, symbols): + def translate(self, message, symbols, namespace='app_base'): """ user ## to add a comment into a translation string the comment can be useful do discriminate different possible @@ -278,6 +308,11 @@ """ #for some reason languages.py gets executed before gaehandler.py # is able to set web2py_runtime_gae, so re-check here + if namespace not in self.t.keys(): + self.t[namespace] = {} + if namespace not in self.language_file.keys(): + self.language_file[namespace] = os.path.join(self.folder, 'languages/', namespace + os.sep , self.accepted_language + '.py') + #self.language_file[namespace] = None is_gae = settings.global_settings.web2py_runtime_gae if not message.startswith('#') and not '\n' in message: tokens = message.rsplit('##', 1) @@ -287,11 +322,11 @@ if len(tokens) == 2: tokens[0] = tokens[0].strip() message = tokens[0] + '##' + tokens[1].strip() - mt = self.t.get(message, None) + mt = self.t[namespace].get(message, None) if mt is None: - self.t[message] = mt = tokens[0] - if self.language_file and not is_gae: - write_dict(self.language_file, self.t) + self.t[namespace][message] = mt = tokens[0] + if self.language_file[namespace] and not is_gae: + write_dict(self.language_file[namespace], self.t[namespace]) if symbols or symbols == 0: return mt % symbols return mt