Author: gh
Date: 2006-12-01 11:19:05 -0700 (Fri, 01 Dec 2006)
New Revision: 2106

Added:
   FormEncode/trunk/docs/i18n.txt
   FormEncode/trunk/formencode/i18n/
   FormEncode/trunk/formencode/i18n/big5/
   FormEncode/trunk/formencode/i18n/big5/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/de/
   FormEncode/trunk/formencode/i18n/de/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/es/
   FormEncode/trunk/formencode/i18n/es/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/pt_BR/
   FormEncode/trunk/formencode/i18n/pt_BR/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/ru/
   FormEncode/trunk/formencode/i18n/ru/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/sk/
   FormEncode/trunk/formencode/i18n/sk/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/sl/
   FormEncode/trunk/formencode/i18n/sl/LC_MESSAGES/
   FormEncode/trunk/tests/test_i18n.py
Removed:
   FormEncode/trunk/formencode/i18n/big5/
   FormEncode/trunk/formencode/i18n/big5/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/de/
   FormEncode/trunk/formencode/i18n/de/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/es/
   FormEncode/trunk/formencode/i18n/es/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/pt_BR/
   FormEncode/trunk/formencode/i18n/pt_BR/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/ru/
   FormEncode/trunk/formencode/i18n/ru/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/sk/
   FormEncode/trunk/formencode/i18n/sk/LC_MESSAGES/
   FormEncode/trunk/formencode/i18n/sl/
   FormEncode/trunk/formencode/i18n/sl/LC_MESSAGES/
Modified:
   FormEncode/trunk/docs/news.txt
   FormEncode/trunk/formencode/api.py
   FormEncode/trunk/formencode/i18n/FormEncode.pot
   FormEncode/trunk/formencode/i18n/big5/LC_MESSAGES/FormEncode.mo
   FormEncode/trunk/formencode/i18n/big5/LC_MESSAGES/FormEncode.po
   FormEncode/trunk/formencode/i18n/de/LC_MESSAGES/FormEncode.mo
   FormEncode/trunk/formencode/i18n/de/LC_MESSAGES/FormEncode.po
   FormEncode/trunk/formencode/i18n/es/LC_MESSAGES/FormEncode.mo
   FormEncode/trunk/formencode/i18n/es/LC_MESSAGES/FormEncode.po
   FormEncode/trunk/formencode/i18n/pt_BR/LC_MESSAGES/FormEncode.mo
   FormEncode/trunk/formencode/i18n/pt_BR/LC_MESSAGES/FormEncode.po
   FormEncode/trunk/formencode/i18n/ru/LC_MESSAGES/FormEncode.mo
   FormEncode/trunk/formencode/i18n/ru/LC_MESSAGES/FormEncode.po
   FormEncode/trunk/formencode/i18n/sk/LC_MESSAGES/FormEncode.mo
   FormEncode/trunk/formencode/i18n/sk/LC_MESSAGES/FormEncode.po
   FormEncode/trunk/formencode/i18n/sl/LC_MESSAGES/FormEncode.mo
   FormEncode/trunk/formencode/i18n/sl/LC_MESSAGES/FormEncode.po
   FormEncode/trunk/formencode/schema.py
   FormEncode/trunk/formencode/validators.py
   FormEncode/trunk/tests/test_cc_expires.py
   FormEncode/trunk/tests/test_cc_validator.py
   FormEncode/trunk/tests/test_schema.py
   FormEncode/trunk/tests/test_sqlschema.py
Log:
merge gettext-enabled branche r1947 into trunk 2105

Added: FormEncode/trunk/docs/i18n.txt
===================================================================
--- FormEncode/trunk/docs/i18n.txt                              (rev 0)
+++ FormEncode/trunk/docs/i18n.txt      2006-12-01 18:19:05 UTC (rev 2106)
@@ -0,0 +1,34 @@
+FormEncode Internationalization (gettext)
++++++++++++++++++++++++++++++++++++++++++
+
+There are different translation options available:
+
+Domain "FormEncode" 
+^^^^^^^^^^^^^^^^^^^
+
+for standalone use of FormEncode. 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"])
+
+The mo files are located in the i18n subdirectory of the formencode 
installation.
+
+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/trunk/docs/news.txt
===================================================================
--- FormEncode/trunk/docs/news.txt      2006-12-01 07:04:20 UTC (rev 2105)
+++ FormEncode/trunk/docs/news.txt      2006-12-01 18:19:05 UTC (rev 2106)
@@ -6,6 +6,8 @@
 svn trunk
 ---------
 
+* gettext-enabled branch merged in
+
 * Fixes `#1457145: Fails on URLs with port numbers
   
<http://sourceforge.net/tracker/index.php?func=detail&aid=1457145&group_id=91231&atid=596416>`_
 

