Commit 70ebcd1a authored by Yoshinori Okuji's avatar Yoshinori Okuji

Base18 is not used any longer.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@20715 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent f7194b71
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
__version__ = "$Revision$"[11:-2]
__doc__ = "This product provides the basic behaviour to CMF object which need\
translation"
from OFS.Folder import Folder
from Products.CMFCore import CMFCorePermissions
from Products.CMFCore.PortalContent import PortalContent
from Products.CMFCore.PortalFolder import PortalFolder
from AccessControl import ClassSecurityInfo
from Products.Localizer.Utils import lang_negotiator
from utils import _translate_stx
from zLOG import LOG
class Base18(PortalContent):
""" Base18 implements the basic translation tactics"""
# Declarative security
security = ClassSecurityInfo()
### Delegate to central repository
def findMessageCatalog(self):
return self.portal_translations.findMessageCatalog(self)
### Common translation methods
security.declareProtected(CMFCorePermissions.View, 'TranslatedDescription')
def TranslatedDescription(self):
"""
Returns translated desc
"""
return self.findMessageCatalog().gettext(self.Description())
security.declareProtected(CMFCorePermissions.View, 'getTranslatedDescription')
getTranslatedDescription = TranslatedDescription
security.declareProtected(CMFCorePermissions.View, 'TranslatedTitle')
def TranslatedTitle(self):
"""
Returns a translated title
"""
#LOG('TranslatedTitle',0,str(self))
return self.findMessageCatalog().gettext(self.Title())
security.declareProtected(CMFCorePermissions.View, 'getTranslatedTitle')
getTranslatedTitle = TranslatedTitle
security.declareProtected(CMFCorePermissions.View, 'TranslatedTitle_or_id')
def TranslatedTitle_or_id(self):
"""
Returns a translated title if title exists
or id otherwise
"""
title=self.title
if callable(title):
title=title()
if title: return self.findMessageCatalog().gettext(title)
return self.getId()
security.declareProtected(CMFCorePermissions.View, 'getTranslatedTitle_or_id')
getTranslatedTitle_or_id = TranslatedTitle_or_id
security.declareProtected(CMFCorePermissions.View, 'getNegotiatedLanguage')
def getNegotiatedLanguage(self,md=None):
if md is None: md = self.findMessageCatalog()
available_languages = list(md._languages)
# Get the language!
lang = lang_negotiator(available_languages)
# Is it None? use the default
if lang is None:
lang = md._default_language
return lang
### Generic Translation methods
security.declareProtected(CMFCorePermissions.View, 'TranslatedBody')
def TranslatedBody(self, stx_level=None, setlevel=0, lang=None, md=None):
"""\
Equivalent to CookedBody but returns a translated version thanks
to the use of message catalog
"""
if md is None: md = self.findMessageCatalog()
if stx_level is None:
stx_level = self._stx_level
cooked = _translate_stx(self.text, md, stx_level, lang)
return cooked
security.declareProtected(CMFCorePermissions.View, 'getTranslatedBody')
getTranslatedBody = TranslatedBody
# Catalog Related Method (required for ERP5)
def getObject(self, REQUEST=None):
"""Returns self - useful for ListBox"""
return self
# For Compatibility Purpose
PortalContent.getTranslatedTitle = Base18.TranslatedTitle
PortalContent.TranslatedTitle = Base18.TranslatedTitle
PortalContent.getTranslatedTitle_or_id = Base18.TranslatedTitle_or_id
PortalContent.TranslatedTitle_or_id = Base18.TranslatedTitle_or_id
PortalFolder.getTranslatedTitle = PortalContent.title_or_id
PortalFolder.TranslatedTitle = PortalContent.title_or_id
PortalFolder.getTranslatedTitle_or_id = PortalFolder.title_or_id
PortalFolder.TranslatedTitle_or_id = PortalFolder.title_or_id
Folder.getTranslatedTitle = Folder.title_or_id
Folder.TranslatedTitle = Folder.title_or_id
Folder.getTranslatedTitle_or_id = Folder.title_or_id
Folder.TranslatedTitle_or_id = Folder.title_or_id
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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 Zope Public License (ZPL) Version 2.0
#
# 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.
#
##############################################################################
from Products.CMFCore.CookieCrumbler import CookieCrumbler
from urllib import quote
from AccessControl import ClassSecurityInfo
class Base18CookieCrumbler(CookieCrumbler):
# Dynamic Patch Class
# Declarative security
security = ClassSecurityInfo()
security.declarePublic('getLoginURL')
def getLoginURL(self):
"""
Redirects to the login page.
XXX Take from CookieCrumbler -> license should be ZPL
"""
if self.auto_login_page:
req = self.REQUEST
resp = req['RESPONSE']
iself = getattr(self, 'aq_inner', self)
parent = getattr(iself, 'aq_parent', None)
page = getattr(parent, self.auto_login_page, None)
if page is not None:
retry = getattr(resp, '_auth', 0) and '1' or ''
came_from = req.get('came_from', None)
if came_from is None:
came_from = req['URL']
came_from_list = list(came_from.split('/'))
# Find the object where we came form
# And forget about trailing URL
try:
came_from_object = parent.restrictedTraverse(came_from_list[3:-1])
url = '%s?came_from=%s&retry=%s&disable_cookie_login__=1' % (
came_from_object.local_absolute_url(target=page), quote(came_from), retry)
return url
except:
try:
url = '%s?came_from=%s&retry=%s&disable_cookie_login__=1' % (
self.local_absolute_url(), quote(came_from), retry)
#self.local_absolute_url(target=page), quote(came_from), retry)
except:
relative_url = self.portal_url.getRelativeUrl(self)
absolute_url=self.portal_url.getPortalObject().absolute_url()
local_absolute_url='%s/%s' % (absolute_url,relative_url)
url = '%s?came_from=%s&retry=%s&disable_cookie_login__=1' % (
local_absolute_url, quote(came_from), retry)
return url
return None
# Dynamic Patch
CookieCrumbler.getLoginURL = Base18CookieCrumbler.getLoginURL
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
__version__ = "$Revision$"[11:-2]
__doc__ = "This product provides multilingual capabilities to the CMFDefault \
Document"
from utils import _translate_stx, _translate_html
from Globals import InitializeClass, PersistentMapping
from AccessControl import ClassSecurityInfo
from Products.CMFCore import CMFCorePermissions
from Products.Localizer.MessageCatalog import MessageCatalog
from Products.CMFDefault.Document import Document
from Base18 import Base18
#import zLOG
# Content Creator
def addDocument18(self, id, title='', description='', text_format='',
text=''):
""" Add a Multilingual Document """
o = Document18(id, title, description, text_format, text)
self._setObject(id,o)
# Content Class
class Document18(Document,Base18):
""" A Multilingual Document - Handles both StructuredText and HTML
and translates sentences through a portal_translations tool
"""
meta_type = 'Base18 Document'
portal_type = 'Document'
isPortalContent = 1
# Default values
cached_translations = None
# Declarative security
security = ClassSecurityInfo()
# CMF Factory Type Information
factory_type_information = ( { 'id' : portal_type
, 'meta_type' : meta_type
, 'description' : """\
Document can contain text that can be formatted using 'Structured Text.\
Text can be automatically translated through the use of message catalogs.'"""
, 'icon' : 'document_icon.gif'
, 'product' : 'Base18'
, 'factory' : 'addDocument18'
, 'immediate_view' : 'metadata_edit_form'
, 'actions' :
( { 'id' : 'view'
, 'name' : 'View'
, 'action' : 'document18_view'
, 'permissions' : (
CMFCorePermissions.View, )
}
, { 'id' : 'print'
, 'name' : 'Print'
, 'action' : 'document18_print'
, 'permissions' : (
CMFCorePermissions.View, )
}
, { 'id' : 'edit'
, 'name' : 'Edit'
, 'action' : 'document_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
, { 'id' : 'metadata'
, 'name' : 'Metadata'
, 'action' : 'metadata_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
, { 'id' : 'translate'
, 'name' : 'Translate'
, 'action' : 'translation_template'
, 'permissions' : (
CMFCorePermissions.View, )
}
)
}
,
)
### Content accessor methods
security.declareProtected(CMFCorePermissions.View, 'SearchableText')
def SearchableText(self, md=None):
"""\
Used by the catalog for basic full text indexing
We are going to concatenate all available translations
"""
if md is None: md = self.findMessageCatalog()
searchable_text = ""
for lang in md.get_languages():
searchable_text = searchable_text + "%s %s %s" % (
md.gettext(self.Title(),lang)
, md.gettext(self.Description(),lang)
, self.TranslatedBody(lang=lang)
)
return searchable_text
# Source Text access
security.declareProtected(CMFCorePermissions.View, 'getText')
def getText(self):
"""
Returns source text
"""
return self.text
# Specific Translation methods
security.declareProtected(CMFCorePermissions.View, 'TranslatedBody')
def TranslatedBody(self, stx_level=None, setlevel=0, lang=None, md=None):
"""\
Equivalent to CookedBody but returns a translated version thanks
to the use of message catalog
"""
if md is None: md = self.findMessageCatalog()
if stx_level is None: stx_level = self._stx_level
if lang is None: lang = self.getNegotiatedLanguage(md)
#zLOG.LOG('Language',0,lang)
# Create a translation cache if necessary
if self.cached_translations is None:
self.cached_translations = PersistentMapping()
if not self.cached_translations.has_key(lang) or \
stx_level != self._stx_level:
if self.text_format == 'html':
cooked = _translate_html(self.text, md, stx_level, lang)
else:
cooked = _translate_stx(self.text, md, stx_level, lang)
self.cached_translations[lang] = \
(md.bobobase_modification_time(),cooked)
elif self.cached_translations[lang][0] != \
md.bobobase_modification_time() or \
self.cached_translations[lang][1] != \
self.bobobase_modification_time():
if self.text_format == 'html':
cooked = _translate_html(self.text, md, stx_level, lang)
else:
cooked = _translate_stx(self.text, md, stx_level, lang)
self.cached_translations[lang] = (md.bobobase_modification_time(),
self.bobobase_modification_time(),cooked)
else:
cooked = self.cached_translations[lang][2]
return cooked
security.declareProtected(CMFCorePermissions.View, 'TranslationTemplate')
def TranslationTemplate(self):
"""\
This method allows to produce of .pot file for this document
"""
# Create a new catalog
md = MessageCatalog('temp', 'Temporary Message Catalog',
self.findMessageCatalog().get_languages())
# Do some dirty acquisition trick
md.aq_base = self
# Run the md on the text body, title and description
cooked = _translate_stx(self.text, md, self._stx_level, None)
md.gettext(self.Title())
md.gettext(self.Description())
# And return the template
return md.manage_export('locale.pt')
InitializeClass(Document18)
Document = Document18
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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 Zope Public License (ZPL) Version 2.0
#
# 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.
#
##############################################################################
"""
Converts instances of Products.CMFDefault.<content> to
instances of Products.Base18.<content>.
"""
# Source
import Products.CMFDefault.NewsItem
import Products.CMFDefault.Link
import Products.CMFDefault.Document
import Products.CMFDefault.File
import Products.CMFDefault.Image
import Products.CMFDefault.DiscussionItem
import Products.CMFDefault.Favorite
import Products.CMFCore.PortalFolder
# Destination
import Products.Base18.NewsItem
import Products.Base18.Replica
import Products.Base18.Document
#
import re
from zLOG import LOG
migrations = {
Products.CMFDefault.Document.Document :\
Products.Base18.Document.Document18,
Products.CMFDefault.NewsItem.NewsItem :\
Products.Base18.NewsItem.NewsItem18,
Products.CMFDefault.Link.Link :\
Products.Base18.Replica.Link18,
Products.CMFDefault.File.File :\
Products.Base18.Replica.File18,
Products.CMFDefault.Image.Image :\
Products.Base18.Replica.Image18,
Products.CMFDefault.DiscussionItem.DiscussionItem :\
Products.Base18.Replica.DiscussionItem18,
Products.CMFDefault.Favorite.Favorite :\
Products.Base18.Replica.Favorite18,
Products.CMFCore.PortalFolder.PortalFolder :\
Products.Base18.Replica.SkinnedFolder18,
Products.CMFWiki.CMFWikiPage.CMFWikiPage :\
Products.Base18.Wiki.CMFWikiPage18,
Products.CMFWiki.CMFWikiPage.CMFWikiFolder :\
Products.Base18.Wiki.CMFWikiFolder18
}
def update_folder(obj):
"""
Folder needs to be updated in order to take into account
changes of classes and in particular meta_type
"""
obase = getattr(obj, 'aq_base', obj)
new_objects =[]
if not obase.__dict__.has_key('_objects'):
return
for dict in obase.__dict__['_objects']:
new_objects.append({'id':dict['id'],
'meta_type': obj._getOb(dict['id']).meta_type})
obase.__dict__['_objects'] = tuple(new_objects)
def migrate_branches(migrations, branch, migrated, visited):
base = getattr(branch, 'aq_base', branch)
if base in visited:
# Don't visit again!
return
visited.append(base)
try: changed = branch._p_changed
except: changed = 1
for id in branch.objectIds():
obj = branch._getOb(id)
LOG("Here",0,id)
obase = getattr(obj, 'aq_base', obj)
klass = obase.__class__
if migrations.has_key(klass):
# Replace this object.
changed = 1
try:
newob = migrations[klass](obase.id)
newob.id = obase.id # This line activates obase.
except:
newob = migrations[klass](id)
newob.id = id
keys = obase.__dict__.keys()
for k in keys:
if k is not 'id':
migrated.append(" %s" % k)
setattr(newob,k,obase.__dict__[k])
#obase = getattr(newob, 'aq_base', obj)
#obase.__dict__.update(obase.__dict__)
#newob.portal_type =
# migrations[klass].factory_type_information[0].id
setattr(branch, id, newob)
#obj.__class__ = migrations[klass]
migrated.append(obj.absolute_url())
# Keep on processing if necessary
obj = branch._getOb(id)
obase = getattr(obj, 'aq_base', obj)
if hasattr(obase, 'objectIds') and \
re.search('Folder',obase.meta_type) is not None:
# Enter a sub-branch.
migrate_branches(migrations, obj, migrated, visited)
# Update meta_type
update_folder(obj)
elif hasattr(obase, 'objectIds') and \
re.search('Folder',obase.meta_type) is not None:
# Enter a sub-branch.
migrate_branches(migrations, obj, migrated, visited)
# Update meta_type
update_folder(obj)
else:
# Unload this object if it has not been changed.
try:
if obj._p_changed is None:
obj._p_deactivate()
except: pass
if changed is None:
# Unload this branch.
object._p_deactivate()
del visited[-1] # ????
# Main Script
def main(REQUEST):
container = REQUEST.PARENTS[0]
pt = container.portal_types
ps = container.portal_skins
# Add FTI
ptlist = ['Document','Image','File','Link','News Item','Folder',
'Discussion Item','Favorite','Translation','Wiki', 'Wiki Page']
for oid in ptlist:
try: pt.manage_delObjects((oid,))
except: pass
pt.manage_addTypeInformation(id=oid,typeinfo_name="Base18: Base18 %s"
% oid)
# Add Skin
try:
from Products.CMFCore.DirectoryView import createDirectoryView
createDirectoryView(ps,'Products/Base18/skins/content18',
id='content18')
except: pass
# Add Translation and Membership Tools
try: container.manage_delObjects(('portal_membership',))
except: pass
addBase18Tool = container.manage_addProduct['Base18'].manage_addTool
try: addBase18Tool('Base18 Translation Tool', None)
except: pass
try: addBase18Tool('Base18 Membership Tool', None)
except: pass
# Eventually keep folder on preferences here
# Add Message Catalog
from Products.Localizer.MessageCatalog import manage_addMessageCatalog
try: manage_addMessageCatalog(container, 'gettext', '',('en',))
except: pass
# Update Content
visited = []
migrated = []
migrate_branches(migrations, container, migrated, visited)
update_folder(container)
from string import join
return 'Converted:\n%s\n\nDone.' % join(migrated, '\n')
# Show Attributes
def showDict(self):
ob = getattr(self,'aq_base')
return "%s \n %s" % (str(ob.__class__) , ob.__dict__)
#return str(ob.__class__) + '\n' + str(ob.meta_type) + '\n' +
# str(ob.portal_type) + '\n'
##############################################################################
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability 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
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from Replica import SkinnedFolder18
Folder18 = SkinnedFolder18
Folder = SkinnedFolder18
\ No newline at end of file
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
##############################################################################
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
Warning
This product is a proof of concept for hard core Zope developers.
Wait version 0.2 to get something usable
Requirements
You will need a Zope system with "CMF":http://cmf.zope.org
and with "Localizer":http://www.nuxeo.org/localizer
Mail list
You may want to subscribe to the Base18 mail list::
http://mail.freesoftware.fsf.org/mailman/listinfo/erp5-base18
erp5-base18@mail.freesoftware.fsf.org
Installation Instructions
Download the Base18 tarball::
http://www.zope.org/Members/nexedi/Base18/Base18-0.1.tar.gz
or the latest CVS::
https://savannah.gnu.org/cgi-bin/viewcvs/erp5/Base18/
Install it in your local Zope product directory (ex. /var/lib/zope/Products on
Debian systems). Untar it.
Copy the files translation_workflow.zexp and migrate_content.zexp in the
Base18 directory into to your Zope import directory (ex. /var/lib/zope/import
on a Debian system).
Copy the file Extensions/MigrateContent.py to your Zope
Extensions directory (ex. /var/lib/zope/Extensions
on a Debian system).
Create a CMF site.
Import migrate_content.zexp at the root of your CMF site.
Import translation_workflow.zexp the content of your portal_worflow.
Execute the migrate_content external method at the root of your CMF
site (click on it and then on the Test button).
This will modify the default portal types and register the Base18 portal
types. You may at this point eventually need to reinder your CMF. The
migrate_content external method can also be used to migrate an entire site.
At this step, you need to modifiy the portal_workflow workflow associations
in order to associate the Translation portal type to the translation_workflow
workflow
Demos
There are two ways to use Base18.
For sites which do not contain much content and which are centralized,
it is sufficient to manage translations through a single gettext message
catalog. Thanks to Base18, content is automatically cut into small paragraphs
or sentences. It is then possible to export sentences with the Localizer
export feature into .pot or .po files. Such files can then be translated
mith toolds such as KBabel (see kbabel.png).
This first approach is used on "Storever":http://www.storever.com for
example
For sites which contain many documents for which different people
may want to translate single documents in multiple languages,
it is then recommended to proceed in 3 steps:
- Use the *Translate* menu of the document you want to translate
in order to download a .pot file which can be edited with kbabel
- Create a new *Translation* document in your personal folder
(My Stuff) within the CMF and upload the .pot file which
you translated at the previous step. At this step, you
must define the target language and the target document
of your translation
- Submit this translation to the portal reviewers so that
they can register your translation for that document
(use the menu on the left)
This process involves two new portal types
- a Translation portal type which is used to store
translations (ie. .po files for 1 language for 1 document)
- a portal_translations which registers the relations
between documents and translations (this tool also
implements the heuristics to find the most appropriate
translation for a given document and a given language)
The whole system allows to split the work of translation
accross all members of a given portal.
This second approach is being tested on the "ERP5 portal":http://www.erp5.org
We recommend to become member of ERP5 (a project to design a Zope based ERP)
in order to try Base18 first.
Localizer Patch
We patched Localizer in order to improve its operation with KBabel and
with cookies.
MessageCatalog.py
  - improved export procedure
    so that it generates multi-line strings properly
    (all lines are exported)
  - improved export procedure
    to escape quotes
        " -> \"
  Exported messages can now be read without errror by KBabel
__init__.py
  - changed language value from string type to tuple type
    so that it is now consistent with AcceptLanguage
    list-based algorithm
zgettext.py
  - improved import procedure so that it handles
    multi-line strings (all lines are now
    read into the message catalog)
  - improved export procedure
    to unescape quotes
        \" -> \
  KBabel .po files can now be read
Les sous-répertoires ./help et /home/jp/Localizer/help sont identiques.
Les sous-répertoires ./img et /home/jp/Localizer/img sont identiques.
Les sous-répertoires ./locale et /home/jp/Localizer/locale sont identiques.
Les sous-répertoires ./tests et /home/jp/Localizer/tests sont identiques.
Les sous-répertoires ./ui et /home/jp/Localizer/ui sont identiques.
diff -u ./Utils.py /home/jp/Localizer/Utils.py
--- ./Utils.py 2003-06-07 03:31:54.000000000 +0200
+++ /home/jp/Localizer/Utils.py 2003-06-07 03:32:44.000000000 +0200
@@ -54,7 +54,8 @@
request = get_request()
- lang = request.AcceptLanguage.select_language(available_languages)
+ return getattr(request.PARENTS[0],'FOLDER_LANGUAGE','en')
+ #lang = request.AcceptLanguage.select_language(available_languages)
# XXX Here we should set the Vary header, but, which value should it have??
@@ -62,7 +63,7 @@
## response.setHeader('Vary', 'accept-language')
## response.setHeader('Vary', '*')
- return lang
+ #return lang
# Defines strings that must be internationalized
Seulement dans ./: Utils.py.orig
Seulement dans /home/jp/Localizer: Utils.py.rej
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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 Zope Public License (ZPL) Version 2.0
#
# 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.
#
##############################################################################
__version__ = "$Revision$"[11:-2]
__doc__ = "This product provides the basic behaviour to CMF object which need\
translation"
"""\
Base18 portal_membership tool.
"""
from Globals import InitializeClass, DTMLFile
from AccessControl import ClassSecurityInfo
from Products.CMFCore.CMFCorePermissions import ManagePortal
from Products.CMFDefault.MembershipTool import MembershipTool
import Document
default_member_content = '''Default page for %s
This is the default document created for you when
you joined this community.
To change the content just select "Edit"
in the Tool Box on the left.
'''
class MembershipTool18( MembershipTool ):
meta_type = 'Base18 Membership Tool'
security = ClassSecurityInfo()
security.declareProtected(ManagePortal, 'createMemberarea')
def createMemberarea(self, member_id):
"""
create a member area
"""
parent = self.aq_inner.aq_parent
members = getattr(parent, 'Members', None)
if members is not None and not hasattr(members, member_id):
f_title = "%s's Home" % member_id
members.manage_addPortalFolder( id=member_id, title=f_title )
#members.invokeFactory(type_name="Folder", id=member_id)
f=getattr(members, member_id)
#f.setTitle(f_title)
# Grant ownership to Member
acl_users = self.__getPUS()
user = acl_users.getUser(member_id).__of__(acl_users)
f.changeOwnership(user)
f.manage_setLocalRoles(member_id, ['Owner'])
# Create Member's home page.
# default_member_content ought to be configurable per
# instance of MembershipTool.
#f.invokeFactory(type_name="Document", id='index_html')
def __getPUS(self):
# Gets something we can call getUsers() and getUserNames() on.
acl_users = self.acl_users
if hasattr(acl_users, 'getUsers'):
return acl_users
else:
# This hack works around the absence of getUsers() in LoginManager.
# Gets the PersistentUserSource object that stores our users
for us in acl_users.UserSourcesGroup.objectValues():
if us.meta_type == 'Persistent User Source':
return us.__of__(acl_users)
InitializeClass( MembershipTool18 )
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
__version__ = "$Revision$"[11:-2]
__doc__ = "This product provides multilingual capabilities to the CMFDefault NewsItem"
from utils import _translate_stx
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
from Products.CMFCore import CMFCorePermissions
from Products.Localizer.MessageCatalog import MessageCatalog
from Products.CMFDefault.NewsItem import NewsItem
from Base18 import Base18
from Document import Document18
from zLOG import LOG
import commands
# Content Creator
def addNewsItem18( self
, id
, title=''
, description=''
, text=''
, text_format='html'
):
"""
Add a Multilingual NewsItem
"""
o=NewsItem18( id=id
, title=title
, description=description
, text=text
, text_format=text_format
)
self._setObject(id, o)
# Content Class
class NewsItem18(NewsItem, Document18):
""" A Multilingual NewsItem - Handles both StructuredText and HTML
and translates sentences through a portal_translations tool
"""
meta_type = 'Base18 News Item'
portal_type = 'News Item'
# Declarative security (replaces __ac_permissions__)
security = ClassSecurityInfo()
# CMF Factory Type Information
factory_type_information = ( { 'id' : portal_type
, 'meta_type' : meta_type
, 'description' : """\
News Items contain short text articles and carry a title as well as an optional description.\
Text can be automatically translated through the use of message catalogs."""
, 'icon' : 'newsitem_icon.gif'
, 'product' : 'Base18'
, 'factory' : 'addNewsItem18'
, 'immediate_view' : 'metadata_edit_form'
, 'actions' :
( { 'id' : 'view'
, 'name' : 'View'
, 'action' : 'newsitem18_view'
, 'permissions' : (
CMFCorePermissions.View, )
}
, { 'id' : 'print'
, 'name' : 'Print'
, 'action' : 'newsitem18_print'
, 'permissions' : (
CMFCorePermissions.View, )
}
, { 'id' : 'mail'
, 'name' : 'Mail'
, 'action' : 'newsitem_mail_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
, { 'id' : 'edit'
, 'name' : 'Edit'
, 'action' : 'newsitem_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
, { 'id' : 'metadata'
, 'name' : 'Metadata'
, 'action' : 'metadata_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
, { 'id' : 'translate'
, 'name' : 'Translate'
, 'action' : 'translation_template'
, 'permissions' : (
CMFCorePermissions.View, )
}
)
}
,
)
security.declareProtected(CMFCorePermissions.View, 'PreformattedView')
def PreformattedView(self):
"""
Return a preformatted rendering of this news
Useful to send by email
"""
LOG('Pref',0, self.local_absolute_url())
result = commands.getoutput("lynx -dump %s/newsitem18_print" % self.local_absolute_url())
LOG('Pref',0,str(result))
return result
InitializeClass( NewsItem18 )
##############################################################################
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
Base18 is a Zope product which allows to build multilingual portals. It uses
Localizer and extends the Zope CMFDefault product to provide a way
to translate documents at a sentence per sentence level.
It implements a new kind of CMF document: Translations. Translations allow to
store a .po file which allows to translate a given document. This approach
was inspired by the poxml approach used by the "KDE":http://www.kde.org project
to translate its documentation.
Because it works at the sentence or paragraph level, it is possible to use
the fuzzy feature of gettext to find similar translations for a given sentence
and accelerate the translation process.
Base18 also includes a translation workflow which allows to keep track
of translations and their association to documents in a portal.
Base18 is currently much of a "proof-of-concept" which needs to be extended.
Future versions will include greater flexibility and will implement relations.
More information can be found on the "Nexedi":http://www.nexedi.org/software
site::
http://www.nexedi.org/software
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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 Zope Public License (ZPL) Version 2.0
#
# 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.
#
##############################################################################
__version__ = "$Revision$"[11:-2]
__doc__ = "This file provides an empty subclass on all CMFDefault content \
classes"
from Globals import InitializeClass
from Products.CMFCore import CMFCorePermissions
from Products.CMFCore.utils import getToolByName
#from AccessControl import ClassSecurityInfo
from Base18 import Base18
from Document import Document18
# Link Empty Sublass
from Products.CMFDefault import Link
def addLink18( self
, id
, title=''
, remote_url=''
, description=''
):
"""
Add a Link instance to 'self'.
"""
o=Link18( id, title, remote_url, description )
self._setObject(id,o)
class Link18(Link.Link, Base18):
meta_type = 'Base18 Link'
portal_type = 'Link'
isPortalContent = 1
factory_type_information = ( { 'id' : portal_type
, 'meta_type' : meta_type
, 'description' : """\
Link items are URLs that come with additional information."""
, 'icon' : 'link_icon.gif'
, 'product' : 'Base18'
, 'factory' : 'addLink18'
, 'immediate_view' : 'metadata_edit_form'
, 'actions' :
( { 'id' : 'view'
, 'name' : 'View'
, 'action' : 'link18_view'
, 'permissions' : (
CMFCorePermissions.View, )
}
, { 'id' : 'edit'
, 'name' : 'Edit'
, 'action' : 'link_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
, { 'id' : 'metadata'
, 'name' : 'Metadata'
, 'action' : 'metadata_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
)
}
,
)
InitializeClass( Link18 )
# File Empty Sublass
from Products.CMFDefault import File
def addFile18( self
, id
, title=''
, file=''
, content_type=''
, precondition=''
, subject=()
, description=''
, contributors=()
, effective_date=None
, expiration_date=None
, format='text/html'
, language=''
, rights=''):
"""
Add a File
"""
# cookId sets the id and title if they are not explicity specified
id, title = OFS.Image.cookId(id, title, file)
self=self.this()
# Instantiate the object and set its description.
fobj = File18( id, title, '', content_type, precondition, subject
, description, contributors, effective_date, expiration_date
, format, language, rights
)
# Add the File instance to self
self._setObject(id, fobj)
# 'Upload' the file. This is done now rather than in the
# constructor because the object is now in the ZODB and
# can span ZODB objects.
self._getOb(id).manage_upload(file)
class File18(File.File,Base18):
meta_type = 'Base18 File'
portal_type = 'File'
isPortalContent = 1
factory_type_information = ( { 'id' : portal_type
, 'meta_type' : meta_type
, 'description' : """\
File objects can contain arbitrary downloadable files."""
, 'icon' : 'file_icon.gif'
, 'product' : 'Base18'
, 'factory' : 'addFile18'
, 'immediate_view' : 'metadata_edit_form'
, 'actions' :
( { 'id' : 'view'
, 'name' : 'View'
, 'action' : 'file18_view'
, 'permissions' : (
CMFCorePermissions.View, )
}
, { 'id' : 'download'
, 'name' : 'Download'
, 'action' : ''
, 'permissions' : (
CMFCorePermissions.View, )
}
, { 'id' : 'edit'
, 'name' : 'Edit'
, 'action' : 'file_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
, { 'id' : 'metadata'
, 'name' : 'Metadata'
, 'action' : 'metadata_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
)
}
,
)
InitializeClass( File18 )
# Image Empty Sublass
from Products.CMFDefault import Image
import OFS.Image
def addImage18( self
, id
, title=''
, file=''
, content_type=''
, precondition=''
, subject=()
, description=''
, contributors=()
, effective_date=None
, expiration_date=None
, format='image/png'
, language=''
, rights=''
):
"""
Add an Image
"""
# cookId sets the id and title if they are not explicity specified
id, title = OFS.Image.cookId(id, title, file)
self=self.this()
# Instantiate the object and set its description.
iobj = Image18( id, title, '', content_type, precondition, subject
, description, contributors, effective_date, expiration_date
, format, language, rights
)
# Add the Image instance to self
self._setObject(id, iobj)
# 'Upload' the image. This is done now rather than in the
# constructor because it's faster (see File.py.)
self._getOb(id).manage_upload(file)
class Image18(Image.Image, Base18):
meta_type = 'Base18 Image'
portal_type = 'Image'
isPortalContent = 1
factory_type_information = ( { 'id' : portal_type
, 'meta_type' : meta_type
, 'description' : """\
Image objects can be embedded in Portal documents."""
, 'icon' : 'image_icon.gif'
, 'product' : 'Base18'
, 'factory' : 'addImage18'
, 'immediate_view' : 'metadata_edit_form'
, 'actions' :
( { 'id' : 'view'
, 'name' : 'View'
, 'action' : 'image18_view'
, 'permissions' : (
CMFCorePermissions.View, )
}
, { 'id' : 'edit'
, 'name' : 'Edit'
, 'action' : 'image_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
, { 'id' : 'metadata'
, 'name' : 'Metadata'
, 'action' : 'metadata_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
)
}
,
)
InitializeClass( Image18 )
# Folder Empty Sublass
from Products.CMFDefault import SkinnedFolder
def addSkinnedFolder18( self, id, title='', description='', REQUEST=None ):
"""
"""
sf = SkinnedFolder18( id, title )
sf.description = description
self._setObject( id, sf )
sf = self._getOb( id )
if REQUEST is not None:
REQUEST['RESPONSE'].redirect( sf.absolute_url() + '/manage_main' )
class SkinnedFolder18(SkinnedFolder.SkinnedFolder,Base18):
meta_type = 'Base18 Folder'
portal_type = 'Folder'
isPortalContent = 1
factory_type_information = ( { 'id' : portal_type
, 'meta_type' : meta_type
, 'description' : """\
Skinned folders can define custom 'view' actions."""
, 'icon' : 'folder_icon.gif'
, 'product' : 'Base18'
, 'factory' : 'addSkinnedFolder18'
, 'filter_content_types' : 0
, 'immediate_view' : 'folder_edit_form'
, 'actions' :
( { 'id' : 'view'
, 'name' : 'View'
, 'action' : 'folder18_view'
, 'permissions' :
(CMFCorePermissions.View,)
, 'category' : 'folder'
}
, { 'id' : 'edit'
, 'name' : 'Edit'
, 'action' : 'folder_edit_form'
, 'permissions' :
(CMFCorePermissions.ManageProperties,)
, 'category' : 'folder'
}
, { 'id' : 'localroles'
, 'name' : 'Local Roles'
, 'action' : 'folder_localrole_form'
, 'permissions' : \
(CMFCorePermissions.ManageProperties,)
, 'category' : 'folder'
}
, { 'id' : 'syndication'
, 'name' : 'Syndication'
, 'action' : 'synPropertiesForm'
, 'permissions' :
(CMFCorePermissions.ManageProperties,)
, 'category' : 'folder'
}
, { 'id' : 'foldercontents'
, 'name' : 'Folder contents'
, 'action' : 'folder_contents'
, 'permissions' :
(CMFCorePermissions.ListFolderContents,)
, 'category' : 'folder'
}
)
}
,
)
InitializeClass( SkinnedFolder18 )
# DiscussionItem Empty Sublass
from Products.CMFDefault import DiscussionItem
def addDiscussionItem18(self, id, title, description, text_format, text,
reply_to, RESPONSE=None):
"""
Add a discussion item
'title' is also used as the subject header
if 'description' is blank, it is filled with the contents of 'title'
'reply_to' is the object (or path to the object) which this is a reply to
Otherwise, same as addDocument
"""
if not description: description = title
item = DiscussionItem( id )
item.title = title
item.description = description
item.text_format = text_format
item.text = text
item.setReplyTo(reply_to)
item._parse()
self._setObject(id, item)
if RESPONSE is not None:
RESPONSE.redirect(self.absolute_url())
class DiscussionItem18(Document18, DiscussionItem.DiscussionItem):
meta_type = 'Base18 Discussion Item'
portal_type = 'Discussion Item'
isPortalContent = 1
factory_type_information = ( { 'id' : portal_type
, 'meta_type' : meta_type
, 'description' : """\
Discussion Items are documents which reply to other content.\
They should *not* be addable through the standard 'folder_factories'\
interface."""
, 'icon' : 'discussionitem_icon.gif'
, 'product' : '' # leave blank to suppress
, 'factory' : ''
, 'immediate_view' : ''
, 'actions' :
( { 'id' : 'view'
, 'name' : 'View'
, 'action' : 'discussionitem18_view'
, 'permissions' : (
CMFCorePermissions.View, )
}
,
)
}
,
)
InitializeClass( DiscussionItem18 )
class DiscussionItem18Container(DiscussionItem.DiscussionItemContainer):
pass
# Favorite Empty Sublass
from Products.CMFDefault import Favorite
def addFavorite18(self, id, title='', remote_url='', description=''):
"""
Add a Favorite
"""
portal_url = getToolByName(self, 'portal_url')
portal_obj = portal_url.getPortalObject()
content_obj = portal_obj.restrictedTraverse( remote_url )
relUrl = portal_url.getRelativeUrl( content_obj )
o=Favorite18( id, title, relUrl, description )
self._setObject(id,o)
class Favorite18(Favorite.Favorite,Base18):
meta_type = 'Base18 Favorite'
portal_type = 'Favorite'
isPortalContent = 1
factory_type_information = ( { 'id' : portal_type
, 'meta_type' : meta_type
, 'description' : """\
A Favorite is a Link to an intra-portal resource."""
, 'icon' : 'link_icon.gif'
, 'product' : 'Base18'
, 'factory' : 'addFavorite18'
, 'immediate_view' : 'metadata_edit_form'
, 'actions' :
( { 'id' : 'view'
, 'name' : 'View'
, 'action' : 'favorite18_view'
, 'permissions' : (
CMFCorePermissions.View, )
}
, { 'id' : 'edit'
, 'name' : 'Edit'
, 'action' : 'link_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
, { 'id' : 'metadata'
, 'name' : 'Metadata'
, 'action' : 'metadata_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
)
}
,
)
InitializeClass( Favorite18 )
TODO:
Version 0.1 (Done)
- proof of concept
Version 1.0
- Release
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
__version__ = "$Revision$"[11:-2]
__doc__ = "This product provides multilingual capabilities to the CMFDefault \
Document"
from utils import _translate_stx
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
from Products.CMFCore import CMFCorePermissions, PortalContent
from Products.Localizer.MessageCatalog import MessageCatalog
from Document import Document18
import string
# Content Creator
def addTranslation(self, id, title='', description=''):
""" Add a Translation Document """
o = Translation(id, title, description)
self._setObject(id,o)
# Content Class
class Translation(Document18):
""" A User Translation Document managed by the CMF
Actually, just a wrapper arround Localize to
make it editable under the CMF
"""
meta_type = 'Base18 Translation'
# Declarative security
security = ClassSecurityInfo()
# CMF Factory Type Information
factory_type_information = ( { 'id' : 'Translation'
, 'meta_type' : 'Base18 Translation'
, 'description' : """\
Translations can contain a list of translation messages formatted according\
to the .po standard. Translations can be registered through a translation\
workflow and provide a translation to an existing document in a portal'"""
, 'icon' : 'document_icon.gif'
, 'product' : 'Base18'
, 'factory' : 'addTranslation'
, 'immediate_view' : 'metadata_edit_form'
, 'actions' : ( { 'id' : 'view'
, 'name' : 'View'
, 'action' : 'translation_view'
, 'permissions' : (CMFCorePermissions.View,)
}
, { 'id' : 'edit'
, 'name' : 'Edit'
, 'action' : 'translation_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
, { 'id' : 'metadata'
, 'name' : 'Metadata'
, 'action' : 'metadata_edit_form'
, 'permissions' : (
CMFCorePermissions.ModifyPortalContent, )
}
, { 'id' : 'template'
, 'name' : 'Translation Template'
, 'action' : 'translation_template'
, 'permissions' : (
CMFCorePermissions.View, )
}
)
}
,
)
### Default values
targetContent = ()
targetLanguage = ('en')
messageCatalog = None
### Edit method
security.declareProtected( CMFCorePermissions.ModifyPortalContent, 'edit' )
def edit( self
, text_format
, text
, file=''
, safety_belt=''
, target_language='en'
, target_content=None
):
"""
*used to be WorkflowAction(_edit)
To add webDav support, we need to check if the content is locked, and if
so return ResourceLockedError if not, call _edit.
Note that this method expects to be called from a web form, and so
disables header processing
"""
self.targetLanguage = target_language
if target_content is not None:
self.targetContent = target_content.getPhysicalPath()
else:
self.targetContent = ('a')
Document18.edit(self, text_format, text, file, safety_belt)
self.messageCatalog = MessageCatalog("mc", "Message Catalog",
(self.targetLanguage,))
self.messageCatalog.manage_import(self.targetLanguage, self.text)
def _edit(self, text, text_format='', safety_belt=''):
""" Edit the Document - Parses headers and cooks the body"""
headers = {}
if not safety_belt:
safety_belt = headers.get('SafetyBelt', '')
if not self._safety_belt_update(safety_belt=safety_belt):
msg = ("Intervening changes from elsewhere detected."
" Please refetch the document and reapply your changes."
" (You may be able to recover your version using the"
" browser 'back' button, but will have to apply them"
" to a freshly fetched copy.)")
raise 'EditingConflict', msg
self.text = self.cooked_text = text
### Content accessor methods
security.declareProtected(CMFCorePermissions.View, 'SearchableText')
def SearchableText(self, md=None):
"""\
Used by the catalog for basic full text indexing
We are going to concatenate all available translations
"""
if md is None: md = self.findMessageCatalog()
searchable_text = self.text
for lang in md.get_languages():
searchable_text = searchable_text + "%s %s" % (
md.gettext(self.Title(),lang)
, md.gettext(self.Description(),lang)
)
return searchable_text
# Translation methods
security.declareProtected(CMFCorePermissions.View, 'TranslatedBody')
def TranslatedBody(self, stx_level=None, setlevel=0, lang=None, md=None):
"""\
Equivalent to CookedBody but returns a translated version thanks
to the use of message catalog
"""
if md is None: md = self.find_md()
if stx_level is None: stx_level = self._stx_level
cooked = _translate_stx(self.text, md, stx_level, lang)
return cooked
security.declareProtected(CMFCorePermissions.View, 'TranslationTemplate')
def TranslationTemplate(self):
"""\
This method allows to produce of .pot file for this document
"""
# Create a new catalog
md = MessageCatalog('temp', 'Temporary Message Catalog',
self.find_md().get_languages())
# Do some dirty acquisition trick
md.aq_base = self
# Run the md on the text body
cooked = _translate_stx(self.text, md, self._stx_level, None)
md.gettext(self.Title())
md.gettext(self.Description())
# And return the template
return md.manage_export('locale.pt')
# Implementation with Message Catalogs
security.declareProtected(CMFCorePermissions.View, 'getMessageCatalog')
def getMessageCatalog(self):
return self.messageCatalog
security.declareProtected(CMFCorePermissions.View, 'targetContentPath')
def targetContentPath(self):
return string.join(self.targetContent,'/')
InitializeClass(Translation)
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
__version__ = "$Revision$"[11:-2]
__doc__ = "This product provides the basic behaviour to CMF object which need\
translation"
"""\
Base18 portal_translation tool.
"""
from OFS.SimpleItem import SimpleItem
from Products.CMFCore.utils import UniqueObject
from Globals import InitializeClass, DTMLFile, PersistentMapping
from AccessControl import ClassSecurityInfo, getSecurityManager
from Products.CMFCore import CMFCorePermissions
from utils import _dtmldir
from Products.Localizer.Utils import lang_negotiator
#import zLOG
class TranslationError( Exception ):
pass
class TranslationTool( UniqueObject, SimpleItem ):
id = 'portal_translations'
meta_type = 'Base18 Translation Tool'
security = ClassSecurityInfo()
#
# Default values.
#
registered_translations = None
def __init__( self ):
self.registered_translations = PersistentMapping()
#
# ZMI methods
#
manage_options = ( ( { 'label' : 'Overview'
, 'action' : 'manage_overview'
}
, { 'label' : 'Properties'
, 'action' : 'propertiesForm'
}
)
+ SimpleItem.manage_options
)
security.declareProtected( CMFCorePermissions.ManagePortal
, 'manage_overview' )
manage_overview = DTMLFile( 'explainTranslationTool', _dtmldir )
security.declareProtected( CMFCorePermissions.ManagePortal
, 'propertiesForm' )
propertiesForm = DTMLFile( 'translationProperties', _dtmldir )
security.declareProtected( CMFCorePermissions.ManagePortal
, 'editProperties' )
def editProperties( self
, publisher=None
, REQUEST=None
):
"""
Form handler for "tool-wide" properties (including list of
metadata elements).
"""
if publisher is not None:
self.publisher = publisher
if REQUEST is not None:
REQUEST[ 'RESPONSE' ].redirect( self.absolute_url()
+ '/propertiesForm'
+ '?manage_tabs_message=Tool+updated.'
)
#
# 'portal_translations' interface
#
security.declarePublic( 'findMessageCatalog' )
def findMessageCatalog(self, content, language=None):
"""
Return the default message catalog for
an object to translate
For now, look in the same directory
or in the acquisition path either for a message catalog for
that object or for a message more global catalog
In the future, we will try to look at message catalogs provided by
users.
A workklow will be used to manage the status of translations
"""
translation = self.findRegisteredTranslation(content)
if translation is not None:
return translation.getMessageCatalog()
else:
return getattr(content.aq_parent, str(content.id) + '.msg' ,
content.gettext)
# Translation registration catalog
# Can be improved a lot (of course)
security.declarePublic( 'registerTranslation' )
def registerTranslation(self, content, translation, language=None):
"""
This function allows to register a user translation
"""
# If language not supplied, look up languages in the user translation
if language is None:
languages = translation.getMessageCatalog().get_languages()
else:
languages=(language,)
# Get the path of content and translation
content_path = content.getPhysicalPath()
translation_path = translation.getPhysicalPath()
# Register the path for content and translation for each available
# language
if not self.registered_translations.has_key(content_path):
self.registered_translations[content_path] = PersistentMapping()
for lang in languages:
self.registered_translations[content_path][lang] = translation_path
security.declarePublic( 'unregisterTranslation' )
def unregisterTranslation(self, content, translation=None, language=None):
"""
This function allows to register a user translation
"""
content_path = content.getPhysicalPath()
# Is content registered ?
if self.registered_translations.has_key(content_path):
if language is None:
languages = self.registered_translations[content_path].keys()
else:
if self.registered_translations[content_path].has_key(language):
languages = (language,)
else:
languages = []
if translation is not None:
translation_path = translation.getPhysicalPath()
for lang in languages:
# If no translation provided, then remove default translation
if translation is None:
del self.registered_translations[content_path][lang]
# if translation is provided, remove that translation only
else:
if self.registered_translations[content_path][lang] == \
translation_path:
del self.registered_translations[content_path][lang]
else:
pass
security.declarePublic( 'findRegisteredTranslation' )
def findRegisteredTranslation(self, content, language=None):
"""
This function allows to find if a translation has been registered
"""
content_path = content.getPhysicalPath()
if self.registered_translations.has_key(content_path):
# Find negociated language if necessary
# zLOG.LOG('Registered Translation Found',0,content_path)
if language is None:
language = lang_negotiator([content.language] +
self.registered_translations[content_path].keys())
# zLOG.LOG('Neg. Language',0,self.language + ',' + language)
if language is None:
return None
translation_path = \
self.registered_translations[content_path].get(language, None)
if translation_path is None:
# zLOG.LOG('No Translation Path Found',0,translation_path)
return None
else:
# zLOG.LOG('Translation Path Found',0,translation_path)
try: return self.restrictedTraverse(translation_path)
except: return None
else:
# zLOG.LOG('No Registered Translation Found',0,content_path)
return None
InitializeClass( TranslationTool )
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
__version__ = "$Revision$"[11:-2]
__doc__ = "This product provides multilingual capabilities to the CMFDefault \
Document"
import os
from utils import _translate_stx, _translate_html
from Globals import InitializeClass, PersistentMapping, package_home
from AccessControl import ClassSecurityInfo, getSecurityManager
from Products.CMFCore import CMFCorePermissions
from Products.Localizer.MessageCatalog import MessageCatalog
from Products.CMFDefault.Document import Document
from Products.CMFWiki import CMFWikiPage, CMFWikiPermissions
from Products.CMFWiki.CMFWikiPage import initPageMetadata, default_perms, \
thunk_substituter
from Products.CMFWiki.ZWikiRegexes import urlchars, url, urlexp, bracketedexpr,\
bracketedexprexp, underlinedexpr, underlinedexprexp, wikiname1,\
wikiname2, simplewikilinkexp, wikiending, urllinkending, wikilink,\
wikilinkexp, wikilink_, interwikilinkexp, remotewikiurlexp,\
protected_lineexp, antidecaptext, antidecapexp, commentsdelim,\
preexp, unpreexp, citedexp, cite_prefixexp, intl_char_entities
from Products.CMFCore.utils import _getViewFor
from Acquisition import aq_base, aq_inner, aq_parent
from Base18 import Base18
from Document import Document18
from utils import _translate_stx
import zLOG
# Content Constructor
def makeCMFWikiPage18(id, title, file):
ob = CMFWikiPage18(source_string=file, __name__=id)
ob.title = title
ob.parents = []
username = getSecurityManager().getUser().getUserName()
ob.manage_addLocalRoles(username, ['Owner'])
ob.setSubOwner('both')
initPageMetadata(ob)
for name, perm in ob._perms.items():
pseudoperm = default_perms[name]
local_roles_map = ob._local_roles_map
roles_map = ob._roles_map
roles = (local_roles_map[name],) + roles_map[pseudoperm]
ob.manage_permission(perm, roles=roles)
return ob
def addCMFWikiPage18(self, id, title='', file=''):
id=str(id)
title=str(title)
ob = makeCMFWikiPage18(id, title, file)
self._setObject(id, ob)
# Content Class
class CMFWikiPage18(CMFWikiPage.CMFWikiPage, Document18):
""" A Multilingual Document - Handles both StructuredText and HTML
and translates sentences through a portal_translations tool
"""
meta_type = 'Base18 Wiki Page'
portal_type = 'Wiki Page'
isPortalContent = 1
# Default values
cached_translations = None
# Declarative security
security = ClassSecurityInfo()
# CMF Factory Type Information
factory_type_information = \
{'id': portal_type,
'content_icon': 'wikipage_icon.gif',
'meta_type': meta_type,
'product': 'Base18',
'factory': 'addCMFWikiPage18',
'immediate_view': 'wikipage_view',
'actions': ({'id': 'view',
'name': 'View',
'action': 'wikipage_view',
'permissions': (CMFWikiPermissions.View,)},
{'id': 'comment',
'name': 'Comment',
'action': 'wikipage_comment_form',
'permissions': (CMFWikiPermissions.Comment,)},
{'id': 'edit',
'name': 'Edit',
'action': 'wikipage_edit_form',
'permissions': (CMFWikiPermissions.Edit,)},
{'id': 'translate',
'name': 'Translate',
'action': 'translation_template',
'permissions': (CMFWikiPermissions.Edit,)},
{'id': 'history',
'name': 'History',
'action': 'wikipage_history',
'permissions': (CMFWikiPermissions.View,)},
{'id': 'backlinks',
'name': 'Backlinks',
'action': 'wikipage_backlinks',
'permissions': (CMFWikiPermissions.View,)},
{'id': 'advanced',
'name': 'Advanced',
'action': 'wikipage_advanced_form',
'permissions': (CMFWikiPermissions.View,)},
{'id': 'toc',
'name': 'Wiki Contents',
'category': 'folder',
'action':'wikipage_toc',
'permissions': (CMFWikiPermissions.View,)},
{'id': 'recent_changes',
'name': 'Recent Changes',
'category': 'folder',
'action':'wikipage_recentchanges',
'permissions': (CMFWikiPermissions.View,)},
{'id': 'create',
'name': 'Create',
'category': 'folder',
'action':'wikipage_create_form',
'permissions': (CMFWikiPermissions.Create,),
'visible': 0 },
),
}
# Fixed Methods
def Title(self): # for CMFCatalog
return self.title_or_id()
# New Rendering Method
def render_structuredtext(self, client=None, REQUEST={},
RESPONSE=None, **kw):
# structured text + wiki links + HTML
if kw.has_key('level'):
t = self.TranslatedBody(stx_level = kw['level'])
else:
t = self.TranslatedBody()
#t = protected_lineexp.sub(self._protect_line, t)
#if self._st_data is None:
# XXX klm: Shouldn't happen -_st_data should've been set by edit.
# t = str(html_with_references(t, level=3))
t = interwikilinkexp.sub(
thunk_substituter(self._interwikilink_replace, t, 1),
t)
t = wikilinkexp.sub(thunk_substituter(self._wikilink_replace, t,
self.isAllowed('create')), t)
return t
RENDERERS = {
'structuredtext' : render_structuredtext
, 'structuredtextonly' : CMFWikiPage.CMFWikiPage.render_structuredtextonly
, 'html' : CMFWikiPage.CMFWikiPage.render_html
, 'classicwiki' : CMFWikiPage.CMFWikiPage.render_classicwiki
, 'plaintext' : CMFWikiPage.CMFWikiPage.render_plaintext
}
### Content accessor methods
security.declareProtected(CMFCorePermissions.View, 'SearchableText')
def SearchableText(self, md=None):
"""\
Used by the catalog for basic full text indexing
We are going to concatenate all available translations
"""
if md is None: md = self.findMessageCatalog()
searchable_text = ""
for lang in md.get_languages():
searchable_text = searchable_text + "%s %s %s" % (
md.gettext(self.Title(),lang)
, md.gettext(self.Description(),lang)
, self.TranslatedBody(lang=lang)
)
return searchable_text
# Content Constructor
def addCMFWikiFolder18(self, id, title=''):
id = str(id)
title = str(title)
ob = CMFWikiFolder18(id, title)
id = self._setObject(id, ob)
ob = getattr(self, id)
p = package_home(globals()) + os.sep + 'default_wiki_content'
fnames = os.listdir(p)
for fname in fnames:
if fname[-5:] != '.wiki': continue
f = open(p + os.sep + fname, 'r')
fname = fname[:-5]
addCMFWikiPage18(ob, fname, title='', file=f.read())
page = getattr(ob, fname)
page.indexObject()
# Hack - may be ok if we continue to have, like, only two pages:
if fname == 'SandBox':
page.parents = ['FrontPage']
# Content Class
class CMFWikiFolder18( CMFWikiPage.CMFWikiFolder, Base18 ):
meta_type = 'Base18 Wiki'
portal_type = 'Wiki'
isPortalContent = 1
# Default values
cached_translations = None
# Declarative security
security = ClassSecurityInfo()
# CMF Factory Type Information
factory_type_information = \
{'id': portal_type,
'content_icon': 'folder_icon.gif',
'meta_type': meta_type,
'description': ('Loosely organized (yet structured) content can be '
'added to Wikis.'),
'product': 'Base18',
'factory': 'addCMFWikiFolder18',
'immediate_view': 'FrontPage',
'actions': ({'id': 'toc',
'name': 'Wiki Contents',
'category': 'folder',
'action':'wiki_toc',
'permissions': (CMFWikiPermissions.View,)},
{'id': 'view',
'name': 'FrontPage',
'category': 'folder',
'action':'FrontPage',
'permissions': (CMFWikiPermissions.View,)},
{'id': 'edit',
'name': 'Edit',
'category': 'folder',
'action':'folder_edit_form',
'permissions': (CMFWikiPermissions.View,)},
{'id': 'all',
'name': 'All Pages',
'category': 'folder',
'action':'wiki_allpages',
'permissions': (CMFWikiPermissions.View,)},
{'id': 'recent_changes',
'name': 'Recent Changes',
'category': 'folder',
'action':'wiki_recentchanges',
'permissions': (CMFWikiPermissions.View,)},
{'id': 'wikihelp',
'name': 'WikiHelp',
'category': 'folder',
'action': 'WikiHelp',
'permissions': (CMFWikiPermissions.View,)}
),
},
security.declareProtected(CMFWikiPermissions.View, '__call__')
def __call__(self, client=None, REQUEST=None, RESPONSE=None, **kw):
'''
Invokes the default view.
'''
if RESPONSE is not None:
return RESPONSE.redirect(self.absolute_url() + '/FrontPage' )
if REQUEST is not None:
return REQUEST.RESPONSE.redirect(self.absolute_url() + '/FrontPage' )
else:
REQUEST = {}
view = _getViewFor( self )
if getattr(aq_base(view), 'isDocTemp', 0):
return apply(view, (self, REQUEST))
else:
if REQUEST:
kw[ 'REQUEST' ] = REQUEST
if RESPONSE:
kw[ 'RESPONSE' ] = RESPONSE
return apply( view, (self,), kw )
index_html = None # This special value informs ZPublisher to use __call__
InitializeClass(CMFWikiPage18)
InitializeClass(CMFWikiFolder18)
CMFWikiPage = CMFWikiPage18
CMFWikiFolder = CMFWikiFolder18
addCMFWikiPage = addCMFWikiPage18
addCMFWikiFolder = addCMFWikiFolder18
Zope Public License (ZPL) Version 2.0
-----------------------------------------------
This software is Copyright (c) Zope Corporation (tm) and
Contributors. All rights reserved.
This license has been certified as open source. It has also
been designated as GPL compatible by the Free Software
Foundation (FSF).
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the
following conditions are met:
1. Redistributions in source code must retain the above
copyright notice, this list of conditions, and the following
disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions, and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
3. The name Zope Corporation (tm) must not be used to
endorse or promote products derived from this software
without prior written permission from Zope Corporation.
4. The right to distribute this software or to use it for
any purpose does not give you the right to use Servicemarks
(sm) or Trademarks (tm) of Zope Corporation. Use of them is
covered in a separate agreement (see
http://www.zope.com/Marks).
5. If any files are modified, you must cause the modified
files to carry prominent notices stating that you changed
the files and the date of any change.
Disclaimer
THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS''
AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL ZOPE CORPORATION OR ITS CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
This software consists of contributions made by Zope
Corporation and many individuals on behalf of Zope
Corporation. Specific attributions are listed in the
accompanying credits file.
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# TODO:
# - Implement Vary so that cache can take into account translated version
# - Implement language caching....
#
##############################################################################
"""
"""
ADD_CONTENT_PERMISSION = 'Add portal content'
import Document, NewsItem, Replica, Translation, Wiki
import TranslationTool, MembershipTool, CookieCrumbler
from Products.CMFCore import utils
import Products.CMFCore
from Products.CMFCore.DirectoryView import registerDirectory
contentClasses = ( Document.Document18
, NewsItem.NewsItem18
, Replica.File18
, Replica.Link18
, Replica.Image18
, Replica.Favorite18
, Replica.DiscussionItem18
, Replica.SkinnedFolder18
, Translation.Translation
, Wiki.CMFWikiPage18
, Wiki.CMFWikiFolder18
)
contentConstructors = ( Document.addDocument18
, NewsItem.addNewsItem18
, Replica.addFile18
, Replica.addLink18
, Replica.addImage18
, Replica.addFavorite18
, Replica.addDiscussionItem18
, Replica.addSkinnedFolder18
, Translation.addTranslation
, Wiki.addCMFWikiPage18
, Wiki.addCMFWikiFolder18
)
contentFactoryTypeInformations = []
for content in contentClasses:
if type(content.factory_type_information) == type({}):
contentFactoryTypeInformations.append(content.factory_type_information)
else:
contentFactoryTypeInformations.append(content.factory_type_information[0])
tools = ( TranslationTool.TranslationTool
, MembershipTool.MembershipTool18
)
bases = contentClasses
import sys
this_module = sys.modules[ __name__ ]
z_bases = utils.initializeBasesPhase1( bases, this_module )
z_tool_bases = utils.initializeBasesPhase1( tools, this_module )
base18_globals=globals()
# Make the skins available as DirectoryViews.
registerDirectory('skins', globals())
registerDirectory('help', globals())
def initialize( context ):
utils.initializeBasesPhase2( z_bases, context )
utils.initializeBasesPhase2( z_tool_bases, context )
utils.ToolInit('Base18 Tool', tools=tools,
product_name='Base18', icon='tool.png',
).initialize( context )
utils.ContentInit( 'Base18 Content'
, content_types=contentClasses
, permission=ADD_CONTENT_PERMISSION
, extra_constructors=contentConstructors
, fti=contentFactoryTypeInformations
).initialize( context )
context.registerHelp()
context.registerHelpTitle('Base18 Help')
Welcome to !CMFWiki, this is a !CMFWikiWeb.
For general Wiki help instructions, see the "Help":WikiHelp .
To see the table of contents or recent changes, or to search this
!CMFWikiWeb, use the "folder contents":folder_contents view
and look for the appropriate actions in the action box.
To experiment, use the SandBox page.
This page is for experimenting.
Use the "Edit" or "Comment" links on the sidebar to fool around.
<dtml-comment>
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
Jean-Paul Smets <jp@nexedi.com>
WARNING: This program as such is intended to be used by professional
programmers who take the whole responsability of assessing all potential
consequences resulting from its eventual inadequacies and bugs
This program as such is not intended to be used by end users. End
users who are looking for a ready-to-use solution with commercial
garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
</dtml-comment>
<dtml-var manage_page_header>
<dtml-var manage_tabs>
<h3> <code>portal_metadata</code> Tool </h3>
<p> This tool embodies site-wide policies concerning content translation.
The default heuristics consists in searching first for a message
catalog next to the document, then a translation created by a member
and in the end a global message catalog.
</p>
<dtml-var manage_page_footer>
Updating an existing Zope CMF
Export your CMF as XML
First use the update-products script on the XML file
Beware : buggy, will destroy some non CMF types !!!
Update portal types (! local roles)
Add
gettext
portal_translations
portal_membership
\ No newline at end of file
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
"""\
Declare interface for Translatable content
"""
import Interface
class Translatable(Interface.Base):
"""\
Returns back a list of objects which implements the Translatable interface.
"""
def TranslationTemplate(self):
"""
Returns a list of results which is to be Syndicated. For example, the normal call
contentValues (on PortalFolders) returns a list of subObjects of the current object
(i.e. objectValues with filtering applied). For the case of a Topic, one would
return a sequence of objects from a catalog query, not the subObjects of the Topic.
What is returned must implement the DublinCore.
"""
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
"""\
Loads interface names into the package.
"""
from Translatable import Translatable
? AcceptLanguage.pyc
? Gettext.pyc
? GettextTag.pyc
? LanguageManager.pyc
? LocalAttributes.pyc
? LocalContent.pyc
? LocalFiles.pyc
? LocalFolder.pyc
? LocalPropertyManager.pyc
? Localizer.pyc
? MessageCatalog.pyc
? Translator.py.org
? Utils.pyc
? __init__.pyc
? jps.diff
? refresh.txt
? zgettext.pyc
? locale/ca.mo
? locale/de.mo
? locale/en.mo
? locale/es.mo
? locale/eu.mo
? locale/fr.mo
? locale/hu.mo
Index: AcceptLanguage.py
===================================================================
RCS file: /cvsroot/lleu/Localizer/AcceptLanguage.py,v
retrieving revision 1.2
diff -u -r1.2 AcceptLanguage.py
--- AcceptLanguage.py 21 Feb 2002 10:53:54 -0000 1.2
+++ AcceptLanguage.py 16 Apr 2002 08:07:44 -0000
@@ -23,7 +23,6 @@
#from UserDict import UserDict
from types import StringType
-
class AcceptLanguageNode:
"""
This class is a recursive representation of a tree.
Index: Localizer.py
===================================================================
RCS file: /cvsroot/lleu/Localizer/Localizer.py,v
retrieving revision 1.53
diff -u -r1.53 Localizer.py
--- Localizer.py 25 Feb 2002 09:46:40 -0000 1.53
+++ Localizer.py 16 Apr 2002 08:07:45 -0000
@@ -215,17 +215,17 @@
stack.append(self.id)
-## # Changing the language, useful snippets
-## security.declarePublic('changeLanguage')
-## changeLanguageForm = LocalDTMLFile('ui/changeLanguageForm', globals())
-## def changeLanguage(self, REQUEST, RESPONSE):
-## """ """
-## lang = REQUEST['lang']
+ # Changing the language, useful snippets
+ security.declarePublic('changeLanguage')
+ changeLanguageForm = LocalDTMLFile('ui/changeLanguageForm', globals())
+ def changeLanguage(self, REQUEST, RESPONSE):
+ """ """
+ lang = REQUEST['lang']
-## path = self.absolute_url()[len(REQUEST['SERVER_URL']):] or '/'
-## RESPONSE.setCookie('LOCALIZER_LANGUAGE', lang, path=path)
+ path = self.absolute_url()[len(REQUEST['SERVER_URL']):] or '/'
+ RESPONSE.setCookie('LOCALIZER_LANGUAGE', lang, path=path)
-## RESPONSE.redirect(REQUEST['HTTP_REFERER'])
+ RESPONSE.redirect(REQUEST['HTTP_REFERER'])
# Upgrading..
security.declarePublic('need_upgrade')
Index: MessageCatalog.py
===================================================================
RCS file: /cvsroot/lleu/Localizer/MessageCatalog.py,v
retrieving revision 1.17
diff -u -r1.17 MessageCatalog.py
--- MessageCatalog.py 25 Feb 2002 09:46:40 -0000 1.17
+++ MessageCatalog.py 16 Apr 2002 08:07:46 -0000
@@ -379,9 +379,14 @@
d[k] = ""
# Generate the file
+ quote_esc = re.compile(r'"')
for k, v in d.items():
- r.append('msgid "%s"' % k)
- r.append('msgstr "%s"' % v)
+ r.append('msgid ""')
+ for line in k.split('\n'):
+ r.append( '"%s"' % quote_esc.sub('\\"',line))
+ r.append('msgstr ""')
+ for line in v.split('\n'):
+ r.append( '"%s"' % quote_esc.sub('\\"',line))
r.append('')
@@ -405,10 +410,29 @@
k, k, k, d = parse_po_file(content)
for k, v in d.items():
- k = k[0]
+ if len(k) == 1:
+ # single line msgid
+ k = k[0]
+ else:
+ # multiline msgid
+ if k[0] == '':
+ k = '\n'.join(k[1:])
+ else:
+ k = '\n'.join(k)
if not messages.has_key(k):
messages[k] = PersistentMapping()
- messages[k][lang] = v[1][0]
+ # Take the commentaries only
+ v = v[1]
+ if len(v) == 1:
+ # single line msgstr
+ v = v[0]
+ else:
+ # multiline msgstr
+ if v[0] == '':
+ v = '\n'.join(v[1:])
+ else:
+ v = '\n'.join(v)
+ messages[k][lang] = v
if REQUEST is not None:
return self.manage_messages(self, REQUEST)
Index: __init__.py
===================================================================
RCS file: /cvsroot/lleu/Localizer/__init__.py,v
retrieving revision 1.35
diff -u -r1.35 __init__.py
--- __init__.py 25 Feb 2002 09:46:40 -0000 1.35
+++ __init__.py 16 Apr 2002 08:07:46 -0000
@@ -115,12 +115,12 @@
# Add the language from the form
lang = request.form.get('LOCALIZER_LANGUAGE', None)
if lang is not None:
- accept_language[lang] = 3.0
+ accept_language[lang.split('-',1)] = 3.0
# Add the language from the cookies
lang = request.cookies.get('LOCALIZER_LANGUAGE', None)
if lang is not None:
- accept_language[lang] = 2.0
+ accept_language[lang.split('-',1)] = 2.0
self.other['USER_PREF_LANGUAGES'] = accept_language
@@ -193,7 +193,7 @@
context.registerClass(
LocalContent.LocalContent,
constructors = (LocalContent.manage_addLocalContentForm,
- LocalContent.manage_addLocalContent),
+ LocalContent.manage_addLocalContent),
icon='img/local_content.gif')
# Register MessageCatalog
Index: zgettext.py
===================================================================
RCS file: /cvsroot/lleu/Localizer/zgettext.py,v
retrieving revision 1.15
diff -u -r1.15 zgettext.py
--- zgettext.py 25 Feb 2002 09:46:40 -0000 1.15
+++ zgettext.py 16 Apr 2002 08:07:47 -0000
@@ -39,10 +39,11 @@
def parse_po_file(content):
# The regular expressions
com = re.compile('^#.*')
- msgid = re.compile(r'^ *msgid *"(.*?[^\\]*)"')
- msgstr = re.compile(r'^ *msgstr *"(.*?[^\\]*)"')
- re_str = re.compile(r'^ *"(.*?[^\\])"')
+ msgid = re.compile(r'^ *msgid *"(.*[^\\]*)"')
+ msgstr = re.compile(r'^ *msgstr *"(.*[^\\]*)"')
+ re_str = re.compile(r'^ *"(.*[^\\])"')
blank = re.compile(r'^\s*$')
+ quote_esc = re.compile(r'\\"')
trans = {}
pointer = 0
@@ -59,7 +60,8 @@
state = 1
pointer = pointer + 1
elif msgid.match(line):
- MSGID.append(msgid.match(line).group(1))
+ line = msgid.match(line).group(1)
+ MSGID.append(quote_esc.sub('"',line))
state = 2
pointer = pointer + 1
elif blank.match(line):
@@ -72,7 +74,8 @@
state = 1
pointer = pointer + 1
elif msgid.match(line):
- MSGID.append(msgid.match(line).group(1))
+ line = msgid.match(line).group(1)
+ MSGID.append(quote_esc.sub('"',line))
state = 2
pointer = pointer + 1
elif blank.match(line):
@@ -85,11 +88,13 @@
state = 2
pointer = pointer + 1
elif re_str.match(line):
- MSGID.append(re_str.match(line).group(1))
+ line = re_str.match(line).group(1)
+ MSGID.append(quote_esc.sub('"',line))
state = 2
pointer = pointer + 1
elif msgstr.match(line):
- MSGSTR.append(msgstr.match(line).group(1))
+ line = msgstr.match(line).group(1)
+ MSGSTR.append(quote_esc.sub('"',line))
state = 3
pointer = pointer + 1
elif blank.match(line):
@@ -102,7 +107,8 @@
trans[tuple(MSGID)] = (COM, MSGSTR)
state = 0
elif re_str.match(line):
- MSGSTR.append(re_str.match(line).group(1))
+ line = re_str.match(line).group(1)
+ MSGSTR.append(quote_esc.sub('"',line))
state = 3
pointer = pointer + 1
elif blank.match(line):
## Script (Python) "TranslatedBody"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=
##title=Modify the status of a content object
##
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
return context.CookedBody()
\ No newline at end of file
## Script (Python) "TranslatedDescription"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=
##title=Modify the status of a content object
##
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
Description = context.Description
if callable(Description):
Description = Description()
if Description: return Description
return ''
## Script (Python) "TranslatedTitle"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=
##title=Modify the status of a content object
##
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
title=context.title
if callable(title):
title=title()
if title: return context.gettext(title)
return ''
## Script (Python) "TranslatedTitle_or_id"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=
##title=Modify the status of a content object
##
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
title=context.title
if callable(title):
title=title()
if title: return title
return context.getId()
<dtml-let relative_to_content="1">
<dtml-var standard_html_header>
</dtml-let>
<div class="Desktop">
<div class="Document">
<dtml-var content_byline>
<div class="Discussion">
<dtml-var aboveInThread>
</div>
<h1> &dtml-TranslatedTitle; </h1>
<dtml-var TranslatedBody>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
</div>
</div>
<dtml-var standard_html_footer>
<dtml-let relative_to_content="1">
<dtml-var standard_html_header>
</dtml-let>
<div class="Desktop">
<div class="Document">
<dtml-var content_byline>
<dtml-var TranslatedBody>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
</div>
</div>
<dtml-var standard_html_footer>
<dtml-var standard_html_header>
<div class="Desktop">
<div class="Link">
<dtml-var content_byline>
<p> <a href="&dtml-getRemoteUrl;">"><dtml-var getRemoteUrl></a> </p>
<dtml-var TranslatedDescription>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
</div>
</div>
<dtml-var standard_html_footer>
<dtml-var standard_html_header>
<div class="Desktop">
<div class="File">
<dtml-var content_byline>
<p>
<b>Filename</b>: <dtml-var getId><br>
<b>Size</b>: <dtml-var size><br>
<b>Content type</b>: <dtml-var content_type><br>
<b>Description</b>: <dtml-var name="description" newline_to_br>
</p>
<a href="&dtml-absolute_url;">Download &dtml-title;</a>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
</div>
</div>
<dtml-var standard_html_footer>
<dtml-var standard_html_header>
<h2><dtml-var title_or_id></h2>
<dtml-let folder_url=absolute_url>
<dtml-in expr="objectValues( [ 'Document', 'News Item', 'Portal Image', 'Portal File', 'Base18 Document', 'Base18 News Item', 'Base18 File', 'Base18 Image' ] )"
skip_unauthorized>
<dtml-if sequence-start>
<h3> Documents, Images, and Files </h3>
<ul>
</dtml-if>
<li> <a href="&dtml-id;"> <dtml-var TranslatedTitle> </a>
<dtml-if name="Description"><blockquote>&dtml-TranslatedDescription;</blockquote></dtml-if></li>
<dtml-if sequence-end>
</ul>
</dtml-if>
</dtml-in>
<dtml-in expr="objectValues( [ 'Link', 'Favorite', 'Base18 Link','Base18 Favorite' ] )" skip_unauthorized>
<dtml-if sequence-start>
<h3> Links </h3>
<ul>
</dtml-if>
<li> <a href="&dtml-getRemoteUrl;"> <dtml-var TranslatedTitle> </a>
<dtml-if name="Description"><blockquote>&dtml-TranslatedDescription;</blockquote></dtml-if></li>
<dtml-if sequence-end>
</ul>
</dtml-if>
</dtml-in>
<dtml-in expr="objectValues( [ 'Folder', 'Portal Folder', 'Skinned Folder' , 'Base18 Folder'] )" skip_unauthorized>
<dtml-if sequence-start>
<h3> Folders </h3>
<ul>
</dtml-if>
<li> <a href="&dtml-id;"> <dtml-var TranslatedTitle_or_id> </a>
<dtml-if name="Description"><blockquote>&dtml-TranslatedDescription;</blockquote></dtml-if></li>
<dtml-if sequence-end>
</ul>
</dtml-if>
</dtml-in>
</dtml-let>
<dtml-var standard_html_footer>
<dtml-comment>
folderfilter cookie maintenance.
</dtml-comment>
<dtml-in filterCookie>
</dtml-in>
<dtml-comment>
Folder contents display.
</dtml-comment>
<dtml-call "REQUEST.set('isDesktop', 1)">
<dtml-var standard_html_header>
<dtml-if "not portal_membership.checkPermission('List folder contents'
, this())">
<dtml-call "RESPONSE.redirect(absolute_url())">
</dtml-if>
<!-- This is the desktop area -->
<div class="Desktop">
<h1> Desktop </h1>
<form action="&dtml-absolute_url;" method="POST">
<table class="FormLayout">
<tr>
<td valign="top">
<table class="ContentsList">
<dtml-if "portal_membership.checkPermission( 'List folder contents'
, this(), 'aq_parent')">
<dtml-let upNav="_.hasattr(this().aq_parent, 'portal_url')"
upID="this().aq_parent.getId()"
>
<tr valign="top">
<td width="16"><br></td>
<td>
<dtml-if upNav>
<a href="../folder_contents"
><img src="&dtml-portal_url;/UpFolder_icon.gif"
alt="[Link]" border="0"></a>
</dtml-if>
</td>
<td>
<dtml-if upNav>
Up to <a href="../folder_contents"><dtml-var upID></a>
<dtml-else>
<span class="mild">Root</span>
</dtml-if>
</td>
</tr>
</dtml-let>
</dtml-if>
<dtml-let filterString="REQUEST.get( 'folderfilter', '' )"
filter="decodeFolderFilter( filterString )"
>
<dtml-in expr="listFolderContents( contentFilter=filter )"
sort="getId" size="19" start=qs skip_unauthorized>
<dtml-if next-sequence>
<dtml-call "REQUEST.set('next-sequence'
, _['next-sequence-start-number'])">
</dtml-if>
<dtml-if previous-sequence>
<dtml-call "REQUEST.set('previous-sequence'
,_['previous-sequence-start-number'])">
</dtml-if>
<dtml-let obj="_.getitem('sequence-item', 0 )"
folderish=isPrincipiaFolderish
portalish="_.hasattr( obj, 'isPortalContent' )
and obj.isPortalContent"
methodID="folderish and '/folder_contents' or ( portalish
and '/view' or '' )"
getIcon="_.hasattr(obj, 'getIcon') and obj.getIcon()"
icon="getIcon or _.getattr(obj, 'icon', '')"
>
<tr valign="top">
<td>
<input type="checkbox" name="ids:list" value="&dtml-getId;"
id="cb_&dtml-getId;" />
</td>
<td>
<dtml-if icon>
<a href="&dtml.url_quote-getId;&dtml-methodID;"
><img src="&dtml-portal_url;/&dtml-icon;"
alt="&dtml-Type;" border="0"></a>
</dtml-if>
</td>
<td>
<a href="&dtml.url_quote-getId;&dtml-methodID;"
>&dtml-getId;<dtml-if title> (&dtml-title;)</dtml-if></a>
</td>
</tr>
<dtml-if qs>
<dtml-if "_['sequence-index'] - _.int(qs) == 7">
</table><dtml-comment> End of first column </dtml-comment>
</td>
<td>
<table class="ContentsList">
</dtml-if>
<dtml-else> <dtml-comment> No batch </dtml-comment>
<dtml-if "_['sequence-index'] == 8">
</table><dtml-comment> End of first column </dtml-comment>
</td>
<td valign="top">
<table class="ContentsList">
</dtml-if>
</dtml-if>
</dtml-let>
</dtml-in>
</dtml-let>
</table>
</td>
</tr>
<tr>
<td align="right">
<dtml-if previous-sequence>
<a href="folder_contents?qs=&dtml-previous-sequence;">Previous items</a>
<dtml-else>
<br>
</dtml-if>
</td>
<td align="left">
<dtml-if next-sequence>
<a href="folder_contents?qs=&dtml-next-sequence;">Next items</a>
<dtml-else>
<br>
</dtml-if>
</td>
</tr>
</table><dtml-comment> End of listing table </dtml-comment>
<table border="0" cellspacing="0" cellpadding="2">
<tr>
<td align="left" valign="top" width="16"></td>
<td align="left" valign="top">
<dtml-if expr="portal_membership.checkPermission('Add portal content'
, this())">
<input type="submit" name="folder_factories:method" value="New...">
</dtml-if>
<dtml-if expr="portal_membership.checkPermission('View management screens'
, this())">
<input type="submit" name="folder_rename_form:method" value="Rename">
<input type="submit" name="folder_cut:method" value="Cut">
<input type="submit" name="folder_copy:method" value="Copy">
<dtml-if cb_dataValid>
<input type="submit" name="folder_paste:method" value="Paste">
</dtml-if>
</dtml-if>
<dtml-if expr="portal_membership.checkPermission('Delete objects', this())">
<input type="submit" name="folder_delete:method" value="Delete">
</dtml-if>
</td>
</tr>
</table>
</form>
<dtml-var folder_filter_form>
</div>
<dtml-var standard_html_footer>
return context.TranslatedBody()
\ No newline at end of file
return context.TranslatedDescription()
\ No newline at end of file
return context.TranslatedTitle()
\ No newline at end of file
return context.TranslatedTitle_or_id()
\ No newline at end of file
<dtml-var standard_html_header>
<div class="Desktop">
<div class="Image">
<dtml-var tag>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
</div>
</div>
<dtml-var standard_html_footer>
<dtml-var standard_html_header>
<div class="Desktop">
<div class="Link">
<dtml-var content_byline>
<p>
<a href="<dtml-var remote_url>"><dtml-var remote_url></a></p>
</p>
<dtml-var TranslatedDescription>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
</div>
</div>
<dtml-var standard_html_footer>
<dtml-let relative_to_content="1">
<dtml-var standard_html_header>
</dtml-let>
<div class="Desktop">
<div class="NewsItem">
<blockquote class="Description">
<dtml-var TranslatedDescription fmt="structured-text">
</blockquote>
<dtml-var content_byline>
<dtml-var TranslatedBody>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
</div>
</div>
<dtml-var standard_html_footer>
## Script (Python) "translation_edit"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=target_content, target_language, text, file='', SafetyBelt='', choice=' Change '
##title=Edit a document
##
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
#try:
if 1:
target_content = context.restrictedTraverse(target_content, None)
context.edit( ''
, text
, file
, safety_belt=SafetyBelt
, target_language=target_language
, target_content=target_content
)
qst='portal_status_message=Document+changed.'
if choice == ' Change and View ':
target_action = context.getTypeInfo().getActionById( 'view' )
else:
target_action = context.getTypeInfo().getActionById( 'edit' )
context.REQUEST.RESPONSE.redirect( '%s/%s?%s' % ( context.absolute_url()
, target_action
, qst
) )
#except Exception, msg:
# target_action = context.getTypeInfo().getActionById( 'edit' )
# context.REQUEST.RESPONSE.redirect('%s/%s?portal_status_message=%s' % (
# context.absolute_url()
# , target_action
# , msg
# ))
<dtml-var standard_html_header>
<div class="Desktop">
<dtml-if message>
<p>&dtml-message;</p>
<hr>
</dtml-if>
<div class="Document">
<h2>Edit &dtml-getId;</h2>
<form action="translation_edit" method="post" enctype="multipart/form-data">
<input type="hidden" name="SafetyBelt" value="&dtml-SafetyBelt;">
<table class="FormLayout">
<tr>
<th>
Title
</th>
<td>
<dtml-var Title>
</td>
</tr>
<tr>
<th>
Description
</th>
<td>
<dtml-var description>
</td>
</tr>
<tr>
<th>
Target
</th>
<td>
<input type="text" name="target_content:string" value="&dtml-targetContentPath;" />
</td>
</tr>
<tr>
<th>
Language
</th>
<td>
<input type="text" name="target_language:string" value="&dtml-targetLanguage;" />
</td>
</tr>
<tr>
<th> Upload </th>
<td>
<input type="file" name="file" size="25">
</td>
</tr>
<tr>
<th class="TextField"> Edit </th>
<td class="TextField">
<textarea name="text:text"
rows="20" cols="80"><dtml-var EditableBody html_quote></textarea>
</td>
</tr>
<tr>
<td> <br> </td>
<td>
<input type="submit" name="choice" value=" Change ">
<input type="submit" name="choice" value=" Change and View ">
</td>
</tr>
</table>
</form>
</div>
</div>
<dtml-var standard_html_footer>
\ No newline at end of file
<dtml-var standard_html_header>
<dtml-let member="portal_membership.getAuthenticatedMember()"
translation_state="portal_workflow.getInfoFor(this(), 'translation_state')"
translation_history="portal_workflow.getInfoFor(this(), 'translation_history')"
url="portal_workflow.getInfoFor(this(), 'url')">
<div class="Desktop">
<h1> Register a Translation </h1>
<dtml-if message>
<h2 class="DesktopTitle">&dtml-message;</h2>
</dtml-if>
<p>To make use of a translation, it has to be reviewed by one of the site's reviewers.
A <b>registered</b> translation becomes the default translation for a given document
to the general member base and anonymous visitors.</p>
<form method="post" action="translation_status_modify">
<table class="FormLayout">
<tr>
<td valign=top align=left>
<strong>Status</strong>
</td>
<td valign=top align=left>
This item is currently in <b>&dtml-translation_state;</b> status.
<input type="hidden" name="workflow_action" value="register">
</td>
</tr>
<tr>
<td valign=top align=left colspan=2>
<strong><em>Comments</em></strong><br>
<textarea name="comment" cols="60" rows="5" wrap="soft"
style="width: 100%"></textarea>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value=" Register Translation "></td>
</tr>
</table>
</form>
<dtml-if review_history>
<p><strong>Reviewing history</strong><br>
<dtml-in review_history mapping reverse>
<dtml-var time fmt="aCommon"> &dtml-action;
<dtml-if effective_date>
(effective: <dtml-var effective_date fmt="aCommon">)
</dtml-if>
by &dtml-actor;<br>
<dtml-if "_['sequence-item']['comments']">
</p><dtml-var "_['sequence-item']['comments']" fmt="structured-text"><p>
</dtml-if>
</dtml-in>
</p>
</dtml-if>
</dtml-let>
</div>
<dtml-var standard_html_footer>
\ No newline at end of file
## Script (Python) "translation_status_modify"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=workflow_action, comment='', url=''
##title=Modify the status of a content object
##
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
context.portal_workflow.doActionFor(
context,
workflow_action,
comment=comment)
content = context.restrictedTraverse(context.targetContent)
language = context.targetLanguage
translation = context.restrictedTraverse(context.id)
if workflow_action == 'unregister':
context.portal_translations.unregisterTranslation(content,translation,language=language)
redirect_url = '%s/view?%s' % ( context.absolute_url()
, 'portal_status_message=Status+changed.'
)
elif workflow_action == 'register':
context.portal_translations.registerTranslation(content,translation,language=language)
redirect_url = '%s/view?%s' % ( context.absolute_url()
, 'portal_status_message=Status+changed.'
)
else:
redirect_url = '%s/view?%s' % ( context.absolute_url()
, 'portal_status_message=Status+changed.'
)
context.REQUEST[ 'RESPONSE' ].redirect( redirect_url )
<dtml-var standard_html_header>
<dtml-let member="portal_membership.getAuthenticatedMember()"
translation_state="portal_workflow.getInfoFor(this(), 'translation_state')"
translation_history="portal_workflow.getInfoFor(this(), 'translation_history')"
url="portal_workflow.getInfoFor(this(), 'url')">
<div class="Desktop">
<h1> Submit a Translation for Review </h1>
<dtml-if message>
<h2 class="DesktopTitle">&dtml-message;</h2>
</dtml-if>
<p>To make use of a translation, it has to be reviewed by one of the site's reviewers.
A <b>registered</b> translation becomes the default translation for a given document
to the general member base and anonymous visitors.</p>
<form method="post" action="translation_status_modify">
<table class="FormLayout">
<tr>
<td valign=top align=left>
<strong>Status</strong>
</td>
<td valign=top align=left>
This item is currently in <b>&dtml-translation_state;</b> status.
<input type="hidden" name="workflow_action" value="submit">
</td>
</tr>
<tr>
<td valign=top align=left colspan=2>
<strong><em>Comments</em></strong><br>
<textarea name="comment" cols="60" rows="5" wrap="soft"
style="width: 100%"></textarea>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value=" Submit Translation "></td>
</tr>
</table>
</form>
<dtml-if review_history>
<p><strong>Reviewing history</strong><br>
<dtml-in review_history mapping reverse>
<dtml-var time fmt="aCommon"> &dtml-action;
<dtml-if effective_date>
(effective: <dtml-var effective_date fmt="aCommon">)
</dtml-if>
by &dtml-actor;<br>
<dtml-if "_['sequence-item']['comments']">
</p><dtml-var "_['sequence-item']['comments']" fmt="structured-text"><p>
</dtml-if>
</dtml-in>
</p>
</dtml-if>
</dtml-let>
</div>
<dtml-var standard_html_footer>
\ No newline at end of file
<dtml-var standard_html_header>
<div class="Desktop">
<div class="File">
<dtml-var content_byline>
<p>
<b>Document</b>: <dtml-var getId><br>
<b>Description</b>: <dtml-var name="description" newline_to_br>
</p>
<a href="&dtml-absolute_url;/TranslationTemplate">Download &dtml-title;</a>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
</div>
</div>
<dtml-var standard_html_footer>
<dtml-let relative_to_content="1">
<dtml-var standard_html_header>
</dtml-let>
<div class="Desktop">
<div class="Document">
<dtml-var content_byline>
<dtml-var CookedBody>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
</div>
</div>
<dtml-var standard_html_footer>
## Script (Python) "change_language"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=
##title=Modify the language cookie
##
request = context.REQUEST
PARENTS = request.PARENTS
portal_root = context.portal_url.getPortalObject()
portal_root_path = portal_root.getPhysicalPath()
lang_list = context.gettext.get_available_languages()
if len(PARENTS) >= (1 + len(portal_root_path)):
section = PARENTS[len(PARENTS) - 1
- len(portal_root.getPhysicalPath())]
if section.id in lang_list:
if len(PARENTS) >= (2 + len(portal_root_path)):
section = PARENTS[len(PARENTS) - 2
- len(portal_root_path)]
else:
section = context
else:
section = context
return section
## Script (Python) "change_language"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=
##title=Modify the language cookie
##
request = context.REQUEST
PARENTS = request.PARENTS
portal_root = context.portal_url.getPortalObject()
portal_root_path = portal_root.getPhysicalPath()
lang_list = context.gettext.get_available_languages()
if len(PARENTS) >= (2 + len(portal_root_path)):
section = PARENTS[len(PARENTS) - 1
- len(portal_root.getPhysicalPath())]
subsection = PARENTS[len(PARENTS) - 2
- len(portal_root.getPhysicalPath())]
if section.id in lang_list:
if len(PARENTS) >= (3 + len(portal_root_path)):
subsection = PARENTS[len(PARENTS) - 3
- len(portal_root_path)]
else:
subsection = context
else:
subsection = context
return subsection
\ No newline at end of file
TODO
- make sure permission to see private folder is OK
\ No newline at end of file
<dtml-let portal_obj="portal_url.getPortalObject()">
<dtml-if "portal_obj != this()">
<a href="&dtml-portal_url;"><dtml-var "portal_obj.Title()"></a>&nbsp;<dtml-in "REQUEST.PARENTS[0:-(_.len(portal_obj.getPhysicalPath()))]" reverse>&gt;&nbsp;<a href="<dtml-var local_absolute_url>"><dtml-var TranslatedTitle_or_id></a>&nbsp;</dtml-in>
<dtml-if "REQUEST.PARENTS[0] != this()">&gt;&nbsp;<a href="<dtml-var local_absolute_url>"><dtml-var TranslatedTitle_or_id></a></dtml-if>
</dtml-if>
</dtml-let>
## Script (Python) "change_language"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=REQUEST
##title=Modify the language cookie
##
lang = REQUEST['lang']
path = context.absolute_url()[len(REQUEST['SERVER_URL']):] or '/'
REQUEST.RESPONSE.setCookie('LOCALIZER_LANGUAGE', lang, path=path)
REQUEST.RESPONSE.redirect(REQUEST['HTTP_REFERER'])
## Script (Python) "combined_subjects"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=
##title=Combine all possible subjects and sub-subjects
##
##############################################################################
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
def buildCombinedSubjects(topic):
myquery = topic.buildQuery()
if myquery.has_key('Subject'):
subjects = [myquery['Subject']]
else:
subjects = []
for subtopic in topic.listSubtopics():
subjects = subjects + buildCombinedSubjects(subtopic)
return subjects
return buildCombinedSubjects(context)
<dtml-comment>
Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
This software is subject to the provisions of the Zope Public License,
Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE
</dtml-comment>
<dtml-var standard_html_header>
<dtml-let member="portal_membership.getAuthenticatedMember()"
review_state="portal_workflow.getInfoFor(this(), 'review_state')"
review_history="portal_workflow.getInfoFor(this(), 'review_history')">
<div class="Desktop">
<h1> Hide Item </h1>
<dtml-if message>
<h2 class="DesktopTitle">&dtml-message;</h2>
</dtml-if>
<p align="center"><img src="corporate_workflow.png" /></p>
<p>A <b>private</b> item is only available to its owner.</p>
<p>Another way to control the visibility of an item is with its <b>effective
date</b>. An item is not publicly available before its effective date,
<em>even if its status is <b>published</b></em>.</p>
<form method="post" action="content_status_modify">
<table class="FormLayout">
<tr>
<td valign=top align=left>
<strong>Status</strong>
</td>
<td valign=top align=left>
This item is currently in <b>&dtml-review_state;</b> status.
<input type="hidden" name="workflow_action" value="hide">
</td>
</tr>
<tr>
<td valign=top align=left colspan=2>
<strong><em>Comments</em></strong><br>
<textarea name="comment" cols="60" rows="5" wrap="soft"
style="width: 100%"></textarea>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value=" Hide this Item "></td>
</tr>
</table>
</form>
<dtml-if review_history>
<p><strong>Reviewing history</strong><br>
<dtml-in review_history mapping reverse>
<dtml-var time fmt="aCommon"> &dtml-action;
<dtml-if effective_date>
(effective: <dtml-var effective_date fmt="aCommon">)
</dtml-if>
by &dtml-actor;<br>
<dtml-if "_['sequence-item']['comments']">
</p><dtml-var "_['sequence-item']['comments']" fmt="structured-text"><p>
</dtml-if>
</dtml-in>
</p>
</dtml-if>
</dtml-let>
</div>
<dtml-var standard_html_footer>
<dtml-comment>
Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
This software is subject to the provisions of the Zope Public License,
Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE
</dtml-comment>
<dtml-var standard_html_header>
<dtml-let member="portal_membership.getAuthenticatedMember()"
review_state="portal_workflow.getInfoFor(this(), 'review_state')"
review_history="portal_workflow.getInfoFor(this(), 'review_history')">
<div class="Desktop">
<h1> Publish Item </h1>
<dtml-if message>
<h2 class="DesktopTitle">&dtml-message;</h2>
</dtml-if>
<p align="center"><img src="corporate_workflow.png" /></p>
<p>A <b>published</b> item is available to the general
member base and anonymous visitors.</p>
<p>Another way to control the visibility of an item is with its <b>effective
date</b>. An item is not publicly available before its effective date,
<em>even if its status is <b>published</b></em>.</p>
<form method="post" action="content_status_modify">
<table class="FormLayout">
<tr>
<td valign=top align=left>
<strong>Status</strong>
</td>
<td valign=top align=left>
This item is currently in <b>&dtml-review_state;</b> status.
<input type="hidden" name="workflow_action" value="publish">
</td>
</tr>
<tr>
<td valign=top align=left colspan=2>
<strong><em>Comments</em></strong><br>
<textarea name="comment" cols="60" rows="5" wrap="soft"
style="width: 100%"></textarea>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value=" Publish this Item "></td>
</tr>
</table>
</form>
<dtml-if review_history>
<p><strong>Reviewing history</strong><br>
<dtml-in review_history mapping reverse>
<dtml-var time fmt="aCommon"> &dtml-action;
<dtml-if effective_date>
(effective: <dtml-var effective_date fmt="aCommon">)
</dtml-if>
by &dtml-actor;<br>
<dtml-if "_['sequence-item']['comments']">
</p><dtml-var "_['sequence-item']['comments']" fmt="structured-text"><p>
</dtml-if>
</dtml-in>
</p>
</dtml-if>
</dtml-let>
</div>
<dtml-var standard_html_footer>
<dtml-comment>
Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
This software is subject to the provisions of the Zope Public License,
Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE
</dtml-comment>
<dtml-var standard_html_header>
<dtml-let member="portal_membership.getAuthenticatedMember()"
review_state="portal_workflow.getInfoFor(this(), 'review_state')"
review_history="portal_workflow.getInfoFor(this(), 'review_history')">
<div class="Desktop">
<h1> Reject Item </h1>
<dtml-if message>
<h2 class="DesktopTitle">&dtml-message;</h2>
</dtml-if>
<p align="center"><img src="corporate_workflow.png" /></p>
<p>Use this form to reject the publication of a content item and set its
status to <b>Private</b>, thereby making it unavailable to
other portal members and visitors.</p>
<form method="post" action="content_status_modify">
<table class="FormLayout">
<tr>
<td valign=top align=left>
<strong>Status</strong>
</td>
<td valign=top align=left>
This item is currently in <b>&dtml-review_state;</b> status.
<input type="hidden" name="workflow_action" value="reject">
</td>
</tr>
<tr>
<td valign=top align=left colspan=2>
<strong><em>Comments</em></strong><br>
<textarea name="comment" cols="60" rows="5" wrap="soft"
style="width: 100%"></textarea>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value=" Reject this Item "></td>
</tr>
</table>
</form>
<dtml-if review_history>
<p><strong>Reviewing history</strong><br>
<dtml-in review_history mapping reverse>
<dtml-var time fmt="aCommon"> &dtml-action;
<dtml-if effective_date>
(effective: <dtml-var effective_date fmt="aCommon">)
</dtml-if>
by &dtml-actor;<br>
<dtml-if "_['sequence-item']['comments']">
</p><dtml-var "_['sequence-item']['comments']" fmt="structured-text"><p>
</dtml-if>
</dtml-in>
</p>
</dtml-if>
</dtml-let>
</div>
<dtml-var standard_html_footer>
<dtml-comment>
Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
This software is subject to the provisions of the Zope Public License,
Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE
</dtml-comment>
<dtml-var standard_html_header>
<dtml-let member="portal_membership.getAuthenticatedMember()"
review_state="portal_workflow.getInfoFor(this(), 'review_state')"
review_history="portal_workflow.getInfoFor(this(), 'review_history')">
<div class="Desktop">
<h1> Release Item </h1>
<dtml-if message>
<h2 class="DesktopTitle">&dtml-message;</h2>
</dtml-if>
<p align="center"><img src="corporate_workflow.png" /></p>
<p>A <b>published</b> item is available to the general
member base but not to anonymous visitors.</p>
<p>Another way to control the visibility of an item is with its <b>effective
date</b>. An item is not publicly available before its effective date,
<em>even if its status is <b>published</b></em>.</p>
<form method="post" action="content_status_modify">
<table class="FormLayout">
<tr>
<td valign=top align=left>
<strong>Status</strong>
</td>
<td valign=top align=left>
This item is currently in <b>&dtml-review_state;</b> status.
<input type="hidden" name="workflow_action" value="publish">
</td>
</tr>
<tr>
<td valign=top align=left colspan=2>
<strong><em>Comments</em></strong><br>
<textarea name="comment" cols="60" rows="5" wrap="soft"
style="width: 100%"></textarea>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value=" Release this Item "></td>
</tr>
</table>
</form>
<dtml-if review_history>
<p><strong>Reviewing history</strong><br>
<dtml-in review_history mapping reverse>
<dtml-var time fmt="aCommon"> &dtml-action;
<dtml-if effective_date>
(effective: <dtml-var effective_date fmt="aCommon">)
</dtml-if>
by &dtml-actor;<br>
<dtml-if "_['sequence-item']['comments']">
</p><dtml-var "_['sequence-item']['comments']" fmt="structured-text"><p>
</dtml-if>
</dtml-in>
</p>
</dtml-if>
</dtml-let>
</div>
<dtml-var standard_html_footer>
<dtml-comment>
Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
This software is subject to the provisions of the Zope Public License,
Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE
</dtml-comment>
<dtml-var standard_html_header>
<dtml-let member="portal_membership.getAuthenticatedMember()"
review_state="portal_workflow.getInfoFor(this(), 'review_state')"
review_history="portal_workflow.getInfoFor(this(), 'review_history')">
<div class="Desktop">
<h1> Retract Item </h1>
<dtml-if message>
<h2 class="DesktopTitle">&dtml-message;</h2>
</dtml-if>
<p align="center"><img src="corporate_workflow.png" /></p>
<p>Use this form to retract a content item by setting its
status to <b>Private</b>, thereby making it unavailable to
other portal members and visitors.</p>
<form method="post" action="content_status_modify">
<table class="FormLayout">
<tr>
<td valign=top align=left>
<strong>Status</strong>
</td>
<td valign=top align=left>
This item is currently in <b>&dtml-review_state;</b> status.
<input type="hidden" name="workflow_action" value="retract">
</td>
</tr>
<tr>
<td valign=top align=left colspan=2>
<strong><em>Comments</em></strong><br>
<textarea name="comment" cols="60" rows="5" wrap="soft"
style="width: 100%"></textarea>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value=" Retract this Item "></td>
</tr>
</table>
</form>
<dtml-if review_history>
<p><strong>Reviewing history</strong><br>
<dtml-in review_history mapping reverse>
<dtml-var time fmt="aCommon"> &dtml-action;
<dtml-if effective_date>
(effective: <dtml-var effective_date fmt="aCommon">)
</dtml-if>
by &dtml-actor;<br>
<dtml-if "_['sequence-item']['comments']">
</p><dtml-var "_['sequence-item']['comments']" fmt="structured-text"><p>
</dtml-if>
</dtml-in>
</p>
</dtml-if>
</dtml-let>
</div>
<dtml-var standard_html_footer>
<dtml-comment>
Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
This software is subject to the provisions of the Zope Public License,
Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE
</dtml-comment>
<dtml-var standard_html_header>
<dtml-let member="portal_membership.getAuthenticatedMember()"
review_state="portal_workflow.getInfoFor(this(), 'review_state')"
review_history="portal_workflow.getInfoFor(this(), 'review_history')">
<div class="Desktop">
<h1> Show Item </h1>
<dtml-if message>
<h2 class="DesktopTitle">&dtml-message;</h2>
</dtml-if>
<p align="center"><img src="corporate_workflow.png" /></p>
<p>A <b>restricted</b> item is available to your partners ie. Members which
have a Partner local role.</p>
<p>Another way to control the visibility of an item is with its <b>effective
date</b>. An item is not publicly available before its effective date,
<em>even if its status is <b>published</b></em>.</p>
<form method="post" action="content_status_modify">
<table class="FormLayout">
<tr>
<td valign=top align=left>
<strong>Status</strong>
</td>
<td valign=top align=left>
This item is currently in <b>&dtml-review_state;</b> status.
<input type="hidden" name="workflow_action" value="show">
</td>
</tr>
<tr>
<td valign=top align=left colspan=2>
<strong><em>Comments</em></strong><br>
<textarea name="comment" cols="60" rows="5" wrap="soft"
style="width: 100%"></textarea>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value=" Show this Item to Partners "></td>
</tr>
</table>
</form>
<dtml-if review_history>
<p><strong>Reviewing history</strong><br>
<dtml-in review_history mapping reverse>
<dtml-var time fmt="aCommon"> &dtml-action;
<dtml-if effective_date>
(effective: <dtml-var effective_date fmt="aCommon">)
</dtml-if>
by &dtml-actor;<br>
<dtml-if "_['sequence-item']['comments']">
</p><dtml-var "_['sequence-item']['comments']" fmt="structured-text"><p>
</dtml-if>
</dtml-in>
</p>
</dtml-if>
</dtml-let>
</div>
<dtml-var standard_html_footer>
<dtml-comment>
Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
This software is subject to the provisions of the Zope Public License,
Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE
</dtml-comment>
<dtml-var standard_html_header>
<dtml-let member="portal_membership.getAuthenticatedMember()"
review_state="portal_workflow.getInfoFor(this(), 'review_state')"
review_history="portal_workflow.getInfoFor(this(), 'review_history')">
<div class="Desktop">
<h1> Submit Item for Review </h1>
<dtml-if message>
<h2 class="DesktopTitle">&dtml-message;</h2>
</dtml-if>
<p align="center"><img src="corporate_workflow.png" /></p>
<p>To make an item published, it
has to be reviewed by one of the site's reviewers.
A <b>published</b> item is available to the general
member base and eventually to anonymous visitors.</p>
<p>Another way to control the visibility of an item is with its <b>effective
date</b>. An item is not publicly available before its effective date,
<em>even if its status is <b>published</b></em>.</p>
<form method="post" action="content_status_modify">
<table class="FormLayout">
<tr>
<td valign=top align=left>
<strong>Status</strong>
</td>
<td valign=top align=left>
This item is currently in <b>&dtml-review_state;</b> status.
<input type="hidden" name="workflow_action" value="submit">
</td>
</tr>
<tr>
<td valign=top align=left colspan=2>
<strong><em>Comments</em></strong><br>
<textarea name="comment" cols="60" rows="5" wrap="soft"
style="width: 100%"></textarea>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value=" Submit Item "></td>
</tr>
</table>
</form>
<dtml-if review_history>
<p><strong>Reviewing history</strong><br>
<dtml-in review_history mapping reverse>
<dtml-var time fmt="aCommon"> &dtml-action;
<dtml-if effective_date>
(effective: <dtml-var effective_date fmt="aCommon">)
</dtml-if>
by &dtml-actor;<br>
<dtml-if "_['sequence-item']['comments']">
</p><dtml-var "_['sequence-item']['comments']" fmt="structured-text"><p>
</dtml-if>
</dtml-in>
</p>
</dtml-if>
</dtml-let>
</div>
<dtml-var standard_html_footer>
<dtml-comment>
Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
This software is subject to the provisions of the Zope Public License,
Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE
</dtml-comment>
<dtml-unless do_inline_css>
<dtml-call "RESPONSE.setHeader('Content-Type','text/css')">
</dtml-unless>
<dtml-with stylesheet_properties>
body {
margin-top: 0;
margin-left: 0;
margin-right: 0;
margin-bottom: 0;
background-color: &dtml-bg_color;;
color: &dtml-base_font_color;;
font-family: &dtml-base_font_family;;
font-size: &dtml-base_font_size;;
}
a:link {
color: &dtml-link_color;;
text-decoration: none;
}
a:visited {
color: &dtml-vlink_color;;
text-decoration: none;
}
a:active {
color: &dtml-alink_color;
text-decoration: none;
}
a:hover {
text-decoration: underline;
color: &dtml-hover_color;;
}
.invisible {
font-size: 80%;
color: &dtml-bg_color;;
}
.mild {
color: #7f7f7f;
}
.DesktopStatusBar{
font-size: 80%;
font-family: &dtml-secondary_font_family;;
color: #ff0000;
}
table {
width: 100%;
border: 0;
}
td.SideBar {
width: 15%;
vertical-align: top;
}
table.ActionBox {
font-family: &dtml-primary_font_family;;
background-color: &dtml-primary_accent_color;;
margin-right: 5px;
margin-left: 1px;
margin-top: 10px;
}
table.ActionBox tr td {
font-size: 70%;
}
table.ActionBox tr td.ActionTitle {
font-weight: bold
}
table.ActionBox tr.GuestActions {
background-color: &dtml-guest_actions_color;;
}
table.ActionBox tr.GuestActions td a:link {
color: &dtml-guest_actions_link_color;;
text-decoration: none;
}
table.ActionBox tr.GuestActions td a:visited {
color: &dtml-guest_actions_link_color;;
text-decoration: none;
}
table.ActionBox tr.GuestActions td a:active {
color: &dtml-guest_actions_link_color;;
text-decoration: none;
}
table.ActionBox tr.GuestActions td a:hover {
color: &dtml-hover_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions {
background-color: &dtml-secondary_accent_color;;
}
table.ActionBox tr.MemberActions td {
color: &dtml-secondary_accent_font_color;;
}
table.ActionBox tr.MemberActions td a:link {
color: &dtml-secondary_accent_link_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions td a:visited {
color: &dtml-secondary_accent_vlink_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions td a:active{
color: &dtml-secondary_accent_alink_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions td a:hover {
color: &dtml-hover_color;;
text-decoration: none;
}
td.Desktop {
vertical-align: top;
}
td.Desktop table tr {
vertical-align: top;
}
div.Desktop p {
font-size: 100%;
margin-right:10pt;
font-family: &dtml-primary_font_family;;
}
div.Desktop h1 {
font-size: 120%;
margin-right:100pt;
font-family: &dtml-secondary_font_family;;
}
div.AuthWarning {
text-align: center;
font-style: italic;
}
div.AuthWarning table {
border: 0;
}
div.AuthWarning tr.Hot {
color: #FF0000;
}
div.Error {
color: #FF0000;
}
p.DesktopStatusBar {
font-size: 100%;
font-family: &dtml-secondary_font_family;;
font-style: italic;
font-weight: bold;
}
table.FormLayout {
width: 80%;
}
table.FormLayout tr {
vertical-align: top;
}
table.FormLayout tr th.TextField {
vertical-align: top;
}
table.FormLayout tr td.TextField {
vertical-align: top;
}
table.FormLayout th {
text-align: right;
}
table.FormLayout dl.FieldHelp dd {
font-size: 70%;
}
table.ContentsList {
}
table.ContentsList tr td img {
border: 0;
}
table.SearchResults {
width: auto;
}
table.SearchResults tr th {
text-align: left;
}
table.SearchResults tr td img {
border: 0;
}
table.Wizard {
width: auto;
}
table.Wizard tr {
vertical-align: top;
}
table.Wizard tr th {
text-align: right;
}
div.NewsBar {
text-align: right;
}
table.NewsItems {
border: 1;
padding: 1;
}
td.NewsBorder {
background-color: &dtml-primary_accent_color;;
}
td.NewsListing {
background-color: &dtml-secondary_accent_color;;
color: &dtml-bg_color;;
}
.NewsLeadin {
background-color: &dtml-bg_color;;
color: &dtml-primary_accent_color;;
}
.NewsByLine {
background-color: &dtml-primary_accent_color;;
color: &dtml-bg_color;;
}
.NewsDateline {
background-color: &dtml-primary_accent_color;;
color: &dtml-bg_color;;
}
td.NewsTitle {
background-color: &dtml-primary_accent_color;;
color: &dtml-primary_accent_font_color;;
text-align: center;
font-size: 90%;
font-weight: bold;
}
tr.NewsItemRow td {
background-color: &dtml-highlight_color;;
font-size: 70%;
}
tr.NewsItemRow td.title {
margin-top: 5px;
margin-bottom: 1px;
font-size: 100%;
font-weight: normal;
}
tr.NewsItemRow td.title p {
margin-top: 3px;
margin-bottom: 1px;
font-size: 100%;
font-weight: normal;
}
tr.NewsItemRow td.title p.description {
margin-top: 0px;
margin-left: 5px;
margin-bottom: 0px;
font-size: 70%;
font-weight: normal;
}
p.NewsHeadline {
background-color: &dtml-primary_accent_color;;
}
td.ListName {
background-color: &dtml-primary_accent_color;;
color: &dtml-primary_accent_font_color;;
font-weight: bold;
}
td.ListDefinition {
font-style: italic;
}
table.logobox {
padding-top: 1px;
padding-left: 2px;
border: 0px;
}
td.TitleBox {
vertical-align: top;
font-family: Verdana, Arial, Helvetica, sans-serif;
color: &dtml-primary_accent_color;;
text-align: right;
font-weight: bolder;
font-size: 18pt;
padding-top: 6px;
}
td.LanguageBox {
vertical-align: top;
text-align: right;
padding-right: 20;
}
.subsectiontitle {
text-align: left;
color: navy;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 8pt;
font-weight: normal;
margin-left: 5pt;
margin-bottom: 1pt;
margin-top: 1pt
}
table.menubox {
margin-right: 5px;
margin-left: 1px;
margin-top: 20px;
}
table.menubox .selected {
background-color: &dtml-secondary_accent_color;;
}
table.menubox td.endline {
border-top: 3px;
border-color: #6524B9;
margin-top: 0px;
}
table.menubox a:link {
color: navy;
text-decoration: none;
}
table.menubox a:visited {
color: navy;
text-decoration: none;
}
table.menubox a:active {
color: navy;
text-decoration: none;
}
table.menubox a:hover {
color: black;
background-color: &dtml-highlight_color;;
text-decoration: underline;
}
table.menubox td.sectiontitle {
border-bottom: 3px;
border-color: #E6BCE6;
padding-bottom: 0px;
padding-top: 10px;
margin-top: 0px;
margin-bottom: 0px;
}
table.menubox p.sectiontitle {
text-align: left;
color: navy;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10pt;
font-weight: bolder;
font-variant: small-caps;
margin-bottom: 2pt;
margin-top: 10pt;
}
div.breadcrumb {
text-align: left;
color: black;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 8pt;
margin-bottom: 10pt;
margin-top: 10pt
}
.breadcrumb p {
text-align: left;
color: black;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 8pt;
margin-bottom: 10pt;
margin-top: 10pt
}
div.Document {
font-size: 11pt;
background-color: &dtml-bg_color;;
color: &dtml-base_font_color;;
font-family: &dtml-base_font_family;;
margin-left: 10pt;
margin-bottom: 3pt;
margin-top: 3pt;
line-height: 17pt;
text-indent: 0pt;
}
div.Document p {
font-family: &dtml-base_font_family;;
font-size: 11pt;
margin-left: 10pt;
margin-bottom: 3pt;
margin-top: 3pt;
line-height: 17pt;
text-indent: 0pt;
}
div.Document p.summary {
font-weight: bold;
}
div.Document ul {
font-family: &dtml-base_font_family;;
font-size: 11pt;
margin-left: 10pt;
margin-bottom: 1pt;
margin-top: 1pt;
line-height: 16pt;
text-indent: 0pt;
vertical-align: middle;
}
div.Document ul li {
margin-left: 0pt;
vertical-align: middle;
}
div.Document ol {
font-family: &dtml-base_font_family;;
font-size: 11pt;
margin-left: 10pt;
margin-bottom: 1pt;
margin-top: 1pt;
line-height: 16pt;
text-indent: 0pt;
vertical-align: middle;
}
div.Document ol li {
margin-left: 0pt;
vertical-align: middle;
}
div.Document h1 {
text-align: left;
color: #333333;
font-family: &dtml-primary_font_family;;
font-weight: bold;
margin-left: 0pt;
margin-top: 15pt;
margin-bottom: 3pt;
font-size: 14pt
}
div.Document h1 a:link {
color: #333333;
}
div.Document h1 a:visited {
color: #333333;
}
div.Document h1 a:active {
color: &dtml-alink_color;
text-decoration: none;
}
div.Document h1 a:hover {
text-decoration: underline;
color: &dtml-hover_color;;
}
div.Document h2 {
text-align: black;
color: #666666;
font-family: &dtml-secondary_font_family;;
font-weight: bold;
margin-left: 10pt;
margin-top: 9pt;
margin-bottom: 3pt;
font-size: 13pt;
}
div.Document h3 {
text-align: left;
color: &dtml-primary_accent_color;;
font-family: &dtml-base_font_family;;
font-style: italic;
font-weight: bolder;
margin-left: 10pt;
margin-top: 6pt;
margin-bottom: 2pt;
letter-spacing: 1pt;
font-size: 10pt;
}
table.tophead {
cellpadding: 1;
cellspacing: 1;
background-color: #CCCCCC;
border-bottom-width: 1pt;
border-top-width: 0;
border-left-width: 0;
border-right-width: 0;
border-color: #6f6f6f;
border-style:solid;
}
table.tophead tr {
font-size: 11px;
font-family: Verdana, Arial, Helvetica, sans-serif;
text-decoration: none;
color: #505050;
vertical-align: middle;
height: 11px;
}
table.tophead td {
vertical-align: middle;
height: 10px;
}
table.tophead p {
line-height: 5pt;
background-color: #6699CC;
}
.legalinfo {
margin-bottom: 40pt;
margin-top: 20pt;
font-size: 8pt;
font-family: Verdana, Arial, Helvetica, sans-serif;
text-align: center;
}
.LanguageBox {
margin-bottom: 0px;
margin-top: 0px;
}
</dtml-with>
<dtml-comment>
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
Jean-Paul Smets <jp@nexedi.com>
WARNING: This program as such is intended to be used by professional
programmers who take the whole responsability of assessing all potential
consequences resulting from its eventual inadequacies and bugs
This program as such is not intended to be used by end users. End
users who are looking for a ready-to-use solution with commercial
garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
</dtml-comment>
<dtml-let relative_to_content="1">
<dtml-var printable_html_header>
</dtml-let>
<div class="Document">
<p class="title">&dtml-TranslatedTitle;</h1>
<dtml-var TranslatedBody>
</div>
<dtml-var printable_html_footer>
<dtml-comment>
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
Jean-Paul Smets <jp@nexedi.com>
WARNING: This program as such is intended to be used by professional
programmers who take the whole responsability of assessing all potential
consequences resulting from its eventual inadequacies and bugs
This program as such is not intended to be used by end users. End
users who are looking for a ready-to-use solution with commercial
garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
</dtml-comment>
<dtml-let relative_to_content="1">
<dtml-var printable_html_header>
</dtml-let>
<div class="Document">
<p class="title">&dtml-TranslatedTitle;</h1>
<p class="summary"><dtml-var TranslatedDescription></p>
<dtml-var TranslatedBody>
</div>
<dtml-var printable_html_footer>
<dtml-let relative_to_content="1">
<dtml-var standard_html_header>
</dtml-let>
<div class="Document">
<dtml-var TranslatedBody>
</div>
<dtml-if "not portal_membership.isAnonymousUser()">
<div class="ContentBy"><dtml-var content_byline></div>
</dtml-if>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
<dtml-var standard_html_footer>
<dtml-comment>
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
Jean-Paul Smets <jp@nexedi.com>
WARNING: This program as such is intended to be used by professional
programmers who take the whole responsability of assessing all potential
consequences resulting from its eventual inadequacies and bugs
This program as such is not intended to be used by end users. End
users who are looking for a ready-to-use solution with commercial
garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
</dtml-comment>
<dtml-let relative_to_content="1">
<dtml-var printable_html_header>
</dtml-let>
<div class="Document">
<div align="center">
<h1><dtml-var title></h1>
</div>
<dtml-var TranslatedBody>
</div>
<dtml-if "not portal_membership.isAnonymousUser()">
<div class="ContentBy"><dtml-var content_byline></div>
</dtml-if>
<dtml-var printable_html_footer>
<dtml-let relative_to_content="1">
<dtml-var standard_html_header>
</dtml-let>
<div class="Document">
<dtml-var CookedBody>
</div>
<dtml-if "not portal_membership.isAnonymousUser()">
<div class="ContentBy"><dtml-var content_byline></div>
</dtml-if>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
<dtml-var standard_html_footer>
<dtml-if "'index.html' in objectIds()">
<dtml-var index.html>
<dtml-elif "'index.stx' in objectIds()">
<dtml-var index.stx>
<dtml-elif "'default.htm' in objectIds()">
<dtml-var default.htm>
<dtml-else>
<dtml-var standard_html_header>
<dtml-let folder_url=absolute_url>
<div class="Document">
<dtml-if name="Description">
<p><dtml-var TranslatedDescription></p>
</dtml-if>
<dtml-in expr="objectValues()" skip_unauthorized
sort=TranslatedTitle_or_id>
<dtml-let obj="_.getitem('sequence-item', 0 )"
folderish=isPrincipiaFolderish
portalish="_.hasattr( obj, 'isPortalContent' ) and obj.isPortalContent"
getIcon="_.hasattr(obj, 'getIcon') and obj.getIcon()"
icon="getIcon or _.getattr(obj, 'icon', '')">
<dtml-if portalish>
<h1>
<dtml-if icon>
<a href="&dtml-folder_url;/&dtml.url_quote-getId;"><img
src="&dtml-portal_url;/&dtml-icon;" alt="&dtml-Type;" border="0">
</a>
</dtml-if>
<a href="&dtml-folder_url;/&dtml.url_quote-getId;"
>&dtml-TranslatedTitle_or_id;</a>
</h1>
<dtml-if name="Description">
<p>&dtml.html_quote-TranslatedDescription;</p>
</dtml-if>
</dtml-if>
</dtml-let>
</dtml-in>
</div>
</dtml-let>
<dtml-var standard_html_footer>
</dtml-if>
<dtml-var standard_html_header>
<div class="Desktop">
<dtml-if message>
<p>&dtml-message;</p>
<hr>
</dtml-if>
<div class="File">
<dtml-if name="role_submit">
<h2>Search results</h2>
<dtml-in expr="portal_membership.searchMembers( search_param=search_param
, search_term=search_term
)" mapping sort="username">
<dtml-if name="sequence-start">
<p>Select Member(s) and a role to assign:</p>
<form method="post" action="folder_localrole_edit">
<input type="hidden" name="change_type" value="add">
<table class="FormLayout">
<tr>
<td width="16">&nbsp;</td>
<td><b>User ID</b></td>
<td><b>Email address</td>
</tr>
</dtml-if>
<dtml-with sequence-item mapping only>
<tr>
<td width="16"><input type="checkbox" name="member_ids:list"
value="&dtml-username;"></td>
<td>&dtml-username;</td>
<td>&dtml-email;</td>
</tr>
</dtml-with>
<dtml-if name="sequence-end">
<tr><td colspan="3">&nbsp;</td></tr>
</tr>
<td colspan="2"><b>Role to assign:</b></td>
<td>
<select name="member_role">
<dtml-in expr="portal_membership.getCandidateLocalRoles( this() )">
<option>&dtml-sequence-item;</option>
</dtml-in>
</select>
</td>
</tr>
<tr><td colspan="3">&nbsp;</td></tr>
<tr>
<td width="16">&nbsp;</td>
<td colspan="2"><input type="submit" value=" Assign Roles "></td>
</tr>
</table>
</form>
</dtml-if>
</dtml-in>
<dtml-else>
<h2>Assign local roles</h2>
<form method="post" action="folder_localrole_form">
<table class="FormLayout">
<tr>
<td><b>Search by</b></td>
<td>
<select name="search_param">
<option value="username">User Name</option>
<option value="email">Email Address</option>
</select>
</td>
</tr>
<tr>
<td><b>Search Term</b></td>
<td><input type="text" name="search_term" size="30"></td>
</tr>
<tr>
<td><br /></td>
<td><input type="submit" name="role_submit" value=" Search "></td>
</tr>
</table>
</form>
<p><hr></p>
<h2>Currently assigned local roles</h2>
<p>These users currently have local roles assigned in this folder:</p>
<form method="post" action="folder_localrole_edit">
<input type="hidden" name="change_type" value="delete">
<input type="hidden" name="member_role" value="">
<table class="FormLayout">
<tr>
<td width="16">&nbsp;</td>
<td><b>User Name</b></td>
<td><b>Role(s)</b></td>
</tr>
<dtml-in expr="this().get_local_roles()">
<tr>
<td width="16">
<dtml-if expr="_['sequence-key'] !=
portal_membership.getAuthenticatedMember().getUserName()">
<input type="checkbox" name="member_ids:list" value="&dtml-sequence-key;">
<dtml-else>
&nbsp;
</dtml-if>
</td>
<td>&dtml-sequence-key;</td>
<td><dtml-var expr="_.string.join( _['sequence-item'], ', ')"></td>
</tr>
</dtml-in>
<tr><td colspan="3">&nbsp;</td></tr>
<tr>
<td><br /></td>
<td colspan="2"><input type="submit" value=" Delete "></td>
</tr>
</table>
</form>
</dtml-if>
</div>
</div>
<dtml-var standard_html_footer>
## Script (Python) "transformation_identity_update"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=lang
##title=
##
from ZTUtils import make_query
request = context.REQUEST
query = make_query(request.form)
# Try to get the id of the DTML method / PT / etc.
method_id = request.URL0[len(request.URL1):]
my_id = context.id
if callable(my_id): my_id = my_id()
if '/' + my_id == method_id:
method_id = ''
relative_url = context.portal_url.getRelativeUrl(context)
# Chop useless language information
for l in context.gettext.get_available_languages():
if relative_url[0:len(l) + 1] == l + '/':
relative_url = relative_url[len(l) + 1:]
# Chop useless /
if relative_url == '':
if len(method_id) > 0:
if method_id[0] == '/':
method_id = method_id[1:]
# Build the new URL
if query == '':
return '%s/%s/%s%s' % (context.portal_url.getPortalObject().absolute_url(), lang,
relative_url,
method_id)
else:
return '%s/%s/%s%s?%s' % (context.portal_url.getPortalObject().absolute_url(), lang,
relative_url,
method_id, query)
<dtml-comment>
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
Jean-Paul Smets <jp@nexedi.com>
WARNING: This program as such is intended to be used by professional
programmers who take the whole responsability of assessing all potential
consequences resulting from its eventual inadequacies and bugs
This program as such is not intended to be used by end users. End
users who are looking for a ready-to-use solution with commercial
garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
</dtml-comment>
<dtml-if "'index.html' in objectIds()">
<dtml-var index.html>
<dtml-else>
<dtml-var standard_html_header>
<div class="Document">
<dtml-var description fmt="structured-text">
</div>
<dtml-var standard_html_footer>
</dtml-if>
<dtml-comment>
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
Jean-Paul Smets <jp@nexedi.com>
WARNING: This program as such is intended to be used by professional
programmers who take the whole responsability of assessing all potential
consequences resulting from its eventual inadequacies and bugs
This program as such is not intended to be used by end users. End
users who are looking for a ready-to-use solution with commercial
garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
</dtml-comment>
<dtml-if "'index.html' in objectIds()">
<dtml-var index.html>
<dtml-else>
<dtml-var standard_html_header>
<div class="Document">
<dtml-var description fmt="structured-text">
</div>
<dtml-var standard_html_footer>
</dtml-if>
<font size="-1">
<dtml-gettext>language</dtml-gettext>:&nbsp;<dtml-in "gettext.get_available_languages()">
<dtml-if expr="gettext.get_selected_language() != _['sequence-item']">
<a href="<dtml-var "getLocalizedPath(_['sequence-item'])">">&dtml-sequence-item;</a>&nbsp;
<dtml-else>
<a href="<dtml-var "getLocalizedPath(_['sequence-item'])">"><b><u>&dtml-sequence-item;</u></b></a>&nbsp;
</dtml-if>
</dtml-in>
<br>
<dtml-let actions="portal_actions.listFilteredActionsFor(this())"
user_actions="actions['object']">
<dtml-in "user_actions" mapping>
<dtml-if "id=='print'">
<a href="&dtml-local_absolute_url;/&dtml-action;"><img src="fileprint.png" border="0"></a>
</dtml-if>
</dtml-in>
</dtml-let>
</font>
<dtml-comment>
Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
This software is subject to the provisions of the Zope Public License,
Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE
</dtml-comment>
<table class="NewsItems" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td class="NewsBorder" width="0" rowspan="13" bgcolor="#6699CC">
<img src="spacer.gif" alt=" "
width="1" height="2" border="0">
</td>
<td valign="top" class="NewsTitle" width="100%">
<b>Latest Additions</b>
</td>
<td class="NewsBorder" width="0" rowspan="13" bgcolor="#6699CC">
<img src="spacer.gif" alt=" "
width="1" height="2" border="0">
</td>
</tr>
<dtml-if "meta_type=='Portal Topic'">
<dtml-in "portal_catalog.searchResults( meta_type=['Base18 File', 'File', 'Document','Link','Base18 Document','Base18 Link']
, sort_on='Date'
, sort_order='reverse'
, review_state='published'
, Subject=combined_subjects()
)" size="10">
<tr class="NewsItemRow">
<td valign="top" class="title">
<p><a href="<dtml-var "getObject().local_absolute_url(lang=gettext.get_selected_language())">"> &dtml-Title; </a></p>
<p class="description"><dtml-var Date> - <dtml-var Description></p>
</td>
</tr>
<dtml-else>
<tr class="NewsItemRow">
<td valign="top" class="title">
No news is no news.
</td>
</tr>
</dtml-in>
<dtml-else>
<dtml-in "portal_catalog.searchResults( meta_type=['Document','Link','Base18 Document','Base18 Link']
, sort_on='Date'
, sort_order='reverse'
, review_state='published'
)" size="10">
<tr class="NewsItemRow">
<td valign="top" class="title">
<p><a href="<dtml-var "getObject().local_absolute_url(lang=gettext.get_selected_language())">"> &dtml-Title; </a></p>
<p class="description"><dtml-var Date> - <dtml-var Description></p>
</td>
</tr>
<dtml-else>
<tr class="NewsItemRow">
<td valign="top" class="title">
No news is no news.
</td>
</tr>
</dtml-in>
</dtml-if>
<tr class="NewsItemRow" >
<td class="title">
<a href="&dtml-local_absolute_url;/recent_additions">More...</a>
</td>
</tr>
<tr class="NewsItemRow" height="1">
<td class="NewsBorder" height="1" bgcolor="#6699CC">
<img src="spacer.gif" alt=" "
width="1" height="1" border="0">
</td>
</tr>
</table>
<ul tal:condition="python:here.public_subtopics is not []">
<span tal:repeat="item here/public_subtopics">
<li ><a tal:content="item/title_or_id" tal:attributes="href item/absolute_url">Title</a></li>
<span tal:replace="structure item/list_subtopics" />
</span>
</ul>
\ No newline at end of file
<dtml-if expr="_.has_key('root_topic')"><dtml-var root_topic>/<dtml-var id>
<dtml-let root_topic="root_topic + '/' + id"><dtml-in public_subtopics><dtml-var
list_topic_vocabulary></dtml-in></dtml-let>
<dtml-else><dtml-var id>
<dtml-let root_topic="id"><dtml-in public_subtopics><dtml-var
list_topic_vocabulary></dtml-in></dtml-let></dtml-if>
\ No newline at end of file
## Script (Python) "local_absolute_url"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=lang=None,target=None
##title=
##
if lang is None: lang = context.gettext.get_selected_language()
relative_url = context.portal_url.getRelativeUrl(context)
return '%s/%s/%s' % (context.portal_url.getPortalObject().absolute_url(), lang,
relative_url)
REQUEST=context.REQUEST
try:
return context.portal_registration.mailPassword(REQUEST['userid'], REQUEST)
except 'NotFound', error:
message = error
except 'ValueError', error:
message = error
redirect_url = '%s/mail_password_form?portal_status_message=%s' % ( context.absolute_url()
, message
)
REQUEST.RESPONSE.redirect( redirect_url )
\ No newline at end of file
<table class="menubox" width="100%" tal:define="
portal_root here/portal_url/getPortalObject;
section here/CurrentSection;
subsection here/CurrentSubSection;
lang python:here.gettext.get_selected_language()">
<tr tal:repeat="item portal_root/sections" class="section">
<td class="sectiontitle">
<div class="" tal:attributes="class python:
'selected'*(section.id==item)">
<p class="sectiontitle"><a href="service"
tal:attributes="href python:'%s/%s/%s' % (here.portal_url(),lang,item)"
tal:content="item">Services</a>
</p>
</div>
<p class="subsectiontitle"
tal:repeat="subitem python:section.objectValues(
['Portal Topic','Document','Base18 Document'
,'Base18 Wiki'])"
tal:condition="python:section.id==item">
<a href="/service/qt.stx"
tal:attributes="href python: here.portal_url() + '/' + lang +
'/' + item + '/' + subitem.id"
tal:content="python:subitem.title"
tal:condition="python:subsection.id!=subitem.id">Qt Development</a>
<a href="/service/qt.stx"
tal:attributes="href python: here.portal_url() + '/' + lang +
'/' + item + '/' + subitem.id"
tal:content="python:'>' + subitem.title"
tal:condition="python:subsection.id==subitem.id">Qt Development</a>
</p>
</td>
</tr>
<tr>
<td class="endline"></td>
</tr>
</table>
<table class="NewsItems" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td class="NewsBorder" width="0" rowspan="8" bgcolor="#6699CC">
<img src="spacer.gif" alt=" "
width="1" height="2" border="0">
</td>
<td valign="top" class="NewsTitle" width="100%">
<b>News</b>
</td>
<td class="NewsBorder" width="0" rowspan="8" bgcolor="#6699CC">
<img src="spacer.gif" alt=" "
width="1" height="2" border="0">
</td>
</tr>
<dtml-in "portal_catalog.searchResults( meta_type=['News Item','Base18 News Item']
, sort_on='Date'
, sort_order='reverse'
, review_state='published'
)" size="5">
<tr class="NewsItemRow">
<td valign="top" class="title">
<dtml-if "getObject()">
<p><a href="<dtml-var "getObject().local_absolute_url(lang=gettext.get_selected_language())">"> <dtml-var "getObject().TranslatedTitle()"> </a></p>
<p class="description"><dtml-var Date> - <dtml-var TranslatedDescription></p>
</dtml-if>
</td>
</tr>
<dtml-else>
<tr class="NewsItemRow">
<td valign="top" class="title">
<dtml-gettext>No news is no news.</dtml-gettext>
</td>
</tr>
</dtml-in>
<tr class="NewsItemRow" >
<td class="title">
<a href="&dtml.url-recent_news;"><dtml-gettext>More...</dtml-gettext></a>
</td>
</tr>
<tr>
<td class="NewsBorder" colspan="3" height="0" bgcolor="#6699CC">
<img src="spacer.gif" alt=" "
width="1" height="1" border="0">
</td>
</tr>
</table>
<dtml-comment>
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
Jean-Paul Smets <jp@nexedi.com>
WARNING: This program as such is intended to be used by professional
programmers who take the whole responsability of assessing all potential
consequences resulting from its eventual inadequacies and bugs
This program as such is not intended to be used by end users. End
users who are looking for a ready-to-use solution with commercial
garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
</dtml-comment>
<dtml-let relative_to_content="1">
<dtml-var pr_printable_html_header>
</dtml-let>
<div class="Document">
<p class="title">&dtml-TranslatedTitle;</h1>
<p class="release"><dtml-gettext>For Immediate Release</dtml-gettext></p>
<p class="summary">&dtml-effective_date; - &dtml-TranslatedDescription;</p>
<dtml-var TranslatedBody>
<h1><dtml-gettext>Permanent URL for this Press Release</dtml-gettext></h1>
<p>&dtml-absolute_url;</p>
<h1><dtml-gettext>About</dtml-gettext>
<dtml-with portal_properties>&dtml-title;</dtml-with></h1>
<p><dtml-var "gettext(news_plate)"></p>
</div>
<dtml-var printable_html_footer>
<dtml-let relative_to_content="1">
<dtml-var standard_html_header>
</dtml-let>
<div class="Document">
<p><dtml-gettext>For Immediate Release</dtml-gettext></p>
<p><b>&dtml-effective_date; - <dtml-var TranslatedDescription></b></p>
<dtml-var TranslatedBody>
<h1><dtml-gettext>Permanent URL for this Press Release</dtml-gettext></h1>
<p>&dtml-absolute_url;</p>
<h1><dtml-gettext>About</dtml-gettext>
<dtml-with portal_properties>&dtml-TranslatedTitle;</dtml-with></h1>
<p><dtml-var "gettext(news_plate)"></p>
</div>
<dtml-if "not portal_membership.isAnonymousUser()">
<div class="ContentBy"><dtml-var content_byline></div>
</dtml-if>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
<dtml-var standard_html_footer>
<dtml-comment>
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
Jean-Paul Smets <jp@nexedi.com>
WARNING: This program as such is intended to be used by professional
programmers who take the whole responsability of assessing all potential
consequences resulting from its eventual inadequacies and bugs
This program as such is not intended to be used by end users. End
users who are looking for a ready-to-use solution with commercial
garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
</dtml-comment>
<dtml-let relative_to_content="1">
<dtml-var standard_html_header>
</dtml-let>
<h1>Send a news release to the press</h1>
<form action="<dtml-var absolute_url>/send_newsitem" method="POST">
<p>Text:</p>
<textarea name="text" rows="25" cols="80" ><dtml-var PreformattedView></textarea>
<p>Journalists:</p>
<textarea name="journalists" rows="25" cols="80" ></textarea>
<p align="center"><input type="submit" name="Send" value="Send" /></p>
</form>
<dtml-var standard_html_footer>
<dtml-let relative_to_content="1">
<dtml-var standard_html_header>
</dtml-let>
<div class="NewsItem">
<blockquote class="Description">
<dtml-var Description fmt="structured-text">
</blockquote>
</div>
<div class="Document">
<dtml-var CookedBody>
</div>
<dtml-if "not portal_membership.isAnonymousUser()">
<div class="ContentBy"><dtml-var content_byline></div>
</dtml-if>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
<dtml-var standard_html_footer>
<dtml-let relative_to_content="1">
<dtml-var standard_html_header>
</dtml-let>
<div class="NewsItem">
<blockquote class="Description">
<dtml-var Description fmt="structured-text">
</blockquote>
</div>
<div class="Document">
<dtml-var CookedBody>
</div>
<dtml-if "not portal_membership.isAnonymousUser()">
<div class="ContentBy"><dtml-var content_byline></div>
</dtml-if>
<div class="Discussion">
<dtml-var viewThreadsAtBottom>
</div>
<dtml-var standard_html_footer>
<dtml-comment>
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
Jean-Paul Smets <jp@nexedi.com>
WARNING: This program as such is intended to be used by professional
programmers who take the whole responsability of assessing all potential
consequences resulting from its eventual inadequacies and bugs
This program as such is not intended to be used by end users. End
users who are looking for a ready-to-use solution with commercial
garantees 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
</dtml-comment>
<dtml-if "_.hasattr(this(),'isEffective') and not isEffective( ZopeTime() )">
<dtml-unless "portal_membership.checkPermission('Request review',this())
or portal_membership.checkPermission('Review portal content',this())">
<dtml-var "RESPONSE.unauthorized()">
</dtml-unless>
</dtml-if>
<html>
<head>
<title><dtml-with portal_properties>&dtml-title;</dtml-with
><dtml-if name="Title">: &dtml-TranslatedTitle;</dtml-if></title>
<link rel="stylesheet" href="pr_printable_stylesheet" type="text/css" />
<dtml-if relative_to_content>
<base href="&dtml-absolute_url;" />
</dtml-if>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<dtml-with stylesheet_properties>
<body font="&dtml-base_font_color;">
</dtml-with>
<dtml-with logo-hires>
<img src="logo-hires" height="&dtml-height;" width="&dtml-width;" />
</dtml-with>
<dtml-unless do_inline_css>
<dtml-call "RESPONSE.setHeader('Content-Type','text/css')">
</dtml-unless>
<dtml-with stylesheet_properties>
body {
margin-top: 0;
margin-left: 0;
margin-right: 0;
margin-bottom: 0;
background-color: &dtml-bg_color;;
color: &dtml-base_font_color;;
font-family: &dtml-base_font_family;;
font-size: &dtml-base_font_size;;
}
a:link {
color: &dtml-link_color;;
text-decoration: none;
}
a:visited {
color: &dtml-vlink_color;;
text-decoration: none;
}
a:active {
color: &dtml-alink_color;
text-decoration: none;
}
a:hover {
text-decoration: underline;
color: &dtml-hover_color;;
}
.invisible {
font-size: 80%;
color: &dtml-bg_color;;
}
.mild {
color: #7f7f7f;
}
.DesktopStatusBar{
font-size: 80%;
font-family: &dtml-secondary_font_family;;
color: #ff0000;
}
table {
width: 100%;
border: 0;
}
td.SideBar {
width: 15%;
vertical-align: top;
}
table.ActionBox {
font-family: &dtml-primary_font_family;;
background-color: &dtml-primary_accent_color;;
margin-right: 5px;
margin-left: 1px;
margin-top: 10px;
}
table.ActionBox tr td {
font-size: 70%;
}
table.ActionBox tr td.ActionTitle {
font-weight: bold
}
table.ActionBox tr.GuestActions {
background-color: &dtml-guest_actions_color;;
}
table.ActionBox tr.GuestActions td a:link {
color: &dtml-guest_actions_link_color;;
text-decoration: none;
}
table.ActionBox tr.GuestActions td a:visited {
color: &dtml-guest_actions_link_color;;
text-decoration: none;
}
table.ActionBox tr.GuestActions td a:active {
color: &dtml-guest_actions_link_color;;
text-decoration: none;
}
table.ActionBox tr.GuestActions td a:hover {
color: &dtml-hover_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions {
background-color: &dtml-secondary_accent_color;;
}
table.ActionBox tr.MemberActions td {
color: &dtml-secondary_accent_font_color;;
}
table.ActionBox tr.MemberActions td a:link {
color: &dtml-secondary_accent_link_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions td a:visited {
color: &dtml-secondary_accent_vlink_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions td a:active{
color: &dtml-secondary_accent_alink_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions td a:hover {
color: &dtml-hover_color;;
text-decoration: none;
}
td.Desktop {
vertical-align: top;
}
td.Desktop table tr {
vertical-align: top;
}
div.Desktop p {
font-size: 100%;
margin-right:100pt;
font-family: &dtml-primary_font_family;;
}
div.Desktop h1 {
font-size: 120%;
margin-right:100pt;
font-family: &dtml-secondary_font_family;;
}
div.AuthWarning {
text-align: center;
font-style: italic;
}
div.AuthWarning table {
border: 0;
}
div.AuthWarning tr.Hot {
color: #FF0000;
}
div.Error {
color: #FF0000;
}
p.DesktopStatusBar {
font-size: 100%;
font-family: &dtml-secondary_font_family;;
font-style: italic;
font-weight: bold;
}
table.FormLayout {
width: 80%;
}
table.FormLayout tr {
vertical-align: top;
}
table.FormLayout tr th.TextField {
vertical-align: top;
}
table.FormLayout tr td.TextField {
vertical-align: top;
}
table.FormLayout th {
text-align: right;
}
table.FormLayout dl.FieldHelp dd {
font-size: 70%;
}
table.ContentsList {
}
table.ContentsList tr td img {
border: 0;
}
table.SearchResults {
width: auto;
}
table.SearchResults tr th {
text-align: left;
}
table.SearchResults tr td img {
border: 0;
}
table.Wizard {
width: auto;
}
table.Wizard tr {
vertical-align: top;
}
table.Wizard tr th {
text-align: right;
}
div.NewsBar {
text-align: right;
}
table.NewsItems {
border: 1;
padding: 1;
}
td.NewsBorder {
background-color: &dtml-primary_accent_color;;
}
td.NewsListing {
background-color: &dtml-secondary_accent_color;;
color: &dtml-bg_color;;
}
.NewsLeadin {
background-color: &dtml-bg_color;;
color: &dtml-primary_accent_color;;
}
.NewsByLine {
background-color: &dtml-primary_accent_color;;
color: &dtml-bg_color;;
}
.NewsDateline {
background-color: &dtml-primary_accent_color;;
color: &dtml-bg_color;;
}
td.NewsTitle {
background-color: &dtml-primary_accent_color;;
color: &dtml-primary_accent_font_color;;
text-align: center;
font-size: 90%;
font-weight: bold;
}
tr.NewsItemRow td {
background-color: &dtml-highlight_color;;
font-size: 70%;
}
tr.NewsItemRow td.title {
margin-top: 5px;
margin-bottom: 1px;
font-size: 100%;
font-weight: normal;
}
tr.NewsItemRow td.title p {
margin-top: 3px;
margin-bottom: 1px;
font-size: 100%;
font-weight: normal;
}
tr.NewsItemRow td.title p.description {
margin-top: 0px;
margin-left: 5px;
margin-bottom: 0px;
font-size: 70%;
font-weight: normal;
}
p.NewsHeadline {
background-color: &dtml-primary_accent_color;;
}
td.ListName {
background-color: &dtml-primary_accent_color;;
color: &dtml-primary_accent_font_color;;
font-weight: bold;
}
td.ListDefinition {
font-style: italic;
}
table.logobox {
padding-top: 1px;
padding-left: 2px;
border: 0px;
}
td.TitleBox {
vertical-align: top;
font-family: Verdana, Arial, Helvetica, sans-serif;
color: &dtml-primary_accent_color;;
text-align: right;
font-weight: bolder;
font-size: 18pt;
padding-top: 6px;
}
td.LanguageBox {
vertical-align: top;
text-align: right;
padding-right: 20;
}
.subsectiontitle {
text-align: left;
color: navy;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 8pt;
font-weight: normal;
margin-left: 5pt;
margin-bottom: 1pt;
margin-top: 1pt
}
table.menubox {
margin-right: 5px;
margin-left: 1px;
margin-top: 20px;
}
table.menubox .selected {
background-color: &dtml-secondary_accent_color;;
}
table.menubox td.endline {
border-top: 3px;
border-color: #6524B9;
margin-top: 0px;
}
table.menubox a:link {
color: navy;
text-decoration: none;
}
table.menubox a:visited {
color: navy;
text-decoration: none;
}
table.menubox a:active {
color: navy;
text-decoration: none;
}
table.menubox a:hover {
color: black;
background-color: &dtml-highlight_color;;
text-decoration: underline;
}
table.menubox td.sectiontitle {
border-bottom: 3px;
border-color: #E6BCE6;
padding-bottom: 0px;
padding-top: 10px;
margin-top: 0px;
margin-bottom: 0px;
}
table.menubox p.sectiontitle {
text-align: left;
color: navy;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10pt;
font-weight: bolder;
font-variant: small-caps;
margin-bottom: 2pt;
margin-top: 10pt;
}
div.breadcrumb {
text-align: left;
color: black;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 8pt;
margin-bottom: 10pt;
margin-top: 10pt
}
.breadcrumb p {
text-align: left;
color: black;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 8pt;
margin-bottom: 10pt;
margin-top: 10pt
}
div.Document {
font-size: 11pt;
background-color: &dtml-bg_color;;
color: &dtml-base_font_color;;
font-family: &dtml-base_font_family;;
margin-left: 30pt;
margin-right: 30pt;
margin-bottom: 3pt;
margin-top: 3pt;
line-height: 17pt;
text-indent: 0pt;
text-align: left;
}
div.Document p {
font-family: &dtml-printer_base_font_family;;
font-size: 11pt;
margin-left: 20pt;
margin-right: 30pt;
margin-bottom: 3pt;
margin-top: 3pt;
line-height: 17pt;
text-indent: 0pt;
}
div.Document p.title {
text-align: center;
font-family: &dtml-printer_primary_font_family;;
font-weight: bold;
margin-left: 20pt;
margin-right: 30pt;
margin-top: 15pt;
margin-bottom: 3pt;
font-size: 14pt
}
div.Document p.release {
text-align: center;
margin-bottom: 20pt;
margin-top: 20pt;
}
div.Document p.summary {
font-weight: bold;
margin-bottom: 10pt;
margin-top: 3pt;
}
div.Document ul {
font-family: &dtml-printer_base_font_family;;
font-size: 11pt;
margin-left: 10pt;
margin-bottom: 2pt;
margin-top: 2pt;
line-height: 17pt;
text-indent: 0pt;
vertical-align: middle;
}
div.Document ul li {
margin-left: 0pt;
vertical-align: middle;
}
div.Document ol {
font-family: &dtml-printer_base_font_family;;
font-size: 11pt;
margin-left: 30pt;
margin-bottom: 2pt;
margin-top: 2pt;
line-height: 17pt;
text-indent: 0pt;
vertical-align: baseline;
}
div.Document ol li {
margin-left: 0pt;
vertical-align: baseline;
}
div.Document ol li ul {
margin-left: 0pt;
}
div.Document h1 {
text-align: black;
color: #666666;
font-family: &dtml-secondary_font_family;;
font-weight: bold;
margin-left: 20pt;
margin-right: 30pt;
margin-top: 9pt;
margin-bottom: 3pt;
font-size: 13pt;
}
div.Document h1 a:link {
color: #333333;
}
div.Document h1 a:visited {
color: #333333;
}
div.Document h1 a:active {
color: &dtml-alink_color;
text-decoration: none;
}
div.Document h1 a:hover {
text-decoration: underline;
color: &dtml-hover_color;;
}
div.Document h2 {
text-align: black;
color: #666666;
font-family: &dtml-secondary_font_family;;
font-weight: bold;
margin-left: 20pt;
margin-right: 30pt;
margin-top: 9pt;
margin-bottom: 3pt;
font-size: 13pt;
font-size: 10pt;
}
div.Document h3 {
text-align: left;
color: &dtml-primary_accent_color;;
font-family: &dtml-base_font_family;;
font-style: italic;
font-weight: bolder;
margin-left: 10pt;
margin-top: 6pt;
margin-bottom: 2pt;
letter-spacing: 1pt;
font-size: 10pt;
}
table.tophead {
cellpadding: 1;
cellspacing: 1;
background-color: #CCCCCC;
border-bottom-width: 1pt;
border-top-width: 0;
border-left-width: 0;
border-right-width: 0;
border-color: #6f6f6f;
border-style:solid;
}
table.tophead tr {
font-size: 11px;
font-family: Verdana, Arial, Helvetica, sans-serif;
text-decoration: none;
color: #505050;
vertical-align: middle;
height: 11px;
}
table.tophead td {
vertical-align: middle;
height: 10px;
}
table.tophead p {
line-height: 5pt;
background-color: #6699CC;
}
.legalinfo {
margin-bottom: 40pt;
margin-top: 20pt;
font-size: 8pt;
font-family: Verdana, Arial, Helvetica, sans-serif;
text-align: center;
}
.LanguageBox {
margin-bottom: 0px;
margin-top: 0px;
}
</dtml-with>
<div class="legalinfo">
<p><dtml-var legal_footer></p>
</div>
</body>
</html>
<dtml-if "_.hasattr(this(),'isEffective') and not isEffective( ZopeTime() )">
<dtml-unless "portal_membership.checkPermission('Request review',this())
or portal_membership.checkPermission('Review portal content',this())">
<dtml-var "RESPONSE.unauthorized()">
</dtml-unless>
</dtml-if>
<html>
<head>
<title><dtml-with portal_properties>&dtml-title;</dtml-with
><dtml-if name="Title">: &dtml-TranslatedTitle;</dtml-if></title>
<link rel="stylesheet" href="printable_stylesheet" type="text/css" />
<dtml-if relative_to_content>
<base href="&dtml-absolute_url;" />
</dtml-if>
<dtml-if HTML_CHARSET>
<meta http-equiv="Content-Type"
content="<dtml-var HTML_CHARSET>" />
<dtml-if "HTML_CHARSET == 'text/html; charset=utf-8'">
<dtml-call "REQUEST.RESPONSE.setHeader('Content-Type','text/html; charset=utf-8')">
</dtml-if>
<dtml-else>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1" />
</dtml-if>
</head>
<dtml-with stylesheet_properties>
<body font="&dtml-base_font_color;">
</dtml-with>
<dtml-let lang="gettext.get_selected_language()">
<dtml-if AFFILIATE_PATH>
<img src="&dtml-portal_url;/&dtml-lang;/&dtml-AFFILIATE_PATH;logo.png"
border="0" />
<dtml-else>
<img src="&dtml-portal_url;/&dtml-lang;/logo.png"
border="0" />
</dtml-if>
</dtml-let>
<dtml-unless do_inline_css>
<dtml-call "RESPONSE.setHeader('Content-Type','text/css')">
</dtml-unless>
<dtml-with stylesheet_properties>
body {
margin-top: 0;
margin-left: 0;
margin-right: 0;
margin-bottom: 0;
background-color: &dtml-bg_color;;
color: &dtml-base_font_color;;
font-family: &dtml-base_font_family;;
font-size: &dtml-base_font_size;;
}
a:link {
color: &dtml-link_color;;
text-decoration: none;
}
a:visited {
color: &dtml-vlink_color;;
text-decoration: none;
}
a:active {
color: &dtml-alink_color;
text-decoration: none;
}
a:hover {
text-decoration: underline;
color: &dtml-hover_color;;
}
.invisible {
font-size: 80%;
color: &dtml-bg_color;;
}
.mild {
color: #7f7f7f;
}
.DesktopStatusBar{
font-size: 80%;
font-family: &dtml-secondary_font_family;;
color: #ff0000;
}
table {
width: 100%;
border: 0;
}
td.SideBar {
width: 15%;
vertical-align: top;
}
table.ActionBox {
font-family: &dtml-primary_font_family;;
background-color: &dtml-primary_accent_color;;
margin-right: 5px;
margin-left: 1px;
margin-top: 10px;
}
table.ActionBox tr td {
font-size: 70%;
}
table.ActionBox tr td.ActionTitle {
font-weight: bold
}
table.ActionBox tr.GuestActions {
background-color: &dtml-guest_actions_color;;
}
table.ActionBox tr.GuestActions td a:link {
color: &dtml-guest_actions_link_color;;
text-decoration: none;
}
table.ActionBox tr.GuestActions td a:visited {
color: &dtml-guest_actions_link_color;;
text-decoration: none;
}
table.ActionBox tr.GuestActions td a:active {
color: &dtml-guest_actions_link_color;;
text-decoration: none;
}
table.ActionBox tr.GuestActions td a:hover {
color: &dtml-hover_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions {
background-color: &dtml-secondary_accent_color;;
}
table.ActionBox tr.MemberActions td {
color: &dtml-secondary_accent_font_color;;
}
table.ActionBox tr.MemberActions td a:link {
color: &dtml-secondary_accent_link_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions td a:visited {
color: &dtml-secondary_accent_vlink_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions td a:active{
color: &dtml-secondary_accent_alink_color;;
text-decoration: none;
}
table.ActionBox tr.MemberActions td a:hover {
color: &dtml-hover_color;;
text-decoration: none;
}
td.Desktop {
vertical-align: top;
}
td.Desktop table tr {
vertical-align: top;
}
div.Desktop p {
font-size: 100%;
margin-right:100pt;
font-family: &dtml-primary_font_family;;
}
div.Desktop h1 {
font-size: 120%;
margin-right:100pt;
font-family: &dtml-secondary_font_family;;
}
div.AuthWarning {
text-align: center;
font-style: italic;
}
div.AuthWarning table {
border: 0;
}
div.AuthWarning tr.Hot {
color: #FF0000;
}
div.Error {
color: #FF0000;
}
p.DesktopStatusBar {
font-size: 100%;
font-family: &dtml-secondary_font_family;;
font-style: italic;
font-weight: bold;
}
table.FormLayout {
width: 80%;
}
table.FormLayout tr {
vertical-align: top;
}
table.FormLayout tr th.TextField {
vertical-align: top;
}
table.FormLayout tr td.TextField {
vertical-align: top;
}
table.FormLayout th {
text-align: right;
}
table.FormLayout dl.FieldHelp dd {
font-size: 70%;
}
table.ContentsList {
}
table.ContentsList tr td img {
border: 0;
}
table.SearchResults {
width: auto;
}
table.SearchResults tr th {
text-align: left;
}
table.SearchResults tr td img {
border: 0;
}
table.Wizard {
width: auto;
}
table.Wizard tr {
vertical-align: top;
}
table.Wizard tr th {
text-align: right;
}
div.NewsBar {
text-align: right;
}
table.NewsItems {
border: 1;
padding: 1;
}
td.NewsBorder {
background-color: &dtml-primary_accent_color;;
}
td.NewsListing {
background-color: &dtml-secondary_accent_color;;
color: &dtml-bg_color;;
}
.NewsLeadin {
background-color: &dtml-bg_color;;
color: &dtml-primary_accent_color;;
}
.NewsByLine {
background-color: &dtml-primary_accent_color;;
color: &dtml-bg_color;;
}
.NewsDateline {
background-color: &dtml-primary_accent_color;;
color: &dtml-bg_color;;
}
td.NewsTitle {
background-color: &dtml-primary_accent_color;;
color: &dtml-primary_accent_font_color;;
text-align: center;
font-size: 90%;
font-weight: bold;
}
tr.NewsItemRow td {
background-color: &dtml-highlight_color;;
font-size: 70%;
}
tr.NewsItemRow td.title {
margin-top: 5px;
margin-bottom: 1px;
font-size: 100%;
font-weight: normal;
}
tr.NewsItemRow td.title p {
margin-top: 3px;
margin-bottom: 1px;
font-size: 100%;
font-weight: normal;
}
tr.NewsItemRow td.title p.description {
margin-top: 0px;
margin-left: 5px;
margin-bottom: 0px;
font-size: 70%;
font-weight: normal;
}
p.NewsHeadline {
background-color: &dtml-primary_accent_color;;
}
td.ListName {
background-color: &dtml-primary_accent_color;;
color: &dtml-primary_accent_font_color;;
font-weight: bold;
}
td.ListDefinition {
font-style: italic;
}
table.logobox {
padding-top: 1px;
padding-left: 2px;
border: 0px;
}
td.TitleBox {
vertical-align: top;
font-family: Verdana, Arial, Helvetica, sans-serif;
color: &dtml-primary_accent_color;;
text-align: right;
font-weight: bolder;
font-size: 18pt;
padding-top: 6px;
}
td.LanguageBox {
vertical-align: top;
text-align: right;
padding-right: 20;
}
.subsectiontitle {
text-align: left;
color: navy;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 8pt;
font-weight: normal;
margin-left: 5pt;
margin-bottom: 1pt;
margin-top: 1pt
}
table.menubox {
margin-right: 5px;
margin-left: 1px;
margin-top: 20px;
}
table.menubox .selected {
background-color: &dtml-secondary_accent_color;;
}
table.menubox td.endline {
border-top: 3px;
border-color: #6524B9;
margin-top: 0px;
}
table.menubox a:link {
color: navy;
text-decoration: none;
}
table.menubox a:visited {
color: navy;
text-decoration: none;
}
table.menubox a:active {
color: navy;
text-decoration: none;
}
table.menubox a:hover {
color: black;
background-color: &dtml-highlight_color;;
text-decoration: underline;
}
table.menubox td.sectiontitle {
border-bottom: 3px;
border-color: #E6BCE6;
padding-bottom: 0px;
padding-top: 10px;
margin-top: 0px;
margin-bottom: 0px;
}
table.menubox p.sectiontitle {
text-align: left;
color: navy;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10pt;
font-weight: bolder;
font-variant: small-caps;
margin-bottom: 2pt;
margin-top: 10pt;
}
div.breadcrumb {
text-align: left;
color: black;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 8pt;
margin-bottom: 10pt;
margin-top: 10pt
}
.breadcrumb p {
text-align: left;
color: black;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 8pt;
margin-bottom: 10pt;
margin-top: 10pt
}
div.Document {
font-size: 11pt;
background-color: &dtml-bg_color;;
color: &dtml-base_font_color;;
font-family: &dtml-base_font_family;;
margin-left: 30pt;
margin-right: 30pt;
margin-bottom: 3pt;
margin-top: 3pt;
line-height: 17pt;
text-indent: 0pt;
text-align: left;
}
div.Document p {
font-family: &dtml-printer_base_font_family;;
font-size: 11pt;
margin-left: 30pt;
margin-right: 30pt;
margin-bottom: 3pt;
margin-top: 3pt;
line-height: 17pt;
text-indent: 0pt;
}
div.Document p.title {
text-align: center;
font-family: &dtml-printer_primary_font_family;;
font-weight: bold;
margin-left: 30pt;
margin-right: 30pt;
margin-top: 15pt;
margin-bottom: 15pt;
font-size: 14pt
}
div.Document p.release {
text-align: center;
margin-bottom: 20pt;
margin-top: 20pt;
}
div.Document p.summary {
background-color:#CCCCCC;
font-weight: normal;
margin-bottom: 10pt;
margin-top: 40pt;
margin-left: 50pt;
margin-right: 50pt;
border-width: 1px;
border-color: black;
}
div.Document ul {
font-family: &dtml-printer_base_font_family;;
font-size: 11pt;
margin-left: 30pt;
margin-bottom: 2pt;
margin-top: 2pt;
line-height: 17pt;
text-indent: 0pt;
vertical-align: baseline;
}
div.Document ul li {
margin-left: 0pt;
vertical-align: baseline;
}
div.Document ul li ul {
margin-left: 0pt;
}
div.Document ol {
font-family: &dtml-printer_base_font_family;;
font-size: 11pt;
margin-left: 30pt;
margin-bottom: 2pt;
margin-top: 2pt;
line-height: 17pt;
text-indent: 0pt;
vertical-align: baseline;
}
div.Document ol li {
margin-left: 0pt;
vertical-align: baseline;
}
div.Document ol li ul {
margin-left: 0pt;
}
div.Document h1 {
text-align: black;
letter-spacing: 0.1em;
color: black;
font-family: &dtml-secondary_font_family;;
font-weight: bold;
margin-left: 10pt;
margin-right: 30pt;
margin-top: 30pt;
margin-bottom: 5pt;
font-size: 13pt;
}
div.Document h1 a:link {
color: #333333;
}
div.Document h1 a:visited {
color: #333333;
}
div.Document h1 a:active {
color: &dtml-alink_color;
text-decoration: none;
}
div.Document h1 a:hover {
text-decoration: underline;
color: &dtml-hover_color;;
}
div.Document h2 {
text-align: black;
color: #666666;
font-family: &dtml-secondary_font_family;;
font-weight: bold;
margin-left: 30pt;
margin-right: 30pt;
margin-top: 9pt;
margin-bottom: 3pt;
font-size: 13pt;
font-size: 10pt;
}
div.Document h3 {
text-align: left;
color: &dtml-primary_accent_color;;
font-family: &dtml-base_font_family;;
font-style: italic;
font-weight: bolder;
margin-left: 30pt;
margin-right: 30pt;
margin-top: 6pt;
margin-bottom: 2pt;
letter-spacing: 1pt;
font-size: 10pt;
}
table.tophead {
cellpadding: 1;
cellspacing: 1;
background-color: #CCCCCC;
border-bottom-width: 1pt;
border-top-width: 0;
border-left-width: 0;
border-right-width: 0;
border-color: #6f6f6f;
border-style:solid;
}
table.tophead tr {
font-size: 11px;
font-family: Verdana, Arial, Helvetica, sans-serif;
text-decoration: none;
color: #505050;
vertical-align: middle;
height: 11px;
}
table.tophead td {
vertical-align: middle;
height: 10px;
}
table.tophead p {
line-height: 5pt;
background-color: #6699CC;
}
.legalinfo {
margin-bottom: 40pt;
margin-top: 20pt;
font-size: 8pt;
font-family: Verdana, Arial, Helvetica, sans-serif;
text-align: center;
}
.LanguageBox {
margin-bottom: 0px;
margin-top: 0px;
}
</dtml-with>
##############################################################################
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
return context.listSubtopics()
<dtml-if "portal_membership.isAnonymousUser()">
<form action="&dtml.url-logged_in;" method="post">
<input type="hidden" name="came_from" value="&dtml-absolute_url;">
<table class="FormLayout" >
<tr>
<td align="left" valign="top">
<strong><font size="-2"><dtml-gettext>Name</dtml-gettext></font></strong>
</td>
<td align="left" valign="top">
<font size="-2"><input type="TEXT" name="__ac_name" size="12"
value="<dtml-var "REQUEST.get('__ac_name', '')">"></font>
</td>
</tr>
<tr>
<td align="left" valign="top">
<strong><font size="-2"><dtml-gettext>Password</dtml-gettext></font></strong>
</td>
<td align="left" valign="top">
<font size="-2"><input type="PASSWORD" name="__ac_password" size="12"></font>
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<font size="-2"><input type="submit" name="submit" value="
<dtml-gettext>Login</dtml-gettext> "></font>
</td>
</tr>
<tr>
<td align="center" colspan="2">
</td>
</tr>
<tr>
<td align="center" colspan="2"><i><font size="-2">
<a href="mail_password_form"><dtml-gettext>Lost your password?</dtml-gettext>
</a></font></i>
</td>
</tr>
<tr>
<td align="center" colspan="2"><i><font size="-2">
<a href="join_form"><dtml-gettext>Apply for membership...</dtml-gettext>
</a></font></i>
</td>
</tr>
</table>
</form>
<dtml-else>
<dtml-comment>
<form action="&dtml.url-logout;" method="post">
<table class="FormLayout" >
<tr><td>
<center><font size="-2"><input type="submit" name="submit" value="
<dtml-gettext>Logout</dtml-gettext> "></font></center>
</td></tr>
</table>
</form>
</dtml-comment>
<table class="FormLayout" >
<tr>
<td align="center" colspan="2"><i><font size="-2">
<a href="password_form"><dtml-gettext>Change Password...</dtml-gettext>
</a></font></i>
</td>
</tr>
</table>
</dtml-if>
<dtml-var standard_html_header>
<dtml-if "meta_type=='Portal Topic'">
<dtml-let newsitems="portal_catalog.searchResults(meta_type=['Document','Link','Base18 Document', 'Base18 Link'],
sort_on='Date', sort_order='reverse', review_state='published', Subject=combined_subjects())">
<dtml-in newsitems size="10" start="batch_start" previous>
<p style="Desktop">
<a href="&dtml-URL;&dtml-sequence-query;batch_start=&dtml-previous-sequence-start-number;">
Next &dtml-previous-sequence-size; more recent articles
</a>
</p>
</dtml-in>
<dtml-in newsitems size="10" start="batch_start">
<dtml-if sequence-start>
<table cellspacing="0" border="0" width="90%">
</dtml-if>
<tr>
<td class="NewsListing" align="left" valign="top">
<a href="&dtml-getURL;"> &dtml-title; </a>
<br> By &dtml-Creator;
</td>
<td class="NewsListing" align="right" valign="top">
<dtml-var Date>
</td>
</tr>
<tr>
<td colspan="2">
<em> <dtml-var Description fmt="structured-text"> </em>
</td>
</tr>
<dtml-if sequence-end>
</table>
<dtml-else>
<tr> <td> <br /> </td> </tr>
</dtml-if>
<dtml-else>
<p class="Desktop">
No news is good news!
</p>
</dtml-in>
<dtml-in newsitems size="10" start="batch_start" next>
<p class="Desktop">
<a href="&dtml-URL;&dtml-sequence-query;batch_start=&dtml-next-sequence-start-number;">
Next &dtml-next-sequence-size; older articles
</a>
</p>
</dtml-in>
</dtml-let>
<dtml-else>
<dtml-let newsitems="portal_catalog.searchResults(meta_type=['Document','Link'],
sort_on='Date', sort_order='reverse', review_state='published')">
<dtml-in newsitems size="10" start="batch_start" previous>
<p style="Desktop">
<a href="&dtml-URL;&dtml-sequence-query;batch_start=&dtml-previous-sequence-start-number;">
Next &dtml-previous-sequence-size; more recent articles
</a>
</p>
</dtml-in>
<dtml-in newsitems size="10" start="batch_start">
<dtml-if sequence-start>
<table cellspacing="0" border="0" width="90%">
</dtml-if>
<tr>
<td class="NewsListing" align="left" valign="top">
<a href="&dtml-getURL;"> &dtml-title; </a>
<br> By &dtml-Creator;
</td>
<td class="NewsListing" align="right" valign="top">
<dtml-var Date>
</td>
</tr>
<tr>
<td colspan="2">
<em> <dtml-var Description fmt="structured-text"> </em>
</td>
</tr>
<dtml-if sequence-end>
</table>
<dtml-else>
<tr> <td> <br /> </td> </tr>
</dtml-if>
<dtml-else>
<p class="Desktop">
No news is good news!
</p>
</dtml-in>
<dtml-in newsitems size="10" start="batch_start" next>
<p class="Desktop">
<a href="&dtml-URL;&dtml-sequence-query;batch_start=&dtml-next-sequence-start-number;">
Next &dtml-next-sequence-size; older articles
</a>
</p>
</dtml-in>
</dtml-let>
</dtml-if>
<dtml-var standard_html_footer>
<dtml-var standard_html_header>
<dtml-let newsitems="portal_catalog.searchResults(meta_type=('News Item', 'Base18 News Item'),
sort_on='Date', sort_order='reverse', review_state='published')">
<dtml-in newsitems size="10" start="batch_start" previous>
<p style="Desktop">
<a href="&dtml-URL;&dtml-sequence-query;batch_start=&dtml-previous-sequence-start-number;">
Next &dtml-previous-sequence-size; more recent articles
</a>
</p>
</dtml-in>
<dtml-in newsitems size="10" start="batch_start">
<dtml-if sequence-start>
<table cellspacing="0" border="0" width="90%">
</dtml-if>
<tr>
<td class="NewsListing" align="left" valign="top">
<a href="&dtml-getURL;"> &dtml-title; </a>
<br> By &dtml-Creator;
</td>
<td class="NewsListing" align="right" valign="top">
<dtml-var Date>
</td>
</tr>
<tr>
<td colspan="2">
<em> <dtml-var Description fmt="structured-text"> </em>
</td>
</tr>
<dtml-if sequence-end>
</table>
<dtml-else>
<tr> <td> <br /> </td> </tr>
</dtml-if>
<dtml-else>
<p class="Desktop">
No news is good news!
</p>
</dtml-in>
<dtml-in newsitems size="10" start="batch_start" next>
<p class="Desktop">
<a href="&dtml-URL;&dtml-sequence-query;batch_start=&dtml-next-sequence-start-number;">
Next &dtml-next-sequence-size; older articles
</a>
</p>
</dtml-in>
</dtml-let>
<dtml-var standard_html_footer>
<dtml-var standard_html_header>
<div class="Desktop">
<h1> Search Results </h1>
<dtml-let results="doFormSearch( REQUEST=REQUEST )">
<p>Found <dtml-var expr="_.len(results)" thousands_commas>
items<dtml-if name="SearchableText"> matching "&dtml-SearchableText;"</dtml-if>.</p>
<dtml-in results size="25" start="batch_start">
<dtml-let objURL="getURL() + '/view'">
<dtml-if sequence-start>
<table class="SearchResults">
<tr>
<td width="16"><br></td>
<th> Title
</th>
<th> Type
</th>
<th> Date
</th>
</tr>
</dtml-if>
<tr>
<td>
<dtml-if getIcon>
<a href="&dtml-objURL;"><img
src="&dtml-portal_url;/&dtml-getIcon;" border="0"
alt="[&dtml.missing-Type;]"
title="[&dtml.missing-Type;]"></a>
</dtml-if>
</td>
<td>
<a href="&dtml-objURL;"><dtml-if name="Title"><dtml-var name="Title" size="75" html_quote><dtml-else>(No title)</dtml-if></a>
</td>
<td>
&dtml.missing-Type;
</td>
<td>
&dtml-Date;
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="3"><em>
<dtml-if name="Description"><dtml-var name="Description"
missing="(No description)" size="100" html_quote>
<dtml-else>(No description)</dtml-if></em></td>
</tr>
<dtml-if sequence-end>
</table>
</dtml-if>
</dtml-let>
<dtml-else>
<p> There are no items matching your specified criteria. </p>
</dtml-in>
<dtml-in results size="25" start="batch_start" next>
<dtml-let url=URL
sqry=sequence-query
next=next-sequence-start-number
nextSize=next-sequence-size
nextURL="'%s%sbatch_start=%s' % (url,sqry,next)"
>
<p> <a href="&dtml-nextURL;"> Next &dtml-nextSize; items </a> </p>
</dtml-let>
</dtml-in>
</dtml-let>
</div>
<dtml-var standard_html_footer>
\ No newline at end of file
<dtml-var standard_html_header>
<div class="Desktop">
<h1> Search portal </h1>
<form action="search">
<table class="FormLayout">
<dtml-if "portal_membership.checkPermission('Review portal content', this())">
<tr>
<th> Review Status
</th>
<td>
<select name="review_state:list" size="3" multiple>
<option value="" selected>-- any --</option>
<option value="private">private</option>
<option value="pending">pending</option>
<option value="published">published</option>
</select>
<dl class="FieldHelp">
<dd> As a reviewer, you may search for items based on their
review state. If you wish to constrain results to items
in certain states, select them from this list.
</dd>
</dl>
</td>
</tr>
</dtml-if>
<tr valign="top">
<th> Full Text
</th>
<td>
<input name="SearchableText" size="40">
<dl class="FieldHelp">
<dd> For a simple text search, enter your search term
here. Multiple words may be found by combining
them with <b>AND</b> and <b>OR</b>. This will
find text in items' contents, title and
description.
</dd>
</dl>
</td>
</tr>
<tr>
<th>Title
</th>
<td>
<input name="Title" size="20">
</td>
</tr>
<tr valign="top">
<th>Subject</th>
<td>
<select name="Subject:list" multiple size="4">
<option value="" selected>-- any --</option>
<dtml-in expr="portal_catalog.uniqueValuesFor( 'Subject' )">
<option value="&dtml-Subject;"> &dtml-Subject; </option>
</dtml-in>
</select>
</td>
</tr>
<tr>
<th> Description
</th>
<td>
<input name="Description" size="20">
<dl class="FieldHelp">
<dd> You may also search the items' descriptions and
titles specifically. Multiple words may be found
by combining them with <b>AND</b> and <b>OR</b>.
</dd>
</dl>
</td>
</tr>
<tr>
<th> Find new items since...
</th>
<td>
<select name="created:date">
<dtml-if "not portal_membership.isAnonymousUser()">
<dtml-let member="portal_membership.getAuthenticatedMember()"
lastLogin="member.last_login_time"
>
<option value="&dtml-lastLogin;"> Last login </option>
</dtml-let>
</dtml-if>
<dtml-let today="ZopeTime().earliestTime()"
yesterday="(today-1).Date()"
lastWeek="(today-7).Date()"
lastMth="(today-31).Date()"
ever="'1970/01/01 00:00:00 GMT'"
>
<option value="&dtml-yesterday;"> Yesterday </option>
<option value="&dtml-lastWeek;"> Last week </option>
<option value="&dtml-lastMth;"> Last month </option>
<option value="&dtml-ever;" selected> Ever </option>
</dtml-let>
</select>
<input type="hidden" name="created_usage" value="range:min">
<dl class="FieldHelp">
<dd> You may find only recent items by selecting a time-frame.
</dd>
</dl>
</td>
</tr>
<tr>
<th> Item type
</th>
<td>
<select name="portal_type:list" multiple size="5">
<option value="" selected>-- any --</option>
<dtml-in expr="portal_types.listTypeInfo()">
<option value="&dtml-getId;">&dtml-Title;</option>
</dtml-in>
</select>
<dl class="FieldHelp">
<dd> You may limit your results to particular kinds of
items by selecting them above. To find all kinds
of items, do not select anything.
</dd>
</dl>
</td>
</tr>
<tr>
<th> Creator
</th>
<td>
<input name="Creator" size="20">
<dl class="FieldHelp">
<dd> To find items by a particular user only, enter
their username above. Note that you must enter
their username <i>exactly</i>.
</dd>
</dl>
</td>
</tr>
<tr>
<td><br></td>
<td>
<input type="submit" value="Search">
</td>
</tr>
</table>
</form>
</div>
<dtml-var standard_html_footer>
## Script (Python) "secure_absolute_url"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=lang=None,target=None
##title=
##
if target is None: target = context
if lang is None: lang = context.gettext.get_selected_language()
relative_url = context.portal_url.getRelativeUrl(target)
return '%s/%s/%s' % (context.secure_url, lang,
relative_url)
## Script (Python) "set_criteria"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=
##title=Update all topics to create a classification hierarchy
##
global changed
changed = 0
def updateCriterion(topic,root_topic):
global changed
# Search for criterium
my_cryterium = None
for criterium in topic.listCriteria():
if criterium.Type() == 'String Criterion':
my_cryterium = criterium
if my_cryterium is not None:
my_cryterium.edit(root_topic + topic.id)
changed = changed + 1
else:
my_cryterium = topic.addCriterion('Subject','String Criterion')
updateCriterion(topic,root_topic)
def updateSubtopics(topic, root_topic=''):
updateCriterion(topic,root_topic)
for subtopic in topic.objectValues('Portal Topic'):
updateSubtopics(subtopic,root_topic=root_topic + topic.id + '/')
for topic in container.objectValues('Portal Topic'):
updateSubtopics(topic)
print changed
return printed
\ No newline at end of file
<dtml-var standard_html_header>
<div class="Document">
<pre>
<dtml-with aq_parent>
<dtml-in expr="objectValues('Portal Topic')"><dtml-var list_topic_vocabulary></dtml-in>
</dtml-with>
</pre>
</div>
<dtml-var standard_html_footer>
<div class="Desktop">
<dtml-if localFooter>
<dtml-var localFooter>
</dtml-if>
</div>
</td>
</tr>
</tbody>
</table>
<!-- Legalese -->
<div class="legalinfo">
<p>Nexedi, SARL au capital 10.000 Euros, 943, av. de la Rpublique 59700 Marcq-en-Baroeul<br />
RCS Roubaix Tourcoing 440 047 504 - IBAN: FR76 3002 7000 3900 0000 1332 336<br />
Email:<a href="mailto:info@nexedi.com"> info@nexedi.com</a> Tel. +33(0)6 62 05 76 14
Fax. +33(0)1 44 75 72 97<br />
<a href="/legal">Legal Notice</a>
</p>
</div>
</body>
</html>
\ No newline at end of file
<div class="Desktop">
<dtml-if localFooter>
<dtml-var localFooter>
</dtml-if>
</div>
</td>
</tr>
</tbody>
</table>
<!-- Legalese -->
<div class="legalinfo">
<p><dtml-var legal_footer></p>
</div>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<dtml-comment>
Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
This software is subject to the provisions of the Zope Public License,
Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE
</dtml-comment>
<dtml-if "_.hasattr(this(),'isEffective') and not isEffective( ZopeTime() )">
<dtml-unless "portal_membership.checkPermission('Request review',this())
or portal_membership.checkPermission('Review portal
content',this())">
<dtml-var "RESPONSE.unauthorized()">
</dtml-unless>
</dtml-if>
<html>
<head>
<title><dtml-with portal_properties>&dtml-title;</dtml-with
><dtml-if name="Title">: &dtml-TranslatedTitle;</dtml-if></title>
<dtml-var css_inline_or_link>
<dtml-if relative_to_content>
<base href="&dtml-absolute_url;" />
</dtml-if>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<dtml-with stylesheet_properties>
<body font="&dtml-base_font_color;">
</dtml-with>
<!-- Top Bar: Global links and search -->
<dtml-var standard_top_bar>
<!-- Main Page -->
<table cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<!-- Logo -->
<td rowspan="2" class="LogoBox" valign="top">
<div class="LogoBox">
<a href="&dtml-portal_url;"><img src="&dtml-portal_url;/logo.png"
border="0" /></a>
</div>
</td>
<!-- Title and Language -->
<td width="90%" class="TitleBox">
<dtml-var TranslatedTitle_or_id>
</td>
</tr>
<tr class="LanguageBox">
<td class="LanguageBox">
<dtml-if show_language_selector><dtml-var language_selector></dtml-if>
</td>
</tr>
</tbody>
</table>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<dtml-if show_menu>
<td valign="top" width="150">
<!-- Optional Action Box-->
<dtml-if "not portal_membership.isAnonymousUser()">
<div class="ActionBox"><dtml-var actions_box></div>
</dtml-if>
<!-- Main menu -->
<dtml-var menu_box>
<!-- Quick Login -->
<dtml-if show_quicklogin><br><dtml-var quick_login></dtml-if>
</td>
<!-- Main Box -->
<td colspan="2" valign="top" class="Desktop">
<dtml-else>
<dtml-if
"portal_membership.getAuthenticatedMember().has_role('Manager')">
<td valign="top" width="150">
<!-- Optional Action Box-->
<div class="ActionBox"><dtml-var actions_box></div>
</td>
<!-- Main Box -->
<td colspan="2" valign="top" class="Desktop">
<dtml-else>
<!-- Main Box -->
<td colspan="3" valign="top" class="Desktop">
</dtml-if>
</dtml-if>
<!-- Main Box -->
<div class="Desktop">
<dtml-if "not portal_membership.isAnonymousUser() and
not _.hasattr(portal_membership.getAuthenticatedMember(),
'getMemberId')">
<div class="AuthWarning">
<table>
<tr class="Host">
<td> Warning! </td>
<tr>
<td> You are presently logged in as a user from outside
this portal. Many parts of the portal will not work!
You may have to shut down and relaunch your browser to
log out, depending on how you originally logged in.
</td>
</tr>
</table>
</div>
</dtml-if>
</div>
<dtml-if show_breadcrumb>
<!-- Breadcrumb -->
<div class="breadcrumb">
<p><dtml-var breadcrumb></p>
</div>
</dtml-if>
<div class="Desktop">
<dtml-if portal_status_message>
<p class="DesktopStatusBar"><dtml-var
"gettext(portal_status_message)"></p>
</dtml-if>
<dtml-if localHeader>
<dtml-var localHeader>
</dtml-if>
</div>
<!-- Top navigation bar: access to Nexedi network and search features -->
<table class="tophead" width="100%">
<form action="&dtml-portal_url;/search" method="POST">
<tr>
<td align="left" nowrap valign="middle">
&nbsp;&nbsp;
<dtml-if partner_sites>
<dtml-in partner_sites>
<a class="topbanner" href="http://&dtml-sequence-item;">&dtml-sequence-item;</a>&nbsp;|&nbsp;
</dtml-in>
</dtml-if>
</td>
<td align="right" nowrap valign="middle" width="90%">
<dtml-if show_sitemap>
<a class="topbanner" href="&dtml-portal_url;/sitemap.html">Site Map</a>&nbsp;|&nbsp;
</dtml-if>
<dtml-if show_search>
<a class="topbanner" href="&dtml-portal_url;/search_form">Search</a>
</dtml-if>
</td>
<td align="right" nowrap valign="middle">
<dtml-if special_top_menu>
<dtml-var special_top_menu>
</dtml-if>
<dtml-if show_multisearch>
<font size="-2">
<select name="site" class="osdn-search">
<dtml-in partner_sites>
<option value="&dtml-sequence-item;">&dtml-sequence-item;</option>
</dtml-in>
</select>
</font>
</dtml-if>
<dtml-if show_search>
<font size="-2">
<input type="text" size="12" name="SearchableText" class="tophead-search" />&nbsp;<input type="submit" value="Go" />
</font>
</dtml-if>
</td>
</tr>
</form>
</table>
alink_color:string=#FFFFFF
base_font_color:string=#000000
base_font_size:string=8pt
bg_color:string=#FFFFFF
guest_actions_color:string=#888888
guest_actions_link_color:string=#660000
highlight_color:string=#D3E1C8
highlight_font_color:string=#000000
hover_color:string=#000066
link_color:string=#0000AA
primary_accent_alink_color:string=#FFFFFF
primary_accent_color:string=#2E3065
primary_accent_font_color:string=#FFFFFF
primary_accent_link_color:string=#FFFFFF
primary_accent_text_color:string=#000066
primary_accent_vlink_color:string=#FFFFFF
primary_font_family:string=Verdana, Arial, Helvetica, sans-serif
secondary_accent_alink_color:string=#FFFFFF
secondary_accent_color:string=#D8D3EB
secondary_accent_font_color:string=#000000
secondary_accent_link_color:string=#3E4088
secondary_accent_vlink_color:string=#3E4088
secondary_font_family:string=Arial, Verdana, Helvetica, sans-serif
select_stylesheet_id:string=default_stylesheet
title:string=ERP5 Portal Style
vlink_color:string=DarkMagenta
base_font_family:string=sans-serif
printer_base_font_family:string=serif
printer_primary_font_family:string=sans-serif
printer_secondary_font_family:string=sans-serif
<dtml-var standard_html_header>
<table border=0 cellspacing=0 cellpadding=0 width="100%">
<tr>
<td width="70%" valign="top">
<div class="Document">
<p><dtml-var Description></p>
<dtml-if "objectValues(['Portal Topic'])">
<h1>Subtopics</h1>
<ul>
<dtml-in expr="contentValues(['Portal Topic'])" sort=Title>
<li><a href="&dtml-local_absolute_url;/topic_view"><dtml-if
Title>&dtml-Title;<dtml-else>&dtml-getId;</dtml-if></a></li>
</dtml-in>
</ul>
</dtml-if>
<h1>Matching items</h1>
<dtml-let results=queryCatalog>
<dtml-in results size="50" start="batch_start" sort=Title>
<dtml-let objURL="getObject().local_absolute_url() + '/view'">
<dtml-if sequence-start>
</dtml-if>
<p><dtml-if getIcon>
<a href="&dtml-objURL;"><img
src="&dtml-portal_url;/&dtml-getIcon;" border="0"
alt="[&dtml.missing-Type;]"
title="[&dtml.missing-Type;]"></a>
</dtml-if>&nbsp;&nbsp;<a href="&dtml-objURL;"><dtml-if name="Title"><dtml-var
name="Title" size="75" html_quote><dtml-else>(No title)</dtml-if></a></p>
<dtml-if sequence-end>
</dtml-if>
</dtml-let>
<dtml-else>
<p> There are no items in this topic. </p>
</dtml-in>
<dtml-in results size="50" start="batch_start" sort=Title next>
<dtml-let url=URL
sqry=sequence-query
next=next-sequence-start-number
nextSize=next-sequence-size
nextURL="'%s%sbatch_start=%s' % (url,sqry,next)"
>
<p> <a href="&dtml-nextURL;"> Next &dtml-nextSize; items </a> </p>
</dtml-let>
</dtml-in>
</dtml-let>
</div>
<div class="Desktop">
<div class="Topic">
<h3> Query Parameters </h3>
<ul>
<dtml-with buildQuery>
<dtml-in items>
<li> <dtml-var sequence-key> : <dtml-var sequence-item> </li>
</dtml-in>
</dtml-with>
</ul>
</div>
</div>
</td>
<td width="30%" valign="top">
<dtml-var news_box><br />
<dtml-var latest_box>
</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</table>
<dtml-var standard_html_footer>
## Script (Python) "update_http_cache"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=my_folder=None
##title=Updates the caching parameters (cache must be called ht)
##
if my_folder is None: my_folder = container
def updateCache(o):
o.ZCacheable_setManagerId(manager_id='ht')
#o.setCacheNamespaceKeys(keys=['__ac_name'])
for o in context.objectValues():
try:
updateCache(o)
print 'Good %s' % o.absolute_url()
except:
print 'Bad %s' % o.absolute_url()
for f in context.objectValues(spec=['Base18 Folder','Folder','portal_skins']):
f.update_http_cache(my_folder=f)
print "Done"
return printed
<dtml-var standard_html_header>
<dtml-var wikipage_header>
<div class="Desktop">
<div class="Document">
<dtml-var render>
</div >
</div>
<dtml-var standard_html_footer>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master">
<metal:block fill-slot="base">
<base href=""
tal:attributes="href python: here.absolute_url() + '/'">
</metal:block>
<body>
<div metal:fill-slot="header">
<h1 id="DesktopTitle"
tal:content="here/Title">Document Title</h1>
<div id="DesktopDescription" tal:content="here/Description">
Document Description goes here.
</div>
<div metal:use-macro="here/content_byline/macros/byline">By Me</div>
</div>
<div metal:fill-slot="main">
<div id="DiscussionAbove">
<span tal:replace="structure here/aboveInThread"></span>
</div>
<div tal:replace="structure here/TranslatedBody">Body</div>
<div class="Discussion">
<span tal:replace="structure here/viewThreadsAtBottom"
tal:condition="here/viewThreadsAtBottom|nothing">Dicussions</span>
</div>
</div>
</body>
</html>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/tal/i18n"
metal:use-macro="here/main_template/macros/master">
<metal:block fill-slot="base">
<base href=""
tal:attributes="href python: here.absolute_url() + '/'">
</metal:block>
<body>
<div metal:fill-slot="header">
<h1 id="DesktopTitle"
tal:content="here/TranslatedTitle">Document Title</h1>
<div id="DesktopDescription" tal:content="here/TranslatedDescription">
Document Description goes here.
</div>
<div metal:use-macro="here/content_byline/macros/byline">By Me</div>
</div>
<div metal:fill-slot="main">
<div tal:replace="structure here/TranslatedBody">Translated Body</div>
<div class="Discussion">
<span tal:replace="structure here/viewThreadsAtBottom"
tal:condition="here/viewThreadsAtBottom|nothing"></span>
</div>
</div>
</body>
</html>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master">
<metal:block fill-slot="base">
<base href=""
tal:attributes="href python: here.absolute_url() + '/'">
</metal:block>
<body>
<div metal:fill-slot="header">
<h1 id="DesktopTitle"
tal:content="here/Title">Document Title</h1>
<div id="DesktopDescription" tal:content="here/Description">
Document Description goes here.
</div>
<div metal:use-macro="here/content_byline/macros/byline">By Me</div>
</div>
<div metal:fill-slot="main">
<p> Link: <a href=""
tal:attributes="href here/getRemoteUrl"
tal:content="here/getRemoteUrl"
>/index_html</a></p>
<div class="Discussion">
<span tal:replace="structure here/viewThreadsAtBottom"
tal:condition="here/viewThreadsAtBottom|nothing"></span>
</div>
</div>
</body>
</html>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master">
<metal:block fill-slot="base">
<base href=""
tal:attributes="href python: here.absolute_url() + '/'">
</metal:block>
<body>
<div metal:fill-slot="header">
<h1 id="DesktopTitle"
tal:content="here/Title">Document Title</h1>
<div id="DesktopDescription" tal:content="here/Description">
Document Description goes here.
</div>
<div metal:use-macro="here/content_byline/macros/byline">By Me</div>
</div>
<div metal:fill-slot="main">
<h2> File Properties </h2>
<table>
<tr>
<th align="right">Filename</th>
<td tal:content="here/getId">My ID</td>
</tr>
<tr>
<th align="right">Size</th>
<td tal:content="here/size">1024K</td>
</tr>
<tr>
<th align="right">Content-type</th>
<td tal:content="here/content_type">application/gzip</td>
<tr>
<tr>
<td> <br> </td>
<td>
</td>
</tr>
</table>
<h2> Download File </h2>
<p> <a href="." title="Download File"
tal:define="file here/absolute_url"
tal:attributes="href file; title here/Title"
tal:content="string:Download ${here/Title}">Download File</a>
</p>
<div class="Discussion">
<span tal:replace="structure here/viewThreadsAtBottom"
tal:condition="here/viewThreadsAtBottom|nothing"></span>
</div>
</div>
</body>
</html>
<span tal:define="dummy here/filterCookie; desktop python: request.set('isDesktop', 1)"></span>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master">
<body>
<div metal:fill-slot="main">
<div tal:condition="python: not(here.portal_membership.checkPermission('List folder contents', here))">
<span tal:define="redirect python: request.RESPONSE.redirect(here.absolute_url())"></span>
</div>
<!-- This is the desktop area -->
<div class="Desktop">
<h1> Desktop </h1>
<form action="" METHOD="POST"
tal:attributes="action here/absolute_url">
<table class="FormLayout">
<tr>
<td valign="top">
<table class="ContentsList">
<tbody tal:condition="python: here.portal_membership.checkPermission('List folder contents', here, 'aq_parent')">
<tr valign="top"
tal:define="upNav python: hasattr(here.aq_parent, 'portal_url');
upID python: here.aq_parent.getId()">
<td colspan="3" align="left">
<span tal:condition="upNav|nothing"><a href="../folder_contents"><img src="" alt="[Link]" border="0"
tal:attributes="src python: here.portal_url() + '/UpFolder_icon.gif'"></a>
</span>&nbsp;&nbsp;
<span tal:condition="upNav">Up to <a href="../folder_contents" tal:content="upID">Up ID</a></span>
<span tal:condition="python: not(upNav)"><span class="mild">Root</span></span>
</td>
</tr>
</tbody>
<tr><td colspan="1" align="left" width="49%">
<table>
<tbody tal:define="global b_start string:0;b_start request/b_start | b_start;
filterString python: request.get('folderfilter', '');
filter python: here.decodeFolderFilter(filterString);
items python: here.listFolderContents(contentFilter=filter);
Batch python:modules['ZTUtils'].Batch;
global batch python:Batch(items, 8, int(b_start), orphan=0);
global batch1 batch/next">
<tr align="top"
tal:repeat="items batch">
<td align="left" width="5" NOWRAP
tal:define="folderish items/isPrincipiaFolderish;
portalish items/isPortalContent|nothing;
global methodID python: folderish and 'folder_contents' or (portalish and 'view' or '');
global icon items/getIcon|items/icon|nothing">
<input type="checkbox" name="ids:list" value="" id=""
tal:attributes="value items/getId; id python: 'cb_' + items.getId()" />
</td>
<td>
<span tal:condition="icon">
<a href=""
tal:attributes="href python: items.getId() + '/' + methodID">
<img src="" alt="" border="0"
tal:attributes="src python: here.portal_url() + '/' + icon;
alt items/Type|nothing"></a>
</span>
</td>
<td>
<a href=""
tal:attributes="href python: items.getId() + '/' + methodID"><span tal:replace="items/getId">ID</span>
<span tal:condition="items/Title"
tal:replace="python: '(' + items.Title() + ')'">(Title)</span></a>
</td>
</tr>
</tbody>
</table>
</td>
<td width="2%">&nbsp;</td>
<td colspan="1" width="49%">
<table>
<tr align="top"
tal:repeat="items batch1">
<td align="left" width="5" NOWRAP
tal:define="folderish items/isPrincipiaFolderish;
portalish items/isPortalContent|nothing;
global methodID python: folderish and 'folder_contents' or (portalish and 'view' or '');
global icon items/getIcon|items/icon|nothing">
<input type="checkbox" name="ids:list" value="" id=""
tal:attributes="value items/getId; id python: 'cb_' + items.getId()" />
</td>
<td>
<span tal:condition="icon">
<a href=""
tal:attributes="href python: items.getId() + '/' + methodID">
<img src="" alt="" border="0"
tal:attributes="src python: here.portal_url() + '/' + icon;
alt items/Type|nothing"></a>
</span>
</td>
<td>
<a href=""
tal:attributes="href python: items.getId() + '/' + methodID"><span tal:replace="items/getId">ID</span>
<span tal:condition="items/Title"
tal:replace="python: '(' + items.Title() + ')'">(Title)</span></a>
</td>
</tr>
</table>
</tr>
<tr>
<td align="left">
<span tal:define="p batch/previous" tal:condition="p">
<a href=""
tal:attributes="href string:folder_contents?b_start=${p/previous/first}">Previous Items</a>
</span>
</td>
<td>&nbsp;</td>
<td align="left">
<span tal:define="n batch1/next|nothing" tal:condition="n">
<a href=""
tal:attributes="href string:folder_contents?b_start=${batch1/end}">Next Items</a>
</span>
</td>
</tr>
<!-- end cotentList -->
</table>
<TABLE BORDER="0" CELLSPACING="0" CELLPADDING=2>
<TR>
<TD ALIGN="LEFT" VALIGN="TOP" WIDTH="16"></TD>
<TD ALIGN="LEFT" VALIGN="TOP">
<span tal:condition="python: here.portal_membership.checkPermission('Add portal content', here)">
<INPUT TYPE="SUBMIT" NAME="folder_factories:method" VALUE="New...">
</span>
<span tal:condition="python: here.portal_membership.checkPermission('View management screens', here)">
<INPUT TYPE="SUBMIT" NAME="folder_rename_form:method" VALUE="Rename">
<INPUT TYPE="SUBMIT" NAME="folder_cut:method" VALUE="Cut">
<INPUT TYPE="SUBMIT" NAME="folder_copy:method" VALUE="Copy">
<span tal:condition="here/cb_dataValid">
<INPUT TYPE="SUBMIT" NAME="folder_paste:method" VALUE="Paste">
</span>
</span>
<span tal:condition="python: here.portal_membership.checkPermission('Delete objects', here)">
<INPUT TYPE="SUBMIT" NAME="folder_delete:method" VALUE="Delete">
</span>
</TD>
</TR>
</TABLE>
</table>
</form>
<span tal:replace="structure here/folder_filter_form">Filter Form Here</span>
</div>
</div>
</body>
</html>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/tal/i18n"
metal:use-macro="here/main_template/macros/master">
<body>
<div metal:fill-slot="main">
<div class="Desktop">
<span tal:replace="request/message"
tal:condition="request/message|nothing"><hr></span>
<div class="Metadata">
<h2 i18n:translate="">Resource Metadata </h2>
<form action="metadata_edit" method="post"
tal:attributes="action string:${here/absolute_url}/metadata_edit"
>
<table class="FormLayout">
<tr>
<th i18n:translate="">
Enable Discussion?
</th>
<td colspan="3">
<select name="allowDiscussion"
tal:define="val here/isDiscussable">
<option value="None"
tal:attributes="selected python: val == None"> Default </option>
<option value="0"
tal:attributes="selected python: val == 0"> Off </option>
<option value="1"
tal:attributes="selected python: val == 1"> On </option>
</select>
</td>
</tr>
<tr valign="top">
<th align="right" i18n:translate=""> Identifier
</th>
<td colspan="3"> <span tal:replace="here/Identifier"></span>
</td>
</tr>
<tr valign="top">
<th align="right" i18n:translate=""> Title
</th>
<td colspan="3">
<input type="text"
name="title"
value=""
size="65"
tal:attributes="value here/Title">
</td>
</tr>
<tr valign="top">
<th align="right" i18n:translate=""> Description
</th>
<td colspan="3">
<textarea name="description:text" rows="5"
cols="65" wrap="soft"
tal:content="here/Description"></textarea>
</td>
</tr>
<tr valign="top">
<th align="right" i18n:translate=""> Subject </th>
<td>
<textarea name="subject:lines" rows="3"
cols="20" wrap="soft"
tal:define="lines here/subjectsList"><span tal:repeat="line lines" tal:replace="line"></span></textarea>
<br>
<select name="subject:list" multiple>
<option value=""
tal:define="items python: here.portal_metadata.listAllowedSubjects(here); subjects here/Subject"
tal:repeat="item items"
tal:attributes="value item; selected python: item in subjects"
tal:content="item">
</option>
</select>
</td>
<th align="right" i18n:translate=""> Contributors </th>
<td>
<textarea name="contributors:lines" rows="5"
cols="30" wrap="soft"
tal:define="items here/Contributors"
tal:repeat="item items"
tal:content="item"></textarea>
</td>
</tr>
<tr valign="top">
<th align="right" i18n:translate=""> Creation Date
</th>
<td> <span tal:replace="here/CreationDate"></span>
</td>
<th align="right" i18n:translate=""> Last Modified Date
</th>
<td> <span tal:replace="here/ModificationDate"></span>
</td>
</tr>
<tr valign="top">
<th align="right" i18n:translate=""> Effective Date
</th>
<td> <input type="text" name="effective_date"
value=""
tal:define="effectiveString python: here.effective_date and here.effective_date.ISO() or 'None'"
tal:attributes="value effectiveString">
</td>
<th align="right" i18n:translate=""> Expiration Date
</th>
<td> <input type="text" name="expiration_date"
value=""
tal:define="expirationString python: here.expiration_date and here.expiration_date.ISO() or 'None'"
tal:attributes="value expirationString">
</td>
</tr>
<tr valign="top">
<th align="right" i18n:translate=""> Format
</th>
<td> <input type="text" name="format" value=""
tal:attributes="value here/Format">
</td>
</tr>
<tr valign="top">
<th align="right" i18n:translate=""> Language
</th>
<td> <input type="text" name="language" value=""
tal:attributes="value here/Language">
</td>
</tr>
<tr valign="top">
<th align="right" i18n:translate=""> Rights
</th>
<td> <input type="text" name="rights" value=""
tal:attributes="value here/Rights">
</td>
</tr>
<tr valign="top">
<td> <br> </td>
<td>
<input type="submit" value=" Change ">
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
</body>
</html>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master">
<metal:block fill-slot="base">
<base href=""
tal:attributes="href python: here.absolute_url() + '/'">
</metal:block>
<body>
<div metal:fill-slot="header">
<h1 id="DesktopTitle"
tal:content="here/Title">Document Title</h1>
<div id="DesktopDescription" tal:content="here/Description">
Document Description goes here.
</div>
<div metal:use-macro="here/content_byline/macros/byline">By Me</div>
</div>
<div metal:fill-slot="main">
<span tal:replace="structure here/tag">Tag</span>
<div class="Discussion">
<span tal:replace="structure here/viewThreadsAtBottom"
tal:condition="here/viewThreadsAtBottom|nothing"></span>
</div>
</div>
</body>
</html>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master">
<metal:block fill-slot="base">
<base href=""
tal:attributes="href python: here.absolute_url() + '/'">
</metal:block>
<body>
<div metal:fill-slot="header">
<h1 id="DesktopTitle"
tal:content="here/Title">Document Title</h1>
<div id="DesktopDescription" tal:content="here/Description">
Document Description goes here.
</div>
<div metal:use-macro="here/content_byline/macros/byline">By Me</div>
</div>
<div metal:fill-slot="main">
<p> Link: <a href=""
tal:attributes="href here/remote_url"
tal:content="here/remote_url"
>http://www.zope.org</a></p>
<div class="Discussion">
<span tal:replace="structure here/viewThreadsAtBottom"
tal:condition="here/viewThreadsAtBottom|nothing"></span>
</div>
</div>
</body>
</html>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master">
<metal:block fill-slot="base">
<base href=""
tal:attributes="href python: here.absolute_url() + '/'">
</metal:block>
<body>
<div metal:fill-slot="header">
<h1 id="DesktopTitle"
tal:content="here/Title">Document Title</h1>
<div id="DesktopDescription" tal:content="here/Description">
Document Description goes here.
</div>
<div metal:use-macro="here/content_byline/macros/byline">By Me</div>
</div>
<div metal:fill-slot="main">
<div tal:replace="structure here/CookedBody">Body</div>
<div class="Discussion">
<span tal:replace="structure here/viewThreadsAtBottom"
tal:condition="here/viewThreadsAtBottom|nothing"></span>
</div>
</div>
</body>
</html>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
metal:use-macro="here/main_template/macros/master">
<metal:block fill-slot="base">
<base href=""
tal:attributes="href python: here.absolute_url() + '/'">
</metal:block>
<body>
<div metal:fill-slot="header">
<h1 id="DesktopTitle"
tal:content="here/Title">Document Title</h1>
<div id="DesktopDescription" tal:content="here/Description">
Document Description goes here.
</div>
<div metal:use-macro="here/content_byline/macros/byline">By Me</div>
</div>
<div metal:fill-slot="main">
<h2> File Properties </h2>
<table>
<tr>
<th align="right">Filename</th>
<td tal:content="here/getId">My ID</td>
</tr>
<tr>
<th align="right">Size</th>
<td tal:content="here/size">1024K</td>
</tr>
<tr>
<th align="right">Content-type</th>
<td tal:content="here/content_type">application/gzip</td>
<tr>
<tr>
<td> <br> </td>
<td>
</td>
</tr>
</table>
<h2> Download File </h2>
<p> <a href="." title="Download File"
tal:define="file here/absolute_url/TranslationTemplate"
tal:attributes="href file; title here/Title"
tal:content="string:Download ${here/Title}">Download File</a>
</p>
<div class="Discussion">
<span tal:replace="structure here/viewThreadsAtBottom"
tal:condition="here/viewThreadsAtBottom|nothing"></span>
</div>
</div>
</body>
</html>
<div metal:define-macro="actions">
<div tal:define="isAnon python:here.portal_membership.isAnonymousUser();
AuthClass python:isAnon and 'GuestActions' or 'MemberActions';
uname python: isAnon and 'Guest' or here.portal_membership.getAuthenticatedMember().getUserName();
actions python:here.portal_actions.listFilteredActionsFor(here);
user_actions python:actions['user'];
folder_actions python:actions['folder'];
object_actions python:(actions['object'] + actions['workflow']);
global_actions python:actions['global']">
<table class="ActionBox" width="100%">
<tbody tal:condition="object_actions">
<tr class="" tal:attributes="class AuthClass">
<td class="ActionTitle">
<img src="http://www.somewhere.org/p_/User_icon" align="left" alt="User"
tal:attributes="src string:${here/portal_url}/p_/User_icon"
>
<span tal:content="uname">user name</span>
</td>
</tr>
<tr class="" tal:attributes="class AuthClass">
<td>
<span tal:repeat="action user_actions"><a href="" tal:attributes="href action/url" tal:content="action/name">Action</a><br></span>
</td>
</tr>
<tr class=""
tal:attributes="class AuthClass">
<td class="ActionTitle"
tal:define="getIcon python:hasattr(here, 'getIcon') and here.getIcon();
icon python:getIcon or getattr(here, 'icon', '');
typ python:getattr(here, 'Type', '');
objID python:here.getId()">
<img src=""
tal:condition="icon" align="left" alt="Type"
tal:attributes="src python:'%s/%s' % (here.portal_url(), icon); alt typ" />
<span tal:replace="structure python: here.truncID(objID, size=15)">ObjectID</span>
</td>
</tr>
<tr class=""
tal:attributes="class AuthClass">
<td tal:define="review_state python:here.portal_workflow.getInfoFor(here, 'review_state', '')">
<span tal:condition="review_state">Status: <span tal:replace="review_state">Private</span><br></span>
<span tal:repeat="action object_actions"><a href="" tal:attributes="href action/url" tal:content="action/name">Action</a><br></span>
</td>
</tr>
<tr class=""
tal:attributes="class AuthClass"
tal:condition="folder_actions">
<td>
<span tal:repeat="action folder_actions"><a href="" tal:attributes="href action/url" tal:content="action/name">Action</a><br></span>
</td>
</tr>
<tr class=""
tal:attributes="class AuthClass"
tal:condition="global_actions">
<td>
<span tal:repeat="action global_actions"><a href="" tal:attributes="href action/url" tal:content="action/name">Action</a><br></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<span tal:condition="python:'index.html' in here.objectIds()"
tal:replace="here/index.html" />
<span tal:condition="python:'index.stx' in here.objectIds()"
tal:replace="here/index.stx" />
<span tal:condition="python:'default.htm' in here.objectIds()"
tal:replace="here/default.htm" />
<html metal:use-macro="here/main_template/macros/master"
tal:condition="python:'default.htm' not in here.objectIds() and
'index.html' not in here.objectIds() and
'index.stx' not in here.objectIds()">
<head>
<title tal:content="template/title">The title</title>
</head>
<body>
<div metal:fill-slot="main"
tal:define="folder_url python:here.local_absolute_url()">
<div class="Document">
<p tal:condition="here/Description" tal:content="here/TranslatedDescription"/>
<div tal:define="auth_filter nocall: modules/ZTUtils/LazyFilter;
default_types python:( 'Document'
, 'Image'
, 'File'
, 'FAQ'
, 'News Item'
, 'Folder'
);
types types | here/show_content_types | default_types;
raw_items python: here.contentValues(
filter={'portal_type': types } );
items python: auth_filter( raw_items, skip='View' );
">
<div tal:condition="items">
<span tal:repeat="item items">
<h1><a href="item_url" tal:attributes="href item/local_absolute_url"><img
valign="middle" border="0"
tal:attributes="src string:${item/portal_url}/${item/getIcon};
alt string:${item/Type};
title string:${item/Type}"></a>
<a href="item_url" tal:attributes="href item/local_absolute_url"
tal:content="item/TranslatedTitle"> Title </a></h1>
<p tal:condition="exists: item/Description"
tal:content="item/TranslatedDescription">
Description <!--fmt="structured-text'-->
</p>
</span>
</div>
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"DTD/xhtml1-strict.dtd">
<?xml-stylesheet href="default_stylesheet" rel="stylesheet" type="text/css"?>
<span tal:replace="nothing">
<!--
Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
Thierry Faucher <tf@nexedi.com>
Jean-Paul Smets <jp@nexedi.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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-->
</span>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"
xml:lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/tal/i18n"
metal:define-macro="master"
tal:define="lang python:here.gettext.get_selected_language();
affiliate_path here/AFFILIATE_PATH | string:;
site_url here/portal_url;
site_url string:$site_url/$lang/$affiliate_path;
is_anonymous python:here.portal_membership.isAnonymousUser();
is_member python:not is_anonymous;
is_manager python:
here.portal_membership.getAuthenticatedMember().has_role('Manager') or here.portal_membership.getAuthenticatedMember().has_role('Partner');
is_member python:is_manager or is_member;
show_menu here/show_menu | nothing;
show_menu python:show_menu or is_manager;
col_num python:3 - show_menu;
portal_object python:here.portal_url.getPortalObject();
HTML_CHARSET here/HTML_CHARSET | nothing">
<!-- HTML Header -->
<head>
<title tal:content="here/getTranslatedTitle">
ERP5 Community: Download ERP5
</title>
<link rel="stylesheet" href="http://www.erp5.org/default_stylesheet" type="text/css" />
<META tal:condition="HTML_CHARSET" http-equiv="Content-Type" content=""
tal:attributes="content HTML_CHARSET" />
<META tal:condition="python: HTML_CHARSET is None" http-equiv="Content-Type"
content="text/html; charset=iso-8859-1"/>
</head>
<body font="#000000">
<span tal:condition="HTML_CHARSET">
<span tal:condition="python:HTML_CHARSET == 'text/html; charset=utf-8'"
tal:define="dummy python:request.RESPONSE.setHeader('Content-Type',HTML_CHARSET)"/>
</span>
<!-- Top Bar: Global links and search -->
<span tal:replace="structure here/standard_top_bar"/>
<!-- Main Page -->
<table cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<!-- Logo -->
<td colspan="2" rowspan="2" class="LogoBox" valign="top">
<div class="LogoBox">
<a href="http://www.erp5.org" tal:attributes="href site_url">
<img src="http://www.erp5.org/logo.png" border="0"
tal:attributes="src string:$site_url/logo.png" />
</a>
</div>
</td>
<!-- Title and Language -->
<td width="90%" class="TitleBox" tal:content="here/getTranslatedTitle">
Download ERP5
</td>
</tr>
<tr class="LanguageBox">
<td class="LanguageBox">
<span tal:condition="here/show_language_selector"
tal:replace="structure here/language_selector"/>
</td>
</tr>
</tbody>
</table>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<td valign="top" width="150"
tal:condition="show_menu">
<!-- Optional Action Box-->
<div class="ActionBox" tal:content="structure here/actions_box"
tal:condition="is_member" />
<!-- Main menu -->
<span tal:replace="structure here/menu_box"/>
<!-- Quick Login -->
<span tal:replace="structure here/quick_login"
tal:condition="here/show_quicklogin" />
</td>
<!-- Main Box -->
<td colspan="2" valign="top" class="Desktop"
tal:attributes="colspan col_num">
<!-- Main Box -->
<div class="Desktop">
</div>
<!-- Breadcrumb -->
<div class="breadcrumb" tal:condition="here/show_breadcrumb"
tal:content="structure here/breadcrumb" />
<!-- Desktop Header -->
<div class="Desktop">
<p class="DesktopStatusBar" tal:condition="request/portal_status_message | nothing"
tal:content="python:here.gettext(request.portal_status_message)">Message</p>
<span tal:condition="here/localHeader | nothing"
tal:replace="structure here/localHeader" />
</div>
<!-- Document -->
<div class="Document" metal:define-slot="main">
<p>The document</p>
</div>
<!-- Desktop Footer -->
<div class="Desktop">
<span tal:condition="here/localFooter | nothing"
tal:replace="structure here/localFooter"/>
</div>
</td>
</tr>
</tbody>
</table>
<!-- Legalese -->
<div class="legalinfo" tal:content="structure here/legal_footer">
<p>(c) ERP5 Community <br />
Content published under <a href="http://www.gpdl.org">GPDL</a> </p>
</div>
<!-- End -->
</body>
</html>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/tal/i18n">
<body>
<!-- Top navigation bar: access to partner sites, sitemap and search features -->
<table class="tophead" width="100%" metal:define-macro="navigation_box">
<form action="search" method="POST"
tal:attributes="action string:${here/portal_url}/search">
<tr>
<td align="left" nowrap valign="middle">
&nbsp;&nbsp;
<!-- List all partner sites as define in partner_sites portal property -->
<span tal:repeat="partner here/partner_sites">
<a class="topbanner" href="http://partner.com"
tal:attributes="href string:http:///${partner}"
tal:content="partner">partner.com</a>&nbsp;|&nbsp;
</span>
</td>
<td align="right" nowrap valign="middle" width="90%">
<!-- Add a sitemap link according to show_sitemap portal property -->
<span tal:condition="here/show_sitemap|nothing">
<a class="topbanner" href="sitemap.html"
tal:attributes="href string:${here/portal_url}/sitemap.html">Site Map</a>&nbsp;|&nbsp;
</span>
<!-- Add a search link according to show_search portal property -->
<span tal:condition="here/show_search">
<a class="topbanner" href="search_form"
tal:attributes="href string:${here/portal_url}/search_form">Search</a>
</span>
</td>
<td align="right" nowrap valign="middle">
<!-- Add an extra menu like in storever.com according to special_top_menu portal property -->
<span tal:condition="here/special_top_menu|nothing">
<!-- <dtml-var special_top_menu> -->
</span>
<!-- Add a search pop-up according to show_multisearch portal property -->
<span tal:condition="here/show_multisearch|nothing">
<font size="-2">
<select name="site" class="osdn-search">
<option tal:repeat="partner here/partner_sites"
value="partner"
tal:content="partner"
tal:attributes="value partner">Partner</option>
</select>
</font>
</span>
<!-- Add a search area according to show_search portal property -->
<span tal:condition="here/show_search|nothing">
<font size="-2">
<input type="text" size="12" name="SearchableText" class="tophead-search" />&nbsp;<input type="submit" value="Go" />
</font>
</span>
</td>
</tr>
</form>
</table>
</body>
</html>
<html metal:use-macro="here/main_template/macros/master">
<head>
<title tal:content="template/title">The title</title>
</head>
<body>
<div metal:fill-slot="main">
<div class="Document">
<p i18n:translate="">For Immediate Release</p>
<p><b tal:content="here/effective_date">A date of publication</b> - <b
tal:content="structure here/TranslatedDescription"
>Description of the news</b></p>
<span tal:replace="structure here/TranslatedBody" />
<h1 i18n:translate="">Permanent URL for this Press Release</h1>
<p tal:content="here/absolute_url">The URL of this news</p>
<h1><span i18n:translate="">About</span> <span
tal:replace="python: here.portal_properties.Title()" /></h1>
<p tal:content="structure here/news_plate" i18n:translate="">News bowlerplate</p>
</div>
<div class="ContentBy"
tal:content="structure here/content_byline"
tal:condition="python: not here.portal_membership.isAnonymousUser()"
>This document is writen by M. X</div>
<div class="Discussion" tal:content="structure here/viewThreadsAtBottom">The
discussion</div>
</div>
</body>
</html>
# File: Base18.spec
#
# Base18
#
# "Base18 is a Zope product to implement multilingual portals
# based on the Zope CMF"
#
# This product currently packages the code
%define PRODUCT_DIRECTORY /var/lib/zope/Products
%define USER jp
Name: Base18
Summary: A Zope product to implement multilingual portals with CMF
Version: 0.2.0
Release: 10nxd
Group: Development/Python
Requires: Zope Localizer CMF
Copyright: GPL
Vendor: Nexedi
URL: http://www.erp5.org
Packager: Jean-Paul Smets <jp@nexedi.com>
BuildRoot: /var/tmp/%{name}-%{version}-rootdir
Source0: http://www.erp5.org/download/%{name}-%{version}.tar.bz2
Source1: %{name}-%{version}.tar.bz2
#----------------------------------------------------------------------
%description
Base18 is a Zope product to implement multilingual portals
It extends the Zope CMF by allowing documents to be split into
a list of paragraphs which can be translated through a message catalog.
Thanks to Localizer, messages are stored in message catalogs which
can be exported and imported as gettext files. This allows to use
applications such as KBabel to search for previous translations of
a give sentence.
http://www.erp5.org
#----------------------------------------------------------------------
%prep
#Create the source code from the local Zope
rm -rf /home/%{USER}/rpm/BUILD/%{name}-%{version}
cp -ur %{PRODUCT_DIRECTORY}/%{name} /home/%{USER}/rpm/BUILD/%{name}-%{version}
cd /home/%{USER}/rpm/BUILD/
tar cjf /home/%{USER}/rpm/SOURCES/%{name}-%{version}.tar.bz2 %{name}-%{version}
rm -rf /home/%{USER}/rpm/BUILD/%{name}-%{version}
rm -rf $RPM_BUILD_ROOT
%setup -a 1
#----------------------------------------------------------------------
%build
#----------------------------------------------------------------------
%install
install -d $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}
install %{name}-%{version}/*.py $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}
install %{name}-%{version}/*.txt $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}
install %{name}-%{version}/*.png $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}
install %{name}-%{version}/*.zexp $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}
install -d $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/help
install %{name}-%{version}/help/*.stx $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/help
install -d $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/dtml
install %{name}-%{version}/dtml/*.dtml $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/dtml
install -d $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi
install %{name}-%{version}/skins/nexedi/*.py $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi
install %{name}-%{version}/skins/nexedi/*.pt $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi
install %{name}-%{version}/skins/nexedi/*.dtml $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi
install %{name}-%{version}/skins/nexedi/*.props $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi
install %{name}-%{version}/skins/nexedi/*.png $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi
install %{name}-%{version}/skins/nexedi/*.ico $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi
install -d $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/content18
install %{name}-%{version}/skins/content18/*.py $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/content18
install %{name}-%{version}/skins/content18/*.dtml $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/content18
install -d $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/zpt_nexedi
install %{name}-%{version}/skins/zpt_nexedi/*.pt $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/zpt_nexedi
install -d $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/zpt_content18
install %{name}-%{version}/skins/zpt_content18/*.pt $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/skins/zpt_content18
install -d $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/interfaces
install %{name}-%{version}/interfaces/*.py $RPM_BUILD_ROOT/usr/lib/zope/lib/python/Products/%{name}/interfaces
%clean
rm -rf $RPM_BUILD_ROOT
#----------------------------------------------------------------------
%files
%defattr(-,root,root,0755)
%doc README.txt INSTALL.txt CREDITS.txt GPL.txt ZPL.txt
/usr/lib/zope/lib/python/Products/%{name}/*.py
/usr/lib/zope/lib/python/Products/%{name}/interfaces/*.py
/usr/lib/zope/lib/python/Products/%{name}/*.txt
/usr/lib/zope/lib/python/Products/%{name}/*.png
/usr/lib/zope/lib/python/Products/%{name}/*.zexp
/usr/lib/zope/lib/python/Products/%{name}/help/*.stx
/usr/lib/zope/lib/python/Products/%{name}/dtml/*.dtml
/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi/*.dtml
/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi/*.py
/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi/*.pt
/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi/*.png
/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi/*.props
/usr/lib/zope/lib/python/Products/%{name}/skins/nexedi/*.ico
/usr/lib/zope/lib/python/Products/%{name}/skins/content18/*.dtml
/usr/lib/zope/lib/python/Products/%{name}/skins/content18/*.py
/usr/lib/zope/lib/python/Products/%{name}/skins/zpt_nexedi/*.pt
/usr/lib/zope/lib/python/Products/%{name}/skins/zpt_content18/*.pt
#----------------------------------------------------------------------
%changelog
* Tue Feb 4 2003 Jean-Paul Smets <jp@nexedi.com> 0.8.1-10nxd
- Updated description
* Thu Jan 30 2003 Jean-Paul Smets <jp@nexedi.com> 0.8.1-9nxd
- Missing interfaces
* Tue Jan 21 2003 Jean-Paul Smets <jp@nexedi.com> 0.8.1-8nxd
- Missing menu_box
* Wed Jan 8 2003 Jean-Paul Smets <jp@nexedi.com> 0.8.1-7nxd
- Fixed again missing skins
* Wed Jan 8 2003 Jean-Paul Smets <jp@nexedi.com> 0.8.1-6nxd
- Fixed again missing skins
* Wed Jan 8 2003 Jean-Paul Smets <jp@nexedi.com> 0.8.1-5nxd
- Code update for latest CMF - recover from crash
* Sat Oct 12 2002 Jean-Paul Smets <jp@nexedi.com> 0.8.1-1nxd
- Initial release
##############################################################################
#
# Base18: a Zope product which provides multilingual services for CMF Default
# documents.
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
#
# This program as such is not intended to be used by end users. End
# users who are looking for a ready-to-use solution with commercial
# garantees 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 Zope Public License (ZPL) Version 2.0
#
# 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.
#
##############################################################################
__version__ = "$Revision$"[11:-2]
__doc__ = "This product provides the basic behaviour to CMF object which need\
translation"
"""
Utility functions for translation
"""
from cgi import escape
from types import StringType
import Globals, StructuredText, string, utils, re, os
from StructuredText.HTMLWithImages import HTMLWithImages
from Products.CMFDefault.utils import parseHeadersBody, formatRFC822Headers
from Products.CMFDefault.utils import SimpleHTMLParser, bodyfinder, _dtmldir
from Products.CMFCore.utils import _format_stx, keywordsplitter, \
CMFHtmlWithImages, DocumentWithImages
from Globals import package_home
#
# DTML Directory for ZMI
#
_dtmldir = os.path.join( package_home( globals() ), 'dtml' )
#
# StructuredText handling
# Translation
#
class Base18HtmlWithImages( HTMLWithImages ):
""" Special subclass of HTMLWithImages, overriding document() """
def dispatch(self, doc, level, output):
getattr(self, self.element_types[doc.getNodeName()])(doc, level, output)
def __call__(self, doc, md, lang, level=1, header=1):
r = []
self.md = md
self.lang = lang
self.header = header
self.dispatch(doc, level-1, r.append)
#return u''.join(r)
result = ''
# We must convert some parts from unicode to a suitable string format
for i in r:
if type(i) is StringType:
result += i
else:
if lang == 'ja':
result += i.encode('utf-8')
else:
result += i.encode('latin-1')
return result
#return ''.join(r)
def appendTranslation(self, output, translatedOutput):
md = self.md
#uTranslatedOutput = u''
#for i in translatedOutput:
# if type(i) is StringType:
# i = unicode(i, 'UTF-8')
# uTranslatedOutput += i
#output(md.gettext(uTranslatedOutput,lang=self.lang))
output(md.gettext(''.join(translatedOutput),lang=self.lang))
def _text(self, doc, level, output):
# Remove line breaks
#output((' '.join(doc.getNodeValue().split('\n'))))
output(doc.getNodeValue())
def section(self, doc, level, output):
children=doc.getChildNodes()
for c in children:
getattr(self, self.element_types[c.getNodeName()])(c, level+1,
output)
def sectionTitle(self, doc, level, output):
output('<h%d>' % (level))
# Prepare translation
translatedOutput=[]
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level,
translatedOutput.append)
# Append translation
self.appendTranslation(output, translatedOutput)
output('</h%d>\n' % (level))
def description(self, doc, level, output):
p=doc.getPreviousSibling()
if p is None or p.getNodeName() is not doc.getNodeName():
output('<dl>\n')
# Prepare translation
translatedOutput=[]
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level,
translatedOutput.append)
# Append translation
self.appendTranslation(output, translatedOutput)
n=doc.getNextSibling()
if n is None or n.getNodeName() is not doc.getNodeName():
output('</dl>\n')
def descriptionTitle(self, doc, level, output):
output('<dt>')
# Prepare translation
translatedOutput=[]
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level,
translatedOutput.append)
# Append translation
self.appendTranslation(output, translatedOutput)
output('</dt>\n')
def descriptionBody(self, doc, level, output):
output('<dd>')
# Prepare translation
translatedOutput=[]
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level,
translatedOutput.append)
# Append translation
self.appendTranslation(output, translatedOutput)
output('</dd>\n')
def bullet(self, doc, level, output):
p=doc.getPreviousSibling()
if p is None or p.getNodeName() is not doc.getNodeName():
output('\n<ul>\n')
output('<li>')
# Prepare translation
translatedOutput=[]
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level,
translatedOutput.append)
# Append translation
self.appendTranslation(output, translatedOutput)
n=doc.getNextSibling()
output('</li>\n')
if n is None or n.getNodeName() is not doc.getNodeName():
output('\n</ul>\n')
def numbered(self, doc, level, output):
p=doc.getPreviousSibling()
if p is None or p.getNodeName() is not doc.getNodeName():
output('\n<ol>\n')
output('<li>')
# Prepare translation
translatedOutput=[]
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level,
translatedOutput.append)
# Append translation
self.appendTranslation(output, translatedOutput)
n=doc.getNextSibling()
output('</li>\n')
if n is None or n.getNodeName() is not doc.getNodeName():
output('\n</ol>\n')
def example(self, doc, level, output):
i=0
for c in doc.getChildNodes():
if i==0:
output('\n<pre>\n')
output(escape(c.getNodeValue()))
output('\n</pre>\n')
else:
getattr(self, self.element_types[c.getNodeName()])(
c, level, output)
def paragraph(self, doc, level, output):
output('<p>')
# Prepare translation
translatedOutput=[]
for c in doc.getChildNodes():
if c.getNodeName() in ['StructuredTextParagraph']:
getattr(self, self.element_types[c.getNodeName()])(
c, level, translatedOutput.append)
else:
getattr(self, self.element_types[c.getNodeName()])(
c, level, translatedOutput.append)
# Append translation
self.appendTranslation(output, translatedOutput)
output('</p>\n')
def link(self, doc, level, output):
output('<a href="%s">' % doc.href)
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
output('</a>')
def emphasis(self, doc, level, output):
output('<em>')
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
output('</em>')
def literal(self, doc, level, output):
output('<code>')
for c in doc.getChildNodes():
output(escape(c.getNodeValue()))
output('</code>')
def strong(self, doc, level, output):
output('<strong>')
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
output('</strong>')
def underline(self, doc, level, output):
output("<u>")
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
output("</u>")
def innerLink(self, doc, level, output):
output('<a href="#ref');
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
output('">[')
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
output(']</a>')
def sgml(self,doc,level,output):
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
def xref(self, doc, level, output):
val = doc.getNodeValue()
output('<a href="#ref%s">[%s]</a>' % (val, val) )
def table(self,doc,level,output):
"""
A StructuredTextTable holds StructuredTextRow(s) which
holds StructuredTextColumn(s). A StructuredTextColumn
is a type of StructuredTextParagraph and thus holds
the actual data.
"""
output('<table border="1" cellpadding="2">\n')
for row in doc.getRows()[0]:
output("<tr>\n")
for column in row.getColumns()[0]:
if hasattr(column,"getAlign"):
str = '<%s colspan="%s" align="%s" valign="%s">' % \
(column.getType(), column.getSpan(), column.getAlign(),
column.getValign())
else:
str = '<td colspan="%s">' % column.getSpan()
output(str)
for c in column.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level,
output)
if hasattr(column,"getType"):
output("</"+column.getType()+">\n")
else:
output("</td>\n")
output("</tr>\n")
output("</table>\n")
def namedLink(self, doc, level, output):
"""\
XXX Trial subclassed implementation of HTMLClass#namedLink(),
as default implementation seems to be broken...
"""
name = doc.getNodeValue()
if name[:2] == '..':
name = name[2:]
output('<a name="%s">[%s]</a>' % (name, name))
def document(self, doc, level, output):
"""\
HTMLWithImages.document renders full HTML (head, title, body). For
CMF Purposes, we don't want that. We just want those nice juicy
body parts perfectly rendered.
"""
for c in doc.getChildNodes():
getattr(self, self.element_types[c.getNodeName()])(c, level, output)
Base18HtmlWithImages = Base18HtmlWithImages()
# We need to add some conversion step to make sure
# pages are rendered properly
# This is taken from CMFWiki and is really uggly
intl_char_entities = (
('\300', '&Agrave;'), ##<--char
('\302', '&Acirc;'), ##
('\311', '&Eacute;'), ##
('\312', '&Ecirc;'), ##
('\316', '&Icirc;'), ##
('\324', '&Ocirc;'), ##
('\333', '&Ucirc;'), ##
('\340', '&agrave;'), ##
('\342', '&acirc;'), ##
('\347', '&ccedil;'), ##
('\350', '&egrave;'), ##
('\351', '&eacute;'), ##
('\352', '&ecirc;'), ##
('\356', '&icirc;'), ##
('\364', '&ocirc;'), ##
('\371', '&ugrave;'), ##
('\373', '&ucirc;'), ##
)
def _translate_stx( text, md, level=1 , lang=None):
"""
Render STX to HTML and Translate.
"""
if callable(text): text = text()
# We do not do conversions in order to preserver UTF text !
# convert international characters to HTML entities for safekeeping
# for c,e in intl_char_entities:
# text = re.sub(c, e, text)
st = StructuredText.Basic( text ) # Creates the basic DOM
if not st: # If it's an empty object
return "" # return now or have errors!
doc = DocumentWithImages( st )
html = Base18HtmlWithImages( doc, md, lang, level )
return html
def _translate_html( text, md, level=1 , lang=None):
"""
Render HTML to HTML and Translate
Must be updated later
"""
if callable(text): text = text()
st = StructuredText.Basic( text ) # Creates the basic DOM
if not st: # If it's an empty object
return "" # return now or have errors!
doc = DocumentWithImages( st )
html = Base18HtmlWithImages( doc, md, lang, level )
return html
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