def date_format(self, time, formatstring): # This is a simplified version of Products.CMFPlone.i18nl10n.ulocalized_time # that can take any format string. # ${a} Locale's abbreviated weekday name. # ${A} Locale's full weekday name. # ${b} Locale's abbreviated month name. # ${B} Locale's full month name. # ${d} Day of the month as a decimal number [01,31]. # ${H} Hour (24-hour clock) as a decimal number [00,23]. # ${I} Hour (12-hour clock) as a decimal number [01,12]. # ${m} Month as a decimal number [01,12]. # ${M} Minute as a decimal number [00,59]. # ${p} Locale's equivalent of either AM or PM. # ${S} Second as a decimal number [00,61]. # ${y} Year without century as a decimal number [00,99]. # ${Y} Year with century as a decimal number. # ${Z} Time zone name (no characters if no time zone exists). # get the format elements used in the formatstring mapping = {} formatelements = _interp_regex.findall(formatstring) # reformat the ${foo} to foo formatelements = [el[2:-1] for el in formatelements] # add used elements to mapping elements = [e for e in formatelements if e in datetime_formatvariables] # add weekday name, abbr. weekday name, month name, abbr month name week_included = True month_included = True name_elements = [e for e in formatelements if e in name_formatvariables] if not ('a' in name_elements or 'A' in name_elements): week_included = False if not ('b' in name_elements or 'B' in name_elements): month_included = False for key in elements: mapping[key]=time.strftime('%'+key) if week_included: weekday = int(time.strftime('%w')) # weekday, sunday = 0 if 'a' in name_elements: mapping['a']=weekdayname_msgid_abbr(weekday) if 'A' in name_elements: mapping['A']=weekdayname_msgid(weekday) if month_included: monthday = int(time.strftime('%m')) # month, january = 1 if 'b' in name_elements: mapping['b']=monthname_msgid_abbr(monthday) if 'B' in name_elements: mapping['B']=monthname_msgid(monthday) # translate translateable elements for key in name_elements: mapping[key] = translate(mapping[key], 'plonelocales', context=self.request, default=mapping[key]) # Apply the data to the format string: return interpolate(formatstring, mapping)
def toCalendarLocalizedTime(self, time): """Convert a date in the calendar date format""" time = DateTime(time.strftime("%Y-%m-%d")) mapping = {} formatstring = translate('date_format_long', 'monet.calendar.extensions', mapping, self.request, default="${A} ${B} ${d} ${Y}") # get the format elements used in the formatstring formatelements = _interp_regex.findall(formatstring) # reformat the ${foo} to foo formatelements = [el[2:-1] for el in formatelements] # add used elements to mapping elements = [e for e in formatelements if e in datetime_formatvariables] # add weekday name, abbr. weekday name, month name, abbr month name week_included = True month_included = True name_elements = [ e for e in formatelements if e in name_formatvariables ] if not ('a' in name_elements or 'A' in name_elements): week_included = False if not ('b' in name_elements or 'B' in name_elements): month_included = False for key in elements: mapping[key] = time.strftime('%' + key) if week_included: weekday = int(time.strftime('%w')) # weekday, sunday = 0 if 'a' in name_elements: mapping['a'] = weekdayname_msgid_abbr(weekday) if 'A' in name_elements: mapping['A'] = weekdayname_msgid(weekday) if month_included: monthday = int(time.strftime('%m')) # month, january = 1 if 'b' in name_elements: mapping['b'] = monthname_msgid_abbr(monthday) if 'B' in name_elements: mapping['B'] = monthname_msgid(monthday) # translate translateable elements for key in name_elements: mapping[key] = translate(mapping[key], 'plonelocales', context=self.request, default=mapping[key]) # translate the time string return translate('date_format_long', 'monet.calendar.extensions', mapping, self.request, default="${A} ${B} ${d} ${Y}")
def test_regexp_interp_regex(self): from Products.CMFPlone.i18nl10n import _interp_regex locales_string = "${H}:${M}" # test for locale string elements: self.assertEquals( _interp_regex.findall(locales_string), ["${H}", "${M}"], )
def toCalendarLocalizedTime(self, time): """Convert a date in the calendar date format""" time = DateTime(time.strftime("%Y-%m-%d")) mapping = {} formatstring = translate('date_format_long', 'monet.calendar.extensions', mapping, self.request, default="${A} ${B} ${d} ${Y}") # get the format elements used in the formatstring formatelements = _interp_regex.findall(formatstring) # reformat the ${foo} to foo formatelements = [el[2:-1] for el in formatelements] # add used elements to mapping elements = [e for e in formatelements if e in datetime_formatvariables] # add weekday name, abbr. weekday name, month name, abbr month name week_included = True month_included = True name_elements = [e for e in formatelements if e in name_formatvariables] if not ('a' in name_elements or 'A' in name_elements): week_included = False if not ('b' in name_elements or 'B' in name_elements): month_included = False for key in elements: mapping[key]=time.strftime('%'+key) if week_included: weekday = int(time.strftime('%w')) # weekday, sunday = 0 if 'a' in name_elements: mapping['a']=weekdayname_msgid_abbr(weekday) if 'A' in name_elements: mapping['A']=weekdayname_msgid(weekday) if month_included: monthday = int(time.strftime('%m')) # month, january = 1 if 'b' in name_elements: mapping['b']=monthname_msgid_abbr(monthday) if 'B' in name_elements: mapping['B']=monthname_msgid(monthday) # translate translateable elements for key in name_elements: mapping[key] = translate(mapping[key], 'plonelocales', context=self.request, default=mapping[key]) # translate the time string return translate('date_format_long', 'monet.calendar.extensions', mapping, self.request, default="${A} ${B} ${d} ${Y}")
def date_format(self, time, formatstring): # This is a simplified version of # Products.CMFPlone.i18nl10n.ulocalized_time # that can take any format string. # ${a} Locale's abbreviated weekday name. # ${A} Locale's full weekday name. # ${b} Locale's abbreviated month name. # ${B} Locale's full month name. # ${d} Day of the month as a decimal number [01,31]. # ${H} Hour (24-hour clock) as a decimal number [00,23]. # ${I} Hour (12-hour clock) as a decimal number [01,12]. # ${m} Month as a decimal number [01,12]. # ${M} Minute as a decimal number [00,59]. # ${p} Locale's equivalent of either AM or PM. # ${S} Second as a decimal number [00,61]. # ${y} Year without century as a decimal number [00,99]. # ${Y} Year with century as a decimal number. # ${Z} Time zone name (no characters if no time zone exists). # get the format elements used in the formatstring mapping = {} formatelements = _interp_regex.findall(formatstring) # reformat the ${foo} to foo formatelements = [el[2:-1] for el in formatelements] # add used elements to mapping elements = [e for e in formatelements if e in datetime_formatvariables] # add weekday name, abbr. weekday name, month name, abbr month name week_included = True month_included = True name_elements = [ e for e in formatelements if e in name_formatvariables ] if not ('a' in name_elements or 'A' in name_elements): week_included = False if not ('b' in name_elements or 'B' in name_elements): month_included = False for key in elements: mapping[key] = time.strftime('%' + key) if week_included: weekday = int(time.strftime('%w')) # weekday, sunday = 0 if 'a' in name_elements: mapping['a'] = weekdayname_msgid_abbr(weekday) if 'A' in name_elements: mapping['A'] = weekdayname_msgid(weekday) if month_included: monthday = int(time.strftime('%m')) # month, january = 1 if 'b' in name_elements: mapping['b'] = monthname_msgid_abbr(monthday) if 'B' in name_elements: mapping['B'] = monthname_msgid(monthday) # translate translateable elements for key in name_elements: mapping[key] = translate(mapping[key], 'plonelocales', context=self.request, default=mapping[key]) # Apply the data to the format string: return interpolate(formatstring, mapping)
def ulocalized_time(time, long_format=None, time_only=False, context=None, domain='plonelocales', formatstring_domain='plonelocales', request=None, target_language=None): """Unicode aware localized time method (l10n), extended from CMFPlone The ONLY change versus CMFPlone is the extra parameter `formatstring_domain`. This allows us to define a different date_format_long in ploneintranet, while still being able to use the default translations provided by plonelocales, e.g. for the month names. """ if time_only: msgid = 'time_format' elif long_format: msgid = 'date_format_long' else: msgid = 'date_format_short' # NOTE: this requires the presence of three msgids inside the translation # catalog date_format_long, date_format_short, and time_format # These msgids are translated using interpolation. # The variables used here are the same as used in the strftime # formating. # Supported are: # %A, %a, %B, %b, %H, %I, %m, %d, %M, %p, %S, %Y, %y, %Z # Each used as variable in the msgstr without the %. # For example: "${A} ${d}. ${B} ${Y}, ${H}:${M} ${Z}" # Each language dependend part is translated itself as well. # From http://docs.python.org/lib/module-time.html # # %a Locale's abbreviated weekday name. # %A Locale's full weekday name. # %b Locale's abbreviated month name. # %B Locale's full month name. # %d Day of the month as a decimal number [01,31]. # %H Hour (24-hour clock) as a decimal number [00,23]. # %I Hour (12-hour clock) as a decimal number [01,12]. # %m Month as a decimal number [01,12]. # %M Minute as a decimal number [00,59]. # %p Locale's equivalent of either AM or PM. # %S Second as a decimal number [00,61]. # %y Year without century as a decimal number [00,99]. # %Y Year with century as a decimal number. # %Z Time zone name (no characters if no time zone exists). mapping = {} # convert to DateTime instances. Either a date string or # a DateTime instance needs to be passed. if not IDateTime.providedBy(time): try: time = DateTime(time) except: log('Failed to convert %s to a DateTime object' % time, severity=logging.DEBUG) return None if context is None: # when without context, we cannot do very much. return time.ISO8601() if request is None: request = aq_acquire(context, 'REQUEST') # 1. if our Enabled flag in the configuration registry is set, # the format string there should override the translation machinery formatstring = get_formatstring_from_registry(msgid) if formatstring is not None: return time.strftime(formatstring) # 2. the normal case: translation machinery, # that is the ".../LC_MESSAGES/plonelocales.po" files # XXX: here, we pass `formatstring_domain` instead of `domain` formatstring = translate(msgid, formatstring_domain, mapping, request, target_language=target_language) # 3. if both failed, fall back to hardcoded ISO style if formatstring == msgid: if msgid == 'date_format_long': formatstring = '%Y-%m-%d %H:%M' # 2038-01-19 03:14 elif msgid == 'date_format_short': formatstring = '%Y-%m-%d' # 2038-01-19 elif msgid == 'time_format': formatstring = '%H:%M' # 03:14 else: formatstring = '[INTERNAL ERROR]' return time.strftime(formatstring) # get the format elements used in the formatstring formatelements = _interp_regex.findall(formatstring) # reformat the ${foo} to foo formatelements = [el[2:-1] for el in formatelements] # add used elements to mapping elements = [e for e in formatelements if e in datetime_formatvariables] # add weekday name, abbr. weekday name, month name, abbr month name week_included = True month_included = True name_elements = [e for e in formatelements if e in name_formatvariables] if not ('a' in name_elements or 'A' in name_elements): week_included = False if not ('b' in name_elements or 'B' in name_elements): month_included = False for key in elements: mapping[key] = time.strftime('%' + key) if week_included: weekday = int(time.strftime('%w')) # weekday, sunday = 0 if 'a' in name_elements: mapping['a'] = weekdayname_msgid_abbr(weekday) if 'A' in name_elements: mapping['A'] = weekdayname_msgid(weekday) if month_included: monthday = int(time.strftime('%m')) # month, january = 1 if 'b' in name_elements: mapping['b'] = monthname_msgid_abbr(monthday) if 'B' in name_elements: mapping['B'] = monthname_msgid(monthday) # translate translateable elements # Note: Here, the normal `domain` is used for key in name_elements: mapping[key] = translate(mapping[key], domain, context=request, default=mapping[key], target_language=target_language) # translate the time string # XXX: here, we pass `formatstring_domain` instead of `domain` return translate(msgid, formatstring_domain, mapping, request, target_language=target_language)
def i18nl10n_ulocalized_time(time, long_format=None, time_only=None, context=None, domain='plonelocales', request=None): """This patched version change the behaviour and the meaning of long_format parameter. This trick is quite ugly, but is the only way to keep compatibility with basic use case of this method all around Plone code. The format must be given using the .po format, so not if for example you want to translate this: '%a %d %b %Y' you need to change it to: '${a} ${d} ${b} ${Y}' """ # get msgid if not long_format or (type(long_format)!=str and type(long_format)!=unicode): msgid = long_format and 'date_format_long' or 'date_format_short' if time_only is not None: msgid = 'time_format' else: msgid = long_format # NOTE: this requires the presence of three msgids inside the translation catalog # date_format_long, date_format_short, and time_format # These msgids are translated using interpolation. # The variables used here are the same as used in the strftime formating. # Supported are %A, %a, %B, %b, %H, %I, %m, %d, %M, %p, %S, %Y, %y, %Z, each used as # variable in the msgstr without the %. # For example: "${A} ${d}. ${B} ${Y}, ${H}:${M} ${Z}" # Each language dependend part is translated itself as well. # From http://docs.python.org/lib/module-time.html # # %a Locale's abbreviated weekday name. # %A Locale's full weekday name. # %b Locale's abbreviated month name. # %B Locale's full month name. # %d Day of the month as a decimal number [01,31]. # %H Hour (24-hour clock) as a decimal number [00,23]. # %I Hour (12-hour clock) as a decimal number [01,12]. # %m Month as a decimal number [01,12]. # %M Minute as a decimal number [00,59]. # %p Locale's equivalent of either AM or PM. # %S Second as a decimal number [00,61]. # %y Year without century as a decimal number [00,99]. # %Y Year with century as a decimal number. # %Z Time zone name (no characters if no time zone exists). mapping = {} # convert to DateTime instances. Either a date string or # a DateTime instance needs to be passed. if not IDateTime.providedBy(time): try: time = DateTime(time) except: log('Failed to convert %s to a DateTime object' % time, severity=logging.DEBUG) return None if context is None: # when without context, we cannot do very much. return time.ISO() if request is None: request = aq_acquire(context, 'REQUEST') # get the formatstring formatstring = translate(msgid, domain, mapping, request) if formatstring is None or formatstring.startswith('date_') or formatstring.startswith('time_'): # msg catalog was not able to translate this msgids # use default setting properties=getToolByName(context, 'portal_properties').site_properties if long_format: format=properties.localLongTimeFormat else: if time_only: format=properties.localTimeOnlyFormat else: format=properties.localTimeFormat return time.strftime(format) # get the format elements used in the formatstring formatelements = _interp_regex.findall(formatstring) # reformat the ${foo} to foo formatelements = [el[2:-1] for el in formatelements] # add used elements to mapping elements = [e for e in formatelements if e in datetime_formatvariables] # add weekday name, abbr. weekday name, month name, abbr month name week_included = True month_included = True name_elements = [e for e in formatelements if e in name_formatvariables] if not ('a' in name_elements or 'A' in name_elements): week_included = False if not ('b' in name_elements or 'B' in name_elements): month_included = False for key in elements: mapping[key]=time.strftime('%'+key) if week_included: weekday = int(time.strftime('%w')) # weekday, sunday = 0 if 'a' in name_elements: mapping['a']=weekdayname_msgid_abbr(weekday) if 'A' in name_elements: mapping['A']=weekdayname_msgid(weekday) if month_included: monthday = int(time.strftime('%m')) # month, january = 1 if 'b' in name_elements: mapping['b']=monthname_msgid_abbr(monthday) if 'B' in name_elements: mapping['B']=monthname_msgid(monthday) # translate translateable elements for key in name_elements: mapping[key] = translate(mapping[key], domain, context=request, default=mapping[key]) # translate the time string return translate(msgid, domain, mapping, request)
def ulocalized_time(time, formatstring, request, target_language=None): """time localization method copied from Products.CMFPlone.i18nl10n. The method was modified to allow for a custom formatstring in the normal python format. From http://docs.python.org/lib/module-time.html %a Locale's abbreviated weekday name. %A Locale's full weekday name. %b Locale's abbreviated month name. %B Locale's full month name. %d Day of the month as a decimal number [01,31]. %H Hour (24-hour clock) as a decimal number [00,23]. %I Hour (12-hour clock) as a decimal number [01,12]. %m Month as a decimal number [01,12]. %M Minute as a decimal number [00,59]. %p Locale's equivalent of either AM or PM. %S Second as a decimal number [00,61]. %y Year without century as a decimal number [00,99]. %Y Year with century as a decimal number. %Z Time zone name (no characters if no time zone exists). """ domain = 'plonelocales' # map to a message string, to make easier reuse of original # method and _interp_regex. formatstring = format_string_to_message_string(formatstring) mapping = {} # convert to DateTime instances. Either a date string or # a DateTime instance needs to be passed. if not IDateTime.providedBy(time): try: time = DateTime(time) except Exception: log('Failed to convert %s to a DateTime object' % time, severity=logging.DEBUG) return None # get the format elements used in the formatstring formatelements = _interp_regex.findall(formatstring) # reformat the ${foo} to foo formatelements = [el[2:-1] for el in formatelements] # add used elements to mapping elements = [e for e in formatelements if e in datetime_formatvariables] # add weekday name, abbr. weekday name, month name, abbr month name week_included = True month_included = True name_elements = [e for e in formatelements if e in name_formatvariables] if not ('a' in name_elements or 'A' in name_elements): week_included = False if not ('b' in name_elements or 'B' in name_elements): month_included = False for key in elements: mapping[key] = time.strftime('%' + key) if week_included: weekday = int(time.strftime('%w')) # weekday, sunday = 0 if 'a' in name_elements: mapping['a'] = weekdayname_msgid_abbr(weekday) if 'A' in name_elements: mapping['A'] = weekdayname_msgid(weekday) if month_included: monthday = int(time.strftime('%m')) # month, january = 1 if 'b' in name_elements: mapping['b'] = monthname_msgid_abbr(monthday) if 'B' in name_elements: mapping['B'] = monthname_msgid(monthday) # translate translateable elements for key in name_elements: mapping[key] = translate(mapping[key], domain, context=request, default=mapping[key], target_language=target_language) # translate the time string return formatstring.replace("${", "{").format(**mapping)