Modified: FormEncode/trunk/formencode/api.py
===================================================================
--- FormEncode/trunk/formencode/api.py  2006-12-01 07:04:20 UTC (rev 2105)
+++ FormEncode/trunk/formencode/api.py  2006-12-01 18:19:05 UTC (rev 2106)
@@ -5,10 +5,34 @@
 import declarative
 import textwrap
 import re
+import os
+from pkg_resources import resource_filename
 
 __all__ = ['NoDefault', 'Invalid', 'Validator', 'Identity',
            'FancyValidator', 'is_validator']
 
+import gettext
+
+def get_localedir():
+    return resource_filename(__name__, "/i18n")
+
+def set_stdtranslation(domain="FormEncode", languages=None, \
+                       localedir = get_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 +141,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 +168,27 @@
         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
+ 
+        if not callable(trans):
+            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 +340,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):

Copied: FormEncode/trunk/formencode/i18n (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n)

Modified: FormEncode/trunk/formencode/i18n/FormEncode.pot
===================================================================

Copied: FormEncode/trunk/formencode/i18n/big5 (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/big5)

Copied: FormEncode/trunk/formencode/i18n/big5/LC_MESSAGES (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/big5/LC_MESSAGES)

Modified: FormEncode/trunk/formencode/i18n/big5/LC_MESSAGES/FormEncode.mo
===================================================================
(Binary files differ)

Modified: FormEncode/trunk/formencode/i18n/big5/LC_MESSAGES/FormEncode.po
===================================================================

Copied: FormEncode/trunk/formencode/i18n/de (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/de)

Copied: FormEncode/trunk/formencode/i18n/de/LC_MESSAGES (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/de/LC_MESSAGES)

Modified: FormEncode/trunk/formencode/i18n/de/LC_MESSAGES/FormEncode.mo
===================================================================
(Binary files differ)

Modified: FormEncode/trunk/formencode/i18n/de/LC_MESSAGES/FormEncode.po
===================================================================

Copied: FormEncode/trunk/formencode/i18n/es (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/es)

Copied: FormEncode/trunk/formencode/i18n/es/LC_MESSAGES (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/es/LC_MESSAGES)

Modified: FormEncode/trunk/formencode/i18n/es/LC_MESSAGES/FormEncode.mo
===================================================================
(Binary files differ)

Modified: FormEncode/trunk/formencode/i18n/es/LC_MESSAGES/FormEncode.po
===================================================================

Copied: FormEncode/trunk/formencode/i18n/pt_BR (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/pt_BR)

Copied: FormEncode/trunk/formencode/i18n/pt_BR/LC_MESSAGES (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/pt_BR/LC_MESSAGES)

Modified: FormEncode/trunk/formencode/i18n/pt_BR/LC_MESSAGES/FormEncode.mo
===================================================================
(Binary files differ)

Modified: FormEncode/trunk/formencode/i18n/pt_BR/LC_MESSAGES/FormEncode.po
===================================================================

Copied: FormEncode/trunk/formencode/i18n/ru (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/ru)

Copied: FormEncode/trunk/formencode/i18n/ru/LC_MESSAGES (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/ru/LC_MESSAGES)

Modified: FormEncode/trunk/formencode/i18n/ru/LC_MESSAGES/FormEncode.mo
===================================================================
(Binary files differ)

Modified: FormEncode/trunk/formencode/i18n/ru/LC_MESSAGES/FormEncode.po
===================================================================

Copied: FormEncode/trunk/formencode/i18n/sk (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/sk)

Copied: FormEncode/trunk/formencode/i18n/sk/LC_MESSAGES (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/sk/LC_MESSAGES)

Modified: FormEncode/trunk/formencode/i18n/sk/LC_MESSAGES/FormEncode.mo
===================================================================
(Binary files differ)

Modified: FormEncode/trunk/formencode/i18n/sk/LC_MESSAGES/FormEncode.po
===================================================================

Copied: FormEncode/trunk/formencode/i18n/sl (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/sl)

Copied: FormEncode/trunk/formencode/i18n/sl/LC_MESSAGES (from rev 2105, 
FormEncode/branches/gettext-enabled/formencode/i18n/sl/LC_MESSAGES)

Modified: FormEncode/trunk/formencode/i18n/sl/LC_MESSAGES/FormEncode.mo
===================================================================
(Binary files differ)

Modified: FormEncode/trunk/formencode/i18n/sl/LC_MESSAGES/FormEncode.po
===================================================================

Modified: FormEncode/trunk/formencode/schema.py
===================================================================
--- FormEncode/trunk/formencode/schema.py       2006-12-01 07:04:20 UTC (rev 
2105)
+++ FormEncode/trunk/formencode/schema.py       2006-12-01 18:19:05 UTC (rev 
2106)
@@ -291,7 +291,7 @@
     if isinstance(v, Exception):
         try:
             return str(v)
