From 206695a2b16d1a99f4d973f0912a11abb44e56a1 Mon Sep 17 00:00:00 2001
From: Kevin Deldycke <kevin@nexedi.com>
Date: Mon, 19 Jun 2006 11:30:28 +0000
Subject: [PATCH] Move RPM patches from ERP5 product to dedicated repository

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@7852 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 .../patch/CMF_local_context_worklist.patch    | 100 ----
 product/ERP5/patch/CMF_make_patch             |   3 -
 product/ERP5/patch/MMMShop-nxd.patch          | 474 ----------------
 product/ERP5/patch/Zope-2.5.1-tal-i18n.patch  | 535 ------------------
 product/ERP5/patch/formulator-1.3.1.patch     | 230 --------
 5 files changed, 1342 deletions(-)
 delete mode 100644 product/ERP5/patch/CMF_local_context_worklist.patch
 delete mode 100644 product/ERP5/patch/CMF_make_patch
 delete mode 100644 product/ERP5/patch/MMMShop-nxd.patch
 delete mode 100644 product/ERP5/patch/Zope-2.5.1-tal-i18n.patch
 delete mode 100644 product/ERP5/patch/formulator-1.3.1.patch

diff --git a/product/ERP5/patch/CMF_local_context_worklist.patch b/product/ERP5/patch/CMF_local_context_worklist.patch
deleted file mode 100644
index acffca47ab..0000000000
--- a/product/ERP5/patch/CMF_local_context_worklist.patch
+++ /dev/null
@@ -1,100 +0,0 @@
---- CMF-1.3.0.org/CMFCore/CatalogTool.py	2003-01-07 22:54:33.000000000 +0100
-+++ CMF-1.3.0/CMFCore/CatalogTool.py	2003-02-18 09:41:46.000000000 +0100
-@@ -67,6 +67,8 @@
-             for role in roles:
-                 if allowed.has_key(role):
-                     allowed['user:' + user] = 1
-+                # Added for ERP5 project by JP Smets
-+                if role != 'Owner': allowed['user:' + user + ':' + role] = 1
-         if allowed.has_key('Owner'):
-             del allowed['Owner']
-         return list(allowed.keys())
-@@ -205,6 +207,20 @@
-         user = _getAuthenticatedUser(self)
-         kw[ 'allowedRolesAndUsers' ] = self._listAllowedRolesAndUsers( user )
- 
-+        # Patch for ERP5 by JP Smets in order
-+        # to implement worklists and search of local roles
-+        if kw.has_key('local_roles'):
-+          # Only consider local_roles if it is not empty
-+          if kw['local_roles'] != '' and  kw['local_roles'] != [] and  kw['local_roles'] is not None:
-+            local_roles = kw['local_roles']
-+            # Turn it into a list if necessary according to ';' separator
-+            if type(local_roles) == type('a'):
-+              local_roles = local_roles.split(';')
-+            # Local roles now has precedence (since it comes from a WorkList)
-+            kw[ 'allowedRolesAndUsers' ] = []
-+            for role in local_roles:
-+                 kw[ 'allowedRolesAndUsers' ].append('user:%s:%s' % (user, role))
-+
-         if not _checkPermission( AccessInactivePortalContent, self ):
-             base = aq_base( self )
-             now = DateTime()
---- CMF-1.3.0.org/DCWorkflow/DCWorkflow.py	2002-11-04 20:25:58.000000000 +0100
-+++ CMF-1.3.0/DCWorkflow/DCWorkflow.py	2003-02-18 09:41:31.000000000 +0100
-@@ -211,30 +211,41 @@
-         for id, qdef in self.worklists.items():
-             if qdef.actbox_name:
-                 guard = qdef.guard
--                if guard is None or guard.check(sm, self, portal):
--                    searchres = None
--                    var_match_keys = qdef.getVarMatchKeys()
--                    if var_match_keys:
--                        # Check the catalog for items in the worklist.
--                        catalog = getToolByName(self, 'portal_catalog')
--                        dict = {}
--                        for k in var_match_keys:
--                            v = qdef.getVarMatch(k)
--                            v_fmt = map(lambda x, info=info: x%info, v)
--                            dict[k] = v_fmt
--                        searchres = apply(catalog.searchResults, (), dict)
--                        if not searchres:
--                            continue
--                    if fmt_data is None:
--                        fmt_data = TemplateDict()
--                        fmt_data._push(info)
--                    searchres_len = lambda searchres=searchres: len(searchres)
--                    fmt_data._push({'count': searchres_len})
--                    res.append((id, {'name': qdef.actbox_name % fmt_data,
--                                     'url': qdef.actbox_url % fmt_data,
--                                     'permissions': (),  # Predetermined.
--                                     'category': qdef.actbox_category}))
--                    fmt_data._pop()
-+                # Patch for ERP5 by JP Smets in order
-+                # to implement worklists and search of local roles
-+                searchres = None
-+                var_match_keys = qdef.getVarMatchKeys()
-+                if var_match_keys:
-+                    # Check the catalog for items in the worklist.
-+                    catalog = getToolByName(self, 'portal_catalog')
-+                    dict = {}
-+                    for k in var_match_keys:
-+                        v = qdef.getVarMatch(k)
-+                        v_fmt = map(lambda x, info=info: x%info, v)
-+                        dict[k] = v_fmt
-+                    # Patch for ERP5 by JP Smets in order
-+                    # to implement worklists and search of local roles
-+                    if not (guard is None or guard.check(sm, self, portal)):
-+                        dict['local_roles'] = guard.roles
-+                    searchres = apply(catalog.searchResults, (), dict)
-+                    if not searchres:
-+                        continue
-+                if fmt_data is None:
-+                    fmt_data = TemplateDict()
-+                    fmt_data._push(info)
-+                searchres_len = lambda searchres=searchres: len(searchres)
-+                fmt_data._push({'count': searchres_len})
-+                # Patch for ERP5 by JP Smets in order
-+                # to implement worklists and search of local roles
-+                if dict.has_key('local_roles'):
-+                  fmt_data._push({'local_roles': join(guard.roles,';')})
-+                else:
-+                  fmt_data._push({'local_roles': ''})
-+                res.append((id, {'name': qdef.actbox_name % fmt_data,
-+                                 'url': qdef.actbox_url % fmt_data,
-+                                 'permissions': (),  # Predetermined.
-+                                 'category': qdef.actbox_category}))
-+                fmt_data._pop()
-         res.sort()
-         return map((lambda (id, val): val), res)
- 
diff --git a/product/ERP5/patch/CMF_make_patch b/product/ERP5/patch/CMF_make_patch
deleted file mode 100644
index a367241486..0000000000
--- a/product/ERP5/patch/CMF_make_patch
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-diff -ur CMF-1.3.0.org/CMFCore/CatalogTool.py CMF-1.3.0/CMFCore/CatalogTool.py > CMF_local_context_worklist.patch
-diff -ur CMF-1.3.0.org/DCWorkflow/DCWorkflow.py CMF-1.3.0/DCWorkflow/DCWorkflow.py >> CMF_local_context_worklist.patch
diff --git a/product/ERP5/patch/MMMShop-nxd.patch b/product/ERP5/patch/MMMShop-nxd.patch
deleted file mode 100644
index b4e540e63f..0000000000
--- a/product/ERP5/patch/MMMShop-nxd.patch
+++ /dev/null
@@ -1,474 +0,0 @@
-diff -u --recursive MMMShop-0.5/MMMShop/CurrencyManager.py MMMShop-0.5.new/MMMShop/CurrencyManager.py
---- MMMShop-0.5/MMMShop/CurrencyManager.py	2001-10-26 16:44:26.000000000 +0200
-+++ MMMShop-0.5.new/MMMShop/CurrencyManager.py	2002-12-30 21:15:48.000000000 +0100
-@@ -17,7 +17,7 @@
- from Products.CMFDefault.utils import tuplize
- 
- factory_type_information = {
--	'id': 'CurrencyManager',
-+	'id': 'Currency Manager',
- 	'meta_type': 'MMM Shop Currency Manager',
- 	'description': 'Use currency manager to administrate your shops currencies',
- 	'product': 'MMMShop',
-diff -u --recursive MMMShop-0.5/MMMShop/ShopManager.py MMMShop-0.5.new/MMMShop/ShopManager.py
---- MMMShop-0.5/MMMShop/ShopManager.py	2001-10-26 16:44:26.000000000 +0200
-+++ MMMShop-0.5.new/MMMShop/ShopManager.py	2002-12-30 21:15:48.000000000 +0100
-@@ -32,6 +32,8 @@
- from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl
- from Products.CMFCore.utils import getToolByName
- 
-+from Products.MMMShop.ShopOrder import addShopOrder
-+
- factory_type_information = {
-       'id': 'ShopManager',
-       'meta_type': 'MMM Shop Manager',
-@@ -41,7 +43,7 @@
-       'factory': 'addShopManager',
-       'filter_content_types': 0,
-       'immediate_view': 'shopmanager_edit_form',
--      'actions': 
-+      'actions':
- 	      ({'name': 'View',
- 	        'action': 'shopmanager_view',
- 		'permissions': ('View',),
-@@ -124,7 +126,7 @@
- 	if local_currency is not None:
- 	   self.local_currency = local_currency
- 
--    security.declarePublic('create_order')
-+    security.declarePublic('createOrder')
-     def createOrder(self, REQUEST):
- 	
- 	credit_details = {}
-@@ -148,16 +150,31 @@
- 		  obj = item
- 		 
- 	if obj is not None:
--	   cart_items=obj.listProducts()
--	   obj.setPersonalDetails(REQUEST['firstname'], REQUEST['lastname'], REQUEST['address'], REQUEST['postcode'], REQUEST['city'], REQUEST['phone'], REQUEST['email'])
-+		 cart_items=obj.listProducts()
-+		 obj.setPersonalDetails( name = REQUEST['cust_name'],
-+		 		 address = REQUEST['cust_address'],
-+		 		 zipcode = REQUEST['cust_zipcode'],
-+		 		 city = REQUEST['cust_city'],
-+		 		 country = REQUEST['cust_country'],
-+		 		 phone = REQUEST['cust_phone'],
-+		 		 email = REQUEST['cust_email'])
- 	else:
- 	   raise 'ObjectError', 'Shopping Cart not assigned'
- 
--	for item in cart_items:
--	   order_item = {}
--	   order_item['product'] = item.getProduct()
--	   order_item['quantity'] = item.getQuantity()
--	   order_details.append(order_item)
-+	if memberfolder is not None:
-+		memberfolder.invokeFactory(id=order_sequence, type_name='Shop Order')
-+		order = memberfolder[str(order_sequence)]
-+		order.title = 'Order %s' % order_sequence
-+		order.vat = float(self.portal_properties.vat)
-+		# This must be changed soon
-+		order.send_fee = float(self.portal_properties.send_fee_local)
-+		order.exchange_fee = 0.0
-+		for item in cart_items:
-+			order.addProductToOrder(item.getProduct(), item.getQuantity(),item.getVariant(),memberfolder.restrictedTraverse(item.getProduct()).computePrice(item.getVariant()))
-+		REQUEST['orderid'] = str(order_sequence)
-+		order.setPersonalDetails(REQUEST)
-+	else:
-+		raise 'ObjectError', 'Ordering Requires to be Member'
- 
-     security.declarePublic('get_order_sequence')
-     def get_order_sequence(self):
-diff -u --recursive MMMShop-0.5/MMMShop/ShopOrder.py MMMShop-0.5.new/MMMShop/ShopOrder.py
---- MMMShop-0.5/MMMShop/ShopOrder.py	2001-10-26 16:44:26.000000000 +0200
-+++ MMMShop-0.5.new/MMMShop/ShopOrder.py	2002-12-30 23:08:53.000000000 +0100
-@@ -22,6 +22,7 @@
- ADD_CONTENT_PERMISSION = 'Add portal content'
- 
- import Globals
-+import string
- import zLOG
- from Persistence import Persistent
- from Globals import HTMLFile
-@@ -33,9 +34,12 @@
- from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl
- from Products.CMFCore.utils import getToolByName
- from popen2 import popen2
-+from OFS.Traversable import Traversable
-+from Acquisition import aq_base
-+from Products.CMFCore.WorkflowCore import WorkflowMethod
- 
- factory_type_information = {
--      'id': 'ShopOrder',
-+      'id': 'Shop Order',
-       'meta_type': 'MMM Shop Order',
-       'description': 'Use orders to get the products to your customers',
-       'product': 'MMMShop',
-@@ -43,7 +47,7 @@
-       'factory': 'addShopOrder',
-       'filter_content_types': 0,
-       'immediate_view': 'shoporder_edit_form',
--      'actions': 
-+      'actions':
- 	      ({'name': 'View',
- 	        'action': 'shoporder_view',
- 		'permissions': ('View',),
-@@ -60,10 +64,12 @@
-     product = None
-     security = ClassSecurityInfo()
- 
--    def __init__(self, order, product, quantity):
-+    def __init__(self, order, product, quantity, variant=None, price=0.0):
-         self.order = order
- 	self.quantity = int(quantity)
- 	self.product = product
-+	self.variant = variant
-+	self.price = price
- 
-     security.declarePublic('getOrder')
-     def getOrder(self):
-@@ -77,6 +83,13 @@
-     def getQuantity(self):
- 	return self.quantity
- 
-+    security.declarePublic('getVariant')
-+    def getVariant(self):
-+	return self.variant
-+
-+    security.declarePublic('getPrice')
-+    def getPrice(self):
-+	return self.price
- 
- class ShopOrder( PortalContent
-           , DefaultDublinCoreImpl
-@@ -98,6 +111,11 @@
-     amount = 0
-     phone = ''
-     orderid = ''
-+    vat = 0.0
-+    send_fee = 0.0
-+    exchange_fee = 0.0
-+    euvat = ''
-+    organisation = ''
- 
-     security = ClassSecurityInfo()
- 
-@@ -118,9 +136,27 @@
- 	"""
- 	List all products in this order
- 	"""
--	
-+
- 	return tuple(self.products)
- 
-+    security.declarePublic('getTotalPrice')
-+    def getTotalPrice(self):
-+    	"""
-+    	Get the total price for this order exc. VAT
-+    	"""
-+    	all_price = self.send_fee
-+    	for item in self.products:
-+    	  all_price = all_price + float(item.quantity) * item.price
-+    	return all_price
-+
-+    security.declarePublic('getTotalPriceVAT')
-+    def getTotalPriceVAT(self):
-+    	"""
-+    	Get the total price for this order exc. VAT
-+    	"""
-+    	all_price = self.getTotalPrice()
-+    	return all_price * ( 1 + self.vat)
-+
-     security.declareProtected(View, 'getProduct')
-     def getProduct(self, id):
- 	zLOG.LOG("Order", 0, "Fetching product %s return: %s" % (id, self.products[id]))
-@@ -136,27 +172,31 @@
- 	self._p_changed = 1
- 
-     security.declareProtected(ManageProperties, 'addProductToOrder')
--    def addProductToOrder(self, product, quantity):
-+    def addProductToOrder(self, product, quantity, variant=None, price=0.0):
- 	"""
- 	Assigns a product and a quantity to the order
- 	"""
- 	zLOG.LOG("Order", 0, "Add %s (quantity: %s) to order %s" % (product, quantity, self.id))
-+	container = aq_base(self)
- 	for item in self.products:
--	    if item.product == product:
-+	    if item.product == product and item.variant == variant:
- 	       item.quantity = int(item.quantity) + int(quantity)
- 	       return
- 
--        self.products.append(OrderObject(order=self, product=product, quantity=quantity))
-+        self.products.append(OrderObject(order=self, product=product, quantity=quantity, variant=variant, price=price))
-         self._p_changed = 1
- 
-     def setPersonalDetails(self, REQUEST):
- 	self.name = REQUEST['cust_name']
-+	self.organisation = REQUEST['cust_organisation']
- 	self.address = REQUEST['cust_address']
-+	self.zipcode = REQUEST['cust_zipcode']
- 	self.city = REQUEST['cust_city']
- 	self.country = REQUEST['cust_country']
- 	self.phone = REQUEST['cust_phone']
- 	self.email = REQUEST['cust_email']
- 	self.orderid = REQUEST['orderid']
-+	self.euvat = REQUEST['cust_vat']
- 
-     def setOrderId(self, orderid=None):
- 	if orderid is not None:
-@@ -179,11 +219,50 @@
-     def _mailMerchant(self, REQUEST=None):
- 	self.doOrderemail(self)
- 
-+    def _online_payment(self):
-+    	"""
-+    	This method is called by the bank
-+    	to update order workflow
-+    	"""
-+    	return 'toto'
-+    
-+    #security.declareProtected( CMFCorePermissions.ModifyPortalContent, 'online_payment' )
-+    security.declarePublic( 'online_payment' )
-+    online_payment = WorkflowMethod(_online_payment,id='online_payment')
-+
-+
-+    security.declareProtected(ManageProperties, 'Description')
-+    def Description(self):
-+        """
-+          Return a short description
-+        """
-+        return "%s\n%s" % (string.join(map(lambda x:str(x.product), self.products),'\n') ,
-+        string.join((self.name,
-+self.organisation ,
-+self.address ,
-+self.zipcode ,
-+self.city,
-+self.country ,
-+self.euvat )))
-+
-+    def TranslatedTitle(self):
-+        """
-+          Return a translated title
-+        """
-+        return "%s %s" % (self.gettext('Order'), self.orderid)
-+
-+    def Title(self):
-+        """
-+          Return the translated title
-+        """
-+        return "Order %s" % self.orderid
-+
-+    security.declareProtected(ManageProperties, 'SearchableText')
-     def SearchableText(self):
-         """
-             text for indexing
-         """
--        return "%s %s" % (self.title, self.description)
-+        return "%s\n%s" % (self.Title(), self.Description())
- 
-     security.declarePublic('orderLines')
-     def orderLines(self):
-diff -u --recursive MMMShop-0.5/MMMShop/ShoppingCart.py MMMShop-0.5.new/MMMShop/ShoppingCart.py
---- MMMShop-0.5/MMMShop/ShoppingCart.py	2001-10-26 16:44:26.000000000 +0200
-+++ MMMShop-0.5.new/MMMShop/ShoppingCart.py	2002-12-30 21:15:48.000000000 +0100
-@@ -51,7 +51,7 @@
- #TRANSMAP=string.maketrans(bad, good)
- 
- factory_type_information = {
--      'id': 'ShoppingCart',
-+      'id': 'Shopping Cart',
-       'meta_type': 'MMM Shop Shopping Cart',
-       'description': 'Use shopping cart to store the orders from members untill they are processed',
-       'product': 'MMMShop',
-@@ -73,19 +73,29 @@
-     shoppingCart = None
-     quantity = None
-     delivery_days = 0
-+    variant = None
- 
-     security = ClassSecurityInfo()
--    
--    def __init__(self, shoppingCart, Product, quantity, delivery_days):
-+
-+    def __init__(self, shoppingCart, Product, quantity, delivery_days, variant=None):
-       self.shoppingCart = shoppingCart
-       self.product = Product
-       self.quantity = int(quantity)
-       self.delivery_days = int(delivery_days)
-+      self.variant = variant
- 
-     security.declarePublic('getShoppingCart')
-     def getShoppingCart(self):
- 	return self.shoppingCart
- 
-+    security.declarePublic('getVariant')
-+    def getVariant(self):
-+        return self.variant
-+
-+    security.declarePublic('setVariant')
-+    def setVariant(self, variant):
-+        self.variant = variant
-+
-     security.declarePublic('getProduct')
-     def getProduct(self):
- 	return self.product
-@@ -125,6 +135,7 @@
-     country = ''
-     phone = ''
-     email = ''
-+    organisation = ''
- 
-     security = ClassSecurityInfo()
- 
-@@ -193,9 +204,9 @@
- 	zLOG.LOG("Shopping Cart", 0, "Delete product with id %s from shopping cart" % (id))
- 	del self.products[id]
- 	self._p_changed = 1
--	
-+
-     security.declareProtected(ManageProperties, 'addProductToCart')
--    def addProductToCart( self, product, quantity, delivery_days ):
-+    def addProductToCart( self, product, quantity, delivery_days , variant=None):
- 	"""
- 	   Assigns a Product and a Quantity to the ShoppingCart
- 	"""
-@@ -203,11 +214,11 @@
- 	zLOG.LOG("Shopping Cart", 0, "Add %s to %s" % (product, quantity))
- 	
- 	for item in self.products:
--	    if item.product == product:
-+	    if item.product == product and item.variant == variant:
- 	       item.quantity = int(item.quantity) + int(quantity)
- 	       return
--	
--	self.products.append(ShoppingCartObject(shoppingCart = self, Product=product, quantity=quantity, delivery_days=delivery_days))
-+
-+	self.products.append(ShoppingCartObject(shoppingCart = self, Product=product, quantity=quantity, delivery_days=delivery_days, variant=variant))
- 	self._p_changed = 1
- 
-     security.declareProtected(ManageProperties, 'clearCart')
-@@ -225,7 +236,7 @@
-     def editShoppingCart(self, title=None, description=None):
- 	if title is not None:
- 	   self.setTitle(title)
--		    
-+
- 	if description is not None:
- 	   self.setDescription(description)
- 
-@@ -238,7 +249,7 @@
- 	"""
- 	return 1
- 
--    def setPersonalDetails(self, name=None, address=None, zipcode=None, city=None, country=None, phone=None, email=None):
-+    def setPersonalDetails(self, name=None, address=None, zipcode=None, city=None, country=None, phone=None, email=None, organisation=None):
- 	emailErr = 'Please enter an email address'
- 
- 	if name is not None:
-@@ -263,11 +274,14 @@
- 	   self.email = email
- 	else:
- 	   raise 'Error in email address', emailErr
--        
-+
-+	if organisation is not None:
-+	   self.organisation = organisation
-+    
-     security.declarePublic('getPersonalDetails')
-     def getPersonalDetails(self):
--	return self.name, self.address, self.zipcode, self.city, self.country, self.phone, self.email
--    
-+	return self.name, self.address, self.zipcode, self.city, self.country, self.phone, self.email, self.organisation
-+
- def addShoppingCart(self, id, title='', REQUEST=None):
- 	ob=ShoppingCart(id,title)
- 	self._setObject(id, ob)
-diff -u --recursive MMMShop-0.5/MMMShop/ShopProduct.py MMMShop-0.5.new/MMMShop/ShopProduct.py
---- MMMShop-0.5/MMMShop/ShopProduct.py	2001-10-26 16:44:26.000000000 +0200
-+++ MMMShop-0.5.new/MMMShop/ShopProduct.py	2002-12-30 21:15:48.000000000 +0100
-@@ -32,7 +32,7 @@
- from DateTime.DateTime import DateTime
- 
- factory_type_information = {
--      'id': 'ShopProduct',
-+      'id': 'Shop Product',
-       'meta_type': 'MMM Shop Product',
-       'description': 'Use products to create an online shopping catalog',
-       'product': 'MMMShop',
-@@ -40,12 +40,14 @@
-       'factory': 'addShopProduct',
-       'filter_content_types': 0,
-       'immediate_view': 'shopproduct_edit_form',
--      'actions': 
-+      'actions':
- 	      ({'name': 'View',
-+	        'id' : 'view',
- 	        'action': 'shopproduct_view',
- 		'permissions': ('View',),
- 		'category': 'object'},
- 	       {'name': 'Edit',
-+	        'id' : 'edit',
- 	        'action': 'shopproduct_edit_form',
- 		'permissions': ('Modify portal content',),
- 		'category': 'object'})
-@@ -122,6 +124,15 @@
- 	if image is not None:
- 	   self.image = image
- 
-+    def computePrice(self, variant=None):
-+        return self.price
-+
-+    def renderVariant(self, variant=None):
-+        return ''
-+
-+    def shortVariant(self, variant=None):
-+        return ''
-+
- def addShopProduct(self, id, title='', REQUEST=None):
- 	ob=ShopProduct(id,title)
- 	self._setObject(id, ob)
-Only in MMMShop-0.5/MMMShop/skins_nobabel: CVS
-diff -u --recursive MMMShop-0.5/MMMShop/skins_nobabel/getMemberFolder.py MMMShop-0.5.new/MMMShop/skins_nobabel/getMemberFolder.py
---- MMMShop-0.5/MMMShop/skins_nobabel/getMemberFolder.py	2001-10-26 16:44:25.000000000 +0200
-+++ MMMShop-0.5.new/MMMShop/skins_nobabel/getMemberFolder.py	2002-12-30 21:15:48.000000000 +0100
-@@ -1,9 +1,9 @@
--### Script (Python) "getMemberFolder"
--###parameters=username=None
--###title=Return the logged in members folder.
-+## Script (Python) "getMemberFolder"
-+##parameters=username=None
-+##title=Return the logged in members folder.
- 
--if username is None:
--   username = context.getMemberObj().getUserName()
-+#if username is None:
-+#   username = context.getMemberObj().getUserName()
- 
- member_folder = context.portal_membership.getHomeFolder(username)
- 
-Only in MMMShop-0.5.new/MMMShop/skins_nobabel: getMemberFolder.py.rej
-diff -u --recursive MMMShop-0.5/MMMShop/skins_nobabel/getMemberObj.py MMMShop-0.5.new/MMMShop/skins_nobabel/getMemberObj.py
---- MMMShop-0.5/MMMShop/skins_nobabel/getMemberObj.py	2001-10-26 16:44:25.000000000 +0200
-+++ MMMShop-0.5.new/MMMShop/skins_nobabel/getMemberObj.py	2002-12-30 21:15:48.000000000 +0100
-@@ -3,5 +3,8 @@
- ##title=Returns the logged in member object
- 
- member = context.portal_membership.getAuthenticatedMember()
-+# This fixes the currency issue which happens sometimes
-+if not hasattr(member,'pref_currency'):
-+  member.pref_currency = context.pref_currency
- 
- return member
-Only in MMMShop-0.5.new/MMMShop/skins_nobabel: getMemberObj.py.rej
-diff -u --recursive MMMShop-0.5/MMMShop/skins_nobabel/update_shopmanager.py MMMShop-0.5.new/MMMShop/skins_nobabel/update_shopmanager.py
---- MMMShop-0.5/MMMShop/skins_nobabel/update_shopmanager.py	2001-10-26 16:44:25.000000000 +0200
-+++ MMMShop-0.5.new/MMMShop/skins_nobabel/update_shopmanager.py	2002-12-30 21:15:48.000000000 +0100
-@@ -1,5 +1,5 @@
- ## Script(Python) "update_shopmanager"
--##para,eters=REQUESTO=None
-+##parameters=REQUEST=None
- ##title=Update the shop manager
- 
- if context.meta_type == 'MMM Shop Manager':
-Only in MMMShop-0.5.new/MMMShop/skins_nobabel: update_shopmanager.py.rej
diff --git a/product/ERP5/patch/Zope-2.5.1-tal-i18n.patch b/product/ERP5/patch/Zope-2.5.1-tal-i18n.patch
deleted file mode 100644
index 7417563fd0..0000000000
--- a/product/ERP5/patch/Zope-2.5.1-tal-i18n.patch
+++ /dev/null
@@ -1,535 +0,0 @@
-Common subdirectories: Zope-2.5.1-src/lib/python/TAL/benchmark and /usr/lib/zope/lib/python/TAL/benchmark
-Only in Zope-2.5.1-src/lib/python/TAL/: .cvsignore
-diff -u Zope-2.5.1-src/lib/python/TAL/driver.py /usr/lib/zope/lib/python/TAL/driver.py
---- Zope-2.5.1-src/lib/python/TAL/driver.py	2001-11-28 16:51:16.000000000 +0100
-+++ /usr/lib/zope/lib/python/TAL/driver.py	2002-08-18 17:24:52.000000000 +0200
-@@ -1,4 +1,4 @@
--#! /usr/bin/env python1.5
-+#! /usr/bin/python
- ##############################################################################
- #
- # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
-Only in /usr/lib/zope/lib/python/TAL/: HTMLParser.pyc
-diff -u Zope-2.5.1-src/lib/python/TAL/HTMLTALParser.py /usr/lib/zope/lib/python/TAL/HTMLTALParser.py
---- Zope-2.5.1-src/lib/python/TAL/HTMLTALParser.py	2001-11-28 16:51:16.000000000 +0100
-+++ /usr/lib/zope/lib/python/TAL/HTMLTALParser.py	2002-08-18 20:49:05.000000000 +0200
-@@ -1,14 +1,14 @@
- ##############################################################################
- #
- # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
--# 
-+#
- # This software is subject to the provisions of the Zope Public License,
- # Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
- # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
- # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
- # FOR A PARTICULAR PURPOSE
--# 
-+#
- ##############################################################################
- """
- Parse HTML and compile to TALInterpreter intermediate code.
-@@ -18,7 +18,7 @@
- import string
- 
- from TALGenerator import TALGenerator
--from TALDefs import ZOPE_METAL_NS, ZOPE_TAL_NS, METALError, TALError
-+from TALDefs import ZOPE_METAL_NS, ZOPE_TAL_NS, ZOPE_I18N_NS, METALError, TALError
- from HTMLParser import HTMLParser, HTMLParseError
- 
- BOOLEAN_HTML_ATTRS = [
-@@ -106,7 +106,7 @@
-         self.gen = gen
-         self.tagstack = []
-         self.nsstack = []
--        self.nsdict = {'tal': ZOPE_TAL_NS, 'metal': ZOPE_METAL_NS}
-+        self.nsdict = {'tal': ZOPE_TAL_NS, 'metal': ZOPE_METAL_NS, 'i18n':ZOPE_I18N_NS}
- 
-     def parseFile(self, file):
-         f = open(file)
-@@ -132,9 +132,9 @@
-     def handle_starttag(self, tag, attrs):
-         self.close_para_tags(tag)
-         self.scan_xmlns(attrs)
--        tag, attrlist, taldict, metaldict = self.process_ns(tag, attrs)
-+        tag, attrlist, taldict, metaldict, i18ndict = self.process_ns(tag, attrs)
-         self.tagstack.append(tag)
--        self.gen.emitStartElement(tag, attrlist, taldict, metaldict,
-+        self.gen.emitStartElement(tag, attrlist, taldict, metaldict, i18ndict,
-                                   self.getpos())
-         if tag in EMPTY_HTML_TAGS:
-             self.implied_endtag(tag, -1)
-@@ -142,13 +142,13 @@
-     def handle_startendtag(self, tag, attrs):
-         self.close_para_tags(tag)
-         self.scan_xmlns(attrs)
--        tag, attrlist, taldict, metaldict = self.process_ns(tag, attrs)
--        if taldict.get("content"):
--            self.gen.emitStartElement(tag, attrlist, taldict, metaldict,
-+        tag, attrlist, taldict, metaldict, i18ndict = self.process_ns(tag, attrs)
-+        if taldict.get("content") or i18ndict.get("translate"):
-+            self.gen.emitStartElement(tag, attrlist, taldict, metaldict, i18ndict,
-                                       self.getpos())
-             self.gen.emitEndElement(tag, implied=-1)
-         else:
--            self.gen.emitStartElement(tag, attrlist, taldict, metaldict,
-+            self.gen.emitStartElement(tag, attrlist, taldict, metaldict, i18ndict,
-                                       self.getpos(), isend=1)
-         self.pop_xmlns()
- 
-@@ -252,7 +252,7 @@
-             prefix, suffix = string.split(name, ':', 1)
-             if prefix == 'xmlns':
-                 nsuri = self.nsdict.get(suffix)
--                if nsuri in (ZOPE_TAL_NS, ZOPE_METAL_NS):
-+                if nsuri in (ZOPE_TAL_NS, ZOPE_METAL_NS, ZOPE_I18N_NS):
-                     return name, name, prefix
-             else:
-                 nsuri = self.nsdict.get(prefix)
-@@ -260,12 +260,15 @@
-                     return name, suffix, 'tal'
-                 elif nsuri == ZOPE_METAL_NS:
-                     return name, suffix,  'metal'
-+                elif nsuri == ZOPE_I18N_NS:
-+                    return name, suffix,  'i18n'
-         return name, name, 0
- 
-     def process_ns(self, name, attrs):
-         attrlist = []
-         taldict = {}
-         metaldict = {}
-+        i18ndict = {}
-         name, namebase, namens = self.fixname(name)
-         for item in attrs:
-             key, value = item
-@@ -283,7 +286,12 @@
-                     raise METALError("duplicate METAL attribute " +
-                                      `keybase`, self.getpos())
-                 metaldict[keybase] = value
-+            elif ns == 'i18n':
-+                if i18ndict.has_key(keybase):
-+                    raise I18NError("duplicate I18N attribute " +
-+                                     `keybase`, self.getpos())
-+                i18ndict[keybase] = value
-             attrlist.append(item)
--        if namens in ('metal', 'tal'):
-+        if namens in ('metal', 'tal', 'i18n'):
-             taldict['tal tag'] = namens
--        return name, attrlist, taldict, metaldict
-+        return name, attrlist, taldict, metaldict, i18ndict
-Only in /usr/lib/zope/lib/python/TAL/: HTMLTALParser.pyc
-Only in /usr/lib/zope/lib/python/TAL/: __init__.pyc
-diff -u Zope-2.5.1-src/lib/python/TAL/markbench.py /usr/lib/zope/lib/python/TAL/markbench.py
---- Zope-2.5.1-src/lib/python/TAL/markbench.py	2001-06-15 16:16:53.000000000 +0200
-+++ /usr/lib/zope/lib/python/TAL/markbench.py	2002-08-18 17:24:52.000000000 +0200
-@@ -1,4 +1,4 @@
--#! /usr/bin/env python1.5
-+#! /usr/bin/python
- 
- '''Run benchmarks of TAL vs. DTML'''
- 
-Only in /usr/lib/zope/lib/python/TAL/: markupbase.pyc
-diff -u Zope-2.5.1-src/lib/python/TAL/ndiff.py /usr/lib/zope/lib/python/TAL/ndiff.py
---- Zope-2.5.1-src/lib/python/TAL/ndiff.py	2001-02-07 19:51:44.000000000 +0100
-+++ /usr/lib/zope/lib/python/TAL/ndiff.py	2002-08-18 17:24:52.000000000 +0200
-@@ -1,4 +1,4 @@
--#! /usr/bin/env python
-+#! /usr/bin/python
- 
- # Module ndiff version 1.6.0
- # Released to the public domain 08-Dec-2000,
-diff -u Zope-2.5.1-src/lib/python/TAL/runtest.py /usr/lib/zope/lib/python/TAL/runtest.py
---- Zope-2.5.1-src/lib/python/TAL/runtest.py	2001-11-28 16:51:16.000000000 +0100
-+++ /usr/lib/zope/lib/python/TAL/runtest.py	2002-08-18 17:24:52.000000000 +0200
-@@ -1,4 +1,4 @@
--#! /usr/bin/env python1.5
-+#! /usr/bin/python
- ##############################################################################
- #
- # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
-diff -u Zope-2.5.1-src/lib/python/TAL/TALDefs.py /usr/lib/zope/lib/python/TAL/TALDefs.py
---- Zope-2.5.1-src/lib/python/TAL/TALDefs.py	2002-03-15 18:46:53.000000000 +0100
-+++ /usr/lib/zope/lib/python/TAL/TALDefs.py	2002-08-18 17:57:12.000000000 +0200
-@@ -1,14 +1,14 @@
- ##############################################################################
- #
- # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
--# 
-+#
- # This software is subject to the provisions of the Zope Public License,
- # Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
- # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
- # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
- # FOR A PARTICULAR PURPOSE
--# 
-+#
- ##############################################################################
- """
- Common definitions used by TAL and METAL compilation an transformation.
-@@ -23,6 +23,7 @@
- 
- ZOPE_TAL_NS = "http://xml.zope.org/namespaces/tal"
- ZOPE_METAL_NS = "http://xml.zope.org/namespaces/metal"
-+ZOPE_I18N_NS = "http://xml.zope.org/namespaces/i18n"
- 
- NAME_RE = "[a-zA-Z_][a-zA-Z0-9_]*"
- 
-@@ -43,9 +44,15 @@
-     "attributes",
-     "on-error",
-     "omit-tag",
--    "tal tag",
-+    "tal tag"
-     ]
- 
-+KNOWN_I18N_ATTRIBUTES = [
-+    "translate"
-+    ]
-+
-+
-+
- class TALError(Exception):
- 
-     def __init__(self, msg, position=(None, None)):
-@@ -65,6 +72,10 @@
- class METALError(TALError):
-     pass
- 
-+class I18NError(TALError):
-+    pass
-+
-+
- class TALESError(TALError):
- 
-     # This exception can carry around another exception + traceback
-Only in /usr/lib/zope/lib/python/TAL/: TALDefs.pyc
-diff -u Zope-2.5.1-src/lib/python/TAL/TALGenerator.py /usr/lib/zope/lib/python/TAL/TALGenerator.py
---- Zope-2.5.1-src/lib/python/TAL/TALGenerator.py	2001-11-28 16:51:16.000000000 +0100
-+++ /usr/lib/zope/lib/python/TAL/TALGenerator.py	2002-08-18 20:53:35.000000000 +0200
-@@ -1,14 +1,14 @@
- ##############################################################################
- #
- # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
--# 
-+#
- # This software is subject to the provisions of the Zope Public License,
- # Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
- # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
- # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
- # FOR A PARTICULAR PURPOSE
--# 
-+#
- ##############################################################################
- """
- Code generator for TALInterpreter intermediate code.
-@@ -24,7 +24,7 @@
- 
-     inMacroUse = 0
-     inMacroDef = 0
--    
-+
-     def __init__(self, expressionCompiler=None, xml=1):
-         if not expressionCompiler:
-             from DummyEngine import DummyEngine
-@@ -98,8 +98,8 @@
-         else:
-             return item[0], tuple(item[1:])
- 
--    actionIndex = {"replace":0, "insert":1, "metal":2, "tal":3, "xmlns":4,
--                   0: 0, 1: 1, 2: 2, 3: 3, 4: 4}
-+    actionIndex = {"replace":0, "insert":1, "metal":2, "tal":3, "xmlns":4, "i18n":5,
-+                   0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5}
-     def optimizeStartTag(self, collect, name, attrlist, end):
-         if not attrlist:
-             collect.append("<%s%s" % (name, end))
-@@ -237,10 +237,10 @@
-         key, expr = parseSubstitution(onError)
-         cexpr = self.compileExpression(expr)
-         if key == "text":
--            self.emit("insertText", cexpr, [])
-+            self.emit("insertText", cexpr, [], None)
-         else:
-             assert key == "structure"
--            self.emit("insertStructure", cexpr, {}, [])
-+            self.emit("insertStructure", cexpr, {}, [], None)
-         self.emitEndTag(name)
-         handler = self.popProgram()
-         self.emit("onError", block, handler)
-@@ -260,15 +260,17 @@
-         program = self.popProgram()
-         self.emit("loop", name, cexpr, program)
- 
--    def emitSubstitution(self, arg, attrDict={}):
-+    def emitSubstitution(self, arg, attrDict={}, translate=None):
-         key, expr = parseSubstitution(arg)
-         cexpr = self.compileExpression(expr)
-+        if translate:
-+          translate = self.compileExpression(translate)
-         program = self.popProgram()
-         if key == "text":
--            self.emit("insertText", cexpr, program)
-+            self.emit("insertText", cexpr, program, translate)
-         else:
-             assert key == "structure"
--            self.emit("insertStructure", cexpr, attrDict, program)
-+            self.emit("insertStructure", cexpr, attrDict, program, translate)
- 
-     def emitDefineMacro(self, macroName):
-         program = self.popProgram()
-@@ -371,9 +373,9 @@
-             newlist.append(item)
-         return newlist
- 
--    def emitStartElement(self, name, attrlist, taldict, metaldict,
-+    def emitStartElement(self, name, attrlist, taldict, metaldict, i18ndict,
-                          position=(None, None), isend=0):
--        if not taldict and not metaldict:
-+        if not taldict and not metaldict and not i18ndict:
-             # Handle the simple, common case
-             self.emitStartTag(name, attrlist, isend)
-             self.todoPush({})
-@@ -395,6 +397,18 @@
-             if not value:
-                 raise TALError("missing value for METAL attribute: " +
-                                `key`, position)
-+        for key, value in i18ndict.items():
-+            if key not in KNOWN_I18N_ATTRIBUTES:
-+                raise I18NError("bad I18N attribute: " + `key`,
-+                position)
-+            if not value:
-+                if key == 'translate':
-+                  # Empty translate means default translation
-+                  # Let us update transtlate to reflect this
-+                  i18ndict['translate'] = "python:here.gettext.gettext(message)"
-+                else:
-+                  raise I18NError("missing value for I18N attribute: " +
-+                                 `key`, position)
-         todo = {}
-         defineMacro = metaldict.get("define-macro")
-         useMacro = metaldict.get("use-macro")
-@@ -405,6 +419,7 @@
-         repeat = taldict.get("repeat")
-         content = taldict.get("content")
-         replace = taldict.get("replace")
-+        translate = i18ndict.get("translate")
-         attrsubst = taldict.get("attributes")
-         onError = taldict.get("on-error")
-         omitTag = taldict.get("omit-tag")
-@@ -416,6 +431,12 @@
-         if content and replace:
-             raise TALError("content and replace are mutually exclusive",
-                            position)
-+        if content and translate:
-+            raise TALError("content and translate are mutually exclusive",
-+                           position)
-+        if replace and translate:
-+            raise TALError("replace and translate are mutually exclusive",
-+                           position)
- 
-         repeatWhitespace = None
-         if repeat:
-@@ -481,6 +502,8 @@
-         if replace:
-             todo["replace"] = replace
-             self.pushProgram()
-+        if translate:
-+            todo["translate"] = translate
-         optTag = omitTag is not None or TALtag
-         if optTag:
-             todo["optional tag"] = omitTag, TALtag
-@@ -499,6 +522,8 @@
-             self.pushProgram()
-         if content:
-             self.pushProgram()
-+        if translate:
-+            self.pushProgram()
-         if todo and position != (None, None):
-             todo["position"] = position
-         self.todoPush(todo)
-@@ -521,6 +546,7 @@
-         repeat = todo.get("repeat")
-         content = todo.get("content")
-         replace = todo.get("replace")
-+        translate = todo.get("translate")
-         condition = todo.get("condition")
-         onError = todo.get("onError")
-         define = todo.get("define")
-@@ -539,13 +565,15 @@
-                       (what, name, name), position)
- 
-         if content:
--            self.emitSubstitution(content, {})
-+            self.emitSubstitution(content, {}, translate=None)
-+        if translate:
-+            self.emitSubstitution(translate , {}, translate=translate)
-         if optTag:
-             self.emitOptTag(name, optTag, isend)
-         elif not isend:
-             self.emitEndTag(name)
-         if replace:
--            self.emitSubstitution(replace, repldict)
-+            self.emitSubstitution(replace, repldict, translate=None)
-         if repeat:
-             self.emitRepeat(repeat)
-         if condition:
-Only in /usr/lib/zope/lib/python/TAL/: TALGenerator.pyc
-diff -u Zope-2.5.1-src/lib/python/TAL/TALInterpreter.py /usr/lib/zope/lib/python/TAL/TALInterpreter.py
---- Zope-2.5.1-src/lib/python/TAL/TALInterpreter.py	2002-03-15 18:46:53.000000000 +0100
-+++ /usr/lib/zope/lib/python/TAL/TALInterpreter.py	2002-08-18 20:55:56.000000000 +0200
-@@ -1,14 +1,14 @@
- ##############################################################################
- #
- # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
--# 
-+#
- # This software is subject to the provisions of the Zope Public License,
- # Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
- # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
- # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
- # FOR A PARTICULAR PURPOSE
--# 
-+#
- ##############################################################################
- """
- Interpreter for a pre-compiled TAL program.
-@@ -16,6 +16,7 @@
- 
- import sys
- import getopt
-+import re
- 
- from cgi import escape
- from string import join, lower, rfind
-@@ -52,6 +53,8 @@
-     "input", "col", "basefont", "isindex", "frame",
- ]
- 
-+_close_tag = re.compile(r'\</[a-z]*\>$', re.IGNORECASE)
-+
- class AltTALGenerator(TALGenerator):
- 
-     def __init__(self, repldict, expressionCompiler=None, xml=0):
-@@ -66,14 +69,15 @@
-         if self.enabled:
-             apply(TALGenerator.emit, (self,) + args)
- 
--    def emitStartElement(self, name, attrlist, taldict, metaldict,
-+    def emitStartElement(self, name, attrlist, taldict, metaldict, i18ndict,
-                          position=(None, None), isend=0):
-         metaldict = {}
-         taldict = {}
-+        i18ndict = {}
-         if self.enabled and self.repldict:
-             taldict["attributes"] = "x x"
-         TALGenerator.emitStartElement(self, name, attrlist,
--                                      taldict, metaldict, position, isend)
-+                                      taldict, metaldict, i18ndict, position, isend)
- 
-     def replaceAttrs(self, attrlist, repldict):
-         if self.enabled and self.repldict:
-@@ -410,7 +414,24 @@
-         self.interpret(stuff[1])
- 
-     def do_insertText_tal(self, stuff):
--        text = self.engine.evaluateText(stuff[0])
-+        translate = stuff[2]
-+        raw_message = stuff[1]
-+        # We can not translate content (yet)
-+        # Either translation or content
-+        if translate:
-+            # get content of html tag and use as message
-+            # taken from CMFLocalizer
-+            for t in raw_message:
-+                if t[0] == 'rawtextOffset':
-+                    message = _close_tag.split(t[1][0])[0]
-+                    break
-+                if t[0] == 'rawtextColumn':
-+                    message = t[1][0]
-+                    break
-+            self.engine.setLocal('message', message)
-+            text = self.engine.evaluateText(translate)
-+        else:
-+          text = self.engine.evaluateText(stuff[0])
-         if text is None:
-             return
-         if text is self.Default:
-@@ -428,7 +449,7 @@
-     def do_insertStructure(self, stuff):
-         self.interpret(stuff[2])
- 
--    def do_insertStructure_tal(self, (expr, repldict, block)):
-+    def do_insertStructure_tal(self, (expr, repldict, block, translate)):
-         structure = self.engine.evaluateStructure(expr)
-         if structure is None:
-             return
-Only in /usr/lib/zope/lib/python/TAL/: TALInterpreter.pyc
-diff -u Zope-2.5.1-src/lib/python/TAL/TALParser.py /usr/lib/zope/lib/python/TAL/TALParser.py
---- Zope-2.5.1-src/lib/python/TAL/TALParser.py	2001-11-28 16:51:16.000000000 +0100
-+++ /usr/lib/zope/lib/python/TAL/TALParser.py	2002-08-18 17:24:53.000000000 +0200
-@@ -58,13 +58,14 @@
-             # attrs is a dict of {name: value}
-             attrlist = attrs.items()
-             attrlist.sort() # For definiteness
--        name, attrlist, taldict, metaldict = self.process_ns(name, attrlist)
-+        name, attrlist, taldict, metaldict, i18ndict = self.process_ns(name, attrlist)
-         attrlist = self.xmlnsattrs() + attrlist
--        self.gen.emitStartElement(name, attrlist, taldict, metaldict)
-+        self.gen.emitStartElement(name, attrlist, taldict, metaldict, i18ndict)
- 
-     def process_ns(self, name, attrlist):
-         taldict = {}
-         metaldict = {}
-+        i18ndict = {}
-         fixedattrlist = []
-         name, namebase, namens = self.fixname(name)
-         for key, value in attrlist:
-@@ -77,10 +78,13 @@
-             elif ns == 'tal':
-                 taldict[keybase] = value
-                 item = item + ("tal",)
-+            elif ns == 'i18n':
-+                i18dict[keybase] = value
-+                item = item + ("i18n",)
-             fixedattrlist.append(item)
--        if namens in ('metal', 'tal'):
-+        if namens in ('metal', 'tal', 'i18n'):
-             taldict['tal tag'] = namens
--        return name, fixedattrlist, taldict, metaldict
-+        return name, fixedattrlist, taldict, metaldict, i18ndict
- 
-     def xmlnsattrs(self):
-         newlist = []
-@@ -89,7 +93,7 @@
-                 key = "xmlns:" + prefix
-             else:
-                 key = "xmlns"
--            if uri in (ZOPE_METAL_NS, ZOPE_TAL_NS):
-+            if uri in (ZOPE_METAL_NS, ZOPE_TAL_NS, ZOPE_I18N_NS):
-                 item = (key, uri, "xmlns")
-             else:
-                 item = (key, uri)
-@@ -109,6 +113,8 @@
-                 ns = 'tal'
-             elif uri == ZOPE_METAL_NS:
-                 ns = 'metal'
-+            elif uri == ZOPE_I18N_NS:
-+                ns = 'i18n'
-             return (prefixed, name, ns)
-         return (name, name, None)
- 
-Only in /usr/lib/zope/lib/python/TAL/: TALParser.pyc
-Common subdirectories: Zope-2.5.1-src/lib/python/TAL/tests and /usr/lib/zope/lib/python/TAL/tests
-diff -u Zope-2.5.1-src/lib/python/TAL/timer.py /usr/lib/zope/lib/python/TAL/timer.py
---- Zope-2.5.1-src/lib/python/TAL/timer.py	2001-11-28 16:51:16.000000000 +0100
-+++ /usr/lib/zope/lib/python/TAL/timer.py	2002-08-18 17:24:53.000000000 +0200
-@@ -1,4 +1,4 @@
--#! /usr/bin/env python1.5
-+#! /usr/bin/python
- ##############################################################################
- #
- # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
-Only in /usr/lib/zope/lib/python/TAL/: XMLParser.pyc
diff --git a/product/ERP5/patch/formulator-1.3.1.patch b/product/ERP5/patch/formulator-1.3.1.patch
deleted file mode 100644
index fce0007f3a..0000000000
--- a/product/ERP5/patch/formulator-1.3.1.patch
+++ /dev/null
@@ -1,230 +0,0 @@
-Common subdirectories: Formulator/dtml and Formulator.jp/dtml
-diff -u Formulator/Field.py Formulator.jp/Field.py
---- Formulator/Field.py	2002-03-05 19:17:13.000000000 +0100
-+++ Formulator.jp/Field.py	2003-02-23 10:55:12.000000000 +0100
-@@ -123,7 +123,7 @@
-     def get_tales(self, id):
-         """Get tales expression method for id."""
-         return self.tales.get(id, "")
--    
-+
-     security.declareProtected('Access contents information', 'is_required')
-     def is_required(self):
-         """Check whether this field is required (utility function)
-@@ -145,7 +145,7 @@
-                 return getattr(self.validator, name)
-             else:
-                 return "Unknown error: %s" % name
--    
-+
-     security.declarePrivate('_render_helper')
-     def _render_helper(self, key, value, REQUEST):
-         value = self._get_default(key, value, REQUEST)
-@@ -164,7 +164,7 @@
-             return self.get_value('default')
- 
-     security.declareProtected('View', 'render')
--    def render(self, value=None, REQUEST=None):
-+    def render(self, value=None, REQUEST=None, key=None):
-         """Render the field widget.
-         value -- the value the field should have (for instance
-                  from validation).
-@@ -174,7 +174,10 @@
-         if value and REQUEST are both None, the 'default' property of
-         the field will be used for the value.
-         """
--        return self._render_helper('field_%s' % self.id, value, REQUEST)
-+        # Patched by JPS for ERP5 in order to
-+        # dynamically change the name
-+        if key is None: key = self.id
-+        return self._render_helper('field_%s' % key, value, REQUEST)
- 
-     security.declareProtected('View', 'render_from_request')
-     def render_from_request(self, REQUEST):
-@@ -182,7 +185,7 @@
-         (unvalidated data), or default if no raw data is found.
-         """
-         return self._render_helper('field_%s' % self.id, None, REQUEST)
--    
-+
-     security.declareProtected('View', 'render_sub_field')
-     def render_sub_field(self, id, value=None, REQUEST=None):
-         """Render a sub field, as part of complete rendering of widget in
-Common subdirectories: Formulator/help and Formulator.jp/help
-Common subdirectories: Formulator/tests and Formulator.jp/tests
-diff -u Formulator/Validator.py Formulator.jp/Validator.py
---- Formulator/Validator.py	2002-11-26 13:50:09.000000000 +0100
-+++ Formulator.jp/Validator.py	2003-03-24 14:47:10.000000000 +0100
-@@ -31,10 +31,10 @@
-     
-     def raise_error(self, error_key, field):
-         raise ValidationError(error_key, field)
--    
--    def validate(self, field, key, REQUEST):    
-+
-+    def validate(self, field, key, REQUEST):
-         pass # override in subclass
--    
-+
- class StringBaseValidator(Validator):
-     """Simple string validator.
-     """
-@@ -48,15 +48,18 @@
-                                     default=1)
- 
-     message_names = Validator.message_names + ['required_not_found']
--    
-+
-     required_not_found = 'Input is required but no input given.'
--        
-+
-     def validate(self, field, key, REQUEST):
--        value = string.strip(REQUEST.get(key, ""))
-+        # We had to add this patch for hidden fields of type "list"
-+        value = REQUEST.get(key, "")
-+        if type(value) is type('a'):
-+          value = string.strip(value)
-         if field.get_value('required') and value == "":
-             self.raise_error('required_not_found', field)
-         return value
--    
-+
- class StringValidator(StringBaseValidator):
-     property_names = StringBaseValidator.property_names +\
-                      ['max_length', 'truncate']
-@@ -259,16 +262,19 @@
-         "If set to 0 or is left empty, there is no maximum."),
-                                      default="",
-                                      required=0)
--    
-+
-     message_names = StringBaseValidator.message_names +\
-                     ['too_many_lines', 'line_too_long', 'too_long']
- 
-     too_many_lines = 'You entered too many lines.'
-     line_too_long = 'A line was too long.'
-     too_long = 'You entered too many characters.'
--    
-+
-     def validate(self, field, key, REQUEST):
-         value = StringBaseValidator.validate(self, field, key, REQUEST)
-+        # Added as a patch for hidden values
-+        if type(value) is type([]) or type(value) is type(()):
-+          value = string.join(value, "\n")
-         # we need to add this check again
-         if value == "" and not field.get_value('required'):
-             return []
-@@ -337,10 +343,10 @@
-             # will remain integers.
-             if str(item_value) == value:
-                 return item_value
--            
-+
-         # if we didn't find the value, return error
-         self.raise_error('unknown_selection', field)
--            
-+
- SelectionValidatorInstance = SelectionValidator()
- 
- class MultiSelectionValidator(Validator):
-@@ -355,10 +361,10 @@
- 
-     message_names = Validator.message_names + ['required_not_found',
-                                                'unknown_selection']
--    
-+
-     required_not_found = 'Input is required but no input given.'
-     unknown_selection = 'You selected an item that was not in the list.'
--    
-+
-     def validate(self, field, key, REQUEST):
-         values = REQUEST.get(key, [])
-         # NOTE: a hack to deal with single item selections
-@@ -372,7 +378,7 @@
-                 self.raise_error('required_not_found', field)
-             else:
-                 return values
--            
-+
-         # create a dictionary of possible values
-         value_dict = {}
-         for item in field.get_value('items'):
-diff -u Formulator/Widget.py Formulator.jp/Widget.py
---- Formulator/Widget.py	2002-10-24 12:35:07.000000000 +0200
-+++ Formulator.jp/Widget.py	2003-03-24 14:33:42.000000000 +0100
-@@ -67,7 +67,7 @@
-         "to add an onClick attribute to use with JavaScript, for instance."),
-                                default="",
-                                required=0)
--      
-+
-     def render(self, field, key, value, REQUEST):
-         """Renders this widget as HTML using property values in field.
-         """
-@@ -79,14 +79,26 @@
-         try:
-             extra = field.get_value('extra')
-         except KeyError:
--    # In case extra is not defined as in DateTimeWidget
-+        # In case extra is not defined as in DateTimeWidget
-             extra = ''
--        return render_element("input",
-+        result = ''
-+        # We must adapt the rendering to the type of the value
-+        # in order to get the correct type back
-+        if type(value) is type([]) or type(value) is type(()):
-+          for v in value:
-+            result += render_element("input",
-+                              type="hidden",
-+                              name="%s:list" % key,
-+                              value=v,
-+                              extra=extra)
-+        else:
-+          result = render_element("input",
-                               type="hidden",
-                               name=key,
-                               value=value,
-                               extra=extra)
--                              
-+        return result
-+
- class TextWidget(Widget):
-     """Text widget
-     """
-@@ -202,7 +214,7 @@
-     """
-     property_names = Widget.property_names +\
-                      ['width', 'height', 'extra']
--    
-+
-     default = fields.TextAreaField('default',
-                                    title='Default',
-                                    description=(
-@@ -210,7 +222,7 @@
-                                    default="",
-                                    width=20, height=3,
-                                    required=0)
--    
-+
-     width = fields.IntegerField('width',
-                                 title='Width',
-                                 description=(
-@@ -228,7 +240,7 @@
-     def render(self, field, key, value, REQUEST):
-         width = field.get_value('width')
-         height = field.get_value('height')
--            
-+
-         return render_element("textarea",
-                               name=key,
-                               css_class=field.get_value('css_class'),
-@@ -236,7 +248,7 @@
-                               rows=height,
-                               contents=html_quote(value),
-                               extra=field.get_value('extra'))
--            
-+
- TextAreaWidgetInstance = TextAreaWidget()
- 
- class LinesTextAreaWidget(TextAreaWidget):
-Common subdirectories: Formulator/www and Formulator.jp/www
-- 
2.30.9