Commit e261e629 authored by Hanno Schlichting's avatar Hanno Schlichting

Switched Products.PageTemplates to directly use zope.i18n.translate and...

Switched Products.PageTemplates to directly use zope.i18n.translate and removed the now obsolete GlobalTranslationService hook.
parent c6ffc44a
......@@ -23,6 +23,9 @@ Known issues
Restructuring
+++++++++++++
- Switched Products.PageTemplates to directly use zope.i18n.translate and
removed the GlobalTranslationService hook.
- Removed bridging code from Product.Five for PlacelessTranslationService
and Localizer. Neither of the two is actually using this anymore.
......
......@@ -4,14 +4,6 @@ Internationalization
Translation
-----------
Five registers its own translation service mockup with the Page
Templates machinery and prevents any other product from also doing so.
That means, Five always assumes control over ZPT i18n. When a certain
domain has not been registered the Zope 3 way, Five's translation
service will see that the utility lookup fails and use the next
available fallback translation service. In case of no other
translation service installed, that is just a dummy fallback.
To register Zope 3 style translation domains, use the following ZCML
statement::
......
##############################################################################
#
# Copyright (c) 2005 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.
#
##############################################################################
"""Mimick Zope3 i18n machinery for Zope 2
$Id$
"""
from Acquisition import aq_get
from zope.i18n.interfaces import IFallbackTranslationDomainFactory
from zope.i18n.interfaces import ITranslationDomain
from zope.component import queryUtility
from zope.i18nmessageid import Message
from zope.publisher.interfaces.browser import IBrowserRequest
class FiveTranslationService:
"""Translation service that delegates to ``zope.i18n`` machinery.
"""
# this is mostly a copy of zope.i18n.translate, with modifications
# regarding fallback and Zope 2 compatability
def translate(self, domain, msgid, mapping=None,
context=None, target_language=None, default=None):
if isinstance(msgid, Message):
domain = msgid.domain
default = msgid.default
mapping = msgid.mapping
if default is None:
default = unicode(msgid)
if domain:
util = queryUtility(ITranslationDomain, domain)
if util is None:
util = queryUtility(IFallbackTranslationDomainFactory)
if util is not None:
util = util(domain)
else:
util = queryUtility(IFallbackTranslationDomainFactory)
if util is not None:
util = util()
if util is None:
# fallback to translation service that was registered,
# DummyTranslationService the worst
ts = _fallback_translation_service
return ts.translate(domain, msgid, mapping=mapping, context=context,
target_language=target_language, default=default)
# in Zope3, context is adapted to IUserPreferredLanguages,
# which means context should be the request in this case.
# Do not attempt to acquire REQUEST from the context, when we already
# got a request as the context
if context is not None:
if not IBrowserRequest.providedBy(context):
context = aq_get(context, 'REQUEST', None)
return util.translate(msgid, mapping=mapping, context=context,
target_language=target_language, default=default)
# Hook that will be used by Products.PageTemplates.GlobalTranslationService
_fallback_translation_service = None
......@@ -53,37 +53,6 @@ def test_directive():
u'Dies ist eine explizite Nachricht'
"""
def test_FiveTranslationService():
"""
Test FiveTranslationService. First we need the GlobalTranslationService:
>>> from Products.PageTemplates import GlobalTranslationService
>>> GTS = GlobalTranslationService.getGlobalTranslationService()
Now, take an arbitrary message id from an arbitrary domain:
>>> from zope.i18nmessageid import MessageFactory
>>> from zope.i18n import translate
>>> _ = MessageFactory('random')
>>> msg = _(u'explicit-msg', u'This is an explicit message')
By default, the i18n message is translated by the DummyTranslationService:
>>> GTS.translate('default', msg, target_language='test')
u'This is an explicit message'
Now, register the TestMessageFallbackDomain:
>>> from zope.component import provideUtility
>>> from zope.i18n.testmessagecatalog import TestMessageFallbackDomain
>>> provideUtility(TestMessageFallbackDomain)
The i18n message is now translated by the TestMessageFallbackDomain:
>>> GTS.translate('default', msg, target_language='test')
u'[[random][explicit-msg (This is an explicit message)]]'
"""
def test_suite():
from zope.testing.doctest import DocTestSuite
......
......@@ -21,6 +21,7 @@ $Id$
import logging
from zope.component import queryUtility
from zope.i18n import translate
from zope.interface import implements
from zope.tales.tales import Context
from zope.tales.tales import ErrorInfo as BaseErrorInfo
......@@ -41,7 +42,6 @@ from zExceptions import NotFound, Unauthorized
from zope.contentprovider.tales import TALESProviderExpression
from Products.PageTemplates import ZRPythonExpr
from Products.PageTemplates.DeferExpr import LazyExpr
from Products.PageTemplates.GlobalTranslationService import getGlobalTranslationService
from Products.PageTemplates.interfaces import IUnicodeEncodingConflictResolver
SecureModuleImporter = ZRPythonExpr._SecureModuleImporter()
......@@ -169,9 +169,9 @@ class ZopeContext(Context):
self._vars_stack = [vars]
def translate(self, msgid, domain=None, mapping=None, default=None):
context = self.contexts.get('context')
return getGlobalTranslationService().translate(
domain, msgid, mapping=mapping,
context = self.contexts.get('request')
return translate(
msgid, domain=domain, mapping=mapping,
context=context, default=default)
def evaluateBoolean(self, expr):
......
##############################################################################
#
# Copyright (c) 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.
#
##############################################################################
"""Global Translation Service for providing I18n to Page Templates.
$Id$
"""
import re
import Products.Five.i18n
from DocumentTemplate.DT_Util import ustr
from zope.tal.taldefs import NAME_RE
class DummyTranslationService:
"""Translation service that doesn't know anything about translation."""
def translate(self, domain, msgid, mapping=None,
context=None, target_language=None, default=None):
def repl(m, mapping=mapping):
return ustr(mapping[m.group(m.lastindex)])
cre = re.compile(r'\$(?:(%s)|\{(%s)\})' % (NAME_RE, NAME_RE))
return cre.sub(repl, default or msgid)
#
# As of Five 1.1, we're by default using Zope 3 Message Catalogs for
# translation, but we allow fallback translation services such as PTS
# and Localizer
#
# TODO We should really deprecate Zope2-style translation service and
# only support Zope3-style i18n in the future.
#
Products.Five.i18n._fallback_translation_service = DummyTranslationService()
fiveTranslationService = Products.Five.i18n.FiveTranslationService()
def getGlobalTranslationService():
return fiveTranslationService
def setGlobalTranslationService(newservice):
oldservice, Products.Five.i18n._fallback_translation_service = \
Products.Five.i18n._fallback_translation_service, newservice
return oldservice
<html>
<body>
<head>
<p i18n:domain="foo" i18n:translate="bar">baz</p>
<a href="foo" alt="alttext" i18n:attributes="alt">link</a>
<p i18n:domain="dom" i18n:translate="">
<span tal:replace="string:Lomax" i18n:name="name" /> was born in
<span tal:replace="string:Antarctica" i18n:name="country" />.
</p>
<p i18n:translate="hmm">
I'm <span tal:replace="python:25" i18n:name="age">Age</span>
</p>
</head>
</body>
</html>
<html>
<body>
<head>
<p>[foo](bar/{})</p>
<a href="foo" alt="[default](alttext/{})">link</a>
<p>[dom](${name} was born in ${country}./{'country':u'Antarctica','name':u'Lomax'})</p>
<p>[default](hmm/{'age':u'25'})</p>
</head>
</body>
</html>
......@@ -18,8 +18,6 @@ from zope.component import provideUtility
from zope.traversing.adapters import DefaultTraversable
from Products.PageTemplates.tests import util
from Products.PageTemplates.PageTemplate import PageTemplate
from Products.PageTemplates.GlobalTranslationService import \
setGlobalTranslationService
from Products.PageTemplates.interfaces import IUnicodeEncodingConflictResolver
from Products.PageTemplates.unicodeconflictresolver import DefaultUnicodeEncodingConflictResolver
from AccessControl import SecurityManager
......@@ -32,16 +30,6 @@ class AqPageTemplate(Implicit, PageTemplate):
class Folder(util.Base):
pass
class TestTranslationService:
def translate(self, domain, msgid, mapping=None, *args, **kw):
maps = []
if mapping is not None:
# Get a deterministic, sorted representation of dicts.
for k, v in mapping.items():
maps.append('%s:%s' % (`k`, `v`))
maps.sort()
return "[%s](%s/{%s})" % (domain, msgid, ','.join(maps))
class UnitTestSecurityPolicy:
"""
......@@ -162,11 +150,6 @@ class HTMLTests(zope.component.testing.PlacelessSetup, unittest.TestCase):
def checkI18nTranslate(self):
self.assert_expected(self.folder.t, 'CheckI18nTranslate.html')
def checkI18nTranslateHooked(self):
old_ts = setGlobalTranslationService(TestTranslationService())
self.assert_expected(self.folder.t, 'CheckI18nTranslateHooked.html')
setGlobalTranslationService(old_ts)
def checkImportOldStyleClass(self):
self.assert_expected(self.folder.t, 'CheckImportOldStyleClass.html')
......@@ -181,7 +164,3 @@ class HTMLTests(zope.component.testing.PlacelessSetup, unittest.TestCase):
def test_suite():
return unittest.makeSuite(HTMLTests, 'check')
if __name__=='__main__':
main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment