Repository: wagtail/wagtail

Issue:
Not L10N aware
Post date date-selection widget defaults to writing the date in the following format `14 Feb 2014`

The admin won't accept the date unless it's written in `2014-02-14` format.



Discussion:
This may be due to javascript errors that were present until the solving of #43, please can you pull wagtail and double check the problem is still present?

I don't think this is a JS issue.

I've seen this happening when USE_L10N = True is set in settings/base.py, but we have that set to false for the demo site - presumably you haven't changed that?

Alternatively - do you have your system set to a non-English locale, by any chance? That's one scenario we haven't tested with.

@gasman you are correct. I have `USE_L10N = True` in my settings. I didn't realise this would be the cause - I'm integrating Wagtail into an existing project.

Glad to track that one down... having to disable L10n is a real annoyance, and hopefully we'll figure out a workaround for that soon.


Resolving patch:
diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py
--- a/wagtail/wagtailadmin/edit_handlers.py
+++ b/wagtail/wagtailadmin/edit_handlers.py
@@ -14,6 +14,7 @@
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured, ValidationError
 from django.core.urlresolvers import reverse
+from django.conf import settings
 
 from wagtail.wagtailcore.models import Page
 from wagtail.wagtailcore.util import camelcase_to_underscore
@@ -76,16 +77,77 @@ def to_python(self, time_string):
             return datetime.time(hour=hour, minute=minute)
         else:
             raise ValidationError("Please type a valid time")
+            
 
+class LocalizedDateInput(forms.DateInput):
+    """
+    A custom DateInput widget that formats localized dates
+    and adds class="friendly_date" to be picked up by jquery datepicker.
+    """
+    def __init__(self, attrs=None):
+        default_attrs = {'class': 'localized_date', 'localize':True}
+        if attrs:
+            default_attrs.update(attrs)
 
-FORM_FIELD_OVERRIDES = {
-    models.DateField: {'widget': FriendlyDateInput},
-    models.TimeField: {'widget': FriendlyTimeInput, 'form_class': FriendlyTimeField},
-}
+        super(LocalizedDateInput, self).__init__(attrs=default_attrs)
+
+
+class LocalizedTimeInput(forms.TimeInput):
+    """
+    A custom TimeInput widget that formats dates as "5.30pm"
+    and adds class="friendly_time" to be picked up by jquery timepicker.
+    """
+    def __init__(self, attrs=None):
+        default_attrs = {'class': 'localized_time'}
+        if attrs:
+            default_attrs.update(attrs)
+        # Just use 24-hour format
+        super(LocalizedTimeInput, self).__init__(attrs=default_attrs, format='%H:%M')
+
+
+class LocalizedTimeField(forms.CharField):
+    def to_python(self, time_string):
+        # Check if the string is blank
+        if not time_string:
+            return None
+
+        # Look for time in the string
+        expr = re.compile("^(?P<hour>\d+)(?:(?:.|:)(?P<minute>\d+))?")
+        match = expr.match(time_string.lower())
+        if match:
+            # Pull out values from string
+            hour_string, minute_string= match.groups()
+
+            # Convert hours and minutes to integers
+            hour = int(hour_string)
+            if minute_string:
+                minute = int(minute_string)
+            else:
+                minute = 0
+            if hour>=24 or hour < 0 or minute >=60 or minute < 0:
+                raise ValidationError("Please type a valid time")            
+                
+            return datetime.time(hour=hour, minute=minute)
+        else:
+            raise ValidationError("Please type a valid time")            
+
+
+if hasattr(settings, 'USE_L10N') and settings.USE_L10N==True:
+    FORM_FIELD_OVERRIDES = {
+        models.DateField: {'widget': LocalizedDateInput},
+        models.TimeField: {'widget': LocalizedTimeInput, 'form_class': LocalizedTimeField},
+    }
+else: # Fall back to friendly date/time            
+    FORM_FIELD_OVERRIDES = {
+        models.DateField: {'widget': FriendlyDateInput},
+        models.TimeField: {'widget': FriendlyTimeInput, 'form_class': FriendlyTimeField},
+    }
 
 WIDGET_JS = {
-    FriendlyDateInput: (lambda id: "initDateChooser(fixPrefix('%s'));" % id),
-    FriendlyTimeInput: (lambda id: "initTimeChooser(fixPrefix('%s'));" % id),
+    FriendlyDateInput: (lambda id: "initFriendlyDateChooser(fixPrefix('%s'));" % id),
+    FriendlyTimeInput: (lambda id: "initFriendlyTimeChooser(fixPrefix('%s'));" % id),
+    LocalizedDateInput: (lambda id: "initLocalizedDateChooser(fixPrefix('%s'));" % id),
+    LocalizedTimeInput: (lambda id: "initLocalizedTimeChooser(fixPrefix('%s'));" % id),
     RichTextArea: (lambda id: "makeRichTextEditable(fixPrefix('%s'));" % id),
     TagWidget: (
         lambda id: "initTagField(fixPrefix('%s'), '%s');" % (
diff --git a/wagtail/wagtailadmin/templatetags/localize.py b/wagtail/wagtailadmin/templatetags/localize.py
new file mode 100644
--- /dev/null
+++ b/wagtail/wagtailadmin/templatetags/localize.py
@@ -0,0 +1,48 @@
+from django import template
+from django.conf import settings
+from django.utils import formats
+from django.utils.translation import get_language
+
+register = template.Library()
+
+# For reasons unkown, the el (greek) locale in django/conf/locale/el/formats.py 
+# *did not* contain a DATE_INPUT_FORMATS -- so it fell back to using the US 
+# date format (mm/dd/yy) which is not the correct one for Greece (dd/mm/yy). 
+# This means that if we used a localized datepicker django *won't* be able to
+# parse the dates! So a test here checks if DATE_INPUT_FORMATS is actually 
+# defined in a format module. If yes then it will just return an empty string 
+# so that the normal, localized date format from datepicker will be used.
+# If DATE_INPUT_FORMATS is not defined then it will return
+@register.assignment_tag
+def get_date_format_override():
+    if hasattr(settings, 'USE_I18N') and settings.USE_I18N==True:
+        
+        for m in formats.get_format_modules():
+            if hasattr(m, 'DATE_INPUT_FORMATS'):
+                return ''
+            else: # fall back to the ISO to be sure date will be parsed
+                return 'yy-mm-dd'
+    else: # Fall back to ISO if I18N is *not* used
+        return 'yy-mm-dd'
+
+# Get the correct i18n + l10n settings for datepicker depending on current 
+# thread language  
+@register.simple_tag
+def get_localized_datepicker_js():
+    if hasattr(settings, 'USE_I18N') and settings.USE_I18N==True and \
+        hasattr(settings, 'USE_L10N') and settings.USE_L10N==True:
+        
+        lang  = get_language()
+        
+        if '-' in lang:
+            lang_parts = lang.split('-')
+            lang = lang_parts[0].lower() +'-'+ lang_parts[1].upper()
+        else:
+            lang=lang.lower()
+        return '<script src="//jquery-ui.googlecode.com/svn/tags/latest/ui/i18n/jquery.ui.datepicker-{0}.js"></script>'.format(
+            lang
+        )
+        
+    else: # Don't write anything if we don't use I18N and L10N
+        return ''        
+        
\ No newline at end of file


Test patch: