[Zope3-checkins] SVN: Zope3/branches/hdima-language-namespace/src/zope/ Added IModifiableUserPreferredLanguages adapter

Dmitry Vasiliev dima at hlabs.spb.ru
Sun Aug 7 08:49:55 EDT 2005


Log message for revision 37767:
  Added IModifiableUserPreferredLanguages adapter
  

Changed:
  U   Zope3/branches/hdima-language-namespace/src/zope/app/i18n/configure.zcml
  U   Zope3/branches/hdima-language-namespace/src/zope/app/publisher/browser/__init__.py
  A   Zope3/branches/hdima-language-namespace/src/zope/app/publisher/browser/tests/test_browserlanguages.py
  U   Zope3/branches/hdima-language-namespace/src/zope/app/traversing/configure.zcml
  U   Zope3/branches/hdima-language-namespace/src/zope/app/traversing/namespace.py
  U   Zope3/branches/hdima-language-namespace/src/zope/i18n/interfaces/__init__.py
  U   Zope3/branches/hdima-language-namespace/src/zope/publisher/browser.py
  U   Zope3/branches/hdima-language-namespace/src/zope/publisher/http.py
  UU  Zope3/branches/hdima-language-namespace/src/zope/publisher/tests/test_browserlanguages.py

-=-
Modified: Zope3/branches/hdima-language-namespace/src/zope/app/i18n/configure.zcml
===================================================================
--- Zope3/branches/hdima-language-namespace/src/zope/app/i18n/configure.zcml	2005-08-07 12:40:19 UTC (rev 37766)
+++ Zope3/branches/hdima-language-namespace/src/zope/app/i18n/configure.zcml	2005-08-07 12:49:54 UTC (rev 37767)
@@ -2,40 +2,44 @@
    xmlns="http://namespaces.zope.org/zope">
 
   <!-- Setup language negotiation -->
-  <utility 
+  <utility
       provides="zope.i18n.interfaces.INegotiator"
-      component="zope.i18n.negotiator.negotiator" 
+      component="zope.i18n.negotiator.negotiator"
       />
-  
-  <adapter factory="zope.publisher.browser.BrowserLanguages"
+
+  <adapter factory="zope.app.publisher.browser.ModifiableBrowserLanguages"
       for="zope.publisher.interfaces.http.IHTTPRequest"
-      provides="zope.i18n.interfaces.IUserPreferredLanguages" 
+      provides="zope.i18n.interfaces.IModifiableUserPreferredLanguages"
       />
-  
+
+  <class class="zope.publisher.http.HTTPRequest">
+      <implements interface="zope.app.annotation.IAttributeAnnotatable" />
+  </class>
+
   <!-- Setup charset negotiation -->
   <adapter factory="zope.publisher.http.HTTPCharsets"
       for="zope.publisher.interfaces.http.IHTTPRequest"
-      provides="zope.i18n.interfaces.IUserPreferredCharsets" 
+      provides="zope.i18n.interfaces.IUserPreferredCharsets"
       />
-  
+
   <!-- Register the Translation Domain as a content object -->
   <localUtility class=".translationdomain.TranslationDomain">
     <factory 
-         id="zope.app.i18n.TranslationDomain" 
+         id="zope.app.i18n.TranslationDomain"
          />
-    <allow interface="zope.i18n.interfaces.ITranslationDomain" 
+    <allow interface="zope.i18n.interfaces.ITranslationDomain"
         />
     <require permission="zope.ManageSite"
-        interface="zope.app.container.interfaces.IContainer" 
+        interface="zope.app.container.interfaces.IContainer"
         />
     <require permission="zope.ManageSite"
-        interface=".interfaces.IWriteTranslationDomain" 
+        interface=".interfaces.IWriteTranslationDomain"
         />
     <require permission="zope.ManageSite"
-        interface=".interfaces.ISyncTranslationDomain" 
+        interface=".interfaces.ISyncTranslationDomain"
         />
   </localUtility>
-  
+
   <subscriber
        for=".interfaces.ILocalTranslationDomain
             ..component.interfaces.registration.IRegistrationActivatedEvent"
@@ -46,34 +50,34 @@
        for=".interfaces.ILocalTranslationDomain
             ..component.interfaces.registration.IRegistrationDeactivatedEvent"
        handler=".translationdomain.unsetDomainOnDeactivation"
