summaryrefslogtreecommitdiff
path: root/addons/web/controllers/main.py
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/controllers/main.py')
-rw-r--r--addons/web/controllers/main.py93
1 files changed, 50 insertions, 43 deletions
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index 3053ad286ee..4d00f5114f8 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -36,7 +36,7 @@ import odoo
import odoo.modules.registry
from odoo.api import call_kw, Environment
from odoo.modules import get_module_path, get_resource_path
-from odoo.tools import image_process, topological_sort, html_escape, pycompat
+from odoo.tools import image_process, topological_sort, html_escape, pycompat, ustr
from odoo.tools.mimetypes import guess_mimetype
from odoo.tools.translate import _
from odoo.tools.misc import str2bool, xlwt, file_open
@@ -63,6 +63,9 @@ env.filters["json"] = json.dumps
# 1 week cache for asset bundles as advised by Google Page Speed
BUNDLE_MAXAGE = 60 * 60 * 24 * 7
+# 1 year cache for content (menus, translations, static qweb)
+CONTENT_MAXAGE = 60 * 60 * 24 * 356
+
DBNAME_PATTERN = '^[a-zA-Z0-9][a-zA-Z0-9_.-]+$'
#----------------------------------------------------------
@@ -451,6 +454,23 @@ class Home(http.Controller):
except AccessError:
return werkzeug.utils.redirect('/web/login?error=access')
+ @http.route('/web/webclient/load_menus/<string:unique>', type='http', auth='user', methods=['GET'])
+ def web_load_menus(self, unique):
+ """
+ Loads the menus for the webclient
+ :param unique: this parameters is not used, but mandatory: it is used by the HTTP stack to make a unique request
+ :return: the menus (including the images in Base64)
+ """
+ menus = request.env["ir.ui.menu"].load_menus(request.debug)
+ body = json.dumps(menus, default=ustr)
+ response = request.make_response(body, [
+ # this method must specify a content-type application/json instead of using the default text/html set because
+ # the type of the route is set to HTTP, but the rpc is made with a get and expects JSON
+ ('Content-Type', 'application/json'),
+ ('Cache-Control', 'public, max-age=31536000'),
+ ])
+ return response
+
@http.route('/web/dbredirect', type='http', auth="none")
def web_db_redirect(self, redirect='/', **kw):
ensure_db()
@@ -549,18 +569,14 @@ class WebClient(http.Controller):
('Cache-Control', 'max-age=36000'),
])
- @http.route('/web/webclient/qweb', type='http', auth="none", cors="*")
- def qweb(self, mods=None, db=None):
+ @http.route('/web/webclient/qweb/<string:unique>', type='http', auth="none", cors="*")
+ def qweb(self, unique, mods=None, db=None):
files = [f[0] for f in manifest_glob('qweb', addons=mods, db=db)]
- last_modified = get_last_modified(files)
- if request.httprequest.if_modified_since and request.httprequest.if_modified_since >= last_modified:
- return werkzeug.wrappers.Response(status=304)
-
- content, checksum = concat_xml(files)
-
- return make_conditional(
- request.make_response(content, [('Content-Type', 'text/xml')]),
- last_modified, checksum)
+ content, _dummy = concat_xml(files)
+ return request.make_response(content, [
+ ('Content-Type', 'text/xml'),
+ ('Cache-Control','public, max-age=' + str(CONTENT_MAXAGE))
+ ])
@http.route('/web/webclient/bootstrap_translations', type='json', auth="none")
def bootstrap_translations(self, mods):
@@ -585,41 +601,32 @@ class WebClient(http.Controller):
return {"modules": translations_per_module,
"lang_parameters": None}
- @http.route('/web/webclient/translations', type='json', auth="none")
- def translations(self, mods=None, lang=None):
+ @http.route('/web/webclient/translations/<string:unique>', type='http', auth="none")
+ def translations(self, unique, mods=None, lang=None):
+ """
+ Load the translations for the specified language and modules
+
+ :param unique: this parameters is not used, but mandatory: it is used by the HTTP stack to make a unique request
+ :param mods: the modules, a comma separated list
+ :param lang: the language of the user
+ :return:
+ """
request.disable_db = False
- if mods is None:
- mods = [x['name'] for x in request.env['ir.module.module'].sudo().search_read(
- [('state', '=', 'installed')], ['name'])]
- if lang is None:
- lang = request.context["lang"]
- langs = request.env['res.lang'].sudo().search([("code", "=", lang)])
- lang_params = None
- if langs:
- lang_params = langs.read([
- "name", "direction", "date_format", "time_format",
- "grouping", "decimal_point", "thousands_sep", "week_start"])[0]
- lang_params['week_start'] = int(lang_params['week_start'])
-
- # 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.
- translations_per_module = {}
- messages = request.env['ir.translation'].sudo().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 {
+
+ translations_per_module, lang_params = request.env["ir.translation"].get_translations_for_webclient(mods, lang)
+
+ body = json.dumps({
'lang_parameters': lang_params,
'modules': translations_per_module,
'multi_lang': len(request.env['res.lang'].sudo().get_installed()) > 1,
- }
+ })
+ response = request.make_response(body, [
+ # this method must specify a content-type application/json instead of using the default text/html set because
+ # the type of the route is set to HTTP, but the rpc is made with a get and expects JSON
+ ('Content-Type', 'application/json'),
+ ('Cache-Control', 'public, max-age=' + str(CONTENT_MAXAGE)),
+ ])
+ return response
@http.route('/web/webclient/version_info', type='json', auth="none")
def version_info(self):