Skip to content

Commit

Permalink
[IMP] formio: Translatable (multilingual) public Forms and Form Builder.
Browse files Browse the repository at this point in the history
- Translatable (multilingual) public Forms, with language-switcher
buttons.
- Translatable (multilingual) Form Builder, with language-switcher
buttons.

Closes #47
Closes #58
  • Loading branch information
bobslee committed Nov 21, 2020
1 parent a8ae71b commit 7d9674a
Show file tree
Hide file tree
Showing 15 changed files with 215 additions and 192 deletions.
2 changes: 1 addition & 1 deletion formio/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{
'name': 'Form.io',
'summary': 'Build, deploy and store web forms with the "Form.io" Form Builder',
'version': '7.6',
'version': '7.7',
'license': 'LGPL-3',
'author': 'Nova Code',
'website': 'https://www.novacode.nl',
Expand Down
65 changes: 18 additions & 47 deletions formio/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ def builder_root(self, builder_id, **kwargs):
# TODO Render template with message?
return request.redirect("/")

# TODO REMOVE (still needed or obsolete legacy?)
# Needed to update language
context = request.env.context.copy()
context.update({'lang': request.env.user.lang})
request.env.context = context

builder = request.env['formio.builder'].browse(builder_id)
values = {
'languages': builder.languages,
'builder': builder,
'formio_css_assets': builder.formio_css_assets,
'formio_js_assets': builder.formio_js_assets,
Expand All @@ -50,8 +52,8 @@ def builder_config(self, builder_id, **kwargs):
if builder:
if builder.schema:
res['schema'] = json.loads(builder.schema)
res['options'] = builder.get_js_options()
res['mode'] = builder.get_js_mode()
res['options'] = builder._get_js_options()
res['params'] = builder._get_js_params()

return res

Expand All @@ -77,39 +79,18 @@ def form_root(self, uuid, **kwargs):
msg = 'Form UUID %s' % uuid
return request.not_found(msg)

# TODO REMOVE (still needed or obsolete legacy?)
# Needed to update language
context = request.env.context.copy()
context.update({'lang': request.env.user.lang})
request.env.context = context

# Get active languages used in Builder translations.
query = """
SELECT
DISTINCT(fbt.lang_id) AS lang_id
FROM
formio_builder_translation AS fbt
INNER JOIN res_lang AS l ON l.id = fbt.lang_id
WHERE
fbt.builder_id = {builder_id}
AND l.active = True
""".format(builder_id=form.builder_id.id)

request.env.cr.execute(query)
builder_lang_ids = [r[0] for r in request.env.cr.fetchall()]

# Always include english (en_US).
domain = ['|', ('id', 'in', builder_lang_ids), ('code', 'in', [request.env.user.lang, 'en_US'])]
languages = request.env['res.lang'].with_context(active_test=False).search(domain, order='name asc')
languages = languages.filtered(lambda r: r.id in builder_lang_ids or r.code == 'en_US')

values = {
'languages': [], # initialize, otherwise template/view crashes.
'languages': form.builder_id.languages,
'form': form,
'formio_css_assets': form.builder_id.formio_css_assets,
'formio_js_assets': form.builder_id.formio_js_assets,
}
if len(languages) > 1:
values['languages'] = languages
return request.render('formio.formio_form_embed', values)

@http.route('/formio/form/<string:form_uuid>/config', type='json', auth='user', website=True)
Expand All @@ -119,8 +100,8 @@ def form_config(self, form_uuid, **kwargs):

if form and form.builder_id.schema:
res['schema'] = json.loads(form.builder_id.schema)
res['options'] = self._prepare_form_options(form)
res['config'] = self._prepare_form_config(form)
res['options'] = self._get_form_js_options(form)
res['params'] = self._get_form_js_params(form)

return res

Expand Down Expand Up @@ -282,29 +263,19 @@ def form_res_data(self, uuid, **kwargs):
except Exception as e:
_logger.error("Exception: %s" % e)

def _prepare_form_options(self, form):
options = {}
context = request.env.context
Lang = request.env['res.lang']

if form.state in [FORM_STATE_COMPLETE, FORM_STATE_CANCEL]:
options['readOnly'] = True

if form.builder_id.view_as_html:
options['renderMode'] = 'html'
options['viewAsHtml'] = True # backwards compatible (version < 4.x)?
def _get_form_js_options(self, form):
options = form._get_js_options()

lang = Lang._lang_get(request.env.user.lang)
if lang:
options['language'] = lang.iso_code[:2]
options['i18n'] = form.i18n_translations()
# default language
if request.env.user.lang in form.languages.mapped('iso_code'):
language = request.env.user.lang
else:
language = request._context['lang']
options['language'] = language.replace('_', '-')
return options

def _prepare_form_config(self, form):
config = {
'portal_submit_done_url': form.portal_submit_done_url
}
return config
def _get_form_js_params(self, form):
return form._get_js_params()

def _get_form(self, uuid, mode):
return request.env['formio.form'].get_form(uuid, mode)
112 changes: 27 additions & 85 deletions formio/controllers/public.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,52 +27,22 @@ def public_form_root(self, uuid, **kwargs):
msg = 'Form UUID %s' % uuid
return request.not_found(msg)

## TODO languages ##
## Determine lang.iso from request.__dict__

# Needed to update language
# context = request.env.context.copy()
# context.update({'lang': request.env.user.lang})
# request.env.context = context

# # Get active languages used in Builder translations.
# query = """
# SELECT
# DISTINCT(fbt.lang_id) AS lang_id
# FROM
# formio_builder_translation AS fbt
# INNER JOIN res_lang AS l ON l.id = fbt.lang_id
# WHERE
# fbt.builder_id = {builder_id}
# AND l.active = True
# """.format(builder_id=form.builder_id.id)

# request.env.cr.execute(query)
# builder_lang_ids = [r[0] for r in request.env.cr.fetchall()]

# # Always include english (en_US).
# domain = ['|', ('id', 'in', builder_lang_ids), ('code', 'in', [request.env.user.lang, 'en_US'])]
# languages = request.env['res.lang'].with_context(active_test=False).search(domain, order='name asc')
# languages = languages.filtered(lambda r: r.id in builder_lang_ids or r.code == 'en_US')

values = {
'languages': [], # initialize, otherwise template/view crashes.
'languages': form.builder_id.languages,
'form': form,
'formio_css_assets': form.builder_id.formio_css_assets,
'formio_js_assets': form.builder_id.formio_js_assets,
}
# if len(languages) > 1:
# values['languages'] = languages
return request.render('formio.formio_form_public_embed', values)

@http.route('/formio/public/form/<string:form_uuid>/config', type='json', auth='public', website=True)
def form_config(self, form_uuid, **kwargs):
form = self._get_public_form(form_uuid, self._check_public_form())
res = {'schema': {}, 'options': {}, 'config': {}}
res = {'schema': {}, 'options': {}, 'params': {}}

if form and form.builder_id.schema:
res['schema'] = json.loads(form.builder_id.schema)
res['options'] = self._prepare_form_options(form)
res['options'] = self._get_public_form_js_options(form)

return res

Expand Down Expand Up @@ -133,45 +103,14 @@ def public_form_create_root(self, builder_uuid, **kwargs):
# msg = 'Form Builder UUID %s not current/published' % builder_uuid
# return request.not_found(msg)

## TODO languages ##
## Determine lang.iso from request.__dict__

# Needed to update language
# context = request.env.context.copy()
# context.update({'lang': request.env.user.lang})
# request.env.context = context

# # Get active languages used in Builder translations.
# query = """
# SELECT
# DISTINCT(fbt.lang_id) AS lang_id
# FROM
# formio_builder_translation AS fbt
# INNER JOIN res_lang AS l ON l.id = fbt.lang_id
# WHERE
# fbt.builder_uuid = {builder_uuid}
# AND l.active = True
# """.format(builder_uuid=form.builder_uuid.id)

# request.env.cr.execute(query)
# builder_lang_ids = [r[0] for r in request.env.cr.fetchall()]

# # Always include english (en_US).
# domain = ['|', ('id', 'in', builder_lang_ids), ('code', 'in', [request.env.user.lang, 'en_US'])]
# languages = request.env['res.lang'].with_context(active_test=False).search(domain, order='name asc')
# languages = languages.filtered(lambda r: r.id in builder_lang_ids or r.code == 'en_US')

values = {
'languages': [], # initialize, otherwise template/view crashes.
'languages': formio_builder.languages,
'builder': formio_builder,
'public_form_create': True,
'formio_builder_uuid': formio_builder.uuid,
'formio_css_assets': formio_builder.formio_css_assets,
'formio_js_assets': formio_builder.formio_js_assets,
}
# if len(languages) > 1:
# values['languages'] = languages

return request.render('formio.formio_form_public_create_embed', values)


Expand All @@ -185,9 +124,8 @@ def public_form_create_config(self, builder_uuid, **kwargs):

if formio_builder.schema:
res['schema'] = json.loads(formio_builder.schema)
#res['options'] = self._prepare_form_options(form)
res['options'] = {'public_create': True, 'embedded': True}
res['config'] = self._prepare_form_config(formio_builder)
res['options'] = self._get_public_create_form_js_options(formio_builder)
res['params'] = self._get_public_form_js_params(formio_builder)

return res

Expand Down Expand Up @@ -223,29 +161,33 @@ def public_form_create_submit(self, builder_uuid, **post):
res = form_model.sudo().create(vals)
return {'form_uuid': res.uuid}

def _prepare_form_options(self, form):
options = {}
context = request.env.context
Lang = request.env['res.lang']

if form.state in [FORM_STATE_COMPLETE, FORM_STATE_CANCEL]:
options['readOnly'] = True
def _get_public_form_js_options(self, form):
options = form._get_js_options()

if form.builder_id.view_as_html:
options['renderMode'] = 'html'
options['viewAsHtml'] = True # backwards compatible (version < 4.x)?

lang = Lang._lang_get(request.env.user.lang)
lang = request.env['res.lang']._lang_get(request.env.user.lang)
if lang:
options['language'] = lang.iso_code[:2]
options['language'] = lang.iso_code
options['i18n'] = form.i18n_translations()
return options

def _prepare_form_config(self, builder):
config = {
'public_submit_done_url': builder.public_submit_done_url
def _get_public_create_form_js_options(self, builder):
options = {
'public_create': True,
'embedded': True,
'i18n': builder.i18n_translations()
}
return config

lang = request.env['res.lang']._lang_get(request.env.user.lang)
if lang:
options['language'] = lang.iso_code
else:
context = request.env.context
options['language'] = context['lang'] if context.get('lang') else self.env.ref('base.lang_en')

return options

def _get_public_form_js_params(self, builder):
return builder._get_public_form_js_params()

def _get_public_form(self, form_uuid, public_share=False):
return request.env['formio.form'].get_public_form(form_uuid, public_share)
Expand Down
Loading

0 comments on commit 7d9674a

Please sign in to comment.