Source code for shoop.xtheme.plugins.widgets
# -*- coding: utf-8 -*-
# This file is part of Shoop.
#
# Copyright (c) 2012-2016, Shoop Ltd. All rights reserved.
#
# This source code is licensed under the AGPLv3 license found in the
# LICENSE file in the root directory of this source tree.
from django import forms
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _
from shoop.utils.i18n import get_language_name
from shoop.xtheme.plugins.consts import FALLBACK_LANGUAGE_CODE
[docs]class TranslatableFieldWidget(forms.Widget):
# This implementation is definitely inspired by forms.MultiWidget.
def __init__(self, languages, input_widget=forms.TextInput, attrs=None):
super(TranslatableFieldWidget, self).__init__(attrs)
self.languages = languages
self.input_widget = input_widget
if not callable(self.input_widget): # pragma: no cover
raise ValueError("%r's input_widget must be callable" % self)
[docs] def render(self, name, value, attrs=None):
value_dict = self.decompress(value)
output = []
final_attrs = self.build_attrs(attrs)
id_ = final_attrs.get('id', None)
for language_code in self._iter_languages():
widget = self._build_widget(language_code)
widget.is_localized = self.is_localized
widget_value = value_dict.get(language_code)
if id_:
final_attrs = dict(final_attrs, id='%s_%s' % (id_, language_code))
html = widget.render(name + '_%s' % language_code, widget_value, final_attrs)
output.append((language_code, final_attrs.get("id"), html))
return mark_safe(self.format_output(output))
def _iter_languages(self):
return (list(self.languages) + [FALLBACK_LANGUAGE_CODE])
def _build_widget(self, language):
return self.input_widget()
[docs] def id_for_label(self, id_):
# See the comment for RadioSelect.id_for_label()
if id_:
id_ += '_%s' % self.languages[0]
return id_
[docs] def value_from_datadict(self, data, files, name):
out_dict = {}
widget = self._build_widget(None)
for language_code in self._iter_languages():
value = widget.value_from_datadict(data, files, name + '_%s' % language_code)
if value not in (None, ""):
out_dict[language_code] = value
if not out_dict:
# Fallback: If the dictionary remained empty to this stage,
# see if it's "just there", and if so, call it the fallback.
value = widget.value_from_datadict(data, files, name)
if value not in (None, ""):
out_dict[FALLBACK_LANGUAGE_CODE] = value
return out_dict
[docs] def format_output(self, widget_pairs):
rendered_table = ["<table><tbody>"]
for language_code, id, html in widget_pairs:
rendered_table.append("<tr><td><label for=\"%(id)s\">%(language_name)s</td><td>%(html)s</td></tr>\n" % {
"id": id,
"language_name": (
get_language_name(language_code)
if language_code != FALLBACK_LANGUAGE_CODE
else _("(Untranslated)")
),
"html": html
})
rendered_table.append("</tbody></table>")
return ''.join(rendered_table)
[docs] def decompress(self, value):
out_dict = {}
if value is None:
return out_dict
if isinstance(value, dict):
out_dict.update(value)
else:
out_dict[FALLBACK_LANGUAGE_CODE] = value
return out_dict