--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_i18n/widget/__init__.py Fri Mar 20 17:28:43 2015 +0100
@@ -0,0 +1,152 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+from pyramid.decorator import reify
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_form.interfaces.form import IFormLayer
+from pyams_i18n.interfaces import II18nManager, INegotiator
+from pyams_i18n.interfaces.schema import II18nField, II18nTextLineField, II18nTextField, II18nFileField
+from pyams_i18n.interfaces.widget import II18nWidget, II18nTextLineWidget, II18nTextWidget, II18nFileWidget
+from z3c.form.interfaces import IDataConverter, IFieldWidget, NO_VALUE
+
+# import packages
+from pyams_form.widget import widgettemplate_config
+from pyams_utils.adapter import adapter_config
+from pyams_utils.registry import query_utility
+from pyams_utils.traversing import get_parent
+from z3c.form.browser.widget import HTMLInputWidget
+from z3c.form.converter import BaseDataConverter
+from z3c.form.util import expandPrefix
+from z3c.form.widget import Widget, FieldWidget
+from zope.interface import implementer_only
+
+
+@adapter_config(context=(II18nField, II18nWidget), provides=IDataConverter)
+class I18nDataConverter(BaseDataConverter):
+ """I18n base data converter"""
+
+ def __init__(self, field, widget):
+ super(I18nDataConverter, self).__init__(field, widget)
+
+ def toWidgetValue(self, value):
+ # I18n widget is using a dict where each key is a lang
+ # and each value is matching widget value
+ result = {}
+ registry = self.widget.request.registry
+ for lang, val in value.items():
+ converter = registry.queryMultiAdapter((self.field.value_type, self.widget.get_widget(lang)),
+ IDataConverter)
+ if converter is not None:
+ result[lang] = converter.toWidgetValue(val)
+ return result
+
+ def toFieldValue(self, value):
+ # I18n widget is using a dict where each key is a lang
+ # and each value is matching widget value
+ result = {}
+ registry = self.widget.request.registry
+ for lang in self.widget.langs:
+ converter = registry.queryMultiAdapter((self.field.value_type, self.widget.get_widget(lang)),
+ IDataConverter)
+ if converter is not None:
+ result[lang] = converter.toFieldValue(self.widget.get_value(lang))
+ return result
+
+
+@widgettemplate_config(mode='input', template='templates/i18n-input.pt', widget=II18nWidget, layer=IFormLayer)
+@widgettemplate_config(mode='display', template='templates/i18n-input.pt', widget=II18nWidget, layer=IFormLayer)
+@implementer_only(II18nWidget)
+class I18nWidget(HTMLInputWidget, Widget):
+ """I18n base widget"""
+
+ @reify
+ def langs(self):
+ langs = []
+ negotiator = query_utility(INegotiator)
+ if negotiator is not None:
+ langs.append(negotiator.server_language)
+ manager = get_parent(self.context, II18nManager)
+ if manager is not None:
+ langs.extend(sorted(filter(lambda x: x not in langs, manager.languages)))
+ elif negotiator is not None:
+ langs.extend(sorted(filter(lambda x: x not in langs, negotiator.offered_languages)))
+ else:
+ langs.append('en')
+ return langs
+
+ def update(self):
+ self.widgets = {}
+ for lang in self.langs:
+ widget = self.request.registry.queryMultiAdapter((self.field.value_type, self.request), IFieldWidget)
+ if widget is not None:
+ prefix = expandPrefix(self.form.prefix) + expandPrefix(self.form.widgets.prefix) + expandPrefix(lang)
+ name = self.field.value_type.__name__ = self.field.__name__
+ widget.name = prefix + name
+ widget.id = widget.name.replace('.', '-')
+ widget.form = self.form
+ widget.field = self.field.value_type
+ widget.context = self.context
+ widget.ignoreContext = self.ignoreContext
+ widget.ignoreRequest = self.ignoreRequest
+ widget.lang = lang
+ widget.update()
+ self.widgets[lang] = widget
+ super(I18nWidget, self).update()
+
+ def extract(self, default=NO_VALUE):
+ result = {}
+ [result.setdefault(lang, self.widgets[lang].extract(default)) for lang in self.widgets.keys()]
+ return result
+
+ def get_widget(self, lang):
+ return self.widgets.get(lang)
+
+ def get_value(self, lang):
+ return self.get_widget(lang).value
+
+
+@implementer_only(II18nTextLineWidget)
+class I18nTextLineWidget(I18nWidget):
+ """I18n text line widget"""
+
+
+@adapter_config(context=(II18nTextLineField, IFormLayer), provides=IFieldWidget)
+def I18nTextLineFieldWidget(field, request):
+ """I18n text line field widget factory"""
+ return FieldWidget(field, I18nTextLineWidget(request))
+
+
+@implementer_only(II18nTextWidget)
+class I18nTextWidget(I18nWidget):
+ """I18n text widget"""
+
+
+@adapter_config(context=(II18nTextField, IFormLayer), provides=IFieldWidget)
+def I18nTextFieldWidget(field, request):
+ """I18n text field widget factory"""
+ return FieldWidget(field, I18nTextWidget(request))
+
+
+@implementer_only(II18nFileWidget)
+class I18nFileWidget(I18nWidget):
+ """I18n file widget"""
+
+
+@adapter_config(context=(II18nFileField, IFormLayer), provides=IFieldWidget)
+def I18nFileFieldWidget(field, request):
+ """I18n file field widget factory"""
+ return FieldWidget(field, I18nFileWidget(request))