Author: gh
Date: 2006-10-02 13:04:46 -0600 (Mon, 02 Oct 2006)
New Revision: 1968

Added:
   FormEncode/branches/gettext-enabled/docs/i18n.txt
   FormEncode/branches/gettext-enabled/formencode/i18n/
   FormEncode/branches/gettext-enabled/formencode/i18n/FormEncode.pot
   FormEncode/branches/gettext-enabled/formencode/i18n/de/
   FormEncode/branches/gettext-enabled/formencode/i18n/de/LC_MESSAGES/
   
FormEncode/branches/gettext-enabled/formencode/i18n/de/LC_MESSAGES/FormEncode.mo
   
FormEncode/branches/gettext-enabled/formencode/i18n/de/LC_MESSAGES/FormEncode.po
   FormEncode/branches/gettext-enabled/tests/test_i18n.py
Modified:
   FormEncode/branches/gettext-enabled/formencode/api.py
   FormEncode/branches/gettext-enabled/formencode/validators.py
   FormEncode/branches/gettext-enabled/tests/test_cc_expires.py
   FormEncode/branches/gettext-enabled/tests/test_cc_validator.py
   FormEncode/branches/gettext-enabled/tests/test_schema.py
   FormEncode/branches/gettext-enabled/tests/test_sqlschema.py
Log:
added basic i18n code and german translation

