Localizer: Integrate old monkey-patches directly

Also, use local imports of itools where this is still necessary,  and remove all mention of itools from ERP5 code.
parent 526cafce
...@@ -1111,8 +1111,7 @@ class ActivityTool (Folder, UniqueObject): ...@@ -1111,8 +1111,7 @@ class ActivityTool (Folder, UniqueObject):
# runing unit tests. Recreate it if it does not exist. # runing unit tests. Recreate it if it does not exist.
if getattr(request.other, 'PARENTS', None) is None: if getattr(request.other, 'PARENTS', None) is None:
request.other['PARENTS'] = parents request.other['PARENTS'] = parents
# XXX: itools (used by Localizer) requires PATH_INFO to be set, and it's # XXX: PATH_INFO might not be set when runing unit tests.
# not when runing unit tests. Recreate it if it does not exist.
if request.environ.get('PATH_INFO') is None: if request.environ.get('PATH_INFO') is None:
request.environ['PATH_INFO'] = '/Control_Panel/timer_service/process_timer' request.environ['PATH_INFO'] = '/Control_Panel/timer_service/process_timer'
......
...@@ -268,7 +268,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin): ...@@ -268,7 +268,7 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
def _doTranslationDomainRegistration(self): def _doTranslationDomainRegistration(self):
from zope.i18n.interfaces import ITranslationDomain from zope.i18n.interfaces import ITranslationDomain
from Products.ERP5Type.patches.Localizer import ( from Products.Localizer.MessageCatalog import (
message_catalog_alias_sources message_catalog_alias_sources
) )
sm = self.getSiteManager() sm = self.getSiteManager()
......
...@@ -44,8 +44,6 @@ from Products.ERP5Type.patches import ActionInformation ...@@ -44,8 +44,6 @@ from Products.ERP5Type.patches import ActionInformation
from Products.ERP5Type.patches import ActionProviderBase from Products.ERP5Type.patches import ActionProviderBase
from Products.ERP5Type.patches import ActionsTool from Products.ERP5Type.patches import ActionsTool
from Products.ERP5Type.patches import CookieCrumbler from Products.ERP5Type.patches import CookieCrumbler
from Products.ERP5Type.patches import i18n
from Products.ERP5Type.patches import Localizer
from Products.ERP5Type.patches import PropertySheets from Products.ERP5Type.patches import PropertySheets
from Products.ERP5Type.patches import CMFCoreSkinnable from Products.ERP5Type.patches import CMFCoreSkinnable
from Products.ERP5Type.patches import CMFCoreSkinsTool from Products.ERP5Type.patches import CMFCoreSkinsTool
......
This diff is collapsed.
##############################################################################
#
# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
# allow access to AcceptLanguage for itools 0.16.2 or later
from itools.i18n.accept import AcceptLanguage
if getattr(AcceptLanguage, '__allow_access_to_unprotected_subobjects__',
None) is None:
AcceptLanguage.__allow_access_to_unprotected_subobjects__ = 1
del AcceptLanguage
...@@ -53,12 +53,6 @@ Globals.get_request = get_request ...@@ -53,12 +53,6 @@ Globals.get_request = get_request
from zope.site.hooks import setSite from zope.site.hooks import setSite
try:
import itools.zope
itools.zope.get_context = get_context
except ImportError:
pass
from Testing import ZopeTestCase from Testing import ZopeTestCase
from Testing.ZopeTestCase import PortalTestCase, user_name from Testing.ZopeTestCase import PortalTestCase, user_name
from Products.CMFCore.utils import getToolByName from Products.CMFCore.utils import getToolByName
......
# -*- coding: UTF-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2000-2004 Juan David Ibáñez Palomar <jdavid@itaapy.com> # Copyright (C) 2000-2004 Juan David Ibáñez Palomar <jdavid@itaapy.com>
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
from urlparse import urlparse from urlparse import urlparse
# Import from itools # Import from itools
from itools.i18n import get_language_name, get_languages from .itools.i18n import get_language_name, get_languages
# Import from Zope # Import from Zope
from App.class_init import InitializeClass from App.class_init import InitializeClass
...@@ -60,8 +60,11 @@ class LanguageManager(Tabs): ...@@ -60,8 +60,11 @@ class LanguageManager(Tabs):
"""Adds a new language. """Adds a new language.
""" """
if language not in self._languages: if language not in self._languages:
self._languages = tuple(self._languages) + (language,) # Sort the language list, else selected languages
# can be nearly random.
new_language_list = tuple(self._languages) + (language,)
new_language_list = tuple(sorted(new_language_list))
self._languages = new_language_list
def del_language(self, language): def del_language(self, language):
"""Removes a language. """Removes a language.
...@@ -77,7 +80,7 @@ class LanguageManager(Tabs): ...@@ -77,7 +80,7 @@ class LanguageManager(Tabs):
that tells wether the language is the default one or not. that tells wether the language is the default one or not.
""" """
return [ {'code': x, return [ {'code': x,
'name': get_language_name(x), 'name': self.get_language_name(x),
'default': x == self._default_language} 'default': x == self._default_language}
for x in self._languages ] for x in self._languages ]
...@@ -127,7 +130,11 @@ class LanguageManager(Tabs): ...@@ -127,7 +130,11 @@ class LanguageManager(Tabs):
""" """
if id is None: if id is None:
id = self.get_default_language() id = self.get_default_language()
return get_language_name(id) language_name = get_language_name(id)
if language_name=='???':
return self.get_user_defined_language_name(id) or language_name
else:
return language_name
security.declarePublic('get_available_languages') security.declarePublic('get_available_languages')
...@@ -188,7 +195,7 @@ class LanguageManager(Tabs): ...@@ -188,7 +195,7 @@ class LanguageManager(Tabs):
""" """
Returns all ISO languages, used by 'manage_languages'. Returns all ISO languages, used by 'manage_languages'.
""" """
return get_languages() return get_languages() + self.get_user_defined_languages()
security.declareProtected('Manage languages', 'manage_addLanguage') security.declareProtected('Manage languages', 'manage_addLanguage')
...@@ -246,6 +253,45 @@ class LanguageManager(Tabs): ...@@ -246,6 +253,45 @@ class LanguageManager(Tabs):
self._upgrade() self._upgrade()
RESPONSE.redirect('manage_main') RESPONSE.redirect('manage_main')
# Add a feature which allows users to be able to add a new language.
security.declarePublic('get_user_defined_language_name')
def get_user_defined_language_name(self, id=None):
"""
Returns the name of the given user defined language code.
"""
for language_dict in self.get_user_defined_languages():
if language_dict['code']==id:
return language_dict['name']
security.declarePublic('get_user_defined_languages')
def get_user_defined_languages(self):
user_define_language_dict_list = []
localizer = getattr(self, 'Localizer', None)
if localizer is not None:
for value in getattr(self, 'user_defined_languages', ()):
splitted_value = value.split(' ', 1)
if len(splitted_value)==2:
user_define_language_dict_list.append(
{'name':splitted_value[0].strip(),
'code':splitted_value[1].strip(),})
return user_define_language_dict_list
def _add_user_defined_language(self, language_name, language_code):
self.user_defined_languages = (
getattr(self, 'user_defined_languages', ())+
('%s %s' % (language_name, language_code),)
)
self._p_changed = True
def _del_user_defined_language(self, language_code):
user_defined_languages = []
for language_dict in self.get_user_defined_languages():
if language_dict['code']!=language_code:
user_defined_languages.append('%s %s' %
(language_dict['name'],
language_dict['code']))
self.user_defined_languages = tuple(user_defined_languages)
self._p_changed = True
......
# -*- coding: UTF-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2000-2004 Juan David Ibáñez Palomar <jdavid@itaapy.com> # Copyright (C) 2000-2004 Juan David Ibáñez Palomar <jdavid@itaapy.com>
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
...@@ -17,9 +17,6 @@ ...@@ -17,9 +17,6 @@
# Import from the Standard Library # Import from the Standard Library
from urllib import unquote from urllib import unquote
# Import from itools
from itools.i18n import get_language_name
# Import from Zope # Import from Zope
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Acquisition import aq_parent from Acquisition import aq_parent
...@@ -27,6 +24,7 @@ from App.class_init import InitializeClass ...@@ -27,6 +24,7 @@ from App.class_init import InitializeClass
from OFS.Folder import Folder from OFS.Folder import Folder
from zLOG import LOG, ERROR, INFO, PROBLEM from zLOG import LOG, ERROR, INFO, PROBLEM
from zope.interface import implements from zope.interface import implements
from zope.i18n import translate
from ZPublisher.BeforeTraverse import registerBeforeTraverse, \ from ZPublisher.BeforeTraverse import registerBeforeTraverse, \
unregisterBeforeTraverse, queryBeforeTraverse, NameCaller unregisterBeforeTraverse, queryBeforeTraverse, NameCaller
...@@ -63,7 +61,8 @@ class Localizer(LanguageManager, Folder): ...@@ -63,7 +61,8 @@ class Localizer(LanguageManager, Folder):
id = 'Localizer' id = 'Localizer'
_properties = ({'id': 'title', 'type': 'string'}, _properties = ({'id': 'title', 'type': 'string'},
{'id': 'accept_methods', 'type': 'tokens'}) {'id': 'accept_methods', 'type': 'tokens'},
{'id': 'user_defined_languages', 'type': 'lines'},)
accept_methods = ('accept_path', 'accept_cookie', 'accept_url') accept_methods = ('accept_path', 'accept_cookie', 'accept_url')
...@@ -74,6 +73,7 @@ class Localizer(LanguageManager, Folder): ...@@ -74,6 +73,7 @@ class Localizer(LanguageManager, Folder):
+ LanguageManager.manage_options \ + LanguageManager.manage_options \
+ Folder.manage_options[1:] + Folder.manage_options[1:]
user_defined_languages = ()
def __init__(self, title, languages): def __init__(self, title, languages):
self.title = title self.title = title
...@@ -207,7 +207,7 @@ class Localizer(LanguageManager, Folder): ...@@ -207,7 +207,7 @@ class Localizer(LanguageManager, Folder):
langs = [] langs = []
for x in ob_languages: for x in ob_languages:
langs.append({'id': x, 'title': get_language_name(x), langs.append({'id': x, 'title': self.get_language_name(x),
'selected': x == ob_language}) 'selected': x == ob_language})
return langs return langs
...@@ -234,6 +234,16 @@ class Localizer(LanguageManager, Folder): ...@@ -234,6 +234,16 @@ class Localizer(LanguageManager, Folder):
response.redirect(goto) response.redirect(goto)
security.declarePublic('translate')
def translate(self, domain, msgid, lang=None, *args, **kw):
"""
backward compatibility shim over zope.i18n.translate. Please avoid.
"""
# parameter reordering/mangling necessary
assert not args
if lang is not None:
kw['target_language'] = lang
return translate(msgid, domain=domain, **kw)
InitializeClass(Localizer) InitializeClass(Localizer)
......
...@@ -568,21 +568,21 @@ class MessageCatalog(LanguageManager, ObjectManager, SimpleItem): ...@@ -568,21 +568,21 @@ class MessageCatalog(LanguageManager, ObjectManager, SimpleItem):
# Get the messages, and perhaps its translations. # Get the messages, and perhaps its translations.
# Convert keys to unicode for proper sorting.
d = {} d = {}
if x == 'locale.pot': if x == 'locale.pot':
filename = x filename = x
for k in self._messages.keys(): for k in self._messages.keys():
d[k] = "" d[to_unicode(k, encoding=charset)] = u""
else: else:
filename = '%s.po' % x filename = '%s.po' % x
for k, v in self._messages.items(): for k, v in self._messages.items():
try: k = to_unicode(k, encoding=charset)
d[k] = v[x] d[k] = to_unicode(v.get(x, ""), encoding=charset)
except KeyError:
d[k] = ""
# Generate the file # Generate the file
def backslashescape(x): def backslashescape(x):
x = to_str(x)
quote_esc = compile(r'"') quote_esc = compile(r'"')
x = quote_esc.sub('\\"', x) x = quote_esc.sub('\\"', x)
...@@ -606,13 +606,6 @@ class MessageCatalog(LanguageManager, ObjectManager, SimpleItem): ...@@ -606,13 +606,6 @@ class MessageCatalog(LanguageManager, ObjectManager, SimpleItem):
RESPONSE.setHeader('Content-Disposition', RESPONSE.setHeader('Content-Disposition',
'inline;filename=%s' % filename) 'inline;filename=%s' % filename)
r2 = []
for x in r:
if isinstance(x, unicode):
r2.append(x.encode(charset))
else:
r2.append(x)
return '\n'.join(r2) return '\n'.join(r2)
...@@ -702,6 +695,17 @@ InitializeClass(MessageCatalog) ...@@ -702,6 +695,17 @@ InitializeClass(MessageCatalog)
InitializeClass(POFile) InitializeClass(POFile)
# This dict define the alias between old Translation Service catalog id
# and new Localizer Message Catalog.
message_catalog_aliases = { "Default": "default"
, "ui" : "erp5_ui"
, "content": "erp5_content"
}
# "invert" message_catalog_aliases mapping
message_catalog_alias_sources = {}
for name, value in message_catalog_aliases.items():
message_catalog_alias_sources.setdefault(value, []).append(name)
def MessageCatalog_moved(object, event): def MessageCatalog_moved(object, event):
# FIXME This does not work if what we move is the folder that contains # FIXME This does not work if what we move is the folder that contains
...@@ -710,9 +714,19 @@ def MessageCatalog_moved(object, event): ...@@ -710,9 +714,19 @@ def MessageCatalog_moved(object, event):
if container is not None: if container is not None:
sm = getSiteManager(container) sm = getSiteManager(container)
sm.unregisterUtility(object, ITranslationDomain, event.oldName) sm.unregisterUtility(object, ITranslationDomain, event.oldName)
# unregister old aliases
oldAliases = message_catalog_alias_sources.get(event.oldName, ())
sm = getSiteManager(event.oldParent)
for alias in oldAliases:
sm.unregisterUtility(object, ITranslationDomain, alias)
container = event.newParent container = event.newParent
if container is not None: if container is not None:
sm = getSiteManager(container) sm = getSiteManager(container)
sm.registerUtility(object, ITranslationDomain, event.newName) sm.registerUtility(object, ITranslationDomain, event.newName)
# register new aliases
newAliases = message_catalog_alias_sources.get(event.newName, ())
sm = getSiteManager(event.newParent)
for alias in newAliases:
sm.registerUtility(object, ITranslationDomain, alias)
# -*- coding: UTF-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2000-2006 Juan David Ibáñez Palomar <jdavid@itaapy.com> # Copyright (C) 2000-2006 Juan David Ibáñez Palomar <jdavid@itaapy.com>
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
...@@ -24,7 +24,7 @@ import os ...@@ -24,7 +24,7 @@ import os
from thread import allocate_lock, get_ident from thread import allocate_lock, get_ident
# Import from itools # Import from itools
from itools.i18n import AcceptLanguageType from .itools.i18n import AcceptLanguageType
# Import from Zope # Import from Zope
import Globals import Globals
......
# -*- coding: UTF-8 -*-
# Copyright (C) 2001, 2002 J. David Ibáñez <j-david@noos.fr>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Test suite for the zgettext.py script.
"""
# Import from the Standard Library
import os
import sys
import unittest
from unittest import TestCase, TestSuite, TextTestRunner
# Import from Localizer
sys.path.append(os.path.join(sys.path[0], '../'))
import zgettext
class GettextTagTestCase(TestCase):
def test_caseSimple(self):
"""Test the 'dtml-gettext' tag without any option."""
text = "<dtml-gettext>\n" \
" message\n" \
"</dtml-gettext>"
assert zgettext.parse_dtml(text) == ['message']
def test_caseVerbatim(self):
"""Test the 'dtml-gettext' tag when using the 'verbatim' option."""
text = "<dtml-gettext verbatim>\n" \
" message\n" \
"</dtml-gettext>"
assert zgettext.parse_dtml(text) == ['\n message\n']
if __name__ == '__main__':
unittest.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