-       />  
+       />
 
   <!-- Setup Message Catalogs -->
   <content class=".messagecatalog.MessageCatalog">
     <factory id="zope.app.MessageCatalog" />
     <implements 
         interface="zope.app.annotation.interfaces.IAttributeAnnotatable" />
-  
+
     <require permission="zope.View" 
         interface="zope.i18n.interfaces.IMessageCatalog" />
     <require permission="zope.ManageSite"
         attributes="setMessage getMessageIds" />
   </content>
-  
-  
+
+
   <!-- Setup Export and Import Filters -->
   <adapter 
       factory=".filters.GettextExportFilter"
       for=".interfaces.ILocalTranslationDomain"
-      provides="zope.i18n.interfaces.IMessageExportFilter" 
+      provides="zope.i18n.interfaces.IMessageExportFilter"
       />
-  
+
   <adapter 
       factory=".filters.GettextImportFilter"
       for=".interfaces.ILocalTranslationDomain"
-      provides="zope.i18n.interfaces.IMessageImportFilter" 
+      provides="zope.i18n.interfaces.IMessageImportFilter"
       />
-  
+
   <include file="locales.zcml" />
   <include package=".xmlrpc" />
   <include package=".browser" />

Modified: Zope3/branches/hdima-language-namespace/src/zope/app/publisher/browser/__init__.py
===================================================================
--- Zope3/branches/hdima-language-namespace/src/zope/app/publisher/browser/__init__.py	2005-08-07 12:40:19 UTC (rev 37766)
+++ Zope3/branches/hdima-language-namespace/src/zope/app/publisher/browser/__init__.py	2005-08-07 12:49:54 UTC (rev 37767)
@@ -20,10 +20,17 @@
 
 import zope.interface
 from zope.interface import implements, directlyProvidedBy, directlyProvides
+from zope.publisher.browser import BrowserLanguages
+from zope.i18n.interfaces import IModifiableUserPreferredLanguages
+
+from zope.app.annotation import IAnnotations
 from zope.app.location import Location
 from zope.app.publisher.interfaces.browser import IBrowserView
 from zope.publisher.interfaces.browser import ISkin
 
+
+key = "zope.app.publisher.browser.IUserPreferredLanguages"
+
 # TODO: needs testing of __parent__ property
 class BrowserView(Location):
     implements(IBrowserView)
@@ -33,7 +40,7 @@
         self.request = request
 
     def __getParent(self):
-        return hasattr(self, '_parent') and self._parent or self.context
+        return getattr(self, '_parent', self.context)
 
     def __setParent(self, parent):
         self._parent = parent
@@ -90,10 +97,10 @@
     >>> class SkinB(Interface): pass
     >>> directlyProvides(SkinB, ISkin)
     >>> class IRequest(Interface): pass
-    
+
     >>> class Request(object):
     ...     implements(IRequest)
-    
+
     >>> req = Request()
 
     >>> applySkin(req, SkinA)
@@ -113,3 +120,27 @@
     # Add the new skin.
     ifaces.append(skin)
     directlyProvides(request, *ifaces)
+
+class ModifiableBrowserLanguages(BrowserLanguages):
+
+    implements(IModifiableUserPreferredLanguages)
+
+    def setPreferredLanguages(self, languages):
+        languages_data = self._getLanguagesData()
+        languages_data["overridden"] = languages
+
+    def getPreferredLanguages(self):
+        languages_data = self._getLanguagesData()
+        if "overridden" in languages_data:
+            return languages_data["overridden"]
+        elif "cached" not in languages_data:
+            languages_data["cached"] = super(ModifiableBrowserLanguages,
+                self).getPreferredLanguages()
+        return languages_data["cached"]
+
+    def _getLanguagesData(self):
+        annotations = IAnnotations(self.request)
+        languages_data = annotations.get(key)
+        if languages_data is None:
+            annotations[key] = languages_data = {}
+        return languages_data

