[MERGE] from trunk

bzr revid: fva@openerp.com-20121004094429-hq4lcntvkycytnj6
This commit is contained in:
Frédéric van der Essen 2012-10-04 11:44:29 +02:00
commit 28a8768a63
17 changed files with 496 additions and 315 deletions

View File

@ -227,6 +227,8 @@ def module_installed_bypass_session(dbname):
return sorted_modules
def module_boot(req):
return [m for m in req.config.server_wide_modules if m in openerpweb.addons_manifest]
# TODO the following will be enabled once we separate the module code and translation loading
serverside = []
dbside = []
for i in req.config.server_wide_modules:
@ -531,6 +533,20 @@ def parse_context(context, session):
except ValueError:
return common.nonliterals.Context(session, context)
def _local_web_translations(trans_file):
messages = []
try:
with open(trans_file) as t_file:
po = babel.messages.pofile.read_po(t_file)
except Exception:
return
for x in po:
if x.id and x.string and "openerp-web" in x.auto_comments:
messages.append({'id': x.id, 'string': x.string})
return messages
#----------------------------------------------------------
# OpenERP Web web Controllers
#----------------------------------------------------------
@ -576,6 +592,7 @@ class Home(openerpweb.Controller):
def login(self, req, db, login, key):
return login_and_redirect(req, db, login, key)
class WebClient(openerpweb.Controller):
_cp_path = "/web/webclient"
@ -658,41 +675,53 @@ class WebClient(openerpweb.Controller):
last_modified, checksum)
@openerpweb.jsonrequest
def translations(self, req, mods, lang):
lang_model = req.session.model('res.lang')
ids = lang_model.search([("code", "=", lang)])
if ids:
lang_obj = lang_model.read(ids[0], ["direction", "date_format", "time_format",
"grouping", "decimal_point", "thousands_sep"])
else:
lang_obj = None
def bootstrap_translations(self, req, mods):
""" Load local translations from *.po files, as a temporary solution
until we have established a valid session. This is meant only
for translating the login page and db management chrome, using
the browser's language. """
lang = req.httprequest.accept_languages.best or 'en'
# For performance reasons we only load a single translation, so for
# sub-languages (that should only be partially translated) we load the
# main language PO instead - that should be enough for the login screen.
if '-' in lang: # RFC2616 uses '-' separators for sublanguages
lang = [lang.split('-',1)[0], lang]
if "_" in lang:
separator = "_"
else:
separator = "@"
langs = lang.split(separator)
langs = [separator.join(langs[:x]) for x in range(1, len(langs) + 1)]
transs = {}
translations_per_module = {}
for addon_name in mods:
transl = {"messages":[]}
transs[addon_name] = transl
addons_path = openerpweb.addons_manifest[addon_name]['addons_path']
for l in langs:
f_name = os.path.join(addons_path, addon_name, "i18n", l + ".po")
if not os.path.exists(f_name):
continue
try:
with open(f_name) as t_file:
po = babel.messages.pofile.read_po(t_file)
except Exception:
continue
for x in po:
if x.id and x.string and "openerp-web" in x.auto_comments:
transl["messages"].append({'id': x.id, 'string': x.string})
return {"modules": transs,
"lang_parameters": lang_obj}
f_name = os.path.join(addons_path, addon_name, "i18n", lang + ".po")
if not os.path.exists(f_name):
continue
translations_per_module[addon_name] = {'messages': _local_web_translations(f_name)}
return {"modules": translations_per_module,
"lang_parameters": None}
@openerpweb.jsonrequest
def translations(self, req, mods, lang):
res_lang = req.session.model('res.lang')
ids = res_lang.search([("code", "=", lang)])
lang_params = None
if ids:
lang_params = res_lang.read(ids[0], ["direction", "date_format", "time_format",
"grouping", "decimal_point", "thousands_sep"])
# Regional languages (ll_CC) must inherit/override their parent lang (ll), but this is
# done server-side when the language is loaded, so we only need to load the user's lang.
ir_translation = req.session.model('ir.translation')
translations_per_module = {}
messages = ir_translation.search_read([('module','in',mods),('lang','=',lang),
('comments','like','openerp-web'),('value','!=',False),
('value','!=','')],
['module','src','value','lang'], order='module')
for mod, msg_group in itertools.groupby(messages, key=operator.itemgetter('module')):
translations_per_module.setdefault(mod,{'messages':[]})
translations_per_module[mod]['messages'].extend({'id': m['src'],
'string': m['value']} \
for m in msg_group)
return {"modules": translations_per_module,
"lang_parameters": lang_params}
@openerpweb.jsonrequest
def version_info(self, req):
@ -769,7 +798,7 @@ class Database(openerpweb.Controller):
{'fileToken': int(token)}
)
except xmlrpclib.Fault, e:
return simplejson.dumps([[],[{'error': e.faultCode, 'title': 'backup Database'}]])
return simplejson.dumps([[],[{'error': e.faultCode, 'title': 'backup Database'}]])
@openerpweb.httprequest
def restore(self, req, db_file, restore_pwd, new_db):

