Fork Localizer and itools

Fork from master branch of Localizer and 0.50 branch of itools into ERP5

Remove almost everything from itools except bare essentials needed by a stripped Localizer for ERP5
parent 498500ed
*.pyc
*.swp
locale/*.mo
locale/*~
# -*- coding: UTF-8 -*-
# Copyright (C) 2000-2002 Juan David Ibáñez Palomar <jdavid@itaapy.com>
#
# 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/>.
"""
Localizer
Adds a new DTML tag:
<dtml-gettext [lang=<language>|lang_expr=<expression>] [verbatim] [catalog=<id>] [data=<expression>]>
...
</dtml-gettext>
"""
# Import from Zope
from DocumentTemplate.DT_Util import Eval, ParseError, parse_params, \
InstanceDict, namespace, render_blocks
# Auxiliar functions
def name_or_expr(mapping, name_attr, expr_attr, default):
name = mapping.get(name_attr, None)
expr = mapping.get(expr_attr, None)
if name is None:
if expr is None:
return default
return Eval(expr)
if expr is None:
return name
raise ParseError, ('%s and %s given' % (name_attr, expr_attr), 'calendar')
class GettextTag:
""" """
name = 'gettext'
blockContinuations = ()
def __init__(self, blocks):
tname, args, section = blocks[0]
self.section = section.blocks
args = parse_params(args, lang=None, lang_expr=None, verbatim=1,
catalog=None, data=None)
self.lang = name_or_expr(args, 'lang', 'lang_expr', None)
self.verbatim = args.get('', None) == 'verbatim' \
or args.get('verbatim', None)
self.catalog = args.get('catalog', None)
self.data = args.get('data', None)
if self.data is not None:
self.data = Eval(self.data)
def __call__(self, md):
# In which language, if any?
lang = self.lang
if lang is not None and type(lang) is not str:
lang = lang.eval(md)
# Get the message!!
ns = namespace(md)[0]
md._push(InstanceDict(ns, md))
message = render_blocks(self.section, md)
md._pop(1)
# Interpret the message as verbatim or not
if not self.verbatim:
message = ' '.join([ x.strip() for x in message.split() ])
# Search in a specific catalog
if self.catalog is None:
gettext = md.getitem('gettext', 0)
else:
gettext = md.getitem(self.catalog, 0).gettext
translation = gettext(message, lang)
# Variable substitution
if self.data is not None:
data = self.data.eval(md)
translation = translation % data
return translation
This diff is collapsed.
# -*- coding: UTF-8 -*-
# Copyright (C) 2000-2004 Juan David Ibáñez Palomar <jdavid@itaapy.com>
#
# 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/>.
# Import from the Standard Library
from urlparse import urlparse
# Import from itools
from itools.i18n import get_language_name, get_languages
# Import from Zope
from App.class_init import InitializeClass
from App.Management import Tabs
from AccessControl import ClassSecurityInfo
# Import from Localizer
from LocalFiles import LocalDTMLFile
from utils import lang_negotiator, _
class LanguageManager(Tabs):
""" """
security = ClassSecurityInfo()
# TODO For backwards compatibility with Python 2.1 the variable
# _languages is a tuple. Change it to a frozenset.
_languages = ()
_default_language = None
########################################################################
# API
########################################################################
def get_languages(self):
"""Returns all the object languages.
"""
return self._languages
def set_languages(self, languages):
"""Sets the object languages.
"""
self._languages = tuple(languages)
def add_language(self, language):
"""Adds a new language.
"""
if language not in self._languages:
self._languages = tuple(self._languages) + (language,)
def del_language(self, language):
"""Removes a language.
"""
if language in self._languages:
languages = [ x for x in self._languages if x != language ]
self._languages = tuple(languages)
def get_languages_mapping(self):
"""Returns a list of dictionary, one for each objects language. The
dictionary contains the language code, its name and a boolean value
that tells wether the language is the default one or not.
"""
return [ {'code': x,
'name': get_language_name(x),
'default': x == self._default_language}
for x in self._languages ]
def get_available_languages(self, **kw):
"""Returns the langauges available. For example, a language could be
considered as available only if there is some data associated to it.
This method is used by the language negotiation code (see
'get_selected_language'), sometimes you will want to redefine it in
your classes.
"""
return self._languages
def get_default_language(self):
"""Returns the default language.
This method is used by the language negotiation code (see
'get_selected_language'), sometimes you will want to redefine it in
your classes.
For example, maybe you will want to define it to return always a
default language, even when internally it is None.
"""
return self._default_language
########################################################################
# Web API
########################################################################
# Security settings
security.declarePublic('get_languages')
security.declareProtected('Manage languages', 'set_languages')
security.declareProtected('Manage languages', 'add_language')
security.declareProtected('Manage languages', 'del_language')
security.declarePublic('get_languages_mapping')
security.declarePublic('get_language_name')
def get_language_name(self, id=None):
"""
Returns the name of the given language code.
XXX Kept here for backwards compatibility only
"""
if id is None:
id = self.get_default_language()
return get_language_name(id)
security.declarePublic('get_available_languages')
security.declarePublic('get_default_language')
# XXX Kept here temporarily, further refactoring needed
security.declarePublic('get_selected_language')
def get_selected_language(self, **kw):
"""
Returns the selected language. Here the language negotiation takes
place.
Accepts keyword arguments which will be passed to
'get_available_languages'.
"""
available_languages = apply(self.get_available_languages, (), kw)
return lang_negotiator(available_languages) \
or self.get_default_language()
########################################################################
# ZMI
########################################################################
manage_options = (
{'action': 'manage_languages', 'label': u'Languages',
'help': ('Localizer', 'LM_languages.stx')},)
def filtered_manage_options(self, REQUEST=None):
options = Tabs.filtered_manage_options(self, REQUEST=REQUEST)
# Insert the upgrade form if needed
if self._needs_upgrade():
options.insert(0,
{'action': 'manage_upgradeForm',
'label': u'Upgrade',
'help': ('Localizer', 'LM_upgrade.stx')})
# Translate the labels
r = []
for option in options:
option = option.copy()
option['label'] = _(option['label'])
r.append(option)
# Ok
return r
security.declareProtected('View management screens', 'manage_languages')
manage_languages = LocalDTMLFile('ui/LM_languages', globals())
security.declarePublic('get_all_languages')
def get_all_languages(self):
"""
Returns all ISO languages, used by 'manage_languages'.
"""
return get_languages()
security.declareProtected('Manage languages', 'manage_addLanguage')
def manage_addLanguage(self, language, REQUEST=None, RESPONSE=None):
""" """
self.add_language(language)
if RESPONSE is not None:
RESPONSE.redirect("%s/manage_languages" % REQUEST['URL1'])
security.declareProtected('Manage languages', 'manage_delLanguages')
def manage_delLanguages(self, languages, REQUEST, RESPONSE):
""" """
for language in languages:
self.del_language(language)
RESPONSE.redirect("%s/manage_languages" % REQUEST['URL1'])
security.declareProtected('Manage languages', 'manage_changeDefaultLang')
def manage_changeDefaultLang(self, language, REQUEST=None, RESPONSE=None):
""" """
self._default_language = language
if REQUEST is not None:
RESPONSE.redirect("%s/manage_languages" % REQUEST['URL1'])
# Unicode support, custom ZMI
manage_page_header = LocalDTMLFile('ui/manage_page_header', globals())
########################################################################
# Upgrade
def _needs_upgrade(self):
return False
def _upgrade(self):
pass
security.declarePublic('need_upgrade')
def need_upgrade(self):
""" """
return self._needs_upgrade()
security.declareProtected(
'Manage Access Rules', 'manage_upgradeForm', 'manage_upgrade')
manage_upgradeForm = LocalDTMLFile('ui/LM_upgrade', globals())
def manage_upgrade(self, REQUEST, RESPONSE):
""" """
self._upgrade()
RESPONSE.redirect('manage_main')
InitializeClass(LanguageManager)
# -*- coding: UTF-8 -*-
# Copyright (C) 2000-2002 Juan David Ibáñez Palomar <jdavid@itaapy.com>
#
# 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/>.
# Import from Zope
from ExtensionClass import Base
class LocalAttribute(Base):
"""
Provides a way to override class variables, useful for example
for title (defined in SimpleItem).
"""
def __init__(self, id):
self.id = id
def __of__(self, parent):
return parent.getLocalAttribute(self.id)
class LocalAttributesBase:
def getLocalAttribute(self, name, lang=None):
""" """
raise NotImplemented
class LocalAttributes(LocalAttributesBase):
"""
Example of a 'LocalAttributesBase' derived class, this also a base class
for 'LocalFolder.LocalFolder' and 'Locale.Locale', it can be considered
the default implementation.
Returns attributes of the form <name>_<lang>. When <lang> has more than
one level, for example es-CO, the dashes are transformed to underscores,
as dashes aren't valid charecters for identifiers in Python. For example,
the call 'getLocalAttribute("long_date", "es-CO")' would return
'self.long_date_es_CO'.
"""
def getLocalAttribute(self, name, lang=None):
if lang is None:
lang = self.get_selected_language()
lang = lang.replace('-', '_')
name = '%s_%s' % (name, lang)
return getattr(self, name)
This diff is collapsed.
# -*- coding: UTF-8 -*-
# Copyright (C) 2000-2005 Juan David Ibáñez Palomar <jdavid@itaapy.com>
#
# 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/>.
"""
Localizer
This module provides several localized classes, that is, classes with the
locale attribute. Currently it only defines the classes LocalDTMLFile and
LocalPageTemplateFile, which should be used instead of DTMLFile and
PageTemplateFile.
"""
# Import from the Standard Library
import os
# Import Zope modules
from App.special_dtml import DTMLFile
# Import from Localizer
from utils import DomainAware
class LocalDTMLFile(DomainAware, DTMLFile):
""" """
def __init__(self, name, _prefix=None, **kw):
DTMLFile.__init__(self, name, _prefix, **kw)
DomainAware.__init__(self, _prefix)
def _exec(self, bound_data, args, kw):
# Add our gettext first
bound_data['gettext'] = self.gettext
return apply(LocalDTMLFile.inheritedAttribute('_exec'),
(self, bound_data, args, kw))
# Zope Page Templates (ZPT)
# XXX Deprecated, use the i18n namespace instead.
try:
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
except ImportError:
# If ZPT is not installed
class LocalPageTemplateFile:
pass
else:
class LocalPageTemplateFile(DomainAware, PageTemplateFile):
""" """
def __init__(self, name, _prefix=None, **kw):
PageTemplateFile.__init__(self, name, _prefix, **kw)
DomainAware.__init__(self, _prefix)
def _exec(self, bound_data, args, kw):
# Add our gettext first
bound_data['gettext'] = self.gettext
return apply(LocalPageTemplateFile.inheritedAttribute('_exec'),
(self, bound_data, args, kw))
# -*- coding: UTF-8 -*-
# Copyright (C) 2000-2004 Juan David Ibáñez Palomar <jdavid@itaapy.com>
#
# 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/>.
# Import from Zope
from App.Common import package_home
from OFS.Folder import Folder
# Import from Localizer
from LanguageManager import LanguageManager
from LocalFiles import LocalDTMLFile
from LocalAttributes import LocalAttribute, LocalAttributes
from utils import _
manage_addLocalFolderForm = LocalDTMLFile('ui/LocalFolder_add', globals())
def manage_addLocalFolder(self, id, title, languages, REQUEST=None):
""" """
id = id.strip()
self._setObject(id, LocalFolder(id, title, languages))
if REQUEST is not None:
return self.manage_main(self, REQUEST)
class LocalFolder(LanguageManager, LocalAttributes, Folder):
""" """
meta_type = 'LocalFolder'
_properties = ({'id': 'title', 'type': 'string'},)
def __init__(self, id, title, languages):
self.id = id
self.title = title
# Language Manager data
self._languages = tuple(languages)
self._default_language = languages[0]
# Local attributes
self._local_attributes = ()
manage_options = \
Folder.manage_options[:1] \
+ ({'action': 'manage_attributes', 'label': u'Attributes'},) \
+ LanguageManager.manage_options \
+ Folder.manage_options[1:]
# Manage attributes
manage_attributes = LocalDTMLFile('ui/LocalFolder_attributes', globals())
def get_local_attributes(self):
return self._local_attributes
def manage_delAttributes(self, attributes, REQUEST=None, RESPONSE=None):
""" """
local_attributes = list(self._local_attributes)
for attr in attributes:
local_attributes.remove(attr)
delattr(self, attr)
self._local_attributes = tuple(local_attributes)
if RESPONSE is not None:
RESPONSE.redirect("%s/manage_attributes" % REQUEST['URL1'])
def manage_addAttribute(self, id, REQUEST=None, RESPONSE=None):
""" """
id = id.strip()
setattr(self, id, LocalAttribute(id))
self._local_attributes = self._local_attributes + (id,)
if RESPONSE is not None:
RESPONSE.redirect("%s/manage_attributes" % REQUEST['URL1'])
This diff is collapsed.
# -*- coding: UTF-8 -*-
# Copyright (C) 2000-2002 Juan David Ibáñez Palomar <jdavid@itaapy.com>
#
# 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/>.
# Import from Localizer
from LocalAttributes import LocalAttributes, LocalAttribute
class Locale(LocalAttributes):
# Time, hours and minutes
time = LocalAttribute('time')
def time_en(self, datetime):
return datetime.strftime('%H:%M')
def time_es(self, datetime):
return datetime.strftime('%H.%M')
# -*- coding: UTF-8 -*-
# Copyright (C) 2000-2004 Juan David Ibáñez Palomar <jdavid@itaapy.com>
#
# 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/>.
# Import from the Standard Library
from urllib import unquote
# Import from itools
from itools.i18n import get_language_name
# Import from Zope
from AccessControl import ClassSecurityInfo
from Acquisition import aq_parent
from App.class_init import InitializeClass
from OFS.Folder import Folder
from zLOG import LOG, ERROR, INFO, PROBLEM
from zope.interface import implements
from ZPublisher.BeforeTraverse import registerBeforeTraverse, \
unregisterBeforeTraverse, queryBeforeTraverse, NameCaller
# Import Localizer modules
from interfaces import ILocalizer
from LocalFiles import LocalDTMLFile
from MessageCatalog import MessageCatalog
from utils import lang_negotiator
from LanguageManager import LanguageManager
# Constructors
manage_addLocalizerForm = LocalDTMLFile('ui/Localizer_add', globals())
def manage_addLocalizer(self, title, languages, REQUEST=None, RESPONSE=None):
"""
Add a new Localizer instance.
"""
self._setObject('Localizer', Localizer(title, languages))
if REQUEST is not None:
RESPONSE.redirect('manage_main')
class Localizer(LanguageManager, Folder):
"""
The Localizer meta type lets you customize the language negotiation
policy.
"""
meta_type = 'Localizer'
implements(ILocalizer)
id = 'Localizer'
_properties = ({'id': 'title', 'type': 'string'},
{'id': 'accept_methods', 'type': 'tokens'})
accept_methods = ('accept_path', 'accept_cookie', 'accept_url')
security = ClassSecurityInfo()
manage_options = \
(Folder.manage_options[0],) \
+ LanguageManager.manage_options \
+ Folder.manage_options[1:]
def __init__(self, title, languages):
self.title = title
self._languages = languages
self._default_language = languages[0]
#######################################################################
# API / Private
#######################################################################
def _getCopy(self, container):
return Localizer.inheritedAttribute('_getCopy')(self, container)
def _needs_upgrade(self):
return not self.hooked()
def _upgrade(self):
# Upgrade to 0.9
if not self.hooked():
self.manage_hook(1)
#######################################################################
# API / Public
#######################################################################
# Get some data
security.declarePublic('get_supported_languages')
def get_supported_languages(self):
"""
Get the supported languages, that is the languages that the
are being working so the site is or will provide to the public.
"""
return self._languages
security.declarePublic('get_selected_language')
def get_selected_language(self):
""" """
return lang_negotiator(self._languages) \
or self._default_language
# Hooking the traversal machinery
# Fix this! a new permission needed?
## security.declareProtected('View management screens', 'manage_hookForm')
## manage_hookForm = LocalDTMLFile('ui/Localizer_hook', globals())
## security.declareProtected('Manage properties', 'manage_hook')
security.declarePrivate('manage_hook')
def manage_hook(self, hook=0):
""" """
if hook != self.hooked():
if hook:
hook = NameCaller(self.id)
registerBeforeTraverse(aq_parent(self), hook, self.meta_type)
else:
unregisterBeforeTraverse(aq_parent(self), self.meta_type)
security.declarePublic('hooked')
def hooked(self):
""" """
if queryBeforeTraverse(aq_parent(self), self.meta_type):
return 1
return 0
# New code to control the language policy
def accept_cookie(self, accept_language):
"""Add the language from a cookie."""
lang = self.REQUEST.cookies.get('LOCALIZER_LANGUAGE', None)
if lang is not None:
accept_language.set(lang, 2.0)
def accept_path(self, accept_language):
"""Add the language from the path."""
stack = self.REQUEST['TraversalRequestNameStack']
if stack and (stack[-1] in self._languages):
lang = stack.pop()
accept_language.set(lang, 3.0)
def accept_url(self, accept_language):
"""Add the language from the URL."""
lang = self.REQUEST.form.get('LOCALIZER_LANGUAGE')
if lang is not None:
accept_language.set(lang, 2.0)
def __call__(self, container, REQUEST):
"""Hooks the traversal path."""
try:
accept_language = REQUEST['AcceptLanguage']
except KeyError:
return
for id in self.accept_methods:
try:
method = getattr(self, id)
method(accept_language)
except:
LOG(self.meta_type, PROBLEM,
'method "%s" raised an exception.' % id)
# Changing the language, useful snippets
security.declarePublic('get_languages_map')
def get_languages_map(self):
"""
Return a list of dictionaries, each dictionary has the language
id, its title and a boolean value to indicate wether it's the
user preferred language, for example:
[{'id': 'en', 'title': 'English', 'selected': 1}]
Used in changeLanguageForm.
"""
# For now only LPM instances are considered to be containers of
# multilingual data.
try:
ob = self.getLocalPropertyManager()
except AttributeError:
ob = self
ob_language = ob.get_selected_language()
ob_languages = ob.get_available_languages()
langs = []
for x in ob_languages:
langs.append({'id': x, 'title': get_language_name(x),
'selected': x == ob_language})
return langs
security.declarePublic('changeLanguage')
changeLanguageForm = LocalDTMLFile('ui/changeLanguageForm', globals())
def changeLanguage(self, lang, goto=None, expires=None):
""" """
request = self.REQUEST
response = request.RESPONSE
# Changes the cookie (it could be something different)
parent = aq_parent(self)
path = parent.absolute_url()[len(request['SERVER_URL']):] or '/'
if expires is None:
response.setCookie('LOCALIZER_LANGUAGE', lang, path=path)
else:
response.setCookie('LOCALIZER_LANGUAGE', lang, path=path,
expires=unquote(expires))
# Comes back
if goto is None:
goto = request['HTTP_REFERER']
response.redirect(goto)
InitializeClass(Localizer)
# Hook/unhook the traversal machinery
# Support for copy, cut and paste operations
def Localizer_moved(object, event):
container = event.oldParent
if container is not None:
unregisterBeforeTraverse(container, object.meta_type)
container = event.newParent
if container is not None:
id = object.id
container = container.this()
hook = NameCaller(id)
registerBeforeTraverse(container, hook, object.meta_type)
# -*- coding: UTF-8 -*-
# Copyright (C) 2002-2004 Juan David Ibáñez Palomar <jdavid@itaapy.com>
#
# 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/>.
"""
This module makes more easy to implement multilingual Zope products based
on Localizer that also work when Localizer is not installed (they are
monolingual in this situation).
It provides dummy versions of some Localizer features. To internationalize
your code copy and paste this module to your product directory and, in the
modules you need it, just type:
from LocalizerSupport import _
from LocalizerSupport import LocalDTMLFile as DTMLFile
from LocalizerSupport import LocalPageTemplateFile as PageTemplateFile
Another option is not to rename the classes, then you will have to
change from 'DTMLFile' to 'LocalDTMLFile' and from 'PageTemplateFile'
to 'LocalPageTemplateFile' wherever you need it.
Note that Localizer requieres Python 2.4 or above, so the multilingual
version of your product will also requiere Python 2.4 or above.
Of course, you don't need to import the features you don't need.
"""
# The version information refers to the Localizer product version.
# If you change this module, please update the version number to
# show it.
__version__ = '1.2.0'
try:
from Products.Localizer import LocalDTMLFile, LocalPageTemplateFile
from Products.Localizer import _
except ImportError:
# For Python code
def _(message, language=None):
"""
Used to markup a string for translation but without translating it,
this is known as deferred translations.
"""
return message
# For DTML and Page Templates
def gettext(self, message, language=None):
""" """
return message
# Document Template Markup Langyage (DTML)
from Globals import DTMLFile
class LocalDTMLFile(DTMLFile):
def _exec(self, bound_data, args, kw):
# Add our gettext first
bound_data['gettext'] = self.gettext
return apply(LocalDTMLFile.inheritedAttribute('_exec'),
(self, bound_data, args, kw))
gettext = gettext
# Zope Page Templates (ZPT)
try:
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
except ImportError:
# If ZPT is not installed
class LocalPageTemplateFile:
pass
else:
class LocalPageTemplateFile(PageTemplateFile):
def _exec(self, bound_data, args, kw):
# Add our gettext first
bound_data['gettext'] = self.gettext
return apply(LocalPageTemplateFile.inheritedAttribute('_exec'),
(self, bound_data, args, kw))
gettext = gettext
# Dummy dtml-gettext tag
from DocumentTemplate.DT_Util import InstanceDict, namespace, render_blocks
class GettextTag:
""" """
name = 'gettext'
blockContinuations = ()
def __init__(self, blocks):
tname, args, section = blocks[0]
self.section = section.blocks
def __call__(self, md):
ns = namespace(md)[0]
md._push(InstanceDict(ns, md))
message = render_blocks(self.section, md)
md._pop(1)
return message
# Register the dtml-gettext tag
from DocumentTemplate.DT_String import String
if not String.commands.has_key('gettext'):
String.commands['gettext'] = GettextTag
PYTHON=python
po:
${PYTHON} zgettext.py *.py ui/*.dtml -l ca de es eu fr hu it ja pt ru
mo:
${PYTHON} zgettext.py -m
clean:
rm -f *~ *.pyc
rm -f locale/*~ locale/locale.pot.bak locale/*.mo
rm -f help/*~
rm -f tests/*~ tests/*.pyc
rm -f ui/*~
test:
${PYTHON} tests/test_zgettext.py
binary: clean mo
rm -f refresh.txt
This diff is collapsed.
Localizer is the de-facto standard to build multilingual applications with
Zope. It helps to internationalize and localize Zope products and to build
multilingual web sites through the Management Interface. It deals with
both user interfaces and content.
Requirements
- Python 2.5.2 or later
- Zope 2.12.2 or later
- itools 0.50.6 or later (download from
"http://www.hforge.org/itools":http://www.hforge.org/itools)
Installation
Download Localizer. Unpack the tarball and install it in the "Products"
directory::
$ tar xzf Localizer-1.3.0.tar.gz
$ cp -r Localizer-1.3.0 <Zope instance>/Products/Localizer
Another option, case you are running Unix, is to use symbolic links::
$ ln -s Localizer-1.3.0 <Zope instance>/Products/Localizer
Resources
- "Home site":http://www.localizer.org/
- "Mailing list subscription":http://www.hforge.org/community
- "Mailing list archives":http://archives.hforge.org/index.cgi?list=localizer
- "Bug Tracker":http://bugs.hforge.org/
Examples of sites powered by Localizer
- "European Environment Agency":http://www.eea.eu.int/
- "Bank Winter":http://www.bankwinter.com/
- "Castagnari":http://www.castagnari.com/
- "Hiru":http://www.hiru.com/
- "Hotsak":http://www.hotsak.com/
- "Ego Ibarra":http://www.egoibarra.com/
- "Udaleuskaltegiak":http://www.udaleuskaltegiak.net/
Author and License
Copyright 2001-2010 J. David Ibez (jdavid@itaapy.com)
2001 Universitat Jaume I
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/":http://www.gnu.org/licenses/
Localizer 1.3.0 (2009/XX/XX)
============================
Localizer is a Zope product for developers and web masters. Localizer
solves the problem of building multilingual products and web sites,
ranging from internationalization and localization of the user
interface to management of multilingual content.
What is new?
------------
Upgraded to Zope 2.12, Python 2.5 and itools 0.50 (previous versions are
not supported).
Some API obsolete since at least 2004 has been removed:
- The 'ugettext' function has been removed from DTML and ZPT templates,
use instead 'gettext'.
- Four methods from the 'LocalPropertyManger' class have been removed:
_setLocalPropValue => set_localpropvalue
_setLocalProperty => set_localproperty
_delLocalProperty => del_localproperty
getLocalProperty => getLocalAttribute
Resources
---------
Download
http://download.hforge.org/localizer/Localizer-1.3.0.tar.gz
http://download.hforge.org/itools/0.50/itools-0.50.7.tar.gz
Home
http://www.localizer.org/
Mailing list
http://www.hforge.org/community
http://archives.hforge.org/index.cgi?list=localizer
Bug Tracker
http://bugs.hforge.org/
See http://in-girum.net/cgi-bin/bugzilla/index.cgi
Things should be removed from here and added to the bug tracker.
Bugs
----
- Bo M. Maryniuck:
"I can't reproduce the error anymore though I can't send you traceback,
but I just found, that Localizer crashes Medusa threads if someone else
object uses "register before traverse". In my case there is an product,
which is always modifies the request. So if I put there also Localizer,
you'll never enter the site.
Quality Assurance
-----------------
- Audit the code, update the idioms (e.g. use "get_context" to access the
request and response objects).
API
---
- When importing modules from Localizer, either the sort or the long
way should always be used. Update the documentation to reflect it
(Rainer Thaden).
Where the sort form is:
from Products.Localizer import LocalPropertyManager
and the long form is:
from Products.Localizer.LocalPropertyManager import LocalPropertyManager
See if this can be addressed without compromising backwards compatibility,
if not document exactly which is the current situation.
- Develop an API to get messages and translations from the message catalog,
see email from Pierre-Yves Delens.
- Implement the whole mapping interface in the "AcceptLanguage" and
"AcceptCharset" classes (itools.i18n.accept). Sugested by Bjorn.
Documentation
-------------
- Update (rewrite) the documentation. Most likely to be in latex, and
distributed with the source.
- Add a section "Localizer application anatomy" to the tutorial:
"One thing you may want to consider is an overview of how a site
using all the products should be laid out. The examples and guide
you are providing are very very good and explain all the techcinal
components of the variouse packages quite well. What seems to be
missing is a higher level view that ties it all together in terms
of layout for a demo site.
An example of a 2-3 language basic site that uses the variouse
components would be very attractive for new programs and users
(moi) and help the adoption of this most excellent product."
- Comment about "management_page_charset" to switch the ZMI to utf-8,
or maybe patch Zope so they're in utf-8 by default.
Localizer.org
-------------
- Kill "http://www.j-david.net/software/localizer", everything should be
in "http://www.ikaaro.org/localizer".
User Interface (ZMI)
--------------------
- Complete the help screens.
- Be sure the framed messages appear in all the management screens every
time an action is performed, i.e. "Content changed (2002-02-08 15:26)".
- Add PrincipiaSearchSource
Standards Support
-----------------
- Support fuzzy in "itools.handlers.PO".
- Use the library libgettextpo introduced in gettext 0.12 to parse the
PO files?? See the docs: "Writing your own programs that process PO
files"
Message Extraction
------------------
- Kill "zgettext", use "igettext" from "itools.i18n" instead.
- Add support for ZPT to "igettext". This means to implement part of
the "i18n" namespace in "itools.xml.ZPT". See [1] for a sample code.
[1] http://savannah.nongnu.org/cgi-bin/viewcvs/opental/opental/OpenPTi18n/i18n_xgettext.py?rev=1.8&content-type=text/vnd.viewcvs-markup
Not yet classified
------------------
- (Zope bug) See if something feasible can be done to remove the hardcoded
use of Latin-1 encoding from Zope and Localizer.
If not, explain which the problems are and what the developer can
do (add this as a task for the documentation).
- When importing a message catalog, should be done something with
the header? When managing the message catalog through FTP, should
the header also be editable?
- François Meehan:
"Also found that using the import/export function in Localizer/zope
can bring corruption to the po file, a problem with the accents it
seems."
- Document the path where Localizer.changeLanguage sets the cookie,
which is the path from where it is called, not its physical path.
See the mails exchanged with Claus Rosenberger. Maybe a FAQ?
- Work on locale information: dates, money, etc..
- Integrate the File System Message Catalog from CMFLocalizer.
- Add the ability to manage localized versions of standard files
in a product: the on-line help system, README.txt, etc..
- Let to implement ZClasses that inherite from 'MessageCatalog'
- Set the 'Vary' header.
The problem is: which value should it have?
This could allow to remove the patch to Zope for images, if UA
take care of the 'Vary' header.
- Rework 'changeLanguageForm' to support browsers without javascript.
- Build user management interfaces similar to the ZMI
(standard_html_header/footer instead of manage_page_header/footer
and manage_tabs).
***************************************************************************
Localizer 0.8.1
***************************************************************************
* The request variable USER_PREF_LANGUAGES isn't a list anymore,
now it's an object that represents a tree. Any code that directly
reads or modifies USER_PREF_LANGUAGES will be broken. Tell me
if you did it.
* The Localizer class provides a feature known as "locale folders"
that lets to manage any kind of multilingual content. Now this
feature is deprecated. A new class named "LocalFolder" provides
a better solution for this, please move to it as soon as posible,
in the next release the deprecated feature will be removed!!
The quickest way to move from "Localizer" to "LocalFolder" is:
0. Do a backup of the database;
1. Create in the root of your web site a "LocalFolder" instance called,
for example, "locale";
2. Go to the management screens of "locale" and create an attribute
named, for example, "folder";
3. Add as many languages as needed in the tab "Languages";
4. Create a folder for every language in the "Contents" tab, for
example, "folder_en", "folder_es", etc..;
5. For each language copy all the stuff from the Localizer instance
to "locale". For example, copy everything in "Localizer/es" to
"locale/folder_es";
6. Now the most time expensive step, go to all the templates and scripts
that refer to any object in the "Localizer" instance and change to
use "locale" instead.
For example, if you had an image named "logo" and you called it with:
<dtml-var logo>
change it to:
<dtml-with locale><dtml-var logo></dtml-with>
or to:
<dtml-var "locale.logo()">
Hopefully you will have to modify few methods;
7. And finally, remove the "Localizer" instance!!
* The previous way to internationalize Python code from Python
products has been deprecated. Read the documentation to know
how it should be done from now on. However, the deprecated
way will be preserved for a while, probably a long while.
***************************************************************************
Localizer 0.8.0
***************************************************************************
* The 0.7 version saw a big redesign of message catalogs, and
also of the way they're used. Before they were implicitly called,
through a globaly available "gettext" method, this feature
was implemented in the "Localizer" class.
In the 0.7 version message catalogs became an independent class,
its instances are explicitly called. The old way to use message
catalogs was preserved for backwards compatibility.
Now, in version 0.8, the old way to use message catalogs (through
the global "gettext" method) has been removed. To upgrade to this
version follow the steps:
0. If you upgrade from a version previous to 0.7 upgrade first
to 0.7.x
1. Move all your 'MessageCatalog' instances with the id
'Messages' that are inside of a 'Localizer' instance
to the same level in the hierarchy where is the
'Localizer' object, but with the name 'gettext'.
For example if you have "/a/b/c/Localizer/Messages" you
should move the 'Messages' object to "/a/b/c/gettext".
[!] This will work in most situations, you only could get
wrong behaviour if you're using Localizer instances
inside other Localizer instances. For example if you
have the objects "/a/b/c/Localizer/Messages" and
"/a/b/c/d/Localizer/Messages".
I guess very few people, if any, will have a configuration
like this one, so I don't provide any upgrade path. If
you've something like this send me an email before doing
anything.
2. Don't do anything for a few days, just to be sure that
everything works.
3. Upgrade to the 0.8 version.
Don't hesitate to contact me if you have any problem or doubt.
***************************************************************************
Localizer 0.7.0
***************************************************************************
* There're several changes that require all Localizer instances
to be upgraded, to do so go to the management interfaces of
each Localizer instance and click the "upgrade" button that
will appear.
Be careful, the upgrading must be done with access rules
deactivated, for example: "www.foo.com/bar/Z/manage"
* LocalContent instances and other instances of classes that
inherit from LocalPropertyManager also need to be upgraded.
To do it just run the same script used to upgrade to the
0.6 version, it is:
obs = context.ZopeFind(context, None, None, None,
'isLocalPropertyManager == 1',
None, None, None, None, 1)
for path, ob in obs:
ob.manage_upgrade()
return '%d objects upgraded' % len(obs)
* There're several changes in the API that could break your
code if you have used directly the Localizer API, if in
doubt send me an email.
***************************************************************************
Localizer 0.6.1
***************************************************************************
Before 0.6.0 changeLanguageForm was a LocalDTMLFile, in 0.6.0
I changed it to a DTML Method. Now it's again a LocalDTMLFile.
To upgrade go to each Localizer instance and remove the
changeLanguageForm method. If you don't do it nothing will
break, but anyway it's encouraged.
If you're curious about this change, it's because I've finally
discovered which is the difference between DTMLFile and HTMLFile:
bindings can be used from a DTMLFile.
***************************************************************************
Localizer 0.6
***************************************************************************
* LocalContent and LocalPropertyManager
All LocalContent objects and instances of classes that inherit
from LocalPropertyManager need to be upgraded.
Create and run a Python script in the root with the code:
obs = context.ZopeFind(context, None, None, None,
'isLocalPropertyManager == 1',
None, None, None, None, 1)
for path, ob in obs:
ob.manage_upgrade()
return '%d objects upgraded' % len(obs)
* All Localizer instances also need to be upgraded, but it's done
automatically. To verify it:
- test that the 'hook_traversal' property has been removed.
- test that the Localizer has a DTML Method called changeLanguageForm.
Some future release, probably 0.7, will be incompatible with
versions < 0.6. So it won't be possible, for example, to upgrade
from 0.5.1 to 0.7 directly; it must be from 0.5.1 to 0.6.x to 0.7.
In short: upgrade to 0.6 as soon as posible!!
* Other minor changes:
- Now get_available_languages returns a list of tuples of two
elements: [(id, title), ..]
For example, [('en', 'English'), ('es', 'Spanish'), ...]
- Now the title of local folders is not used in changeLanguageForm.
Perhaps there're other minor changes that could break something.
***************************************************************************
Localizer 0.3
***************************************************************************
In Localizer versions < 0.3 the way to localize DTML files was:
from Products.Localizer.LocalizedDTMLFile import LocalizedDTMLFile
xxx = LocalizedDTMLFile('xxx', globals())
Since version 0.3 the right way to do it is:
from Products.Localizer import LocalDTMLFile
xxx = LocalDTMLFile('xxx', globals())
In 0.3 version the old way was still supported, but deprecated. Since
version 0.4 the old way is no longer available, so products using it
will break.
# -*- coding: UTF-8 -*-
# Copyright (C) 2000-2005 Juan David Ibáñez Palomar <jdavid@itaapy.com>
#
# 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/>.
# Check whether itools is installed
msg = ('itools 0.50 or later is needed, download from '
'http://download.hforge.org/itools/0.50')
try:
import itools
except ImportError:
raise ImportError, msg
# Check itools is version 0.50 or later
if itools.__version__ < '0.50':
raise ImportError, msg
# Import from the Standard Library
import os.path
# Import from Zope
from App.ImageFile import ImageFile
from DocumentTemplate.DT_String import String
# Import from Localizer
from patches import get_request
import Localizer, LocalContent, MessageCatalog, LocalFolder
from LocalAttributes import LocalAttribute
from LocalFiles import LocalDTMLFile, LocalPageTemplateFile
from LocalPropertyManager import LocalPropertyManager, LocalProperty
from GettextTag import GettextTag
misc_ = {'arrow_left': ImageFile('img/arrow_left.gif', globals()),
'arrow_right': ImageFile('img/arrow_right.gif', globals()),
'eye_opened': ImageFile('img/eye_opened.gif', globals()),
'eye_closed': ImageFile('img/eye_closed.gif', globals()),
'obsolete': ImageFile('img/obsolete.gif', globals())}
def initialize(context):
# Check Localizer is not installed with a name different than Localizer
# (this is a common mistake).
filename = os.path.split(os.path.split(__file__)[0])[1]
if filename != 'Localizer':
message = (
"The Localizer product must be installed within the 'Products'"
" folder with the name 'Localizer' (not '%s').") % filename
raise RuntimeError, message
# XXX This code has been written by Cornel Nitu, it may be a solution to
# upgrade instances.
## root = context._ProductContext__app
## for item in root.PrincipiaFind(root, obj_metatypes=['LocalContent'],
## search_sub=1):
## item[1].manage_upgrade()
# Register the Localizer
context.registerClass(Localizer.Localizer,
constructors = (Localizer.manage_addLocalizerForm,
Localizer.manage_addLocalizer),
icon = 'img/localizer.gif')
# Register LocalContent
context.registerClass(
LocalContent.LocalContent,
constructors = (LocalContent.manage_addLocalContentForm,
LocalContent.manage_addLocalContent),
icon='img/local_content.gif')
# Register MessageCatalog
context.registerClass(
MessageCatalog.MessageCatalog,
constructors = (MessageCatalog.manage_addMessageCatalogForm,
MessageCatalog.manage_addMessageCatalog),
icon='img/message_catalog.gif')
# Register LocalFolder
context.registerClass(
LocalFolder.LocalFolder,
constructors = (LocalFolder.manage_addLocalFolderForm,
LocalFolder.manage_addLocalFolder),
icon='img/local_folder.gif')
context.registerHelp()
# Register the dtml-gettext tag
String.commands['gettext'] = GettextTag
***************************************************************************
See the "RELEASE.txt" file
***************************************************************************
1.1.2 (2005/10/21)
Upgrade to itools 0.9
1.1.1 (2005/05/26)
User Interface
- Improved message catalog user interface, suggested by Christopher
Lozinski.
Fixes
- Fix "LPM.get_available_languages" when property is empty.
- Backwards compatility improvements by Yoshinori Okuji.
- Fix Localizer with Zope 2.8, problem found by Lennart Regebro.
- Fixed english of the release notes, by Chris H.
1.1.0 (2005/04/10)
Nothing new, just some information files have been updated.
1.1.0rc1 (2005/03/21)
User Interface
- The text area to edit local properties is bigger now.
Packaging
- Check itools and iHotfix are installed.
1.1.0b5 (2005/01/28)
ZPT
- More robust support for the "i18n" namespace, check the domain object is
a message catalog.
User Interface
- New LocalPropertyManager/LocalContent interface, by Cornel Nitu.
Translations
- Updated the portuguese translation, by Rodrigo Senra.
Plone
- Remove conflict with PlacelessTranslationService, Plone and Localizer
work again together.
1.1.0b4 (2005/01/09)
ZPT
- Add support for i18n:domain
1.1.0b3 (2004/12/17)
Translations
- Added the italian version, by Marco Bizzarri
***************************************************************************
See "RELEASE.txt" for the changes between 0.8.1 and 1.1.0b3
***************************************************************************
0.8.1 (2002/02/25)
Now the language selection algorithm is compliant with the
RFC 2068 (HTTP 1.1).
New meta type LocalFolder. Now the "locale folders" feature of
the Localizer meta type are is deprecated, the new meta type
LocalFolder should be used instead.
Change internationalization of Python code from Python products.
Little cleanups: LocalObjects moved to LocalFiles;..
0.8.0 (2002/01/31)
Fixed bug in the ZMI reported by Magnus Heino.
Fixed use of file system message catalogs from ZPT.
Some improvements in the LanguageManager API.
Updated the few tests available to use PyUnit.
Fixed export of message catalogs, now the empty message is included.
Now LocalContent is CatalogAware, still remains to update the catalog
each time it's edited.
Now LocalPropertyManager implements __getattr__ to define attributes
of the form <name>_<lang>.
Moved the changeLanguageForm and changeLanguage helper methods to
the LanguageManager class.
Added the ugettext method in LocalObjects, beginning to work with
unicode.
Disabled the global gettext method that was added with a dynamnic patch
to to the Application class.
Improvements in the LocalPropertyManager web interface.
Now it's possible to change the default template for a LocalContent object.
0.7.1 (2001/10/26)
Improved zgettext.py script
First unit tests.
More online help screens.
Several security fixes.
Several bugs fixed.
Some minor improvements in the user interfaces.
Completed internationalization.
Updated several translations: french, hungarian and spanish.
0.7.0 (2001/10/10)
Several fixes in zgettext.py
New meta type MessageCatalog, it's possible to create message catalogs
with any id. Now the Localizer class no longer stores messages, but it
can contain MessageCatalog instances; specifically, if it contains a
MC named "Messages" gettext will behave in a similar way than before.
New mixin class LanguageManager that allows to manage list of available
languages and a default language. Used in LocalPropertyManager,
MessageCatalog and Localizer classes.
Added a dtml-gettext tag, useful for long messages.
Added the hungarian translation, thanks to Gabor Suveg.
Updated documentation.
More online help screens, improved some web interfaces.
0.6.2 (2001/10/01)
Completed the list of languages, ISO 639 compliance.
Now the language negotation algortithm is implemented in
a helper function (before this code was replicated in several
places).
Improvements in the message catalog user interface. Added a
help screen.
Minor changes in standard files (VERSION.txt and LICENSE.txt)
to comply ZDG guidelines.
0.6.1 (2001/09/28)
Added "original language" to LocalPropertyManager.
Minor improvements in the LocalPropertyManager user interface.
Now Localizer can be refreshed, except if Zope version >= 2.4.1b1.
Added the basque translation.
changeLanguageForm is a LocalDTMLFile again. Read UPGRADE.txt if
you're upgrading from 0.6.0
Some internal changes in the way message translations are searched.
Sometimes the translations were looked for in the wrong place, this
bug is fixed.
Now the localizer tutorial works with Zope < 2.4
0.6.0 (2001/09/25)
LocalPropertyManager
LocalProperty must be used always.
Improved user interface: posibility to add/delete languages;
show only few properties at a time.
Added a isLocalPropertyManager class attribute.
LocalPropertyManager can be used as base class for ZClasses.
LocalContent
Inherit also from PropertyManeger.
Localizer
Export and import message catalogs to and from .pot/.po files.
Changed the way to hook/unhook the traversal machinery.
Now changeLanguageForm is a DTML Method.
Now get_available_languages returns a list of tuples: [(id, title),..]
New method get_languages_map, used from changeLanguageForm.
Securtiy
Use "Declarative Assertions".
Several bugs fixed, mainly related with local folders. Also fixes
in zgettext.py, and probably others I don't remember now.
0.5.1 (2001/07/19)
Several fixes for LocalPropertyManager and LocalContent.
Added a tutorial (localizer_tutorial.zexp).
Now __version__ module attributes show the CVS revision number.
0.5.0 (2001/07/17)
Reorganization of the directory structure.
Added the LocalPropertyManager and LocalContent classes.
Patch OFS.Image to prevent browsers to cache images in localized folders.
0.4.0 (2001/07/10)
The gettext and locale modules have been removed, Python 2.x required.
License changed to GPL.
Management interface tabs internationalized, spanish and catalan
translations updated.
Fixed a bug in changeLanguage when the Localizer was used with other
SiteAccess, virtual hosting for example.
The script zgettext now keeps the locale.pot changes and uses msgmerge
to build the .po files.
Added new files BUGS.txt, TODO.txt and UPGRADE.txt
Old LocalizedDTMLFile removed.
0.3.0 (2001/06/..)
Fixed a bug that prevented proper copy&paste of Localized objects.
Changed the usage of localized dtml files, old usage preserved for
backwards compatibility.
Added support for page template files. Added documentation about
how to localize zpt.
0.2.1 (2001/05/23)
Ops, 0.2.0 bug fixed, I should test the code before releasing it,
apologies.
0.2.0 (2001/05/22)
Localized strings are looked for in all the Localizer instances in the path.
Now it's possible to override the user prefered language with the path.
Added the german version.
Some bugs fixed.
0.1.1 (2001/??/??)
Bug fixing release.
0.1.0 (2001/??/??)
Initial version.
Localizer 0.9.0
===============
General arquitecture
In the version 0.9 there're four meta types (Localizer, MessageCatalog,
LocalContent and LocalFolder), each one specialized in one task, finishing
this way with the confusion present in previous versions, where the
different features weren't clearly separated.
Previous versions mixed two features in the Localizer meta type, language
negotiation and generic support of multilingual objects.
Now the Localizer meta type is specialized in language negotiation. And a
new meta type, named LocalFolder, provides the generic support for language
negotiation following a different approach.
The old "locale folders" feature that was present in the Localizer meta
type has been definitely removed.
Language negotiation
This is one of the areas that has seen mayor improvements since version
0.8, now there's a simple default criteria to choose the language, based
only in the browser configuration. But the developer has much more power
to customize the language negotiation policy through the Localizer meta
type.
Also, the algorithm that chooses the language is finally standards compliant.
Unicode
The Unicode support is another of the big new features in this version.
To implement it now Localizer depends on the Unicode patches from Toby
Dickenson (http://www.zope.org/Members/htrd/wstring), which are part of
Zope since the version 2.6.
Now the policy is to use Python Unicode strings for everything:
- translations in the message catalog are stored as unicode strings;
- multilingual properties of LocalContent objects are stored as unicode
strings;
- the gettext method, when used from the file system, always returns
unicode strings (as the "ugettext" method of the "gettext" python
module).
The problem could raise when unicode and normal strings are mixed. By
default Python converts the normal strings to unicode as if they were
in ASCII. However, in Zope the default is considered to be iso-8859-1,
which is hardcoded in several places. Just be careful if you mix normal
and unicode strings, specially if they're in an encoding different than
iso-8859-1.
But maybe the main problem is the lack of proper unicode support in ZPT,
this will cause problems to anybody that wants to use ZPT and Unicode.
So it's likely that both Zope and Localizer will need a bit of work before
the Unicode support becomes stable.
Message Catalog
The message catalog interface has been completely redone. Now it correctly
supports multiline messages, including correct import and export from and
to PO files (thanks to Jean-Paul Smets).
There're other minor changes, like some improvements in the management
screens. The relevant links are:
- Home page
http://www.j-david.net/localizer
- Download
http://sourceforge.net/projects/lleu
- Mailing list
http://mail.freesoftware.fsf.org/mailman/listinfo/nuxeo-localizer
Localizer 0.9.1
===============
Localizer is a Zope [1] product that provides a set of facilities
to develop multilingual web applications. It offers solutions to
internationalize the user interfaces and to manage multilingual
content.
Localizer becomes beta
----------------------
Finally I've decided to officially declare Localizer as beta. This
means that no new features will be added for the 1.0 release, the
focus will be stability and documentation.
What's new
----------
Added unicode support to ZPT. Final version by Florent Guillaume.
New icons for all the meta types. Now Localizer has a logo (see logo.gif).
This is a contribution of Maite Rementeria, from Code&Syntax [2].
Spanish translation updated. New japanese version!, by Kazuya Fukamachi.
Some minor bugs fixed.
Resources
---------
Home page
http://www.j-david.net/software/localizer
Download
http://sourceforge.net/projects/lleu
Mailing list
http://mail.freesoftware.fsf.org/mailman/listinfo/nuxeo-localizer
Footnotes
---------
[1] http://www.zope.org
[2] http://www.codesyntax.com
Localizer 0.9.2
===============
Localizer is a Zope product that provides a set of facilities
to develop multilingual web applications. It offers solutions to
internationalize the user interfaces and to manage multilingual
content.
This is a bug fix release, the changes are:
- The "zgettext.py" script correctly parses Python files, to do
it the xgettext program from the GNU Gettext utilities is used.
- Now "zgettext.py" don't preserves the old messages in the
locale.pot file.
- Updated the Unicode patch, by Florent Guillaume.
- In some rare conditions the request object dissapears from the
global dictionary, this produces a key error when it's tried to be
removed. Fixed catching the exception (I couldn't reproduce the
error).
And a new "feature":
- Added the new module "LocalizerSupport.py", it helps to develop
Localizer based products that become monolingual when Localizer
is not installed (instead of becoming broken). It provides dummy
versions for some of the features of Localizer, not all.
Resources
---------
Home page
http://www.j-david.net/software/localizer
Download
http://sourceforge.net/projects/lleu
Mailing list
http://mail.freesoftware.fsf.org/mailman/listinfo/nuxeo-localizer
Localizer 0.9.3
===============
Localizer is a Zope product that provides a set of facilities
to develop multilingual web applications. It offers solutions to
internationalize the user interfaces and to manage multilingual
content.
This is a bug fix release, the changes are:
- Open MO files as binary files, this caused problems on Windows.
Thanks to Johan Carlsson
- Correctly copy and paste Localizer instances.
- Correctly detect Netscape 4.x, before Internet Explorer was thought
to be NS, this caused problems with the language negotiation. Thanks
to Olivier Nibart.
- Add the languages from a Localizer instance (if it exists) to the
languages input box of the LocalFolder add screen (as it already
was done with LocalContent).
- Quote messages in the Message Catalog interface, thanks to Geir Bækholt.
Resources
---------
Home page
http://www.localizer.org
Download
http://sourceforge.net/projects/lleu
Mailing list
http://mail.freesoftware.fsf.org/mailman/listinfo/nuxeo-localizer
Localizer 1.0.0
===============
Localizer is a Zope product that provides a set of facilities
to develop multilingual web applications. It offers solutions to
internationalize the user interfaces and to manage multilingual
content.
This is a bug fix release, the changes are:
- The dynamic global request patch is not installed if the static
version (by Tim McLaughlin) is already applied.
Resources
---------
Home page
http://www.localizer.org
Download
http://sourceforge.net/projects/lleu
Mailing list
http://mail.freesoftware.fsf.org/mailman/listinfo/nuxeo-localizer
Localizer 1.0.1
===============
Localizer is a Zope product that provides a set of facilities
to develop multilingual web applications. It offers solutions to
internationalize the user interfaces and to manage multilingual
content.
The changes of this release are:
- Added missing docstring to the Localizer class, thanks to
Christian Scholz.
- Strip the quality when parsing an accept header, this lets the
browser w3m and mobile phones to work, thanks to Helge Tesdal.
- Don't trigger Localizer instances when traversing if the request
variable AcceptLanguage does not exist. Thanks to Florent Guillaume.
- Now LocalPropertyManager.get_default_language returns None if
there isn't _default_language and get_languages returns an
empty list. Thanks to Greg Ward.
- Renamed the VERSION.txt file to version.txt, this lets to see the
version string from the control panel in the Zope management screens.
Thanks to Gilles Lenfant.
- Fixed bug in MessageCatalog.manage_export, thanks to Joachim Werner.
Resources
---------
Home page
http://www.localizer.org
Download
http://sourceforge.net/projects/lleu
Mailing list
http://mail.freesoftware.fsf.org/mailman/listinfo/nuxeo-localizer
Localizer 1.1
=============
April 11, 2005 - Two years after release of Localizer 1.0, I am
pleased to announce the availability of the next major version,
Localizer 1.1.
Localizer is a Zope [1] product for developers and web masters.
Localizer solves the problem of building multilingual products
and web sites, ranging from internationalization and localization
of the user interface to management of multilingual content.
jdavid at itaapy.com [2]
What's new in 1.1
-----------------
This release brings several new features. Specifically Localizer
now supports industry standards such as TMX [3] and XLIFF [4],
which enhance the interoperability of Localizer based applications
within mainstream environments.
Native support for 'i18n' namespaces for ZPT (Zope Page Templates)
is included avoiding the need to install other products.
The user interfaces have been vastly improved, specially for
'LocalContent' objects.
Four new translations are available: Danish, Italian, Portuguese
and Russian.
Localizer 1.1 has been re-packaged and now depends on itools Python
package and iHotfix Zope product. While these changes make installation
a bit more complex, the added benefit is simplified source management.
Furthermore this subtle change makes Localizer Services available to
the wider audience of Python [5] developers.
Last but not least, Localizer's stability has been dramatically
improved by resolution of many bugs resulting in a mature and even
more reliable product.
Credits
-------
This is the first release where the majority of work has been
contributed by community users and the original author. Credit
where credit is due.
To Eduardo Corrales and Roberto Quero from the Deusto University [6],
for the original implementation of the TMX standard.
To Søren Roug and Cornel Nitu from the European Environment Agency [7],
for their work on the TMX code, the implementation of the XLIFF standard,
the overhaul of the LocalContent interfaces, and the Danish translation.
To Alexey Lubimov for the Russian translation.
To Mario Olimpio de Menezes for the original Portuguese translation.
To Rodrigo Senra for updating the Portuguese translation, and for improving
the Localizer API.
To Marco Bizzarri for the Italian translation, and for improving the
stability.
Download and Install
--------------------
1. Download the Localizer meta-package from http://www.localizer.org
2. Unpack the tarball
3. Follow the instructions within the README file
Resources
---------
Home
http://www.localizer.org
Mailing list
http://in-girum.net/mailman/listinfo/localizer
Bug Tracker
http://in-girum.net/cgi-bin/bugzilla/index.cgi
References
----------
[1] http://www.zope.org
[2] http://www.itaapy.com
[3] http://www.lisa.org/tmx/
[4] http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xliff
[5] http://www.python.org
[6] http://www.deusto.es/
[7] http://www.eea.eu.int/
Localizer 1.1.3 (2006/12/13)
============================
Localizer is a Zope product for developers and web masters. Localizer
solves the problem of building multilingual products and web sites,
ranging from internationalization and localization of the user interface
to management of multilingual content.
The 1.1.3 release brings some new features for ZPT. Most important is
the support of interpolation. And now message catalogs are searched for
within the "Localizer" objects, if it exists.
There are also a couple of bugs fixed:
- The method "LocalPropertyManager.__getattr__" works again.
- The function "Utils.lang_negotiator" works now when the context
is not available.
Credits:
- Mikel Larreategi fixed "LocalPropertyManager.__getattr__".
- Josef Meile worked on ZPT.
- Yoshinori Okuji fixed "Utils.lang_negotiator".
Resources
---------
Download
http://download.ikaaro.org/localizer/Localizer-1.1.3.tar.gz
Home
http://www.localizer.org
Mailing list
http://mail.ikaaro.org/mailman/listinfo/localizer
Bug Tracker
http://bugs.ikaaro.org/
ASCII
ISO-8859-1
ISO-8859-2
ISO-8859-3
ISO-8859-4
ISO-8859-5
ISO-8859-6
ISO-8859-7
ISO-8859-8
ISO-8859-9
ISO-8859-13
ISO-8859-15
KOI8-R
KOI8-U
CP850
CP866
CP874
CP932
CP949
CP950
CP1250
CP1251
CP1252
CP1253
CP1254
CP1255
CP1256
CP1257
GB2312
EUC-JP
EUC-KR
EUC-TW
BIG5
BIG5-HKSCS
GBK
GB18030
SHIFT_JIS
JOHAB
TIS-620
VISCII
UTF-8
<configure xmlns="http://namespaces.zope.org/zope">
<subscriber
for="Products.Localizer.Localizer.Localizer
zope.lifecycleevent.interfaces.IObjectMovedEvent"
handler="Products.Localizer.Localizer.Localizer_moved" />
<subscriber
for="Products.Localizer.MessageCatalog.MessageCatalog
zope.lifecycleevent.interfaces.IObjectMovedEvent"
handler="Products.Localizer.MessageCatalog.MessageCatalog_moved" />
</configure>
Localizer 1.2.0 (2006/12/22)
============================
Localizer is a Zope product for developers and web masters. Localizer
solves the problem of building multilingual products and web sites,
ranging from internationalization and localization of the user interface
to management of multilingual content.
The release 1.2.0 is a version update: it requires Python 2.4 and
itools 0.13.10, and the product iHotfix is not required anymore (it
has been merged back into Localizer).
This grid show the possible software combinations:
Localizer Python Zope itools
1.2 2.4 2.9, 2.10 0.13
1.1 (+iHotfix) 2.3 2.7, 2.8 0.9
1.0 2.1 2.6 ---
Of course it is recommended to use Localizer 1.2 with Zope 2.9 or later.
Resources
---------
Download
http://download.ikaaro.org/localizer/Localizer-1.2.0.tar.gz
http://download.ikaaro.org/itools/itools-0.13.10.tar.gz
Home
http://www.localizer.org
Mailing list
http://mail.ikaaro.org/mailman/listinfo/localizer
Bug Tracker
http://bugs.ikaaro.org/
Localizer 1.2.1 (2007/02/12)
============================
Localizer is a Zope product for developers and web masters. Localizer
solves the problem of building multilingual products and web sites,
ranging from internationalization and localization of the user interface
to management of multilingual content.
Fixed a serious regression, with 1.2.0 the Localizer object (used to
customize the language negotiation policy) stopped working. Thanks to
Igor Leturia for pointing out the problem.
Resources
---------
Download
http://download.ikaaro.org/localizer/Localizer-1.2.1.tar.gz
http://download.ikaaro.org/itools/itools-0.13.10.tar.gz
Home
http://www.localizer.org
Mailing list
http://mail.ikaaro.org/mailman/listinfo/localizer
Bug Tracker
http://bugs.ikaaro.org/
Localizer 1.2.2 (2008/01/18)
============================
Localizer is a Zope product for developers and web masters. Localizer
solves the problem of building multilingual products and web sites,
ranging from internationalization and localization of the user interface
to management of multilingual content.
What is new?
- Upgraded itools version to 0.20
- Compatibility fixes for Zope 2.10
- Upgraded the license to GPL version 3
Resources
---------
Download
http://download.ikaaro.org/localizer/Localizer-1.2.2.tar.gz
http://download.ikaaro.org/itools/itools-0.20.2.tar.gz
Home
http://www.localizer.org
Mailing list
http://mail.ikaaro.org/mailman/listinfo/localizer
Bug Tracker
http://bugs.ikaaro.org/
Localizer 1.2.3 (2008/12/03)
============================
Localizer is a Zope product for developers and web masters. Localizer
solves the problem of building multilingual products and web sites,
ranging from internationalization and localization of the user
interface to management of multilingual content.
What is new?
- Compatibility fixes for Zope 2.10/2.11 (bug #381)
- Other minor fixes (including bug #304)
Resources
---------
Download
http://download.hforge.org/localizer/Localizer-1.2.3.tar.gz
http://download.hforge.org/itools/itools-0.20.6.tar.gz
Home
http://www.localizer.org/
Mailing list
http://www.hforge.org/community
http://archives.hforge.org/index.cgi?list=localizer
Bug Tracker
http://bugs.hforge.org/
_build
figures
autodoc/modules
# -*- coding: utf-8 -*-
#
# Localizer documentation build configuration file, created by
# sphinx-quickstart on Fri Nov 19 19:55:33 2010.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Localizer'
copyright = u'2010, J. David Ibáñez'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '1.2'
# The full version, including alpha/beta/rc tags.
release = '1.2.3'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'Localizerdoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'Localizer.tex', u'Localizer Documentation',
u'J. David Ibáñez', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'localizer', u'Localizer Documentation',
[u'J. David Ibáñez'], 1)
]
This diff is collapsed.
This diff is collapsed.
Introduction
============
This chapter provides background information about the topic. And also links
if you want to learn more. The sections are:
.. toctree::
:maxdepth: 1
i18n
unicode
multilingual-software
multilingual-data
web
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
The web
=======
A personal computer is configured with what is known as a locale, it specifies
the encoding system, the user language, the timezone and other parameters that
will be used by the applications to show their interfaces adapted to the user.
When an application starts, for example a word processor, it reads the locale
information, it only needs to be done once, at the begining. This process is
more complex in a networking environment like the web, where there are many
computers involved with different locale configurations.
In the web the client must send the locale information to the server each time
it requests a page. With this information the server can decide in which
language send the data.
Things become more complex when there is a cache between the server and the
client, then the needed dialog to choose the language involves more parties,
the server, the client and the cache.
.. seealso::
Related links
* `HTTP 1.1 language negotiation
<http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4>`_
* `Apache content negotiation
<http://httpd.apache.org/docs-2.0/content-negotiation.html>`_
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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