Added: Zope3/branches/hdima-language-namespace/src/zope/app/publisher/browser/tests/test_browserlanguages.py
===================================================================
--- Zope3/branches/hdima-language-namespace/src/zope/app/publisher/browser/tests/test_browserlanguages.py	2005-08-07 12:40:19 UTC (rev 37766)
+++ Zope3/branches/hdima-language-namespace/src/zope/app/publisher/browser/tests/test_browserlanguages.py	2005-08-07 12:49:54 UTC (rev 37767)
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# 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.
+#
+##############################################################################
+"""Test Modifiable Browser Languages detector
+
+$Id$
+"""
+import unittest
+
+from zope.interface import directlyProvides
+from zope.publisher.tests.test_browserlanguages import BrowserLanguagesTest
+from zope.publisher.tests.test_browserlanguages import TestRequest
+
+from zope.app.testing import ztapi
+from zope.app.testing.placelesssetup import PlacelessSetup
+from zope.app.annotation import IAttributeAnnotatable, IAnnotations
+from zope.app.annotation.attribute import AttributeAnnotations
+from zope.app.publisher.browser import ModifiableBrowserLanguages
+
+
+class ModifiableBrowserLanguagesTests(PlacelessSetup, BrowserLanguagesTest):
+
+    def setUp(self):
+        super(ModifiableBrowserLanguagesTests, self).setUp()
+        ztapi.provideAdapter(IAttributeAnnotatable, IAnnotations,
+            AttributeAnnotations)
+
+    def factory(self, request):
+        directlyProvides(request, IAttributeAnnotatable)
+        return ModifiableBrowserLanguages(request)
+
+    def test_setPreferredLanguages(self):
+        browser_languages = self.factory(TestRequest("da, en, pt"))
+        self.assertEqual(list(browser_languages.getPreferredLanguages()),
+            ["da", "en", "pt"])
+        browser_languages.setPreferredLanguages(["ru", "en"])
+        self.assertEqual(list(browser_languages.getPreferredLanguages()),
+            ["ru", "en"])
+
+    def test_cached_languages(self):
+        request = TestRequest("da, en, pt")
+        browser_languages = self.factory(request)
+        self.assertEqual(list(browser_languages.getPreferredLanguages()),
+            ["da", "en", "pt"])
+        request["HTTP_ACCEPT_LANGUAGE"] = "ru, en"
+        self.assertEqual(list(browser_languages.getPreferredLanguages()),
+            ["da", "en", "pt"])
+
+
+def test_suite():
+    loader=unittest.TestLoader()
+    return loader.loadTestsFromTestCase(ModifiableBrowserLanguagesTests)
+
+if __name__=='__main__':
+    unittest.TextTestRunner().run(test_suite())


Property changes on: Zope3/branches/hdima-language-namespace/src/zope/app/publisher/browser/tests/test_browserlanguages.py
___________________________________________________________________
Name: svn:keywords
   + Id

Modified: Zope3/branches/hdima-language-namespace/src/zope/app/traversing/configure.zcml
===================================================================
--- Zope3/branches/hdima-language-namespace/src/zope/app/traversing/configure.zcml	2005-08-07 12:40:19 UTC (rev 37766)
+++ Zope3/branches/hdima-language-namespace/src/zope/app/traversing/configure.zcml	2005-08-07 12:49:54 UTC (rev 37767)
@@ -1,16 +1,16 @@
 <configure xmlns="http://namespaces.zope.org/zope">
 
-<adapter 
+<adapter
     for="*"
     factory="zope.app.traversing.adapters.Traverser"
     provides="zope.app.traversing.interfaces.ITraverser" />
 
-<adapter 
+<adapter
     for="*"
     factory="zope.app.traversing.adapters.DefaultTraversable"
     provides="zope.app.traversing.interfaces.ITraversable" />
 
-<adapter 
+<adapter
     provides="zope.app.traversing.interfaces.IPhysicallyLocatable"
     for="zope.app.traversing.interfaces.IContainmentRoot"
     factory="zope.app.traversing.adapters.RootPhysicallyLocatable" />
@@ -18,89 +18,100 @@
 <adapter
     name="etc"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.etc" 
+    factory="zope.app.traversing.namespace.etc"
     />
 <view
     name="etc"
     type="zope.interface.Interface"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.etc" 
+    factory="zope.app.traversing.namespace.etc"
     />
 
 <adapter
     name="attribute"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.attr" 
+    factory="zope.app.traversing.namespace.attr"
     />
 <view
     name="attribute"
     type="zope.interface.Interface"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.attr" 
+    factory="zope.app.traversing.namespace.attr"
     />
 
 <adapter
     name="adapter"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.adapter" 
+    factory="zope.app.traversing.namespace.adapter"
     />
 <view
     name="adapter"
     type="zope.interface.Interface"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.adapter" 