View File

@ -57,7 +57,12 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
if(self.session_is_valid()) {
return deferred.pipe(function() { return self.load_modules(); });
}
return deferred;
return $.when(
deferred,
self.rpc('/web/webclient/bootstrap_translations', {mods: instance._modules}).pipe(function(trans) {
instance.web._t.database.set_bundle(trans);
})
);
});
},
/**
@ -537,13 +542,9 @@ instance.web.qweb.preprocess_node = function() {
if (translation && translation.value === 'off') {
return;
}
var ts = _.str.trim(this.node.data);
if (ts.length === 0) {
return;
}
var tr = instance.web._t(ts);
if (tr !== ts) {
this.node.data = tr;
var match = /^(\s*)(.+?)(\s*)$/.exec(this.node.data);
if (match) {
this.node.data = match[1] + instance.web._t(match[2]) + match[3];
}
break;
case 1:
@ -600,8 +601,7 @@ var messages_by_seconds = function() {
[120, _t("Don't leave yet,<br />it's still loading...")],
[300, _t("You may not believe it,<br />but the application is actually loading...")],
[420, _t("Take a minute to get a coffee,<br />because it's loading...")],
[600, _t("It's loading...<br />By the way, did you tried the kitten mode?")],
[3600, _t("Maybe you should consider pressing F5...")],
[3600, _t("Maybe you should consider reloading the application by pressing F5...")],
];
};

View File

@ -1494,7 +1494,7 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
return $.when(facet_from(this, value));
}
assert(value.length <= 1,
_("M2O search fields do not currently handle multiple default values"));
_t("M2O search fields do not currently handle multiple default values"));
// there are many cases of {search_default_$m2ofield: [id]}, need
// to handle this as if it were a single value.
value = value[0];
@ -1578,7 +1578,7 @@ instance.web.search.CustomFilters = instance.web.search.Input.extend({
$filter.unbind('click').click(function () {
self.view.query.reset([{
category: _("Custom Filter"),
category: _t("Custom Filter"),
icon: 'M',
field: {
get_context: function () { return filter.context; },

View File

@ -2081,7 +2081,7 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w
var self = this;
var trans = new instance.web.DataSet(this, 'ir.translation');
return trans.call_button('translate_fields', [this.view.dataset.model, this.view.datarecord.id, this.name, this.view.dataset.get_context()]).then(function(r) {
self.do_action(r.result);
self.do_action(r);
});
},
});
@ -4282,7 +4282,7 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({
this.dataset.create_function = function(data, sup) {
var fct = self.options.create_function || sup;
return fct.call(this, data).then(function(r) {
self.created_elements.push(r.result);
self.created_elements.push(r);
});
};
this.dataset.write_function = function(id, data, options, sup) {

View File

@ -1190,7 +1190,7 @@ instance.web.View = instance.web.Widget.extend({
var context = new instance.web.CompoundContext(dataset.get_context(), action_data.context || {});
var handler = function (r) {
var action = r.result;
var action = r;
if (action && action.constructor == Object) {
var ncontext = new instance.web.CompoundContext(context);
if (record_id) {

View File

@ -2,12 +2,6 @@
<!-- vim:fdl=1:
-->
<templates id="template" xml:space="preserve">
<t t-name="ui.Header">
<header>
<t t-raw="__content__"/>
</header>
</t>
<t t-name="EmptyComponent">
<div></div>
</t>
@ -413,7 +407,7 @@
<a class="oe_logo" href="#"><img t-att-src='_s + "/web/static/src/img/logo.png"'/></a>
<div class="oe_secondary_menus_container"/>
<div class="oe_footer">
Powered by <a href="http://www.openerp.com" target="_blank"><span>Open</span>ERP</a>
Powered by <a href="http://www.openerp.com" target="_blank"><span>OpenERP</span></a>
</div>
</td>
<td class="oe_application">
@ -1128,7 +1122,7 @@
<td>
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
<t t-set="fileupload_style">width: 83px;</t>
<t t-set="fileupload_style" t-translation="off">width: 83px;</t>
<button class="oe_button oe_field_button" type="button">
<img t-att-src='_s + "/web/static/src/img/icons/STOCK_DIRECTORY.png"'/>
<span>Select</span>

View File

@ -0,0 +1,144 @@
# Persian translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
"PO-Revision-Date: 2012-10-03 10:24+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Persian <fa@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-10-04 05:33+0000\n"
"X-Generator: Launchpad (build 16061)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "تقویم"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr "فیلتر"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr "امروز"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr "روز"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr "هفته"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr "ماه"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr "رویداد جدید"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr "ذخیره"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr "لغو کردن"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr "جزئیات "
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr "ویرایش"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr "حذف"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr "رویداد حذف خواهد شد. آیا مطمئن هستید؟"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr "توضیحات"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr "بازه زمانی"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr "تمام روز"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr "آیا میخواهید مجموعه کامل رویدادهای تکراری را ویرایش کنید؟"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr "تکرار رویداد"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr "غیرفعال"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr "فعال"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr "دستور کار"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr "تاریخ"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr "سال"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr ""
#~ msgid "Navigator"
#~ msgstr "هدایتگر"

View File

@ -0,0 +1,81 @@
# Persian translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
"PO-Revision-Date: 2012-10-03 10:07+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Persian <fa@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-10-04 05:33+0000\n"
"X-Generator: Launchpad (build 16061)\n"
#. openerp-web
#: addons/web_diagram/static/src/js/diagram.js:11
msgid "Diagram"
msgstr "نمودار"
#. openerp-web
#: addons/web_diagram/static/src/js/diagram.js:165
msgid "Are you sure?"
msgstr "آیا مطمئن هستید؟"
#. openerp-web
#: addons/web_diagram/static/src/js/diagram.js:195
msgid ""
"Deleting this node cannot be undone.\n"
"It will also delete all connected transitions.\n"
"\n"
"Are you sure ?"
msgstr ""
"عمل حذف برگشت پذیر نیست.\n"
"همچنین تمام اتصال ها را نیز حذف میکند.\n"
"\n"
"آیا مطمئن هستید؟"
#. openerp-web
#: addons/web_diagram/static/src/js/diagram.js:213
msgid ""
"Deleting this transition cannot be undone.\n"
"\n"
"Are you sure ?"
msgstr ""
"حذف این انتقال برگشت پذیر نیست.\n"
"\n"
"آیا از خذف مطمئن هستید؟"
#. openerp-web
#: addons/web_diagram/static/src/js/diagram.js:224
#: addons/web_diagram/static/src/js/diagram.js:257
msgid "Activity"
msgstr "فعالیت"
#. openerp-web
#: addons/web_diagram/static/src/js/diagram.js:232
#: addons/web_diagram/static/src/js/diagram.js:296
msgid "Open: "
msgstr "باز: "
#. openerp-web
#: addons/web_diagram/static/src/js/diagram.js:262
#: addons/web_diagram/static/src/js/diagram.js:314
msgid "Create:"
msgstr "ایجاد کردن"
#. openerp-web
#: addons/web_diagram/static/src/js/diagram.js:289
#: addons/web_diagram/static/src/js/diagram.js:308
msgid "Transition"
msgstr "انتقال"
#. openerp-web
#: addons/web_diagram/static/src/xml/base_diagram.xml:6
msgid "New Node"
msgstr "گره جدید"

View File

@ -0,0 +1,28 @@
# Persian translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
"PO-Revision-Date: 2012-10-03 10:11+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Persian <fa@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-10-04 05:33+0000\n"
"X-Generator: Launchpad (build 16061)\n"
#. openerp-web
#: addons/web_gantt/static/src/js/gantt.js:11
msgid "Gantt"
msgstr "گانت"
#. openerp-web
#: addons/web_gantt/static/src/xml/web_gantt.xml:10
msgid "Create"
msgstr "ایجاد کردن"

View File

@ -0,0 +1,98 @@
# Persian translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
"PO-Revision-Date: 2012-10-03 10:12+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Persian <fa@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-10-04 05:33+0000\n"
"X-Generator: Launchpad (build 16061)\n"
#. openerp-web
#: addons/web_graph/static/src/js/graph.js:19
msgid "Graph"
msgstr "گراف"
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:5
msgid "Graph Options"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:7
msgid "Graph Mode"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:11
msgid "Pie"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:12
msgid "Bars"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:14
msgid "Lines"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:15
msgid "Areas"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:18
msgid "Radar"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:20
msgid "Legend"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:24
msgid "Hidden"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:25
msgid "Inside"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:26
msgid "Top"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:28
msgid "Actions"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:32
msgid "Switch Axis"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:33
msgid "Show Data"
msgstr ""
#. openerp-web
#: addons/web_graph/static/src/xml/web_graph.xml:34
msgid "Download as PNG"
msgstr ""

View File

@ -0,0 +1,66 @@
# Persian translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
"PO-Revision-Date: 2012-10-03 10:14+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Persian <fa@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-10-04 05:33+0000\n"
"X-Generator: Launchpad (build 16061)\n"
#. openerp-web
#: addons/web_kanban/static/src/js/kanban.js:10
msgid "Kanban"
msgstr ""
#. openerp-web
#: addons/web_kanban/static/src/js/kanban.js:293
msgid "Undefined"
msgstr "تعریف نشده"
#. openerp-web
#: addons/web_kanban/static/src/js/kanban.js:471
msgid "Are you sure you want to delete this record ?"
msgstr "آیا از حذف این رکورد مطمئن هستید؟"
#. openerp-web
#: addons/web_kanban/static/src/js/kanban.js:839
msgid "Create: "
msgstr ""
#. openerp-web
#: addons/web_kanban/static/src/xml/web_kanban.xml:41
msgid "Show more... ("
msgstr "نمایش بیشتر"
#. openerp-web
#: addons/web_kanban/static/src/xml/web_kanban.xml:41
msgid "remaining)"
msgstr ""
#. openerp-web
#: addons/web_kanban/static/src/xml/web_kanban.xml:71
msgid "Add"
msgstr ""
#. openerp-web
#: addons/web_kanban/static/src/xml/web_kanban.xml:71
msgid "or"
msgstr ""
#. openerp-web
#: addons/web_kanban/static/src/xml/web_kanban.xml:72
msgid "Cancel"
msgstr ""
#~ msgid "Create"
#~ msgstr "ایجاد کردن"

View File

@ -1,6 +0,0 @@
[extractors]
qweb = npybabel:extract_qweb
javascript = npybabel:extract_javascript
[javascript: static/src/js/**.js]
[qweb: static/src/xml/**.xml]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -22,8 +22,6 @@ Contents:
list-view
form-notes
templates
guides/client-action
Indices and tables

View File

@ -1,45 +0,0 @@
.. highlight:: xml
Generic templates
=================
Generic template names should be prefixed by ``ui.`` to indicate their
special role.
Global Header: ``ui.Header``
----------------------------
Role
++++
This template is mostly dedicated to client actions taking over the
whole content area, and full-HTML form views (especially those opening
in the ``inline`` target).
It is used to display a buttons container (and can also be used for
status bars). The buttons should simply be placed inside the
``ui.Header`` body.
Arguments
+++++++++
The template only uses its body as argument.
Example
+++++++
::
<t t-call="ui.Header">
<button string="Apply" type="object" name="execute" class="oe_highlight"/>
or
<button string="Cancel" type="object" name="cancel" class="oe_link"/>
</t>
This block demonstrates a common pattern in OpenERP views and widgets:
a highlighted button, and a discard button styled as a link to cancel
the action:
.. image:: ./images/templates/ui.Header.*
In this case, both buttons are OpenERP action buttons.

View File

@ -1,66 +0,0 @@
#!/bin/sh
usage() {
cat << EOF
usage: $0 -a [DIR]
usage: $0 <ADDON_DIR> <OUTPUT_FILE>
OPTIONS:
-a [DIR] export the .pot files for all web addons found
at target path (default: ./addons)
-h print this message
EOF
exit 0
}
do_all=
while getopts "a" opt
do
case "$opt" in
a)
do_all=true;;
h)
usage;;
\?)
usage;;
esac
done
shift $((OPTIND-1))
if [ -n "$do_all" ]
then
if [ "x$(which msgcat)" = "x" ]
then
echo "The msgcat command from the gettext tools is required in the PATH."
echo "On a Debian/Ubuntu system you may install gettext via 'sudo apt-get install gettext'"
exit 1
fi
echo "Extracting all web addons translations"
executable=$0
target_dir=${1:-./addons}
echo "Using target dir: ${target_dir}"
for mod in $(find ${target_dir} -type d -name 'static' -exec sh -c 'basename $(dirname {})' \;); do
echo ${mod}
mod_pot=${target_dir}/${mod}/i18n/${mod}.pot
web_pot=${mod_pot}.web
mkdir -p $(dirname ${web_pot})
$executable ${target_dir}/${mod} ${web_pot}
if [ -f "${mod_pot}" ]; then
echo "Merging with existing PO file: ${mod_pot}"
msgcat --force-po -o "${mod_pot}.tmp" ${mod_pot} ${web_pot}
mv ${mod_pot}.tmp ${mod_pot}
rm ${web_pot}
else
echo "Renaming to final PO file: ${mod_pot}"
mv ${web_pot} ${mod_pot}
fi
done
elif [ -n "$2" ]
then
./npybabel.py extract -F babel.cfg -o $2 -k _t -k _lt --no-default-keywords $1
else
usage
fi

View File

@ -1,140 +0,0 @@
#!/usr/bin/env python
# EASY-INSTALL-ENTRY-SCRIPT: 'Babel==0.9.6','console_scripts','pybabel'
__requires__ = 'Babel==0.9.6'
import sys
from pkg_resources import load_entry_point
import re
import json
from lxml import etree as elt
from babel.messages import extract
if __name__ == '__main__':
sys.exit(
load_entry_point('Babel==0.9.6', 'console_scripts', 'pybabel')()
)
XMLJS_EXPR = re.compile(r"""(?:\_t *\( *((?:"(?:[^"\\]|\\.)*")|(?:'(?:[^'\\]|\\.)*')) *\))""")
TRANSLATION_FLAG_COMMENT = "openerp-web"
# List of etree._Element subclasses that we choose to ignore when parsing XML.
# We include the *Base ones just in case, currently they seem to be subclasses of the _* ones.
SKIPPED_ELEMENT_TYPES = (elt._Comment, elt._ProcessingInstruction, elt.CommentBase, elt.PIBase)
def extract_xmljs(fileobj, keywords, comment_tags, options):
"""Extract messages from Javascript code embedded into XML documents.
This complements the ``extract_javascript`` extractor which works
only on pure .js files, and the``extract_qweb`` extractor, which only
extracts XML text.
:param fileobj: the file-like object the messages should be extracted
from
:param keywords: a list of keywords (i.e. function names) that should
be recognized as translation functions
:param comment_tags: a list of translator tags to search for and
include in the results
:param options: a dictionary of additional options (optional)
:return: an iterator over ``(lineno, funcname, message, comments)``
tuples
:rtype: ``iterator``
"""
assert False, """ the XMLJS extractor does not work and was removed:
* Babel apparently does not accept two extractors for the same set of files
so it would not run the xmljs extractor at all, extraction of JS stuff
needs to be done from the XML extractor
* The regex above fails up if there are back-slashed quotes within the
translatable string (the string marked with _t), it just won't match the
string
* While extraction succeeds on XML entities (e.g. &quot;), translation
matching will fail if those entities are kept in the PO msgid as the
XML parser will get an un-escaped string, without those entities (so a
text extractor will extract ``Found match &quot;%s&quot;``, but the msgid
of the PO file must be ``Found match "%s"`` or the translation will fail
* single-quoted strings are not valid JSON string, so single-quoted strings
matched by the regex (likely since XML attributes are double-quoted,
single quotes within them don't have to be escaped) will blow up when
json-parsed for their content
I think that's about it.
If this extractor is reimplemented, it should be integrated into
extract_qweb, either in the current pass (probably not a good idea) or as
a separate pass using iterparse, matching either elements with t-js or
some other kinds of t-* directives (@t-esc, @t-raw, @t-att, others?),
shove the attribute content into a StringIO and pass *that* to Babel's
own extract_javascript; then add a line offset in order to yield the
correct line number.
"""
content = fileobj.read()
found = XMLJS_EXPR.finditer(content)
index = 0
line_nbr = 0
for f in found:
msg = f.group(1)
msg = json.loads(msg)
while index < f.start():
if content[index] == "\n":
line_nbr += 1
index += 1
yield (line_nbr, None, msg, [TRANSLATION_FLAG_COMMENT])
def extract_qweb(fileobj, keywords, comment_tags, options):
"""Extract messages from qweb template files.
:param fileobj: the file-like object the messages should be extracted
from
:param keywords: a list of keywords (i.e. function names) that should
be recognized as translation functions
:param comment_tags: a list of translator tags to search for and
include in the results
:param options: a dictionary of additional options (optional)
:return: an iterator over ``(lineno, funcname, message, comments)``
tuples
:rtype: ``iterator``
"""
result = []
def handle_text(text, lineno):
text = (text or "").strip()
if len(text) > 1: # Avoid mono-char tokens like ':' ',' etc.
result.append((lineno, None, text, [TRANSLATION_FLAG_COMMENT]))
# not using elementTree.iterparse because we need to skip sub-trees in case
# the ancestor element had a reason to be skipped
def iter_elements(current_element):
for el in current_element:
if isinstance(el, SKIPPED_ELEMENT_TYPES): continue
if "t-js" not in el.attrib and \
not ("t-jquery" in el.attrib and "t-operation" not in el.attrib) and \
not ("t-translation" in el.attrib and el.attrib["t-translation"].strip() == "off"):
handle_text(el.text, el.sourceline)
for att in ('title', 'alt', 'label', 'placeholder'):
if att in el.attrib:
handle_text(el.attrib[att], el.sourceline)
iter_elements(el)
handle_text(el.tail, el.sourceline)
tree = elt.parse(fileobj)
iter_elements(tree.getroot())
return result
def extract_javascript(fileobj, keywords, comment_tags, options):
"""Extract messages from Javascript source files. This extractor delegates
to babel's buit-in javascript extractor, but adds a special comment
used as a flag to identify web translations.
:param fileobj: the file-like object the messages should be extracted
from
:param keywords: a list of keywords (i.e. function names) that should
be recognized as translation functions
:param comment_tags: a list of translator tags to search for and
include in the results
:param options: a dictionary of additional options (optional)
:return: an iterator over ``(lineno, funcname, message, comments)``
tuples
:rtype: ``iterator``
"""
for (message_lineno, funcname, messages, comments) in \
extract.extract_javascript(fileobj, keywords, comment_tags, options):
comments.append(TRANSLATION_FLAG_COMMENT)
yield (message_lineno, funcname, messages, comments)