Source code for pyams_i18n.negotiator

#
# 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.
#

__docformat__ = 'restructuredtext'

from persistent import Persistent
from zope.container.contained import Contained
from zope.i18n.interfaces import INegotiator as IZopeNegotiator
from zope.i18n.locales import locales
from zope.interface import Interface, implementer
from zope.schema.fieldproperty import FieldProperty
from zope.traversing.interfaces import ITraversable

from pyams_i18n.interfaces import INegotiator, LANGUAGE_CACHE_KEY
from pyams_skin.layer import IPyAMSUserLayer
from pyams_utils.adapter import ContextRequestAdapter, adapter_config
from pyams_utils.i18n import get_browser_language
from pyams_utils.registry import get_global_registry, query_utility, utility_config


[docs]@implementer(INegotiator) class Negotiator(Persistent, Contained): """Language negotiator utility""" policy = FieldProperty(INegotiator['policy']) server_language = FieldProperty(INegotiator['server_language']) offered_languages = FieldProperty(INegotiator['offered_languages']) cache_enabled = FieldProperty(INegotiator['cache_enabled'])
[docs] def get_language(self, request): """See :intf:`INegotiator`""" # lang parameter, if defined, is of higher priority if 'lang' in request.params: return request.params['lang'] policies = self.policy.split(' --> ') for policy in policies: # check server policy if policy == 'server': if self.server_language: return self.server_language # check session policy elif policy == 'session': if self.cache_enabled: try: cached = request.annotations[LANGUAGE_CACHE_KEY] return cached except AttributeError: return self.server_language except KeyError: session = request.session lang = session.get('language') if lang is not None: request.annotations[LANGUAGE_CACHE_KEY] = lang return lang else: session = request.session lang = session.get('language') if lang is not None: return lang # check browser policy elif policy == 'browser': lang = get_browser_language(request) if lang is not None: return lang return None
[docs] def clear_cache(self, request): """Clear cached language value""" try: del request.annotations[LANGUAGE_CACHE_KEY] except KeyError: pass
[docs]@adapter_config(name='lang', context=(Interface, IPyAMSUserLayer), provides=ITraversable) class LangNamespaceTraverser(ContextRequestAdapter): """++lang++ namespace traverser This traverser is mainly used for backward compatibility with previous Zope 3 websites. """
[docs] def traverse(self, name, furtherpath=None): if name != '*': self.request.GET['lang'] = name return self.context
[docs]def locale_negotiator(request): """Negotiate language based on server, browser, request and user settings Locale is extracted from request's "lang" parameter, from browser settings or from negotiator utility """ negotiator = query_utility(INegotiator) if negotiator is not None: locale_name = negotiator.get_language(request) else: locale_name = get_browser_language(request) if not locale_name: registry = get_global_registry() locale_name = registry.settings.get('pyramid.default_locale_name', 'en') if '-' in locale_name: # remove 'sub-locale' to prevent Babel and Zope exceptions for unknown locales locale_name = locale_name.split('-')[0] return locale_name
[docs]def get_locale(request): """Get zope.i18n "locale" attribute""" return locales.getLocale(request.locale_name)
[docs]@utility_config(provides=IZopeNegotiator) class ZopeNegotiator(object): """Zope language negotiator"""
[docs] def getLanguage(self, langs, env): return locale_negotiator(env)