+    factory="zope.app.traversing.namespace.adapter"
     />
 
 <adapter
     name="item"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.item" 
+    factory="zope.app.traversing.namespace.item"
     />
 <view
     name="item" type="*"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.item" 
+    factory="zope.app.traversing.namespace.item"
     />
 
 <adapter
     name="acquire"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.acquire" 
+    factory="zope.app.traversing.namespace.acquire"
     />
 <view
     name="acquire" type="*"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.acquire" 
+    factory="zope.app.traversing.namespace.acquire"
     />
 
 <view
     name="view" type="*"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.view" 
+    factory="zope.app.traversing.namespace.view"
     />
 
 <view
     name="resource" type="*"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.resource" 
+    factory="zope.app.traversing.namespace.resource"
     />
 
+<adapter
+    name="language"
+    provides="zope.app.traversing.interfaces.ITraversable" for="*"
+    factory="zope.app.traversing.namespace.language"
+    />
 <view
+    name="language" type="*"
+    provides="zope.app.traversing.interfaces.ITraversable" for="*"
+    factory="zope.app.traversing.namespace.language"
+    />
+
+<view
     name="skin" type="*"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.skin" 
+    factory="zope.app.traversing.namespace.skin"
     />
 
 <view
     name="vh" type="*"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.vh" 
+    factory="zope.app.traversing.namespace.vh"
     />
 
 <view
     name="debug" type="*"
     provides="zope.app.traversing.interfaces.ITraversable" for="*"
-    factory="zope.app.traversing.namespace.debug" 
+    factory="zope.app.traversing.namespace.debug"
     />
 
 </configure>

Modified: Zope3/branches/hdima-language-namespace/src/zope/app/traversing/namespace.py
===================================================================
--- Zope3/branches/hdima-language-namespace/src/zope/app/traversing/namespace.py	2005-08-07 12:40:19 UTC (rev 37766)
+++ Zope3/branches/hdima-language-namespace/src/zope/app/traversing/namespace.py	2005-08-07 12:49:54 UTC (rev 37767)
@@ -20,6 +20,7 @@
 import zope.deprecation
 import zope.component
 import zope.interface
+from zope.i18n.interfaces import IModifiableUserPreferredLanguages
 from zope.component.exceptions import ComponentLookupError
 from zope.interface import providedBy, directlyProvides, directlyProvidedBy
 from zope.publisher.interfaces.browser import ISkin
@@ -36,6 +37,7 @@
 
 import warnings
 
+
 class UnexpectedParameters(TraversalError):
     "Unexpected namespace parameters were provided."
 
@@ -346,8 +348,8 @@
             return method()
         except ComponentLookupError:
             raise TraversalError(ob, name)
-            
 
+
 class view(object):
 
     zope.interface.implements(ITraversable)
@@ -371,6 +373,14 @@
         # resource, which is needed to generate the absolute URL.
         return getResource(self.context, name, self.request)
 
+class language(view):
+
+    def traverse(self, name, ignored):
+        self.request.shiftNameToApplication()
+        languages = IModifiableUserPreferredLanguages(self.request)
+        languages.setPreferredLanguages([name])
+        return self.context
+
 class skin(view):
 
     def traverse(self, name, ignored):
@@ -588,5 +598,3 @@
             ...
             ValueError: Debug flags only allowed in debug mode
         """
-
-        

Modified: Zope3/branches/hdima-language-namespace/src/zope/i18n/interfaces/__init__.py
===================================================================
--- Zope3/branches/hdima-language-namespace/src/zope/i18n/interfaces/__init__.py	2005-08-07 12:40:19 UTC (rev 37766)
+++ Zope3/branches/hdima-language-namespace/src/zope/i18n/interfaces/__init__.py	2005-08-07 12:49:54 UTC (rev 37767)
@@ -202,7 +202,16 @@
         languages first.
         """
 
+class IModifiableUserPreferredLanguages(IUserPreferredLanguages):
 
+    def setPreferredLanguages(languages):
+        """Set a sequence of user preferred languages.
+
+        The sequence should be sorted in order of quality, with the most
+        preferred languages first.
+        """
+
+
 class IMessageExportFilter(Interface):
     """The Export Filter for Translation Service Messages.
 
@@ -394,5 +403,3 @@
 
     calendar = Attribute("""This object must implement ILocaleCalendar. See
                             this interface's documentation for details.""")