Added: FormEncode/branches/gettext-enabled/docs/i18n.txt
===================================================================
--- FormEncode/branches/gettext-enabled/docs/i18n.txt                           
(rev 0)
+++ FormEncode/branches/gettext-enabled/docs/i18n.txt   2006-10-02 19:04:46 UTC 
(rev 1968)
@@ -0,0 +1,32 @@
+FormEncode Internationalization (gettext)
++++++++++++++++++++++++++++++++++++++++++
+
+There are different translation options available:
+
+Domain "FormEncode" 
+^^^^^^^^^^^^^^^^^^^
+
+for standalone use of FormEncode, just place the compiled files in 
/usr/share/locale/<lang>/LC_MESSAGES/FormEncode.mo The language to use is 
determined out of the local system (see gettext documentation 
http://docs.python.org/lib/node733.html). Optionally you can also set the 
language or the domain explicitly with the function
+
+example:
+formencode.api.set_stdtranslation(domain="FormEncode", languages=["de"])
+
+state._
+^^^^^^^
+A custom _ gettext function provided as attribute of the state object.
+
+__builtins__._
+^^^^^^^^^^^^^^
+A custom _ gettext function provided in the builtin namespace.
+This function is only used when:
+
+Validator.use_builtin_gettext == True (True is default)
+
+
+Without translation
+^^^^^^^^^^^^^^^^^^^
+
+If no translation mechanism is found a fallback returns the plain string.
+
+
+Gregor Horvath, 2006 [EMAIL PROTECTED]

Modified: FormEncode/branches/gettext-enabled/formencode/api.py
===================================================================
--- FormEncode/branches/gettext-enabled/formencode/api.py       2006-10-02 
14:23:09 UTC (rev 1967)
+++ FormEncode/branches/gettext-enabled/formencode/api.py       2006-10-02 
19:04:46 UTC (rev 1968)
@@ -5,10 +5,32 @@
 import declarative
 import textwrap
 import re
+import os
+import formencode
 
 __all__ = ['NoDefault', 'Invalid', 'Validator', 'Identity',
            'FancyValidator', 'is_validator']
 
+import gettext
+
+def set_stdtranslation(domain="FormEncode", languages=None, \
+                       localedir = "%s%s%s" % \
+                       (os.path.dirname(formencode.__file__), os.path.sep, 
"i18n")):
+    print localedir
+    t = gettext.translation(domain=domain, \
+                            languages=languages, \
+                            localedir=localedir, fallback=True)
+    global _stdtrans
+    _stdtrans = t.ugettext
+
+set_stdtranslation()
+
+#def _(s): return s # dummy i18n translation function, nothing is translated 
here.
+                   # Instead this is actually done in api.Validator.message.
+                   # The surrounding _("string") of the strings is only for 
extracting
+                   # the strings automatically
+                   # if you run pygettext with this source comment this 
function out temporarly 
+
 class NoDefault:
     pass
 
@@ -117,7 +139,10 @@
     if_missing = NoDefault
     repeating = False
     compound = False
-
+    gettextargs = {}
+    use_builtins_gettext = True #In case you dont want to use __builtins__._
+                                #altough it may be definied, set this to False
+    
     __singletonmethods__ = ('to_python', 'from_python')
 
     def __classinit__(cls, new_attrs):
@@ -141,8 +166,21 @@
         return value
 
     def message(self, msgName, state, **kw):
+        #determine translation function
         try:
-            return self._messages[msgName] % kw
+            trans = state._
+        except AttributeError:
+            try:
+                if self.use_builtins_gettext:
+                    import __builtin__
+                    trans = __builtin__._
+                else:
+                    trans = _stdtrans
+            except AttributeError:
+                trans = _stdtrans
+
+        try:
+            return trans(self._messages[msgName], **self.gettextargs) % kw
         except KeyError, e:
             raise KeyError(
                 "Key not found (%s) for %r=%r %% %r (from: %s)"
@@ -294,9 +332,9 @@
     strip = False
 
     messages = {
-        'empty': "Please enter a value",
-        'badType': "The input must be a string (not a %(type)s: %(value)r)",
-        'noneType': "The input must be a string (not None)",
+        'empty': _("Please enter a value"),
+        'badType': _("The input must be a string (not a %(type)s: %(value)r)"),
+        'noneType': _("The input must be a string (not None)"),
         }
 
     def to_python(self, value, state=None):

Added: FormEncode/branches/gettext-enabled/formencode/i18n/FormEncode.pot
===================================================================
--- FormEncode/branches/gettext-enabled/formencode/i18n/FormEncode.pot          
                (rev 0)
+++ FormEncode/branches/gettext-enabled/formencode/i18n/FormEncode.pot  
2006-10-02 19:04:46 UTC (rev 1968)
@@ -0,0 +1,325 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR ORGANIZATION
+# FIRST AUTHOR <[EMAIL PROTECTED]>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2006-10-02 20:59+CEST\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <[EMAIL PROTECTED]>\n"
+"Language-Team: LANGUAGE <[EMAIL PROTECTED]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: ENCODING\n"
+"Generated-By: pygettext.py 1.5\n"
+
+
+#: api.py:335 validators.py:433
+msgid "Please enter a value"
+msgstr ""
+
+#: api.py:336
+msgid "The input must be a string (not a %(type)s: %(value)r)"
+msgstr ""
+
+#: api.py:337
+msgid "The input must be a string (not None)"
+msgstr ""
+
+#: validators.py:160
+msgid "%(object)r is not a subclass of %(subclass)s"
+msgstr ""
+
+#: validators.py:161
+msgid "%(object)r is not a subclass of one of the types %(subclassList)s"
+msgstr ""
+
+#: validators.py:162
+msgid "%(object)r must be one of the types %(typeList)s"
+msgstr ""
+
+#: validators.py:163
+msgid "%(object)r must be of the type %(type)s"
+msgstr ""
+
+#: validators.py:344
+msgid "Enter a value less than %(maxLength)i characters long"
+msgstr ""
+
+#: validators.py:345 validators.py:399
+msgid "Invalid value (value with length expected)"
+msgstr ""
+
+#: validators.py:398
+msgid "Enter a value at least %(minLength)i characters long"
+msgstr ""
+
+#: validators.py:458
+msgid "You cannot enter a value here"
+msgstr ""
+
+#: validators.py:509
+msgid "The input is not valid"
+msgstr ""
+
+#: validators.py:565
+msgid "Enter only letters, numbers, or _ (underscore)"
+msgstr ""
+
+#: validators.py:604
+msgid "Invalid value"
+msgstr ""
+
+#: validators.py:605
+msgid "Value must be one of: %(items)s (not %(value)r)"
+msgstr ""
+
+#: validators.py:668
+msgid "Choose something"
+msgstr ""
+
+#: validators.py:669
+msgid "Enter a value from: %(items)s"
+msgstr ""
+
+#: validators.py:670
+msgid "That value is not known"
+msgstr ""
+
+#: validators.py:671
+msgid "Nothing in my dictionary goes by the value %(value)s.  Choose one of: 
%(items)s"
+msgstr ""
+
+#: validators.py:732
+msgid "Must be an integer index"
+msgstr ""
+
+#: validators.py:733
+msgid "Index out of range"
+msgstr ""
+
+#: validators.py:734
+msgid "Item %(value)s was not found in the list"
+msgstr ""
+
+#: validators.py:809
+msgid "Date must be after %(date)s"
+msgstr ""
+
+#: validators.py:810
+msgid "Date must be before %(date)s"
+msgstr ""
+
+#: validators.py:812
+msgid "%%A, %%d %%B %%Y"
+msgstr ""
+
+#: validators.py:813
+msgid "The date must be sometime in the future"
+msgstr ""
+
+#: validators.py:913
+msgid "Please enter an integer value"
+msgstr ""
+
+#: validators.py:945
+msgid "Please enter a number"
+msgstr ""
+
+#: validators.py:998
+msgid "Enter a value less than %(max)i characters long"
+msgstr ""
+
+#: validators.py:999
+msgid "Enter a value %(min)i characters long or more"
+msgstr ""
+
+#: validators.py:1050
+msgid "Invalid data or incorrect encoding"
+msgstr ""
+
+#: validators.py:1178
+msgid "Please enter an email address"
+msgstr ""
+
+#: validators.py:1179
+msgid "An email address must contain a single @"
+msgstr ""
+
+#: validators.py:1180
+msgid "The username portion of the email address is invalid (the portion 
before the @: %(username)s)"
+msgstr ""
+
+#: validators.py:1181 validators.py:1294
+msgid "An error occured when trying to connect to the server: %(error)s"
+msgstr ""
+
+#: validators.py:1182
+msgid "The domain portion of the email address is invalid (the portion after 
the @: %(domain)s)"
+msgstr ""
+
+#: validators.py:1183
+msgid "The domain of the email address does not exist (the portion after the 
@: %(domain)s)"
+msgstr ""
+
+#: validators.py:1291
+msgid "You must start your URL with http://, https://, etc"
+msgstr ""
+
+#: validators.py:1292
+msgid "That is not a valid URL"
+msgstr ""
+
+#: validators.py:1293
+msgid "An error occurred when trying to access the URL: %(error)s"
+msgstr ""
+
+#: validators.py:1295
+msgid "The server responded that the page could not be found"
+msgstr ""
+
+#: validators.py:1296
+msgid "The server responded with a bad status code (%(status)s)"
+msgstr ""
+
+#: validators.py:1399
+msgid "Please enter a state code"
+msgstr ""
+
+#: validators.py:1400
+msgid "Please enter a state code with TWO letters"
+msgstr ""
+
+#: validators.py:1401
+msgid "That is not a valid state code"
+msgstr ""
+
+#: validators.py:1452
+msgid "Please enter a number, with area code, in the form ###-###-####, 
optionally with \"ext.####\""
+msgstr ""
+
+#: validators.py:1614 validators.py:1622
+msgid "Please enter the date in the form %(format)s"
+msgstr ""
+
+#: validators.py:1615
+msgid "Please enter a month from 1 to 12"
+msgstr ""
+
+#: validators.py:1616
+msgid "Please enter a valid day"
+msgstr ""
+
+#: validators.py:1617
+msgid "That month only has %(days)i days"
+msgstr ""
+
+#: validators.py:1618
+msgid "That is not a valid day (%(exception)s)"
+msgstr ""
+
+#: validators.py:1619
+msgid "Unknown month name: %(month)s"
+msgstr ""
+
+#: validators.py:1620
+msgid "Please enter a number for the year"
+msgstr ""
+
+#: validators.py:1621
+msgid "Please enter a four-digit year"
+msgstr ""
+
+#: validators.py:1800
+msgid "You must indicate AM or PM"
+msgstr ""
+
+#: validators.py:1801
+msgid "There are too many :'s"
+msgstr ""
+
+#: validators.py:1802
+msgid "You may not enter seconds"
+msgstr ""
+
+#: validators.py:1803
+msgid "You must enter seconds"
+msgstr ""
+
+#: validators.py:1804
+msgid "You must enter minutes (after a :)"
+msgstr ""
+
+#: validators.py:1805
+msgid "The %(part)s value you gave is not a number: %(number)r"
+msgstr ""
+
+#: validators.py:1806
+msgid "You must enter an hour in the range %(range)s"
+msgstr ""
+
+#: validators.py:1807
+msgid "You must enter a minute in the range 0-59"
+msgstr ""
+
+#: validators.py:1808
+msgid "You must enter a second in the range 0-59"
+msgstr ""
+
+#: validators.py:1962
+msgid "Please enter a zip code (5 digits)"
+msgstr ""
+
+#: validators.py:1986
+msgid "The name %(name)s is missing"
+msgstr ""
+
+#: validators.py:2027
+msgid "Value should be %(true)r or %(false)r"
+msgstr ""
+
+#: validators.py:2062
+msgid "Value does not contain a signature"
+msgstr ""
+
+#: validators.py:2063
+msgid "Signature is not correct"
+msgstr ""
+
+#: validators.py:2185
+msgid "Fields do not match (should be %(match)s)"
+msgstr ""
+
+#: validators.py:2186
+msgid "Fields do not match"
+msgstr ""
+
+#: validators.py:2248
+msgid "Please enter only the number, no other characters"
+msgstr ""
+
+#: validators.py:2249
+msgid "You did not enter a valid number of digits"
+msgstr ""
+
+#: validators.py:2250
+msgid "That number is not valid"
+msgstr ""
+
+#: validators.py:2365
+msgid "Please enter numbers only for month and year"
+msgstr ""
+
+#: validators.py:2366
+msgid "Invalid Expiration Date"
+msgstr ""
+
+#: validators.py:2435
+msgid "Please enter numbers only for credit card security code"
+msgstr ""
+
+#: validators.py:2436
+msgid "Invalid credit card security code length"
+msgstr ""
+

