[Zope-Checkins] CVS: Zope3/lib/python/Zope/I18n - Domain.py:1.1.2.1 IDomain.py:1.1.2.1 MessageCatalog.py:1.1.2.1 Translate.py:1.1.2.1 TranslationService.py:1.1.2.1 IMessageCatalog.py:1.1.2.9 INegotiator.py:1.1.2.4 ITranslationService.py:1.1.2.5 Negotiator.py:1.1.2.6 i18n.zcml:1.1.2.2 IInterpolationVariable.py:NONE
Stephan Richter
srichter@cbu.edu
Wed, 5 Jun 2002 14:48:51 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/I18n
In directory cvs.zope.org:/tmp/cvs-serv4962
Modified Files:
Tag: Zope-3x-branch
IMessageCatalog.py INegotiator.py ITranslationService.py
Negotiator.py i18n.zcml
Added Files:
Tag: Zope-3x-branch
Domain.py IDomain.py MessageCatalog.py Translate.py
TranslationService.py
Removed Files:
Tag: Zope-3x-branch
IInterpolationVariable.py
Log Message:
First couple things for I18n. More coming soon. Not much is working, but
Fred and Barry would like to have the luxury to look at code. I will write
the real checkin message when it is done and working.
=== Added File Zope3/lib/python/Zope/I18n/Domain.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""
$Id: Domain.py,v 1.1.2.1 2002/06/05 18:48:50 srichter Exp $
"""
=== Added File Zope3/lib/python/Zope/I18n/IDomain.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""
$Id: IDomain.py,v 1.1.2.1 2002/06/05 18:48:50 srichter Exp $
"""
from Interface import Interface
class IDomain(Interface):
"""Since it is often tedious to always specify a domain and place for a
particular translation, the idea of a Domain object was created, which
allows to save the place and domain for a set of translations.
Usage:
domain = Domain(self, 'MyProduct')
domain.translate('MyProductTitle', context)
Constructor Arguments:
place -- A location where the Domain should look for the translation
service.
domain -- Secifies the domain to look up for the translation. See
ITranslationService for more details on domains."""
def translate(source, mapping=None, context=None, target_language=None):
"""Translate the the source to its appropriate language. See
ITranslationService for details."""
=== Added File Zope3/lib/python/Zope/I18n/MessageCatalog.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""A simple implementation of a Message Catalog.
$Id: MessageCatalog.py,v 1.1.2.1 2002/06/05 18:48:50 srichter Exp $
"""
from Zope.I18n.IMessageCatalog import IMessageCatalog
class MessageCatalog:
__implements__ = IMessageCatalog
def __init__(self, language, domain="global"):
"""Initialize the message catalog"""
self._language = language
self._domain = domain
self._messages = {}
def setMessage(self, id, message):
"""Set a message to the catalog."""
self._messages[id] = message
############################################################
# Implementation methods for interface
# Zope.I18n.IMessageCatalog.
def getMessage(self, id):
'See Zope.I18n.IMessageCatalog.IMessageCatalog'
return self._messages[id]
def queryMessage(self, id, default=None):
'See Zope.I18n.IMessageCatalog.IMessageCatalog'
if default is None:
default = id
return self._messages.get(id, default)
def getLanguage(self):
'See Zope.I18n.IMessageCatalog.IMessageCatalog'
return self._language
def getDomain(self):
'See Zope.I18n.IMessageCatalog.IMessageCatalog'
return self._domain
def getIdentifier(self):
'See Zope.I18n.IMessageCatalog.IMessageCatalog'
return (self._language, self._domain)
#
############################################################
=== Added File Zope3/lib/python/Zope/I18n/Translate.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""
$Id: Translate.py,v 1.1.2.1 2002/06/05 18:48:50 srichter Exp $
"""
def translate(place, domain, source, mapping=None, context=None,
target_language=None):
"""Translates a source text based on a location in the Zope architecture
and a domain."""
# Lookup service...
service = None
return service.translate(domain, source, mapping, context,
target_language):
=== Added File Zope3/lib/python/Zope/I18n/TranslationService.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""
$Id: TranslationService.py,v 1.1.2.1 2002/06/05 18:48:50 srichter Exp $
"""
import re
from types import StringTypes, TupleType
import Persistence
from Persistence.BTrees.OOBTree import OOBTree
from Zope.App.OFS.Container.BTreeContainer import BTreeContainer
from IMessageCatalog import IMessageCatalog
from ITranslationService import ITranslationService
from Zope.App.OFS.Container.IContainer import IContainer
NAME_RE = r"[a-zA-Z][a-zA-Z0-9_]*"
_interp_regex = re.compile(r'(?<!\$)(\$(?:%(n)s|{%(n)s}))' %({'n': NAME_RE}))
_get_var_regex = re.compile(r'%(n)s' %({'n': NAME_RE}))
class ILocalTranslationService(ITranslationService, IContainer):
"""TTW manageable translation service"""
class TranslationService(BTreeContainer):
''' '''
__implements__ = ILocalTranslationService
def __init__(self, default_domain='global'):
''' '''
self.__data = OOBTree()
self._catalogs = OOBTree()
def _registerMessageCatalog(self, language, domain, catalog_name):
''' '''
if (language, domain) not in self._catalogs.keys():
self._catalogs[(language, domain)] = []
mc = self._catalogs[(language, domain)]
mc.append(catalog_name)
def _unregisterMessageCatalog(self, language, domain, catalog_name):
''' '''
mc = self._catalogs.get((language, domain), [])
mc.append(catalog_name)
############################################################
# Implementation methods for interface
# Zope.App.OFS.Container.IContainer.IWriteContainer
def setObject(self, name, object):
'See Zope.App.OFS.Container.IContainer.IWriteContainer'
if type(name) in StringTypes and len(name)==0:
raise ValueError
if not self.isAddable(getattr(object,'__implements__', None)):
raise UnaddableError (self, object, name)
self.__data[name] = object
self._registerMessageCatalog(object.getLanguage(), object.getDomain(),
name)
def delObject(self, name):
'See Zope.App.OFS.Container.IContainer.IWriteContainer'
del self.__data[name]
self._unregisterMessageCatalog(object.language, object.domain, name)
def isAddable(self, interfaces):
'See Zope.App.OFS.Container.IContainer.IWriteContainer'
if type(interfaces) != TupleType:
interfaces = (interfaces,)
if IMessageCatalog in interfaces:
return 1
return 0
#
############################################################
############################################################
# Implementation methods for interface
# Zope.I18n.ITranslationService.
def translate(self, domain, source, mapping=None, context=None,
target_language=None):
'''See interface ITranslationService'''
if domain is None:
domain = self.default_domain
if target_language is None:
if context is None:
raise TypeError, 'No destination language'
else:
target_language = context['language']
# Get the translation. Default is the source text itself.
text = self.__data.get((target_language, domain), {}
).get(source, source)
# Now we need to do the interpolation
return self.interpolate(text, mapping)
#
############################################################
def interpolate(self, text, mapping):
"""Insert the data passed from mapping into the text"""
to_replace = _interp_regex.findall(text)
for string in to_replace:
var = _get_var_regex.findall(string)[0]
text = text.replace(string, mapping.get(var))
return text
=== Zope3/lib/python/Zope/I18n/IMessageCatalog.py 1.1.2.8 => 1.1.2.9 ===
"""Translation Service
- This interface provides a method for translating text, including
- text with interpolation.
+ This interface provides a method for translating a message or message id,
+ including text with interpolation. The message catalog basically serves as
+ a fairly simple mapping object.
- When we refer to text here, we mean text that follows the standard
- Zope 3 text representation (tbd).
- """
-
- def translateSequence(source_sequence, object, context=None,
- destination_language_tag=None):
- """Translate a source sequence that represents text with interpolation
-
- The source sequence is translated for an object, which
- provides a place setting language negotiation policies, and a
- context, which represents a client, such as a web browser,
- with which there are language preferences.
+ A single Message Catalog represents a particular language and
+ domain. Therefore you will have the following constructor arguments:
- The source sequence is a sequence of text and IVariable
- object. The IVariable objects define interpolation names for
- data to be interpolated during or after translation.
+ language -- The language of the returning language. This is a read-only
+ attribute.
- Optional arguments:
+ domain -- The translation domain for this messages. This is a read-only
+ attribute. See ITranslationService.
- destination_language_tag -- The language tag of the langauge
- to translate to.
-
- context -- An object that provides contextual information for
- determining client language preferences. It must
- implement or have an adapter that implements
- IUserPreferedLanguages.
-
- Note that one of destination_language or context must be
- passed. Otherwise a TypeError will be raised.
-
- Also note that languages tags are defined by RFC 1766.
+ When we refer to text here, we mean text that follows the standard
+ Zope 3 text representation.
+ """
- A sequence is returned including translated text and IVariable
- objects.
+ def getMessage(id):
+ """Return the appropriate text for the given id. As all get methods,
+ this will raise an error, if the id is not found
"""
+ def queryMessage(id, default=None):
+ """Return the appropriate test for the given id, but if the id is not
+ found, it should not raise an error, instead returning default. If
+ default is None, then the id itself is returned.
+ """
+
+ def getLanguage():
+ """Return the langauge this message catalog is representing.
+ """
+
+ def getDomain():
+ """Return the domain this message catalog is serving.
+ """
-
-
-
+ def getIdentifier():
+ """Return a identifier for this message catalog. Note that this
+ identifier does not have to be unique as several message catalog
+ could serve the same domain and language.
+ """
=== Zope3/lib/python/Zope/I18n/INegotiator.py 1.1.2.3 => 1.1.2.4 ===
"""
- def getLanguage(user_languages, env):
-
+ def getLanguage(object_langs, env):
"""getLanguage implements a decision making algorithm to decide
what language should be used based on the available languages
for an object and a list of user prefered languages.
Arguments:
- user_languages -- sequence of languages (not necessarily ordered)
+ object_langs -- sequence of languages (not necessarily ordered)
env -- environment passed to the service to determine a sequence
of user prefered languages
=== Zope3/lib/python/Zope/I18n/ITranslationService.py 1.1.2.4 => 1.1.2.5 ===
When we refer to text here, we mean text that follows the standard
- Zope 3 text representation (tbd).
+ Zope 3 text representation.
Standard arguments:
- destination_language_tag -- The language tag of the langauge
- to translate to.
+ domain -- The domain is used to specify which translation to use.
+ Different products will often use a specific domain naming
+ translations supplied with the product.
+ Stephan's (my) favorite example is: How do you translate
+ "Sun"? Is it our star, the abbreviation of Sunday or the
+ company? Specifying the domain, such as "Stars" will solve
+ this problem for us.
+
+ source -- The source message or message id that should be translated.
+
+ mapping -- The object to get the interpolation data from.
+
+ target_language -- The language to translate to.
context -- An object that provides contextual information for
determining client language preferences. It must
@@ -41,38 +52,26 @@
Note that one of destination_language or context must be
passed. Otherwise a TypeError will be raised.
- Also note that languages tags are defined by RFC 1766.
-
- domain -- The domain is used to specify which translation to use.
- Different products will often use a specific domain naming
- translations supplied with the product.
+ Also note that language tags are defined by RFC 1766.
"""
- def translateSequence(source_sequence, domain,
- context=None,
- destination_language_tag=None,
- data=None):
- """Translate a source sequence that represents text with interpolation
-
- The source sequence is a sequence of text and IVariable
- object. The IVariable objects define interpolation names for
- data to be interpolated during or after translation.
-
- A data mapping may be passed with keys for the values to be
- interpolated. Extra keys are ignored. If any interpolation
- names defined in the message don't have a key in the data
- dictionary, then IVariable objects will be included in the
- output for those names.
-
- A sequence is returned including translated text and IVariable
- objects for any interpolated names not supplied in the data
- mapping.
+
+ def translate(domain, source, mapping=None,
+ context=None, target_language=None):
+ """Translate source text. Translated text is returned.
+
+ However, the method does a little more than a vanilla
+ translation. The method also looks for a possible language to
+ translate to.
+ After a translation it also replaces any variables inside the
+
+ Note: The TranslationService interface does not support simplified
+ translation methods, since it is totally hidden by ZPT and in
+ Python you should use a Domain object, since it supports all
+ the simplifications.
"""
- def translate(source_text, domain,
- context=None,
- destination_language_tag=None):
- """Translate source text
- Translated text is returned.
- """
+ def getDomain(domain):
+ """Get the domain for the passed domain name"""
+
=== Zope3/lib/python/Zope/I18n/Negotiator.py 1.1.2.5 => 1.1.2.6 ===
=== Zope3/lib/python/Zope/I18n/i18n.zcml 1.1.2.1 => 1.1.2.2 ===
xmlns:zmi='http://namespaces.zope.org/zmi'
xmlns:browser='http://namespaces.zope.org/browser'
+ xmlns:service='http://namespaces.zope.org/service'
>
<serviceType name="LanguageNegotiation"
@@ -16,5 +17,30 @@
provides="Zope.I18n.IUserPreferedLanguages"
/>
-->
+
+
+<security:protectClass class=".TranslationService.">
+ <security:protect interface="Zope.I18n.ITranslationService."
+ permission_id="Zope.I18n" />
+ <security:protect interface="Zope.App.OFS.Container.IContainer."
+ permission_id="Zope.ManageServices" />
+</security:protectClass>
+
+<security:protectClass class=".MessageCatalog.">
+ <security:protect interface="Zope.App.Security.IMessageCatalog."
+ permission_id="Zope.Security" />
+</security:protectClass>
+
+
+<service:factoryFromClass name="TranslationService"
+ class=".TranslationService."
+ permission_id="Zope.ManageServices"
+ title="Translation Service" />
+
+<factory component=".MessageCatalog." />
+
+<include package=".Views" file="views.zcml" />
+
+
</zopeConfigure>
=== Removed File Zope3/lib/python/Zope/I18n/IInterpolationVariable.py ===