-
-

Modified: Zope3/branches/hdima-language-namespace/src/zope/publisher/browser.py
===================================================================
--- Zope3/branches/hdima-language-namespace/src/zope/publisher/browser.py	2005-08-07 12:40:19 UTC (rev 37766)
+++ Zope3/branches/hdima-language-namespace/src/zope/publisher/browser.py	2005-08-07 12:49:54 UTC (rev 37767)
@@ -202,12 +202,13 @@
     implements(IBrowserRequest, IBrowserApplicationRequest)
 
     __slots__ = (
-        '__provides__',      # Allow request to directly provide interfaces
-        'form',   # Form data
+        '__provides__', # Allow request to directly provide interfaces
+        'form', # Form data
         'charsets', # helper attribute
         '__meth',
         '__tuple_items',
         '__defaults',
+        '__annotations__',
         )
 
     # Set this to True in a subclass to redirect GET requests when the

Modified: Zope3/branches/hdima-language-namespace/src/zope/publisher/http.py
===================================================================
--- Zope3/branches/hdima-language-namespace/src/zope/publisher/http.py	2005-08-07 12:40:19 UTC (rev 37766)
+++ Zope3/branches/hdima-language-namespace/src/zope/publisher/http.py	2005-08-07 12:49:54 UTC (rev 37767)
@@ -230,6 +230,7 @@
         'method',         # The upper-cased request method (REQUEST_METHOD)
         '_locale',        # The locale for the request
         '_vh_root',       # Object at the root of the virtual host
+        '__annotations__',
         )
 
     retry_max_count = 3    # How many times we're willing to retry
@@ -809,7 +810,7 @@
                 status=302
             else:
                 status=303
-                
+
         self.setStatus(status)
         self.setHeader('Location', location)
         return location
@@ -897,7 +898,7 @@
 
     def output(self, data):
         """Output the data to the world.
-        
+
         There are a couple of steps we have to do:
 
         1. Check that there is a character encoding for the data. If not,
@@ -921,7 +922,7 @@
         if self.getHeader('content-type', '').startswith('text'):
             data = self._encode(data)
             self._updateContentLength(data)
-        
+
         if (not ('content-length' in self._headers)
             and not ('transfer-encoding' in self._headers)):
             self._updateContentLength()

Modified: Zope3/branches/hdima-language-namespace/src/zope/publisher/tests/test_browserlanguages.py
===================================================================
--- Zope3/branches/hdima-language-namespace/src/zope/publisher/tests/test_browserlanguages.py	2005-08-07 12:40:19 UTC (rev 37766)
+++ Zope3/branches/hdima-language-namespace/src/zope/publisher/tests/test_browserlanguages.py	2005-08-07 12:49:54 UTC (rev 37767)
@@ -17,6 +17,9 @@
 """
 import unittest
 
+from zope.publisher.browser import BrowserLanguages
+
+
 # Note: The expected output is in order of preference,
 # empty 'q=' means 'q=1', and if theres more than one
 # empty, we assume they are in order of preference.
@@ -29,17 +32,24 @@
     ('ro,en-us;q=0,es;q=0.5,fr;q=0,ru;q=1,it', ['ro', 'ru', 'it', 'es'])
     ]
 
+class TestRequest(dict):
 
+    def __init__(self, languages):
+        self["HTTP_ACCEPT_LANGUAGE"] = languages
+
 class BrowserLanguagesTest(unittest.TestCase):
 
+    def factory(self, request):
+        return BrowserLanguages(request)
+
     def test_browser_language_handling(self):
-        from zope.publisher.browser import BrowserLanguages
         for req, expected in data:
-            request = {'HTTP_ACCEPT_LANGUAGE': req}
-            browser_languages = BrowserLanguages(request)
+            request = TestRequest(req)
+            browser_languages = self.factory(request)
             self.assertEqual(list(browser_languages.getPreferredLanguages()),
                              expected)
 
+
 def test_suite():
     loader=unittest.TestLoader()
     return loader.loadTestsFromTestCase(BrowserLanguagesTest)


Property changes on: Zope3/branches/hdima-language-namespace/src/zope/publisher/tests/test_browserlanguages.py
___________________________________________________________________
Name: svn:keywords
   + Id



More information about the Zope3-Checkins mailing list