-        except UnicodeDecodeError:
+        except (UnicodeDecodeError, UnicodeEncodeError):
             # There doesn't seem to be a better way to get a str()
             # version if possible, and unicode() if necessary, because
             # testing for the presence of a __unicode__ method isn't

Modified: FormEncode/trunk/formencode/validators.py
===================================================================
--- FormEncode/trunk/formencode/validators.py   2006-12-01 07:04:20 UTC (rev 
2105)
+++ FormEncode/trunk/formencode/validators.py   2006-12-01 18:19:05 UTC (rev 
2106)
@@ -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):
@@ -555,7 +561,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):
@@ -594,8 +600,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):
@@ -658,10 +664,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):
@@ -722,9 +728,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):
@@ -799,11 +805,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):
@@ -903,7 +909,7 @@
     """
 
     messages = {
-        'integer': "Please enter an integer value",
+        'integer': _("Please enter an integer value"),
         }
 
     def _to_python(self, value, state):
@@ -935,7 +941,7 @@
     """
     
     messages = {
-        'number': "Please enter a number",
+        'number': _("Please enter a number"),
         }
     
     def _to_python(self, value, state):
@@ -988,8 +994,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):
@@ -1040,7 +1046,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):
@@ -1170,12 +1176,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):
@@ -1283,12 +1289,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):
@@ -1391,9 +1397,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):
@@ -1444,7 +1450,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):
@@ -1608,15 +1614,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):
@@ -1794,15 +1800,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):
@@ -1956,7 +1962,7 @@
     strip = True
 
     messages = {
-        'invalid': 'Please enter a zip code (5 digits)',
+        'invalid': _('Please enter a zip code (5 digits)'),
         }
 
 class StripField(FancyValidator):
@@ -1980,7 +1986,7 @@
     __unpackargs__ = ('name',)
 
     messages = {
-        'missing': 'The name %(name)s is missing',
+        'missing': _('The name %(name)s is missing'),
         }
 
     def _to_python(self, valueDict, state):
@@ -2021,7 +2027,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)):
@@ -2056,8 +2062,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
@@ -2179,8 +2185,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):
@@ -2242,9 +2248,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):
@@ -2359,8 +2365,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):
@@ -2429,8 +2435,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/trunk/tests/test_cc_expires.py
===================================================================
--- FormEncode/trunk/tests/test_cc_expires.py   2006-12-01 07:04:20 UTC (rev 
2105)
+++ FormEncode/trunk/tests/test_cc_expires.py   2006-12-01 18:19:05 UTC (rev 
2106)
@@ -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/trunk/tests/test_cc_validator.py
===================================================================
--- FormEncode/trunk/tests/test_cc_validator.py 2006-12-01 07:04:20 UTC (rev 
2105)
+++ FormEncode/trunk/tests/test_cc_validator.py 2006-12-01 18:19:05 UTC (rev 
2106)
@@ -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/trunk/tests/test_i18n.py
===================================================================
--- FormEncode/trunk/tests/test_i18n.py                         (rev 0)
+++ FormEncode/trunk/tests/test_i18n.py 2006-12-01 18:19:05 UTC (rev 2106)
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+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 unicode(e) == notemptytext
+  
+  formencode.api.set_stdtranslation() #set back to defaults
+
+    
+def test_de():
+  _test_lang("de", u"Bitte einen Wert eingeben")
+
+def test_es():
+  _test_lang("es", u"Por favor introduzca un valor")
+
+def test_pt_BR():
+  _test_lang("pt_BR", u"Por favor digite um valor")
+
+def test_big5():
+  _test_lang("big5", u"請輸入一個值")
+
+def test_sk():
+  _test_lang("sk",u"Zadajte hodnotu, prosím")
+
+def test_ru():
+  _test_lang("ru",u"Необходимо ввести значение")
+
+
+def test_sl():
+  _test_lang("sl",u"Prosim, izpolnite polje")
+

Modified: FormEncode/trunk/tests/test_schema.py
===================================================================
--- FormEncode/trunk/tests/test_schema.py       2006-12-01 07:04:20 UTC (rev 
2105)
+++ FormEncode/trunk/tests/test_schema.py       2006-12-01 18:19:05 UTC (rev 
2106)
@@ -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/trunk/tests/test_sqlschema.py
===================================================================
--- FormEncode/trunk/tests/test_sqlschema.py    2006-12-01 07:04:20 UTC (rev 
2105)
+++ FormEncode/trunk/tests/test_sqlschema.py    2006-12-01 18:19:05 UTC (rev 
2106)
@@ -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