Added: 
FormEncode/branches/gettext-enabled/formencode/i18n/de/LC_MESSAGES/FormEncode.mo
===================================================================
(Binary files differ)


Property changes on: 
FormEncode/branches/gettext-enabled/formencode/i18n/de/LC_MESSAGES/FormEncode.mo
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: 
FormEncode/branches/gettext-enabled/formencode/i18n/de/LC_MESSAGES/FormEncode.po
===================================================================
--- 
FormEncode/branches/gettext-enabled/formencode/i18n/de/LC_MESSAGES/FormEncode.po
                            (rev 0)
+++ 
FormEncode/branches/gettext-enabled/formencode/i18n/de/LC_MESSAGES/FormEncode.po
    2006-10-02 19:04:46 UTC (rev 1968)
@@ -0,0 +1,325 @@
+# German strings for FormEncode
+# Copyright (C) 2006 Gregor Horvath, licence: LGPL V2.0
+# Gregor Horvath <[EMAIL PROTECTED]>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: FormEncode 0.5.1\n"
+"POT-Creation-Date: 2006-09-26 07:57+CEST\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Gregor Horvath <[EMAIL PROTECTED]>\n"
+"Language-Team: Gregor Horvath <[EMAIL PROTECTED]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO8859-1\n"
+"Content-Transfer-Encoding: ISO8859-1\n"
+"Generated-By: pygettext.py 1.5\n"
+
+
+#: api.py:319 validators.py:433
+msgid "Please enter a value"
+msgstr "Bitte einen Wert eingeben"
+
+#: api.py:320
+msgid "The input must be a string (not a %(type)s: %(value)r)"
+msgstr "Die Eingabe mu� eine Zeichenfolge sein (nicht ein %(type)s: %(value)r)"
+
+#: api.py:321
+msgid "The input must be a string (not None)"
+msgstr "Die Eingabe mu� eine Zeichenfolge sein (nicht Nichts)"
+
+#: validators.py:160
+msgid "%(object)r is not a subclass of %(subclass)s"
+msgstr "%(object)r ist keine Unterklasse von %(subclass)s"
+
+#: validators.py:161
+msgid "%(object)r is not a subclass of one of the types %(subclassList)s"
+msgstr "%(object)r ist keine Unterklasse von einer der Klassen 
%(subclassList)s"
+
+#: validators.py:162
+msgid "%(object)r must be one of the types %(typeList)s"
+msgstr "%(object)r Typ mu� von eine von diesen sein: %(typeList)s"
+
+#: validators.py:163
+msgid "%(object)r must be of the type %(type)s"
+msgstr "%(object)r mu� vom Typ %(type)s sein"
+
+#: validators.py:344
+msgid "Enter a value less than %(maxLength)i characters long"
+msgstr "Geben Sie einen Wert k�rzer als %(maxLength)i Zeichen ein."
+
+#: validators.py:345 validators.py:399
+msgid "Invalid value (value with length expected)"
+msgstr "Ung�ltiger Wert (Wert mit L�nge erwartet)"
+
+#: validators.py:398
+msgid "Enter a value at least %(minLength)i characters long"
+msgstr "Geben Sie einen Wert mit mindestens %(minLength)i Zeichen ein."
+
+#: validators.py:458
+msgid "You cannot enter a value here"
+msgstr "Sie k�nnen hier keinen Wert eingeben"
+
+#: validators.py:509
+msgid "The input is not valid"
+msgstr "Die Eingabe ist ung�ltig"
+
+#: validators.py:565
+msgid "Enter only letters, numbers, or _ (underscore)"
+msgstr "Geben Sie nur Buchstaben, Nummern oder _ (Unterstriche) ein."
+
+#: validators.py:604
+msgid "Invalid value"
+msgstr "Ung�ltiger Wert"
+
+#: validators.py:605
+msgid "Value must be one of: %(items)s (not %(value)r)"
+msgstr "Wert mu� einer von diesen sein: %(items)s (nicht %(value)r) "
+
+#: validators.py:668
+msgid "Choose something"
+msgstr "Etwas ausw�hlen"
+
+#: validators.py:669
+msgid "Enter a value from: %(items)s"
+msgstr "Geben Sie einen Wert aus %(items)s ein."
+
+#: validators.py:670
+msgid "That value is not known"
+msgstr "Dieser Wert ist unbekannt"
+
+#: validators.py:671
+msgid "Nothing in my dictionary goes by the value %(value)s.  Choose one of: 
%(items)s"
+msgstr "Mein W�rterbuch enth�lt nicht den Wert: %(value)s. W�hle einen Wert 
aus: %(items)s"
+
+#: validators.py:732
+msgid "Must be an integer index"
+msgstr "Mu� ein Ganzahlindex sein."
+
+#: validators.py:733
+msgid "Index out of range"
+msgstr "Index ausserhalb des Bereiches"
+
+#: validators.py:734
+msgid "Item %(value)s was not found in the list"
+msgstr "Wert %(value)s wurde in der Liste nicht gefunden"
+
+#: validators.py:809
+msgid "Date must be after %(date)s"
+msgstr "Datum mu� nach %(date)s sein"
+
+#: validators.py:810
+msgid "Date must be before %(date)s"
+msgstr "Datum mu� vor %(date)s sein"
+
+#: validators.py:812
+msgid "%%A, %%d %%B %%Y"
+msgstr "%%A, %%d %%B %%Y"
+
+#: validators.py:813
+msgid "The date must be sometime in the future"
+msgstr "Das Datum mu� in der Zukunft liegen"
+
+#: validators.py:913
+msgid "Please enter an integer value"
+msgstr "Bitte einen Ganzzahlwert eingeben"
+
+#: validators.py:945
+msgid "Please enter a number"
+msgstr "Bitte eine Zahl eingeben"
+
+#: validators.py:998
+msgid "Enter a value less than %(max)i characters long"
+msgstr "Bitte einen Wert k�rzer als %(max)i Zeichen eingeben."
+
+#: validators.py:999
+msgid "Enter a value %(min)i characters long or more"
+msgstr "Bitte einen Wert mit %(min)i oder mehr Zeichen eingeben"
+
+#: validators.py:1050
+msgid "Invalid data or incorrect encoding"
+msgstr "Ung�ltige Daten oder falsche Kodierung"
+
+#: validators.py:1178
+msgid "Please enter an email address"
+msgstr "Bitte eine E-mail Adresse eingeben"
+
+#: validators.py:1179
+msgid "An email address must contain a single @"
+msgstr "Eine E-mail Adresse mu� ein einzelnes @ Zeichen enthalten"
+
+#: validators.py:1180
+msgid "The username portion of the email address is invalid (the portion 
before the @: %(username)s)"
+msgstr "Der Benutzer Teil der E-mail Adresse is ung�ltig (Der Teil vor dem @: 
%(username)s)"
+
+#: validators.py:1181 validators.py:1294
+msgid "An error occured when trying to connect to the server: %(error)s"
+msgstr "Ein Fehler ist beim Verbindungsversuch mit dem Server aufgetreten: 
%(error)s"
+
+#: validators.py:1182
+msgid "The domain portion of the email address is invalid (the portion after 
the @: %(domain)s)"
+msgstr "Der Domain Teil der E-mail Adresse ist ung�ltig (Der Teil nach dem @: 
%(domain)s)"
+
+#: validators.py:1183
+msgid "The domain of the email address does not exist (the portion after the 
@: %(domain)s)"
+msgstr "Die Domaine der E-mail Adresse existiert nicht (Der Teil nach dem @: 
%(domain)s)"
+
+#: validators.py:1291
+msgid "You must start your URL with http://, https://, etc"
+msgstr "Die URL mu� mit http://, https://, etc beginnen"
+
+#: validators.py:1292
+msgid "That is not a valid URL"
+msgstr "Das ist eine ung�ltige URL"
+
+#: validators.py:1293
+msgid "An error occurred when trying to access the URL: %(error)s"
+msgstr "Beim Versuch die URL zu erreichen ist ein Fehler aufgetreten: 
%(error)s"
+
+#: validators.py:1295
+msgid "The server responded that the page could not be found"
+msgstr "Der Server hat geantwortet, dass die Seite nicht gefunden werden 
konnte"
+
+#: validators.py:1296
+msgid "The server responded with a bad status code (%(status)s)"
+msgstr "Der Server antwortete mit einem schlechten Statuskode (%(status)s)"
+
+#: validators.py:1399
+msgid "Please enter a state code"
+msgstr "Bitte eine Landesk�rzel eingeben"
+
+#: validators.py:1400
+msgid "Please enter a state code with TWO letters"
+msgstr "Bitte ein Landesk�rzel mit 2 Buchstaben eingeben"
+
+#: validators.py:1401
+msgid "That is not a valid state code"
+msgstr "Das ist kein g�ltiges Landesk�rzel"
+
+#: validators.py:1452
+msgid "Please enter a number, with area code, in the form ###-###-####, 
optionally with \"ext.####\""
+msgstr "Bitte geben Sie eine Nummer mit Gebietskode in der Form ###-###-####, 
alternativ mit \"ext.####\ ein"
+
+#: validators.py:1614 validators.py:1622
+msgid "Please enter the date in the form %(format)s"
+msgstr "Bitte geben Sie das Datum in der Form %(format)s ein."
+
+#: validators.py:1615
+msgid "Please enter a month from 1 to 12"
+msgstr "Bitte ein Monat von 1 bis 12 eingeben."
+
+#: validators.py:1616
+msgid "Please enter a valid day"
+msgstr "Bitte einen g�ltigen Tag eingeben"
+
+#: validators.py:1617
+msgid "That month only has %(days)i days"
+msgstr "Dieser Monat hat nur %(days)i Tage"
+
+#: validators.py:1618
+msgid "That is not a valid day (%(exception)s)"
+msgstr "Das ist kein g�ltiger Tag (%(exception)s)"
+
+#: validators.py:1619
+msgid "Unknown month name: %(month)s"
+msgstr "Unbekannter Monatsname: %(month)s"
+
+#: validators.py:1620
+msgid "Please enter a number for the year"
+msgstr "Bitte eine Zahl f�r das Jahr eingeben"
+
+#: validators.py:1621
+msgid "Please enter a four-digit year"
+msgstr "Bitte eine vierstellige Jahreszahl eingeben."
+
+#: validators.py:1800
+msgid "You must indicate AM or PM"
+msgstr "Sie m�ssen AM oder PM angeben"
+
+#: validators.py:1801
+msgid "There are too many :'s"
+msgstr "Hier sind zu viele :'s"
+
+#: validators.py:1802
+msgid "You may not enter seconds"
+msgstr "Keine Sekunden eingeben"
+
+#: validators.py:1803
+msgid "You must enter seconds"
+msgstr "Sie m�ssen Sekunden eingeben"
+
+#: validators.py:1804
+msgid "You must enter minutes (after a :)"
+msgstr "Sie m�ssen Minuten eingeben (nach a :)"
+
+#: validators.py:1805
+msgid "The %(part)s value you gave is not a number: %(number)r"
+msgstr "Der %(part)s Wert den Sie angaben ist keine Nummer: %(number)r"
+
+#: validators.py:1806
+msgid "You must enter an hour in the range %(range)s"
+msgstr "Sie m�ssen eine Stunde im Bereich %(range)s eingeben."
+
+#: validators.py:1807
+msgid "You must enter a minute in the range 0-59"
+msgstr "Sie m�ssen eine Minute im Bereich 0-59 eingeben."
+
+#: validators.py:1808
+msgid "You must enter a second in the range 0-59"
+msgstr "Sie m�ssen eine Sekunde im Bereicg 0-59 eingeben."
+
+#: validators.py:1962
+msgid "Please enter a zip code (5 digits)"
+msgstr "Bitte eine Postleitzahl eingeben (5 Stellen)"
+
+#: validators.py:1986
+msgid "The name %(name)s is missing"
+msgstr "Der Name %(name)s fehlt"
+
+#: validators.py:2027
+msgid "Value should be %(true)r or %(false)r"
+msgstr "Wert sollte %(true)r oder %(false)r sein"
+
+#: validators.py:2062
+msgid "Value does not contain a signature"
+msgstr "Wert enth�lt keine Signatur"
+
+#: validators.py:2063
+msgid "Signature is not correct"
+msgstr "Signatur ist nicht korrekt"
+
+#: validators.py:2185
+msgid "Fields do not match (should be %(match)s)"
+msgstr "Felder stimmen nicht �berein (sollten sein %(match)s)"
+
+#: validators.py:2186
+msgid "Fields do not match"
+msgstr "Felder stimmen nicht �berein"
+
+#: validators.py:2248
+msgid "Please enter only the number, no other characters"
+msgstr "Bitte nur die Nummer, keine anderen Zeichen eingeben."
+
+#: validators.py:2249
+msgid "You did not enter a valid number of digits"
+msgstr "Sie haben keine g�ltige Zahl aus Ziffern eingegeben"
+
+#: validators.py:2250
+msgid "That number is not valid"
+msgstr "Diese Nummer ist ung�ltig"
+
+#: validators.py:2365
+msgid "Please enter numbers only for month and year"
+msgstr "Bitte Nummern nur f�r das Monat und Jahr eingeben"
+
+#: validators.py:2366
+msgid "Invalid Expiration Date"
+msgstr "Ung�ltiges Ablaufdatum"
+
+#: validators.py:2435
+msgid "Please enter numbers only for credit card security code"
+msgstr "Bitte Nummern nur f�r den Kreditkarten Sicherheitskode eingeben."
+
+#: validators.py:2436
+msgid "Invalid credit card security code length"
+msgstr "Ung�ltige Kreditkartensicherheitscodel�nge"
+

