diff options
-rw-r--r-- | BRANCH-TODO.txt | 8 | ||||
-rw-r--r-- | src/zope/i18n/interfaces/locales.py | 79 | ||||
-rw-r--r-- | src/zope/i18n/locales/__init__.py | 21 | ||||
-rw-r--r-- | src/zope/i18n/locales/xmlfactory.py | 154 |
4 files changed, 226 insertions, 36 deletions
diff --git a/BRANCH-TODO.txt b/BRANCH-TODO.txt index 967923e..7704814 100644 --- a/BRANCH-TODO.txt +++ b/BRANCH-TODO.txt @@ -15,12 +15,10 @@ maintain full backward compatibility with earlier locale interfaces. CLDR 1.1 (LDML 1.1) ------------------- -Updated the XML files and fixed incompatibilities. +- Updated the XML files and fixed incompatibilities. +- Added support day and month contexts and widths. -Still need to add interface/implementation for day/month context -and day/month width system. - -Review other non-critical changes and implement them. +Still need to review other not so critical changes and implement them. CLDR 1.2 (LDML 1.2) ------------------- diff --git a/src/zope/i18n/interfaces/locales.py b/src/zope/i18n/interfaces/locales.py index bafcfe5..a4505b7 100644 --- a/src/zope/i18n/interfaces/locales.py +++ b/src/zope/i18n/interfaces/locales.py @@ -247,6 +247,59 @@ class ILocaleFormatLength(Interface): readonly = True) +class ILocaleMonthContext(Interface): + """Specifices a usage context for month names""" + + type = TextLine( + title=u'Month context type', + description=u"Name of the month context, format or stand-alone.") + + defaultWidth = TextLine( + title=u'Default month name width', + default=u'wide') + + months = Dict( + title=u'Month Names', + description=u'A mapping of month name widths to a mapping of' + u'corresponding month names.', + key_type=Choice( + title=u'Width type', + values=(u'wide', u'abbreviated', u'narrow')), + value_type=Dict( + title=u'Month name', + key_type=Int(title=u'Type', min=1, max=12), + value_type=TextLine(title=u'Month Name')) + ) + + +class ILocaleDayContext(Interface): + """Specifices a usage context for days names""" + + type = TextLine( + title=u'Day context type', + description=u"Name of the day context, format or stand-alone.") + + defaultWidth = TextLine( + title=u'Default day name width', + default=u'wide') + + days = Dict( + title=u'Day Names', + description=u'A mapping of day name widths to a mapping of' + u'corresponding day names.', + key_type=Choice( + title=u'Width type', + values=(u'wide', u'abbreviated', u'narrow')), + value_type=Dict( + title=u'Day name', + key_type=Choice( + title=u"Type", + values=(u'sun', u'mon', u'tue', u'wed', + u'thu', u'fri', u'sat')), + value_type=TextLine(title=u'Day Name')) + ) + + class ILocaleCalendar(Interface): """There is a massive amount of information contained in the calendar, which made it attractive to be added.""" @@ -255,6 +308,19 @@ class ILocaleCalendar(Interface): title=u"Calendar Type", description=u"Name of the calendar, for example 'gregorian'.") + defaultMonthContext = TextLine( + title=u'Default month context', + default=u'format') + + monthContexts = Dict( + title=u'Month Contexts', + description=u'A mapping of month context types to ' + u'ILocaleMonthContext objects', + key_type=Choice(title=u'Type', + values=(u'format', u'stand-alone')), + value_type=Field(title=u'ILocaleMonthContext object')) + + # BBB: leftover from CLDR 1.0 months = Dict( title = u"Month Names", description = u"A mapping of all month names and abbreviations", @@ -262,6 +328,19 @@ class ILocaleCalendar(Interface): value_type = Tuple(title=u"Month Name and Abbreviation", min_length=2, max_length=2)) + defaultDayContext = TextLine( + title=u'Default day context', + default=u'format') + + dayContexts = Dict( + title=u'Day Contexts', + description=u'A mapping of day context types to ' + u'ILocaleDayContext objects', + key_type=Choice(title=u'Type', + values=(u'format', u'stand-alone')), + value_type=Field(title=u'ILocaleDayContext object')) + + # BBB: leftover from CLDR 1.0 days = Dict( title=u"Weekdays Names", description = u"A mapping of all month names and abbreviations", diff --git a/src/zope/i18n/locales/__init__.py b/src/zope/i18n/locales/__init__.py index d7ea842..907424d 100644 --- a/src/zope/i18n/locales/__init__.py +++ b/src/zope/i18n/locales/__init__.py @@ -29,6 +29,7 @@ from zope.i18n.interfaces.locales import ILocaleTimeZone, ILocaleCalendar from zope.i18n.interfaces.locales import ILocaleCurrency, ILocaleNumbers from zope.i18n.interfaces.locales import ILocaleFormat, ILocaleFormatLength from zope.i18n.interfaces.locales import ILocaleOrientation +from zope.i18n.interfaces.locales import ILocaleDayContext, ILocaleMonthContext from zope.i18n.format import NumberFormat, DateTimeFormat from zope.i18n.locales.inheritance import \ AttributeInheritance, InheritingDictionary, NoParentException @@ -234,6 +235,26 @@ class LocaleFormatLength(AttributeInheritance): self.default = None +class LocaleMonthContext(AttributeInheritance): + + implements(ILocaleMonthContext) + + def __init__(self, type=None): + """Initialize the object.""" + self.type = type + self.default = u'wide' + + +class LocaleDayContext(AttributeInheritance): + + implements(ILocaleDayContext) + + def __init__(self, type=None): + """Initialize the object.""" + self.type = type + self.default = u'wide' + + class LocaleCalendar(AttributeInheritance): """Represents locale data for a calendar, like 'gregorian'. diff --git a/src/zope/i18n/locales/xmlfactory.py b/src/zope/i18n/locales/xmlfactory.py index 53d44d6..8b16930 100644 --- a/src/zope/i18n/locales/xmlfactory.py +++ b/src/zope/i18n/locales/xmlfactory.py @@ -21,7 +21,8 @@ from zope.i18n.locales import Locale, LocaleDisplayNames, LocaleDates from zope.i18n.locales import LocaleVersion, LocaleIdentity, LocaleTimeZone from zope.i18n.locales import LocaleCalendar, LocaleCurrency, LocaleNumbers from zope.i18n.locales import LocaleFormat, LocaleFormatLength, dayMapping -from zope.i18n.locales import LocaleOrientation +from zope.i18n.locales import LocaleOrientation, LocaleDayContext +from zope.i18n.locales import LocaleMonthContext from zope.i18n.locales.inheritance import InheritingDictionary class LocaleFactory(object): @@ -298,7 +299,9 @@ class LocaleFactory(object): >>> from xml.dom.minidom import parseString >>> xml = u''' ... <months> + ... <default type="format" /> ... <monthContext type="format"> + ... <default type="wide" /> ... <monthWidth type="wide"> ... <month type="1">Januar</month> ... <month type="2">Februar</month> @@ -332,6 +335,30 @@ class LocaleFactory(object): >>> dom = parseString(xml) >>> factory._extractMonths(dom.documentElement, calendar) + The contexts and widths were introduced in CLDR 1.1, the way + of getting month names is like this:: + + >>> calendar.defaultMonthContext + u'format' + + >>> ctx = calendar.monthContexts[u'format'] + >>> ctx.defaultWidth + u'wide' + + >>> names = [ctx.months[u'wide'][type] for type in xrange(1,13)] + >>> names[:7] + [u'Januar', u'Februar', u'Maerz', u'April', u'Mai', u'Juni', u'Juli'] + >>> names[7:] + [u'August', u'September', u'Oktober', u'November', u'Dezember'] + + >>> abbrs = [ctx.months[u'abbreviated'][type] for type in xrange(1,13)] + >>> abbrs[:6] + [u'Jan', u'Feb', u'Mrz', u'Apr', u'Mai', u'Jun'] + >>> abbrs[6:] + [u'Jul', u'Aug', u'Sep', u'Okt', u'Nov', u'Dez'] + + The old, CLDR 1.0 way of getting month names and abbreviations:: + >>> names = [calendar.months.get(type, (None, None))[0] ... for type in range(1, 13)] >>> names[:7] @@ -345,25 +372,46 @@ class LocaleFactory(object): [u'Jan', u'Feb', u'Mrz', u'Apr', u'Mai', u'Jun'] >>> abbrs[6:] [u'Jul', u'Aug', u'Sep', u'Okt', u'Nov', u'Dez'] + + """ + + defaultMonthContext_node = months_node.getElementsByTagName('default') + if defaultMonthContext_node: + calendar.defaultMonthContext = defaultMonthContext_node[0].getAttribute('type') + monthContext_nodes = months_node.getElementsByTagName('monthContext') if not monthContext_nodes: return - format_node = None - for node in monthContext_nodes: - if node.getAttribute('type') == 'format': - format_node = node - break - if not format_node: - return - names_node = abbrs_node = None - for node in format_node.getElementsByTagName('monthWidth'): - type = node.getAttribute('type') - if type == 'abbreviated': - abbrs_node = node - elif type == 'wide': - names_node = node + calendar.monthContexts = InheritingDictionary() + names_node = abbrs_node = None # BBB + + for node in monthContext_nodes: + context_type = node.getAttribute('type') + mctx = LocaleMonthContext(context_type) + calendar.monthContexts[context_type] = mctx + + defaultWidth_node = node.getElementsByTagName('default') + if defaultWidth_node: + mctx.defaultWidth = defaultWidth_node[0].getAttribute('type') + + widths = InheritingDictionary() + mctx.months = widths + for width_node in node.getElementsByTagName('monthWidth'): + width_type = width_node.getAttribute('type') + width = InheritingDictionary() + widths[width_type] = width + + for month_node in width_node.getElementsByTagName('month'): + mtype = int(month_node.getAttribute('type')) + width[mtype] = self._getText(month_node.childNodes) + + if context_type == 'format': + if width_type == 'abbreviated': + abbrs_node = width_node + elif width_type == 'wide': + names_node = width_node if not (names_node and abbrs_node): return @@ -400,7 +448,9 @@ class LocaleFactory(object): >>> from xml.dom.minidom import parseString >>> xml = u''' ... <days> + ... <default type="format" /> ... <dayContext type="format"> + ... <default type="wide" /> ... <dayWidth type="wide"> ... <day type="sun">Sonntag</day> ... <day type="mon">Montag</day> @@ -424,37 +474,79 @@ class LocaleFactory(object): >>> dom = parseString(xml) >>> factory._extractDays(dom.documentElement, calendar) + Day contexts and widths were introduced in CLDR 1.1, here's + how to use them:: + + >>> calendar.defaultDayContext + u'format' + + >>> ctx = calendar.dayContexts[u'format'] + >>> ctx.defaultWidth + u'wide' + + >>> names = [ctx.days[u'wide'][type] for type in xrange(1,8)] + >>> names[:4] + [u'Montag', u'Dienstag', u'Mittwoch', u'Donnerstag'] + >>> names[4:] + [u'Freitag', u'Samstag', u'Sonntag'] + + >>> abbrs = [ctx.days[u'abbreviated'][type] for type in xrange(1,8)] + >>> abbrs + [u'Mo', u'Di', u'Mi', u'Do', u'Fr', u'Sa', u'So'] + + And here's the old CLDR 1.0 way of getting day names and + abbreviations:: + >>> names = [calendar.days.get(type, (None, None))[0] - ... for type in range(1, 8)] + ... for type in xrange(1, 8)] >>> names[:4] [u'Montag', u'Dienstag', u'Mittwoch', u'Donnerstag'] >>> names[4:] [u'Freitag', u'Samstag', u'Sonntag'] >>> abbrs = [calendar.days.get(type, (None, None))[1] - ... for type in range(1, 8)] + ... for type in xrange(1, 8)] >>> abbrs [u'Mo', u'Di', u'Mi', u'Do', u'Fr', u'Sa', u'So'] """ + + defaultDayContext_node = days_node.getElementsByTagName('default') + if defaultDayContext_node: + calendar.defaultDayContext = defaultDayContext_node[0].getAttribute('type') + dayContext_nodes = days_node.getElementsByTagName('dayContext') if not dayContext_nodes: return - format_node = None - for node in dayContext_nodes: - if node.getAttribute('type') == 'format': - format_node = node - break - if not format_node: - return - names_node = abbrs_node = None - for node in format_node.getElementsByTagName('dayWidth'): - type = node.getAttribute('type') - if type == 'abbreviated': - abbrs_node = node - elif type == 'wide': - names_node = node + calendar.dayContexts = InheritingDictionary() + names_node = abbrs_node = None # BBB + for node in dayContext_nodes: + context_type = node.getAttribute('type') + dctx = LocaleDayContext(context_type) + calendar.dayContexts[context_type] = dctx + + defaultWidth_node = node.getElementsByTagName('default') + if defaultWidth_node: + dctx.defaultWidth = defaultWidth_node[0].getAttribute('type') + + widths = InheritingDictionary() + dctx.days = widths + for width_node in node.getElementsByTagName('dayWidth'): + width_type = width_node.getAttribute('type') + width = InheritingDictionary() + widths[width_type] = width + + for day_node in width_node.getElementsByTagName('day'): + dtype = dayMapping[day_node.getAttribute('type')] + width[dtype] = self._getText(day_node.childNodes) + + if context_type == 'format': + if width_type == 'abbreviated': + abbrs_node = width_node + elif width_type == 'wide': + names_node = width_node + if not (names_node and abbrs_node): return |