Sunday, 17 March 2013

OpenERP Translation

How transation/POTs got generated ?(Export translation with option tgz, this will gnerated pot for installed modules)

Settings -> Translation -> Import/Export Translation -> Export translation wizard, load(object button) translation with option tgz, this will call method trans_export method(Note this wizard has fields like lang, modules many2many field with relation to ir.module.module to apply modules in trans_export signature, buffer in method definition will be the object of cStringIO.StringIO()), this method will call trans_generate method of which is responsible to generate translation for views, models, js, and web xml's.

The method trans_genrate will fires two sql injection, one on ir.model(contains information regarding model, like Model description, model information), query fired on this will translate _contraint, sql_constraint and second on contains data related to model, like view, wizard, report, fields), now based on model it will translate view(ir.ui.view) by calling trans_parse_view, wizard(ir.actions.wizard, this will also call trans_parse_view), fields(ir.model.fields, converts fields string, help, selection field), report( This methos will get addons path as we passed as a command line argument or set in .cfg file, and iterate through *.py, *.mako, *.js, *.xml(also web xmls, because web is also a module) and calls babel_extract_terms, this will collects translation terms of .js and qweb files and all this translaation is pushed by calling push_translation which will appends tranlsations into _to_translate list, which is returned to "trans_export", and after colleting translation trans_export will call _process which will generates pot file, if we gonna generate pot file then we not going to pass lang parameter in trans_export because based on lang parameter it will either generates .po or .pot, if there is no lang parameter defined then it will generates .pot file with translation = '' for each term.

How entries created in ir.translation ?

load method of ir.translation object is called from update_translation method of ir.module.module(which is basically called by load object button method), this load method go through each module(passed from update_translation method of ir.module.module, which gets those whose state = installed), and will call trans_load( method for each module which again calls trans_load_data of, this trans_load_data method will go through language.po file(language you going to load) and fetches ir.translation cursor through _get_import_cursor method of ir.translation object which retruns object of ir_translation_import_cursor(this is an object which creates a temporary cursor to insert mass data into ir.translation, that is it creates TEPORARY Table by inheriting ir.translation table), this temporary cursor has method push which creates entry temporary table when you call ir_translation_import_cursor.push, so trans_load_data go through each term of .po file and and calls that tempoary cursor's push method after enumerating through whole .po file it will call ir_translation_import_cursor.finish method, finish method of temporary cursor will transfers whole data in ir.translation in batch, after inserting data in bulk from temporary table, the temporary table got dropped.

So this way ir.translation got updated, and we all know entries in .po file updated through .pot whenever translation is updated by launchpad.

VERY IMPORTANT NOTE:- This is VERY IMPORTANT to NOTE that, from version 7.0 all the translations are stored in ir.translation table, my mean to all includes WEB also, translation of web static terms are also stored in ir.translation, this the reason I have written this doc on translation, as translation entries in pot is already did by trans_export method of, so whenever .po's got updated translation of web specific terms will also be available in ir.translation.

How views, fields and web_xmls(i.e. qwebs) are translated ?

Noe the here the main topic for which I have dig my head inside translation is because of web xml's as this is different then previous version, in previous version for web specific terms we were reads .po file of user language when web instance initiated and creates one translation database at client side, so when wherever static tanslation terms needed we take it from that translation databse bundle through _t orr _lt method of that object.

But from version 7.0 everything got stored in ir.translation so now when Web instance initiated we will read ir,translation table instead of reading .po file, rest process is same that we creates Translation database bundle and wherever tranlation rewuires we takes translation term from that translation bundle, say for example it there is button in web with lable "Validate" so to translate that string we web people uses _t("Validate") same as _(underscore) instance we uses in server addons.

Upto this it is ok that translation in js tatic terms can be done using _t or _lt but what about web xml files, what about translation of templates, just look inside template of pos.xml, there are lots of static terms and messages and there is no any method used to translate that static messages(for server addons views, server _view_look_dom method will return translated view), So the answer is web itself transltes all templates, there is a function named instance.web.qweb.preprocess_node which is called by Qweb(Our rendering engine) itself for each Element, this  instance.web.qweb.preprocess_node method will lookup into Element and checks its attributes like 'label', 'title', 'alt', 'placeholder' and translates it by _t by replacing tranlated term on this Elment, also this method checks for Text data inside the element say for exaple
<p>Hello World!</p>, so here Hello World! is my text, this method will also replace this texts by translated terms, so before rendering Qweb processes nodes for translation.

All above is about OpenERP Translation, mainly I have written this note on Web translation, how it works, please add your inputs if you something else regarding translation topic and correct me if I am wrong anywhere.