Modified: FormEncode/branches/gettext-enabled/formencode/validators.py
===================================================================
--- FormEncode/branches/gettext-enabled/formencode/validators.py        
2006-10-02 14:23:09 UTC (rev 1967)
+++ FormEncode/branches/gettext-enabled/formencode/validators.py        
2006-10-02 19:04:46 UTC (rev 1968)
@@ -44,6 +44,12 @@
 
 True, False = (1==1), (0==1)
 
+#def _(s): return s # dummy translation function, nothing is translated here.
+                   # Instead this is actually done in api.message.
+                   # The surrounding _("string") of the strings is only for 
extracting
+                   # the strings automatically
+                   # if you run pygettext with this source comment this 
function out temporarly 
+
 ############################################################
 ## Utility methods
 ############################################################
@@ -151,10 +157,10 @@
     type = None
 
     messages = {
-        'subclass': "%(object)r is not a subclass of %(subclass)s",
-        'inSubclass': "%(object)r is not a subclass of one of the types 
%(subclassList)s",
-        'inType': "%(object)r must be one of the types %(typeList)s",
-        'type': "%(object)r must be of the type %(type)s",
+        'subclass': _("%(object)r is not a subclass of %(subclass)s"),
+        'inSubclass': _("%(object)r is not a subclass of one of the types 
%(subclassList)s"),
+        'inType': _("%(object)r must be one of the types %(typeList)s"),
+        'type': _("%(object)r must be of the type %(type)s"),
         }
 
     def __init__(self, *args, **kw):
@@ -335,8 +341,8 @@
 
     __unpackargs__ = ('maxLength',)
     messages = {
-        'tooLong': "Enter a value less than %(maxLength)i characters long",
-        'invalid': "Invalid value (value with length expected)",
+        'tooLong': _("Enter a value less than %(maxLength)i characters long"),
+        'invalid': _("Invalid value (value with length expected)"),
         }
 
     def validate_python(self, value, state):
@@ -389,8 +395,8 @@
     __unpackargs__ = ('minLength',)
 
     messages = {
-        'tooShort': "Enter a value at least %(minLength)i characters long",
-        'invalid': "Invalid value (value with length expected)",
+        'tooShort': _("Enter a value at least %(minLength)i characters long"),
+        'invalid': _("Invalid value (value with length expected)"),
         }
 
     def validate_python(self, value, state):
@@ -424,7 +430,7 @@
     not_empty = True
 
     messages = {
-        'empty': "Please enter a value",
+        'empty': _("Please enter a value"),
         }
 
     def validate_python(self, value, state):
@@ -449,7 +455,7 @@
     """
 
     messages = {
-        'notEmpty': "You cannot enter a value here",
+        'notEmpty': _("You cannot enter a value here"),
         }
 
     def validate_python(self, value, state):
@@ -500,7 +506,7 @@
     __unpackargs__ = ('regex',)
 
     messages = {
-        'invalid': "The input is not valid",
+        'invalid': _("The input is not valid"),
         }
     
     def __init__(self, *args, **kw):
@@ -556,7 +562,7 @@
     regex = r"^[a-zA-Z_\-0-9]*$"
 
     messages = {
-        'invalid': 'Enter only letters, numbers, or _ (underscore)',
+        'invalid': _('Enter only letters, numbers, or _ (underscore)'),
         }
 
 class OneOf(FancyValidator):
@@ -595,8 +601,8 @@
     __unpackargs__ = ('list',)
 
     messages = {
-        'invalid': "Invalid value",
-        'notIn': "Value must be one of: %(items)s (not %(value)r)",
+        'invalid': _("Invalid value"),
+        'notIn': _("Value must be one of: %(items)s (not %(value)r)"),
         }
     
     def validate_python(self, value, state):
@@ -659,10 +665,10 @@
     __unpackargs__ = ('dict',)
 
     messages = {
-        'keyNotFound': "Choose something",
-        'chooseKey': "Enter a value from: %(items)s",
-        'valueNotFound': "That value is not known",
-        'chooseValue': "Nothing in my dictionary goes by the value %(value)s.  
Choose one of: %(items)s",
+        'keyNotFound': _("Choose something"),
+        'chooseKey': _("Enter a value from: %(items)s"),
+        'valueNotFound': _("That value is not known"),
+        'chooseValue': _("Nothing in my dictionary goes by the value 
%(value)s.  Choose one of: %(items)s"),
         }
     
     def _to_python(self, value, state):
@@ -723,9 +729,9 @@
     __unpackargs__ = ('list',)
 
     messages = {
-        'integer': "Must be an integer index",
-        'outOfRange': "Index out of range",
-        'notFound': "Item %(value)s was not found in the list",
+        'integer': _("Must be an integer index"),
+        'outOfRange': _("Index out of range"),
+        'notFound': _("Item %(value)s was not found in the list"),
         }
     
     def _to_python(self, value, state):
@@ -800,11 +806,11 @@
     datetime_module = None
 
     messages = {
-        'after': "Date must be after %(date)s",
-        'before': "Date must be before %(date)s",
+        'after': _("Date must be after %(date)s"),
+        'before': _("Date must be before %(date)s"),
         # Double %'s, because this will be substituted twice:
-        'date_format': "%%A, %%d %%B %%Y",
-        'future': "The date must be sometime in the future",
+        'date_format': _("%%A, %%d %%B %%Y"),
+        'future': _("The date must be sometime in the future"),
         }
 
     def validate_python(self, value, state):
@@ -904,7 +910,7 @@
     """
 
     messages = {
-        'integer': "Please enter an integer value",
+        'integer': _("Please enter an integer value"),
         }
 
     def _to_python(self, value, state):
@@ -936,7 +942,7 @@
     """
     
     messages = {
-        'number': "Please enter a number",
+        'number': _("Please enter a number"),
         }
     
     def _to_python(self, value, state):
@@ -989,8 +995,8 @@
     not_empty = None
 
     messages = {
-        'tooLong': "Enter a value less than %(max)i characters long",
-        'tooShort': "Enter a value %(min)i characters long or more",
+        'tooLong': _("Enter a value less than %(max)i characters long"),
+        'tooShort': _("Enter a value %(min)i characters long or more"),
         }
 
     def __initargs__(self, new_attrs):
@@ -1041,7 +1047,7 @@
     """
     encoding = 'utf-8'
     messages = {
-        'badEncoding' : "Invalid data or incorrect encoding",
+        'badEncoding' : _("Invalid data or incorrect encoding"),
     }
     
     def __init__(self, inputEncoding=None, outputEncoding=None, **kw):
@@ -1169,12 +1175,12 @@
     domainRE = re.compile(r"^[a-z0-9][a-z0-9\.\-_]*\.[a-z]+$", re.I)
 
     messages = {
-        'empty': 'Please enter an email address',
-        'noAt': 'An email address must contain a single @',
-        'badUsername': 'The username portion of the email address is invalid 
(the portion before the @: %(username)s)',
-        'socketError': 'An error occured when trying to connect to the server: 
%(error)s',
-        'badDomain': 'The domain portion of the email address is invalid (the 
portion after the @: %(domain)s)',
-        'domainDoesNotExist': 'The domain of the email address does not exist 
(the portion after the @: %(domain)s)',
+        'empty': _('Please enter an email address'),
+        'noAt': _('An email address must contain a single @'),
+        'badUsername': _('The username portion of the email address is invalid 
(the portion before the @: %(username)s)'),
+        'socketError': _('An error occured when trying to connect to the 
server: %(error)s'),
+        'badDomain': _('The domain portion of the email address is invalid 
(the portion after the @: %(domain)s)'),
+        'domainDoesNotExist': _('The domain of the email address does not 
exist (the portion after the @: %(domain)s)'),
         }
     
     def __init__(self, *args, **kw):
@@ -1282,12 +1288,12 @@
     scheme_re = re.compile(r'^[a-zA-Z]+:')
 
     messages = {
-        'noScheme': 'You must start your URL with http://, https://, etc',
-        'badURL': 'That is not a valid URL',
-        'httpError': 'An error occurred when trying to access the URL: 
%(error)s',
-        'socketError': 'An error occured when trying to connect to the server: 
%(error)s',
-        'notFound': 'The server responded that the page could not be found',
-        'status': 'The server responded with a bad status code (%(status)s)',
+        'noScheme': _('You must start your URL with http://, https://, etc'),
+        'badURL': _('That is not a valid URL'),
+        'httpError': _('An error occurred when trying to access the URL: 
%(error)s'),
+        'socketError': _('An error occured when trying to connect to the 
server: %(error)s'),
+        'notFound': _('The server responded that the page could not be found'),
+        'status': _('The server responded with a bad status code 
(%(status)s)'),
         }
 
     def _to_python(self, value, state):
@@ -1390,9 +1396,9 @@
     __unpackargs__ = ('extra_states',)
 
     messages = {
-        'empty': 'Please enter a state code',
-        'wrongLength': 'Please enter a state code with TWO letters',
-        'invalid': 'That is not a valid state code',
+        'empty': _('Please enter a state code'),
+        'wrongLength': _('Please enter a state code with TWO letters'),
+        'invalid': _('That is not a valid state code'),
         }
 
     def validate_python(self, value, state):
@@ -1443,7 +1449,7 @@
     _phoneRE = re.compile(r'^\s*(?:1-)?(\d\d\d)[\- \.]?(\d\d\d)[\- 
\.]?(\d\d\d\d)(?:\s*ext\.?\s*(\d+))?\s*$', re.I)
 
     messages = {
-        'phoneFormat': 'Please enter a number, with area code, in the form 
###-###-####, optionally with "ext.####"',
+        'phoneFormat': _('Please enter a number, with area code, in the form 
###-###-####, optionally with "ext.####"'),
         }
         
     def _to_python(self, value, state):
@@ -1605,15 +1611,15 @@
         9: 30, 10: 31, 11: 30, 12: 31}
 
     messages = {
-        'badFormat': 'Please enter the date in the form %(format)s',
-        'monthRange': 'Please enter a month from 1 to 12',
-        'invalidDay': 'Please enter a valid day',
-        'dayRange': 'That month only has %(days)i days',
-        'invalidDate': 'That is not a valid day (%(exception)s)',
-        'unknownMonthName': "Unknown month name: %(month)s",
-        'invalidYear': 'Please enter a number for the year',
-        'fourDigitYear': 'Please enter a four-digit year',
-        'wrongFormat': 'Please enter the date in the form %(format)s',
+        'badFormat': _('Please enter the date in the form %(format)s'),
+        'monthRange': _('Please enter a month from 1 to 12'),
+        'invalidDay': _('Please enter a valid day'),
+        'dayRange': _('That month only has %(days)i days'),
+        'invalidDate': _('That is not a valid day (%(exception)s)'),
+        'unknownMonthName': _("Unknown month name: %(month)s"),
+        'invalidYear': _('Please enter a number for the year'),
+        'fourDigitYear': _('Please enter a four-digit year'),
+        'wrongFormat': _('Please enter the date in the form %(format)s'),
         }
 
     def _to_python(self, value, state):
@@ -1791,15 +1797,15 @@
     datetime_module = None
 
     messages = {
-        'noAMPM': 'You must indicate AM or PM',
-        'tooManyColon': 'There are too many :\'s',
-        'noSeconds': 'You may not enter seconds',
-        'secondsRequired': 'You must enter seconds',
-        'minutesRequired': 'You must enter minutes (after a :)',
-        'badNumber': 'The %(part)s value you gave is not a number: %(number)r',
-        'badHour': 'You must enter an hour in the range %(range)s',
-        'badMinute': 'You must enter a minute in the range 0-59',
-        'badSecond': 'You must enter a second in the range 0-59',
+        'noAMPM': _('You must indicate AM or PM'),
+        'tooManyColon': _('There are too many :\'s'),
+        'noSeconds': _('You may not enter seconds'),
+        'secondsRequired': _('You must enter seconds'),
+        'minutesRequired': _('You must enter minutes (after a :)'),
+        'badNumber': _('The %(part)s value you gave is not a number: 
%(number)r'),
+        'badHour': _('You must enter an hour in the range %(range)s'),
+        'badMinute': _('You must enter a minute in the range 0-59'),
+        'badSecond': _('You must enter a second in the range 0-59'),
         }
 
     def _to_python(self, value, state):
@@ -1953,7 +1959,7 @@
     strip = True
 
     messages = {
-        'invalid': 'Please enter a zip code (5 digits)',
+        'invalid': _('Please enter a zip code (5 digits)'),
         }
 
 class StripField(FancyValidator):
@@ -1977,7 +1983,7 @@
     __unpackargs__ = ('name',)
 
     messages = {
-        'missing': 'The name %(name)s is missing',
+        'missing': _('The name %(name)s is missing'),
         }
 
     def _to_python(self, valueDict, state):
@@ -2018,7 +2024,7 @@
     true_values = ['true', 't', 'yes', 'y', 'on', '1']
     false_values = ['false', 'f', 'no', 'n', 'off', '0']
 
-    messages = { "string" : "Value should be %(true)r or %(false)r" }
+    messages = { "string" : _("Value should be %(true)r or %(false)r") }
     
     def _to_python(self, value, state):
         if isinstance(value, (str, unicode)):
@@ -2053,8 +2059,8 @@
     """
 
     messages = {
-        'malformed': 'Value does not contain a signature',
-        'badsig': 'Signature is not correct',
+        'malformed': _('Value does not contain a signature'),
+        'badsig': _('Signature is not correct'),
         }
 
     secret = None
@@ -2176,8 +2182,8 @@
     __unpackargs__ = ('*', 'field_names')
 
     messages = {
-        'invalid': "Fields do not match (should be %(match)s)",
-        'invalidNoMatch': "Fields do not match",
+        'invalid': _("Fields do not match (should be %(match)s)"),
+        'invalidNoMatch': _("Fields do not match"),
         }
     
     def validate_partial(self, field_dict, state):
@@ -2239,9 +2245,9 @@
     __unpackargs__ = ('cc_type_field', 'cc_number_field')
 
     messages = {
-        'notANumber': "Please enter only the number, no other characters",
-        'badLength': "You did not enter a valid number of digits",
-        'invalidNumber': "That number is not valid",
+        'notANumber': _("Please enter only the number, no other characters"),
+        'badLength': _("You did not enter a valid number of digits"),
+        'invalidNumber': _("That number is not valid"),
         }
 
     def validate_partial(self, field_dict, state):
@@ -2356,8 +2362,8 @@
     datetime_module = None
 
     messages = {
-        'notANumber': "Please enter numbers only for month and year",
-        'invalidNumber': "Invalid Expiration Date",
+        'notANumber': _("Please enter numbers only for month and year"),
+        'invalidNumber': _("Invalid Expiration Date"),
         }
 
     def validate_partial(self, field_dict, state):
@@ -2426,8 +2432,8 @@
     __unpackargs__ = ('cc_type_field', 'cc_code_field')
 
     messages = {
-        'notANumber': "Please enter numbers only for credit card security 
code",
-        'badLength': "Invalid credit card security code length",
+        'notANumber': _("Please enter numbers only for credit card security 
code"),
+        'badLength': _("Invalid credit card security code length"),
         }
 
     def validate_partial(self, field_dict, state):

Modified: FormEncode/branches/gettext-enabled/tests/test_cc_expires.py
===================================================================
--- FormEncode/branches/gettext-enabled/tests/test_cc_expires.py        
2006-10-02 14:23:09 UTC (rev 1967)
+++ FormEncode/branches/gettext-enabled/tests/test_cc_expires.py        
2006-10-02 19:04:46 UTC (rev 1968)
@@ -9,11 +9,11 @@
     except Invalid, e:
         return e.unpack_errors()['ccExpiresMonth']
 
-messages = CreditCardExpires._messages
+messages = ed.message
 
 def test_ed():
     assert validate('11', '2250') is None
-    assert validate('11', 'test') == messages['notANumber']
-    assert validate('test', '2250') == messages['notANumber']
-    assert validate('10', '2005') == messages['invalidNumber']
-    assert validate('10', '05') == messages['invalidNumber']
+    assert validate('11', 'test') == messages('notANumber', None)
+    assert validate('test', '2250') == messages('notANumber', None)
+    assert validate('10', '2005') == messages('invalidNumber', None)
+    assert validate('10', '05') == messages('invalidNumber', None)

Modified: FormEncode/branches/gettext-enabled/tests/test_cc_validator.py
===================================================================
--- FormEncode/branches/gettext-enabled/tests/test_cc_validator.py      
2006-10-02 14:23:09 UTC (rev 1967)
+++ FormEncode/branches/gettext-enabled/tests/test_cc_validator.py      
2006-10-02 19:04:46 UTC (rev 1968)
@@ -9,11 +9,11 @@
     except Invalid, e:
         return e.unpack_errors()['ccNumber']
 
-messages = CreditCardValidator._messages
+messages = cc.message
 
 def test_cc():
     assert validate('visa', '4'+('1'*15)) is None
-    assert validate('visa', '5'+('1'*12)) == messages['invalidNumber']
-    assert validate('visa', '4'+('1'*11) + '2') == messages['invalidNumber']
-    assert validate('visa', 'test') == messages['notANumber']
-    assert validate('visa', '4'+('1'*10)) == messages['badLength']
+    assert validate('visa', '5'+('1'*12)) == messages('invalidNumber', None)
+    assert validate('visa', '4'+('1'*11) + '2') == messages('invalidNumber', 
None)
+    assert validate('visa', 'test') == messages('notANumber', None)
+    assert validate('visa', '4'+('1'*10)) == messages('badLength', None)

Added: FormEncode/branches/gettext-enabled/tests/test_i18n.py
===================================================================
--- FormEncode/branches/gettext-enabled/tests/test_i18n.py                      
        (rev 0)
+++ FormEncode/branches/gettext-enabled/tests/test_i18n.py      2006-10-02 
19:04:46 UTC (rev 1968)
@@ -0,0 +1,64 @@
+import formencode
+
+import os
+
+ne = formencode.validators.NotEmpty()
+
+def _test_builtins(func):
+  def dummy(s):
+    return "builtins dummy"
+  import __builtin__
+  __builtin__._ = dummy
+
+  try:
+      ne.to_python("")
+  except formencode.api.Invalid, e:
+    func(e)
+  
+  del __builtin__._
+
+def test_builtins():
+  def withbuiltins(e):
+      assert str(e) == "builtins dummy"
+    
+  _test_builtins(withbuiltins)
+
+
+def test_bultins_disabled():
+  def withoutbuiltins(e):
+      assert str(e) <> "builtins dummy"
+      
+  ne.use_builtins_gettext = False
+  _test_builtins(withoutbuiltins)
+
+
+
+def test_state():
+  class st(object):
+    def _(self, s):
+      return "state dummy"
+  
+  try:
+    ne.to_python("", state=st())
+  except formencode.api.Invalid, e:
+    assert str(e) == "state dummy"
+
+  
+def _test_lang(language, notemptytext):
+
+  formencode.api.set_stdtranslation(languages=[language])
+ 
+  try:
+    ne.to_python("")
+  except formencode.api.Invalid, e:
+    assert str(e) == notemptytext
+  
+  formencode.api.set_stdtranslation() #set back to defaults
+
+    
+def test_de():
+  _test_lang("de", u"Bitte einen Wert eingeben")
+
+
+
+  

Modified: FormEncode/branches/gettext-enabled/tests/test_schema.py
===================================================================
--- FormEncode/branches/gettext-enabled/tests/test_schema.py    2006-10-02 
14:23:09 UTC (rev 1967)
+++ FormEncode/branches/gettext-enabled/tests/test_schema.py    2006-10-02 
19:04:46 UTC (rev 1968)
@@ -4,6 +4,23 @@
 from formencode.variabledecode import NestedVariables
 import cgi
 
+
+def setup_module(module):
+    """Disable i18n translation
+    """
+    def notranslation(s): return s
+    import __builtin__
+    __builtin__._ = notranslation
+
+    
+
+def teardown_module(module):
+    """Remove translation function
+    """
+    import __builtin__
+    del __builtin__._
+
+
 def d(**kw): return kw
 
 def cgi_parse(qs):
@@ -114,9 +131,11 @@
         text="The input field 'whatever' was not expected.")
 
 def test_this():
+
     for case in all_cases:
         yield case.test
 
+
 def test_merge():
     assert (merge_dicts(dict(a='a'), dict(b='b'))
             == dict(a='a', b='b'))
@@ -128,4 +147,5 @@
                              c='foo'))
             == dict(a=['a1\naa1', 'a2'], b=['b\nbb', 'bbb'],
                     c=['c']))
-    
+
+

Modified: FormEncode/branches/gettext-enabled/tests/test_sqlschema.py
===================================================================
--- FormEncode/branches/gettext-enabled/tests/test_sqlschema.py 2006-10-02 
14:23:09 UTC (rev 1967)
+++ FormEncode/branches/gettext-enabled/tests/test_sqlschema.py 2006-10-02 
19:04:46 UTC (rev 1968)
@@ -3,6 +3,22 @@
 from formencode import validators
 from datetime import datetime, date
 
+def setup_module(module):
+    """Disable i18n translation
+    """
+    def notranslation(s): return s
+    import __builtin__
+    __builtin__._ = notranslation
+
+    
+
+def teardown_module(module):
+    """Remove translation function
+    """
+    import __builtin__
+    del __builtin__._
+
+
 sqlhub.processConnection = connectionForURI('sqlite:/:memory:')
 
 class EventObject(SQLObject):


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
FormEncode-CVS mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/formencode-cvs

Reply via email to