[Zope3-checkins] CVS: Zope3/src/zope/i18n/locales - README.txt:1.1 __init__.py:1.1 inheritance.py:1.1 provider.py:1.1 xmlfactory.py:1.1 af.xml:NONE af_ZA.xml:NONE am.xml:NONE am_ET.xml:NONE ar.xml:NONE ar_AE.xml:NONE ar_BH.xml:NONE ar_DZ.xml:NONE ar_EG.xml:NONE ar_IN.xml:NONE ar_IQ.xml:NONE ar_JO.xml:NONE ar_KW.xml:NONE ar_LB.xml:NONE ar_LY.xml:NONE ar_MA.xml:NONE ar_OM.xml:NONE ar_QA.xml:NONE ar_SA.xml:NONE ar_SD.xml:NONE ar_SY.xml:NONE ar_TN.xml:NONE ar_YE.xml:NONE az.xml:NONE az_AZ.xml:NONE be.xml:NONE be_BY.xml:NONE bg.xml:NONE bg_BG.xml:NONE bn.xml:NONE bn_IN.xml:NONE ca.xml:NONE ca_ES.xml:NONE ca_ES_PREEURO.xml:NONE cs.xml:NONE cs_CZ.xml:NONE da.xml:NONE da_DK.xml:NONE de.xml:NONE de_AT.xml:NONE de_AT_PREEURO.xml:NONE de_BE.xml:NONE de_CH.xml:NONE de_DE.xml:NONE de_DE_PREEURO.xml:NONE de_LI.xml:NONE de_LU.xml:NONE de_LU_PREEURO.xml:NONE de__PHONEBOOK.xml:NONE div.xml:NONE div_MV.xml:NONE el.xml:NONE el_GR.xml:NONE el_GR_PREEURO.xml:NONE en.xml:NONE en_AS.xml:NONE en_AU.xml:NON! E en_BE.xml:NONE en_BE_PREEURO.xml:NONE en_BW.xml:NONE en_BZ.xml:NONE en_CA.xml:NONE en_GB.xml:NONE en_GB_EURO.xml:NONE en_GU.xml:NONE en_HK.xml:NONE en_IE.xml:NONE en_IE_PREEURO.xml:NONE en_IN.xml:NONE en_JM.xml:NONE en_MH.xml:NONE en_MP.xml:NONE en_MT.xml:NONE en_NZ.xml:NONE en_PH.xml:NONE en_SG.xml:NONE en_TT.xml:NONE en_UM.xml:NONE en_US.xml:NONE en_US_POSIX.xml:NONE en_VI.xml:NONE en_ZA.xml:NONE en_ZW.xml:NONE eo.xml:NONE es.xml:NONE es_AR.xml:NONE es_BO.xml:NONE es_CL.xml:NONE es_CO.xml:NONE es_CR.xml:NONE es_DO.xml:NONE es_EC.xml:NONE es_ES.xml:NONE es_ES_PREEURO.xml:NONE es_GT.xml:NONE es_HN.xml:NONE es_MX.xml:NONE es_NI.xml:NONE es_PA.xml:NONE es_PE.xml:NONE es_PR.xml:NONE es_PY.xml:NONE es_SV.xml:NONE es_US.xml:NONE es_UY.xml:NONE es_VE.xml:NONE es__TRADITIONAL.xml:NONE et.xml:NONE et_EE.xml:NONE eu.xml:NONE eu_ES.xml:NONE eu_ES_PREEURO.xml:NONE fa.xml:NONE fa_IN.xml:NONE fa_IR.xml:NONE fi.xml:NONE fi_FI.xml:NONE fi_FI_PREEURO.xml:NONE fo.xml:NONE fo_FO.xml:NONE f! r.xml:NONE fr_BE.xml:NONE fr_BE_PREEURO.xml:NONE fr_CA.xml:NON! E fr_CH

Stephan Richter srichter at cosmos.phy.tufts.edu
Thu Feb 5 17:52:32 EST 2004


Update of /cvs-repository/Zope3/src/zope/i18n/locales
In directory cvs.zope.org:/tmp/cvs-serv7674/src/zope/i18n/locales

Added Files:
	README.txt __init__.py inheritance.py provider.py 
	xmlfactory.py 
Removed Files:
	af.xml af_ZA.xml am.xml am_ET.xml ar.xml ar_AE.xml ar_BH.xml 
	ar_DZ.xml ar_EG.xml ar_IN.xml ar_IQ.xml ar_JO.xml ar_KW.xml 
	ar_LB.xml ar_LY.xml ar_MA.xml ar_OM.xml ar_QA.xml ar_SA.xml 
	ar_SD.xml ar_SY.xml ar_TN.xml ar_YE.xml az.xml az_AZ.xml 
	be.xml be_BY.xml bg.xml bg_BG.xml bn.xml bn_IN.xml ca.xml 
	ca_ES.xml ca_ES_PREEURO.xml cs.xml cs_CZ.xml da.xml da_DK.xml 
	de.xml de_AT.xml de_AT_PREEURO.xml de_BE.xml de_CH.xml 
	de_DE.xml de_DE_PREEURO.xml de_LI.xml de_LU.xml 
	de_LU_PREEURO.xml de__PHONEBOOK.xml div.xml div_MV.xml el.xml 
	el_GR.xml el_GR_PREEURO.xml en.xml en_AS.xml en_AU.xml 
	en_BE.xml en_BE_PREEURO.xml en_BW.xml en_BZ.xml en_CA.xml 
	en_GB.xml en_GB_EURO.xml en_GU.xml en_HK.xml en_IE.xml 
	en_IE_PREEURO.xml en_IN.xml en_JM.xml en_MH.xml en_MP.xml 
	en_MT.xml en_NZ.xml en_PH.xml en_SG.xml en_TT.xml en_UM.xml 
	en_US.xml en_US_POSIX.xml en_VI.xml en_ZA.xml en_ZW.xml eo.xml 
	es.xml es_AR.xml es_BO.xml es_CL.xml es_CO.xml es_CR.xml 
	es_DO.xml es_EC.xml es_ES.xml es_ES_PREEURO.xml es_GT.xml 
	es_HN.xml es_MX.xml es_NI.xml es_PA.xml es_PE.xml es_PR.xml 
	es_PY.xml es_SV.xml es_US.xml es_UY.xml es_VE.xml 
	es__TRADITIONAL.xml et.xml et_EE.xml eu.xml eu_ES.xml 
	eu_ES_PREEURO.xml fa.xml fa_IN.xml fa_IR.xml fi.xml fi_FI.xml 
	fi_FI_PREEURO.xml fo.xml fo_FO.xml fr.xml fr_BE.xml 
	fr_BE_PREEURO.xml fr_CA.xml fr_CH.xml fr_FR.xml 
	fr_FR_PREEURO.xml fr_LU.xml fr_LU_PREEURO.xml fr_MC.xml ga.xml 
	ga_IE.xml ga_IE_PREEURO.xml gl.xml gl_ES.xml gl_ES_PREEURO.xml 
	gu.xml gu_IN.xml gv.xml gv_GB.xml he.xml he_IL.xml hi.xml 
	hi_IN.xml hi__DIRECT.xml hr.xml hr_HR.xml hu.xml hu_HU.xml 
	hy.xml hy_AM.xml hy_AM_REVISED.xml id.xml id_ID.xml index.xml 
	is.xml is_IS.xml it.xml it_CH.xml it_IT.xml it_IT_PREEURO.xml 
	iw.xml iw_IL.xml ja.xml ja_JP.xml ka.xml ka_GE.xml kk.xml 
	kk_KZ.xml kl.xml kl_GL.xml kn.xml kn_IN.xml ko.xml ko_KR.xml 
	kok.xml kok_IN.xml kw.xml kw_GB.xml ky.xml ky_KG.xml 
	license.html lt.xml lt_LT.xml lv.xml lv_LV.xml mk.xml 
	mk_MK.xml mn.xml mn_MN.xml mr.xml mr_IN.xml ms.xml ms_BN.xml 
	ms_MY.xml mt.xml mt_MT.xml nb.xml nb_NO.xml nl.xml nl_BE.xml 
	nl_BE_PREEURO.xml nl_NL.xml nl_NL_PREEURO.xml nn.xml nn_NO.xml 
	no.xml no_NO.xml no_NO_NY.xml om.xml om_ET.xml om_KE.xml 
	pa.xml pa_IN.xml pl.xml pl_PL.xml pt.xml pt_BR.xml pt_PT.xml 
	pt_PT_PREEURO.xml ro.xml ro_RO.xml root.xml ru.xml ru_RU.xml 
	ru_UA.xml sa.xml sa_IN.xml sh.xml sh_YU.xml sk.xml sk_SK.xml 
	sl.xml sl_SI.xml so.xml so_DJ.xml so_ET.xml so_KE.xml 
	so_SO.xml sq.xml sq_AL.xml sr.xml sr_YU.xml sv.xml sv_FI.xml 
	sv_SE.xml sw.xml sw_KE.xml sw_TZ.xml syr.xml syr_SY.xml ta.xml 
	ta_IN.xml te.xml te_IN.xml th.xml th_TH.xml ti.xml ti_ER.xml 
	ti_ET.xml tr.xml tr_TR.xml tt.xml tt_RU.xml uk.xml uk_UA.xml 
	ur.xml ur_PK.xml uz.xml uz_UZ.xml vi.xml vi_VN.xml zh.xml 
	zh_CN.xml zh_HK.xml zh_MO.xml zh_SG.xml zh_TW.xml 
	zh_TW_STROKE.xml zh__PINYIN.xml 
Log Message:
ICU joined openi18n.org and developed a locale data XML standard called 
LDML. A result of this was that all locale files were changed to this new 
format. To stay up-to-date with the latest data, I converted the locale
parser to read the new format. While I was at it, I also changed the Locale
data structure a bit, since I wanted to keep the objects similar to the 
XML. Furthermore, the first time around I did not implement the inheritance
of object attributes and dictionaries correctly (I just faked it for the 
API calls), so I think I got it right this time. Finally I updated views 
and tests that relied on the old Locale API. Be aware that you might need
to change some of your product code as well. 


=== Added File Zope3/src/zope/i18n/locales/README.txt ===
Locales XML Files

  The XML locale files were produced as part of the ICU I18n and L10n
  framework. They are provided here under the original ICU License - ICU 1.8.1
  and later license. 


  ICU Web site

    http://oss.software.ibm.com/icu/


  Locale Data Markup Language

    The XML files follow the now public and completed LDML format. 

    The DTD can be found at

      http://www.openi18n.org/spec/ldml/1.0/ldml-spec.htm

    The specification is at

      http://www.openi18n.org/spec/ldml/1.0/ldml.dtd

  
  Download

    ::

      $ cvs -d :pserver:anoncvs at oss.software.ibm.com:/usr/cvs/icu login
      Password: anoncvs
      $ cvs -d :pserver:anoncvs at oss.software.ibm.com:/usr/cvs/icu co \
        -d new_locales locale/common/main -d data


=== Added File Zope3/src/zope/i18n/locales/__init__.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Locale and LocaleProvider Implementation.

$Id: __init__.py,v 1.1 2004/02/05 22:52:23 srichter Exp $
"""
import os
from datetime import datetime, date
from time import strptime

from zope.interface import implements
from zope.i18n.interfaces.locales import ILocale
from zope.i18n.interfaces.locales import ILocaleDisplayNames, ILocaleDates
from zope.i18n.interfaces.locales import ILocaleVersion, ILocaleIdentity
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.format import NumberFormat, DateTimeFormat
from zope.i18n.locales.inheritance import \
     AttributeInheritance, InheritingDictionary, NoParentException
from zope.i18n.locales.provider import LocaleProvider, LoadLocaleError

# Setup the locale directory
from zope import i18n
LOCALEDIR = os.path.join(os.path.dirname(i18n.__file__), "locales", "data")

# Global LocaleProvider. We really just need this single one.
locales = LocaleProvider(LOCALEDIR)

# Define some constants that can be used

JANUARY = 1
FEBRUARY = 2
MARCH = 3
APRIL = 4
MAY = 5
JUNE = 6
JULY = 7
AUGUST = 8
SEPTEMBER = 9
OCTOBER = 10
NOVEMBER = 11
DECEMBER = 12

MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7

dayMapping = {'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4,
              'fri': 5, 'sat': 6, 'sun': 7}

BC = 1
AD = 2

class LocaleIdentity(object):
    """Represents a unique identification of the locale

    This class does not have to deal with inheritance.

    Examples::
    
      >>> id = LocaleIdentity('en')
      >>> id
      <LocaleIdentity (en, None, None, None)>

      >>> id = LocaleIdentity('en', 'latin')
      >>> id
      <LocaleIdentity (en, latin, None, None)>

      >>> id = LocaleIdentity('en', 'latin', 'US')
      >>> id
      <LocaleIdentity (en, latin, US, None)>

      >>> id = LocaleIdentity('en', 'latin', 'US', 'POSIX')
      >>> id
      <LocaleIdentity (en, latin, US, POSIX)>

      >>> id = LocaleIdentity('en', None, 'US', 'POSIX')
      >>> id
      <LocaleIdentity (en, None, US, POSIX)>
    """
    implements(ILocaleIdentity)

    def __init__(self, language=None, script=None, territory=None, variant=None):
        """Initialize object."""
        self.language = language
        self.script = script
        self.territory = territory
        self.variant = variant
        self.version = None

    def __repr__(self):
        """See zope.i18n.interfaces.ILocaleIdentity
        """
        return "<LocaleIdentity (%s, %s, %s, %s)>" %(
            self.language, self.script, self.territory, self.variant)


class LocaleVersion(object):
    """Represents a particular version of a locale

    This class does not have to deal with inheritance.

    Examples::

      >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
      ...     LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes again'))
      0

      >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
      ...     LocaleVersion('1.0', datetime(2004, 1, 2), 'no notes again'))
      -1

      >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
      ...     LocaleVersion('0.9', datetime(2004, 1, 2), 'no notes again'))
      -1

      >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
      ...     LocaleVersion('0.9', datetime(2004, 1, 1), 'no notes again'))
      1

    """
    implements(ILocaleVersion)

    def __init__(self, number, generationDate, notes):
        """Initialize object."""
        self.number = number
        assert(isinstance(generationDate, (date, type(None))))
        self.generationDate = generationDate
        self.notes = notes

    def __cmp__(self, other):
        "See zope.i18n.interfaces.ILocaleVersion"
        return cmp((self.generationDate, self.number),
                   (other.generationDate, other.number))


class LocaleDisplayNames(AttributeInheritance):
    """Locale display names with inheritable data.

    Examples::

      >>> from zope.i18n.locales.tests.test_docstrings import \\
      ...     LocaleInheritanceStub
      >>> root = LocaleInheritanceStub()
      >>> root.displayNames = LocaleDisplayNames()
      >>> root.displayNames.languages = ['en', 'de']
      >>> root.displayNames.keys = ['foo', 'bar']

      >>> locale = LocaleInheritanceStub(nextLocale=root)
      >>> locale.displayNames = LocaleDisplayNames()
      >>> locale.displayNames.keys = ['fu', 'bahr']

      Here you can see the inheritance in action 

      >>> locale.displayNames.languages
      ['en', 'de']
      >>> locale.displayNames.keys
      ['fu', 'bahr']
    """

    implements(ILocaleDisplayNames)

    def __init__(self):
        """Initialize object."""
        self.languages = None
        self.scripts = None
        self.territories = None
        self.keys = None
        self.types = None


class LocaleTimeZone(object):
    """Specifies one of the timezones of a specific locale.

    The attributes of this class are not inherited, since all timezone
    information is always provided together.

    Example::

      >>> tz = LocaleTimeZone('Europe/Berlin')
      >>> tz.cities = ['Berlin']
      >>> tz.names = {'standard': ('Mitteleuropaeische Zeit', 'MEZ'),
      ...             'daylight': ('Mitteleuropaeische Sommerzeit', 'MESZ')}

      >>> tz.type
      'Europe/Berlin'
      >>> tz.cities
      ['Berlin']
    """
    

    implements(ILocaleTimeZone)

    def __init__(self, type):
        """Initialize the object."""
        self.type = type
        self.cities = []
        self.names = {}


class LocaleFormat(object):
    """Specifies one of the format of a specific format length.

    The attributes of this class are not inherited, since all format
    information is always provided together. Note that this information by
    itself is often not useful, since other calendar data is required to use
    the specified pattern for formatting and parsing.
    """
    
    implements(ILocaleFormat)

    def __init__(self, type=None):
        """Initialize the object."""
        self.type = type
        self.displayName = u''
        self.pattern = u''

class LocaleFormatLength(AttributeInheritance):
    """Specifies one of the format lengths of a specific quantity, like
    numbers, dates, times and datetimes."""
    
    implements(ILocaleFormatLength)

    def __init__(self, type=None):
        """Initialize the object."""
        self.type = type
        self.default = None
        self.formats = None


class LocaleCalendar(AttributeInheritance):
    """Represents locale data for a calendar, like 'gregorian'.

    This object is particular tricky, since the calendar not only inherits
    from higher-up locales, but also from the specified gregorian calendar
    available for this locale. This was done, since most other calendars have
    different year and era data, but everything else remains the same.

    Example::

      Even though the 'Locale' object has no 'calendar' attribute for real, it
      helps us here to make the example simpler. 

      >>> from zope.i18n.locales.tests.test_docstrings import \\
      ...     LocaleInheritanceStub
      >>> root = LocaleInheritanceStub()
      >>> root.calendar = LocaleCalendar('gregorian')
      >>> locale = LocaleInheritanceStub(nextLocale=root)
      >>> locale.calendar = LocaleCalendar('gregorian')

      >>> root.calendar.months = InheritingDictionary(
      ...     {1: (u'January', u'Jan'), 2: (u'February', u'Feb')})
      >>> locale.calendar.months = InheritingDictionary(
      ...     {2: (u'Februar', u'Feb'), 3: (u'Maerz', u'Mrz')})
      >>> locale.calendar.getMonthNames()[:4]
      [u'January', u'Februar', u'Maerz', None]
      >>> locale.calendar.getMonthTypeFromName(u'January')
      1
      >>> locale.calendar.getMonthTypeFromName(u'Februar')
      2
      >>> locale.calendar.getMonthAbbreviations()[:4]
      [u'Jan', u'Feb', u'Mrz', None]
      >>> locale.calendar.getMonthTypeFromAbbreviation(u'Jan')
      1
      >>> locale.calendar.getMonthTypeFromAbbreviation(u'Mrz')
      3

      >>> root.calendar.days = InheritingDictionary(
      ...     {1: (u'Monday', u'Mon'), 2: (u'Tuesday', u'Tue')})
      >>> locale.calendar.days = InheritingDictionary(
      ...     {2: (u'Dienstag', u'Die'), 3: (u'Mittwoch', u'Mit')})
      >>> locale.calendar.getDayNames()[:4]
      [u'Monday', u'Dienstag', u'Mittwoch', None]
      >>> locale.calendar.getDayTypeFromName(u'Monday')
      1
      >>> locale.calendar.getDayTypeFromName(u'Dienstag')
      2
      >>> locale.calendar.getDayAbbreviations()[:4]
      [u'Mon', u'Die', u'Mit', None]
      >>> locale.calendar.getDayTypeFromAbbreviation(u'Mon')
      1
      >>> locale.calendar.getDayTypeFromAbbreviation(u'Die')
      2

      Let's test the direct attribute access as well.

      >>> root.am = u'AM'
      >>> root.pm = u'PM'
      >>> locale.am = None
      >>> locale.pm = u'nachm.'
      >>> locale.pm
      u'nachm.'
      >>> locale.am
      u'AM'
    """

    implements(ILocaleCalendar)
    
    def __init__(self, type):
        """Initialize the object."""
        self.type = type
        # See zope.i18n.interfaces.ILocaleCalendar
        # I am initializing all attributes with None, so that the inheriting
        # mechanism can get the entire dictionary from the higher-up locale,
        # instead of searching for each key from the beginning.
        self.months = None
        self.days = None
        self.week = None
        self.am = None
        self.pm = None
        self.eras = None

        self.defaultDateFormat = None
        self.dateFormats = None

        self.defaultTimeFormat = None
        self.timeFormats = None

        self.defaultDateTimeFormat = None
        self.dateTimeFormats = None

    def getMonthNames(self):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        return [self.months.get(type, (None, None))[0] for type in range(1, 13)]

    def getMonthTypeFromName(self, name):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        for item in self.months.items():
            if item[1][0] == name:
                return item[0]

    def getMonthAbbreviations(self):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        return [self.months.get(type, (None, None))[1] for type in range(1, 13)]

    def getMonthTypeFromAbbreviation(self, abbr):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        for item in self.months.items():
            if item[1][1] == abbr:
                return item[0]

    def getDayNames(self):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        return [self.days.get(type, (None, None))[0] for type in range(1, 8)]

    def getDayTypeFromName(self, name):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        for item in self.days.items():
            if item[1][0] == name:
                return item[0]

    def getDayAbbreviations(self):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        return [self.days.get(type, (None, None))[1] for type in range(1, 8)]

    def getDayTypeFromAbbreviation(self, abbr):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        for item in self.days.items():
            if item[1][1] == abbr:
                return item[0]

    def isWeekend(self, datetime):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        day = datetime.weekday()
        time = datetime.time()
        # XXX: todo
        return False

    def getFirstWeekDayName(self):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        return self.days[dayMapping[self.week['firstDay']]][0]
        

class LocaleDates(AttributeInheritance):
    """Simple ILocaleDates implementation that can inherit data from other
    locales.

    Examples::

      >>> from zope.i18n.tests.test_formats import LocaleCalendarStub as Stub
      >>> from datetime import datetime, date, time
      >>> dates = LocaleDates()
      >>> cal = LocaleCalendar('gregorian')
      >>> cal.months = Stub.months
      >>> cal.days = Stub.days
      >>> cal.am = Stub.am
      >>> cal.pm = Stub.pm
      >>> cal.eras = Stub.eras
      >>> dates.calendars = {'gregorian': cal}

      Setting up and accessing date format through a specific length
      (very common scenario)

      >>> fulllength = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u'EEEE, d. MMMM yyyy'
      >>> fulllength.formats = {None: format}

      >>> mediumlength = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u'dd.MM.yyyy'
      >>> mediumlength.formats = {None: format}

      >>> cal.dateFormats = {'full': fulllength, 'medium': mediumlength}
      >>> cal.defaultDateFormat = 'medium'

      >>> formatter = dates.getFormatter('date')
      >>> formatter.format(date(2004, 02, 04))
      u'04.02.2004'

      >>> formatter = dates.getFormatter('date', length='full')
      >>> formatter.format(date(2004, 02, 04))
      u'Mittwoch, 4. Februar 2004'

      Let's also test the time formatter

      >>> fulllength = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u"H:mm' Uhr 'z"
      >>> fulllength.formats = {None: format}

      >>> mediumlength = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u'HH:mm:ss'
      >>> mediumlength.formats = {None: format}

      >>> cal.timeFormats = {'full': fulllength, 'medium': mediumlength}
      >>> cal.defaultTimeFormat = 'medium'

      >>> formatter = dates.getFormatter('time')
      >>> formatter.format(time(12, 15, 00))
      u'12:15:00'

      >>> formatter = dates.getFormatter('time', length='full')
      >>> formatter.format(time(12, 15, 00))
      u'12:15 Uhr +000'

      The datetime formatter is a bit special, since it is constructed from
      the other two:

      >>> length = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u'{1} {0}'
      >>> length.formats = {None: format}
      >>> cal.dateTimeFormats = {None: length}

      >>> formatter = dates.getFormatter('dateTime')
      >>> formatter.format(datetime(2004, 02, 04, 12, 15, 00))
      u'04.02.2004 12:15:00'

      >>> formatter = dates.getFormatter('dateTime', length='full')
      >>> formatter.format(datetime(2004, 02, 04, 12, 15, 00))
      u'Mittwoch, 4. Februar 2004 12:15 Uhr +000'

      
    """

    implements(ILocaleDates)


    def __init__(self):
        # See zope.i18n.interfaces.ILocaleCalendar
        self.localizedPatternChars = None
        self.calendars = None
        self.timezones = None

    def getFormatter(self, category, length=None, name=None,
                     calendar=u'gregorian'):
        """See zope.i18n.interfaces.locales.ILocaleDates

        Examples::

          XXX

        """
        assert category in (u'date', u'time', u'dateTime')
        assert calendar in (u'gregorian', u'arabic', u'chinese', u'civil-arabic',
                            u'hebrew', u'japanese', u'thai-buddhist')
        assert length in (u'short', u'medium', u'long', u'full', None)

        cal = self.calendars[calendar]

        formats = getattr(cal, category+'Formats')
        if length is None:
            length = getattr(
                cal,
                'default'+category[0].upper()+category[1:]+'Format',
                formats.keys()[0])

        # 'datetime' is always a bit special; we often do not have a length
        # specification, but we need it for looking up the date and time
        # formatters 
        if category == 'dateTime':
            formatLength = formats.get(length, formats[None])
        else:
            formatLength = formats[length]

        if name is None:
            name = formatLength.default

        format = formatLength.formats[name]
        pattern = format.pattern

        if category == 'dateTime':
            date_pat = self.getFormatter(
                'date', length, name, calendar).getPattern()
            time_pat = self.getFormatter(
                'time', length, name, calendar).getPattern()
            pattern = pattern.replace('{1}', date_pat)
            pattern = pattern.replace('{0}', time_pat)

        return DateTimeFormat(pattern, cal)

    
class LocaleCurrency(object):
    """Simple implementation of ILocaleCurrency without inheritance support,
    since it is not needed for a single currency."""
    implements(ILocaleCurrency)

    def __init__(self, type):
        """Initialize object."""
        self.type = type
        self.symbol = None
        self.symbolChoice = False
        self.displayName = None


class LocaleNumbers(AttributeInheritance):
    """Implementation of ILocaleCurrency including inheritance support.

    Examples::

      >>> numbers = LocaleNumbers()
      >>> numbers.symbols = {
      ...     'decimal': ',', 'group': '.', 'list': ';', 'percentSign': '%',
      ...     'nativeZeroDigit': '0', 'patternDigit': '#', 'plusSign': '+',
      ...     'minusSign': '-', 'exponential': 'E', 'perMille': 'o/oo',
      ...     'infinity': 'oo', 'nan': 'N/A'}

      Setting up and accessing totally unnamed decimal format
      (very common scenario)

      >>> length = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u'#,##0.###;-#,##0.###'
      >>> length.formats = {None: format}
      >>> numbers.decimalFormats = {None: length}
      >>> formatter = numbers.getFormatter('decimal')
      >>> formatter.format(3.4)
      u'3,4'
      >>> formatter.format(-3.4567)
      u'-3,456'
      >>> formatter.format(3210.4)
      u'3.210,4'

      Setting up and accessing scientific formats with named format lengths

      >>> longlength = LocaleFormatLength('long')
      >>> format = LocaleFormat()
      >>> format.pattern = u'0.000###E+00'
      >>> longlength.formats = {None: format}
      >>> mediumlength = LocaleFormatLength('long')
      >>> format = LocaleFormat()
      >>> format.pattern = u'0.00##E+00'
      >>> mediumlength.formats = {None: format}
      >>> numbers.scientificFormats = {'long': longlength,
      ...                              'medium': mediumlength}
      >>> numbers.defaultScientificFormat = 'long'
      >>> formatter = numbers.getFormatter('scientific')
      >>> formatter.format(1234.5678)
      u'1,234567E+03'
      >>> formatter = numbers.getFormatter('scientific', 'medium')
      >>> formatter.format(1234.5678)
      u'1,2345E+03'

      Setting up and accessing percent formats with named format lengths
      and format names

      >>> longlength = LocaleFormatLength('long')
      >>> fooformat = LocaleFormat()
      >>> fooformat.pattern = u'0.##0%'
      >>> barformat = LocaleFormat()
      >>> barformat.pattern = u'0%'
      >>> longlength.formats = {None: fooformat, 'bar': barformat}
      >>> numbers.percentFormats = {'long': longlength}
      >>> numbers.defaultPercentFormat = 'long'
      >>> formatter = numbers.getFormatter('percent')
      >>> formatter.format(123.45678)
      u'123,456%'
      >>> formatter = numbers.getFormatter('percent', name='bar')
      >>> formatter.format(123.45678)
      u'123%'

      ...using a default name
      
      >>> numbers.percentFormats['long'].default = 'bar'
      >>> formatter = numbers.getFormatter('percent')
      >>> formatter.format(123.45678)
      u'123%'

    """
    implements(ILocaleNumbers)

    def __init__(self):
        """Initialize object."""
        # See zope.i18n.interfaces.ILocaleNumbers    
        self.symbols = None

        self.defaultDecimalFormat = None
        self.decimalFormats = None

        self.defaultScientificFormat = None
        self.scientificFormats = None

        self.defaultPercentFormat = None
        self.percentFormats = None

        self.defaultCurrencyFormat = None
        self.currencyFormats = None
        self.currencies = None


    def getFormatter(self, category, length=None, name=None):
        """See zope.i18n.interfaces.locales.ILocaleNumbers"""
        assert category in (u'decimal', u'percent', u'scientific', u'currency')
        assert length in (u'short', u'medium', u'long', u'full', None)

        formats = getattr(self, category+'Formats')
        if length is None:
            length = getattr(
                self,
                'default'+category[0].upper()+category[1:]+'Format',
                formats.keys()[0])
        formatLength = formats[length]

        if name is None:
            name = formatLength.default

        format = formatLength.formats[name]

        return NumberFormat(format.pattern, self.symbols)


class Locale(AttributeInheritance):
    """Implementation of the ILocale interface."""

    implements(ILocale)

    def __init__(self, id):
        self.id = id
        self.displayNames = None
        self.dates = None
        self.numbers = None
        self.delimiters = None

    def getLocaleID(self):
        """Return the locale id."""
        id = self.id
        pieces = filter(None,
                        (id.language, id.script, id.territory, id.variant))
        id_string = '_'.join(pieces)
        # XXX: What about keys??? Where do I get this info from?
        pieces = [key+'='+type for key, type in ()]
        if pieces:
            id_string += '@' + ','.join(pieces)
        return id_string

    def getInheritedSelf(self):
        """See XXX...

        This is the really interesting method that looks up the next (more
        general) Locale object. This is used in case this locale object does
        not have the required information.

        This method works closely with with LocaleProvider.
        """
        language = self.id.language
        territory = self.id.territory
        variant = self.id.variant
        if variant is not None:
            return locales.getLocale(language, territory, None)
        elif territory is not None:
            return locales.getLocale(language, None, None)
        elif language is not None:
            return locales.getLocale(None, None, None)
        else:
            # Well, this is bad; we are already at the root locale
            raise NoParentException, 'Cannot find a more general locale.'


=== Added File Zope3/src/zope/i18n/locales/inheritance.py ===
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Locale Inheritance Support

This module provides support for locale inheritance.

Note: In many respects this is similar to Zope 2's acquisition model, since
locale inheritance is not inheritance in the programming sense. 

$Id: inheritance.py,v 1.1 2004/02/05 22:52:24 srichter Exp $
"""
from zope.interface import implements
from zope.i18n.interfaces.locales import \
     ILocaleInheritance, IAttributeInheritance, IDictionaryInheritance

class NoParentException(AttributeError):
    pass

class Inheritance(object):
    """A simple base version of locale inheritance.

    This object contains some shared code amongst the various
    'ILocaleInheritance' implementations.
    """

    implements(ILocaleInheritance)

    # See zope.i18n.interfaces.locales.ILocaleInheritance
    __parent__ = None

    # See zope.i18n.interfaces.locales.ILocaleInheritance
    __name__ = None

    def getInheritedSelf(self):
        """See zope.i18n.interfaces.locales.ILocaleInheritance"""
        if self.__parent__ is None:
            raise NoParentException, 'No parent was specified.'
        parent = self.__parent__.getInheritedSelf()
        if isinstance(parent, dict):
            return parent[self.__name__]
        return getattr(parent, self.__name__)


class AttributeInheritance(Inheritance):
    """Implementation of locale inheritance for attributes.

    Example::

      >>> from zope.i18n.locales.tests.test_docstrings import \\
      ...     LocaleInheritanceStub

      >>> root = LocaleInheritanceStub()
      >>> root.data = 'value'
      >>> root.attr = 'bar value'
      >>> root.data2 = AttributeInheritance()
      >>> root.data2.attr = 'value2' 

      >>> locale = LocaleInheritanceStub(root)
      >>> locale.data = None
      >>> locale.attr = 'foo value'
      >>> locale.data2 = AttributeInheritance()
      >>> locale.data2.attr = None

      Here is an attribute lookup directly from the locale ...

      >>> locale.data
      'value'
      >>> locale.attr
      'foo value'

      ... however, we can also have any amount of nesting.

      >>> locale.data2.attr
      'value2'
    """

    implements(IAttributeInheritance)

    def __setattr__(self, name, value):
        """See zope.i18n.interfaces.locales.ILocaleInheritance"""
        if ILocaleInheritance.isImplementedBy(value) and \
               not name.startswith('__'):
            value.__parent__ = self
            value.__name__ = name
        super(AttributeInheritance, self).__setattr__(name, value)


    def __getattribute__(self, name):
        """See zope.i18n.interfaces.locales.ILocaleInheritance"""
        if not name.startswith('__') and name != 'getInheritedSelf':
            dict = self.__dict__
            if dict.has_key(name) and dict[name] is None:
                try:
                    selfUp = self.getInheritedSelf()
                except NoParentException:
                    # There was simply no parent anymore, so let's go the
                    # usual way
                    pass
                else:
                    return selfUp.__getattribute__(name)
        return super(AttributeInheritance, self).__getattribute__(name)


class InheritingDictionary(Inheritance, dict):
    """Implementation of a dictionary that can also inherit values.

    Example::

      >>> from zope.i18n.locales.tests.test_docstrings import \\
      ...     LocaleInheritanceStub

      >>> root = LocaleInheritanceStub()
      >>> root.data = InheritingDictionary({1: 'one', 2: 'two', 3: 'three'})
      >>> root.data2 = AttributeInheritance()
      >>> root.data2.dict = InheritingDictionary({1: 'i', 2: 'ii', 3: 'iii'})

      >>> locale = LocaleInheritanceStub(root)
      >>> locale.data = InheritingDictionary({1: 'eins'})
      >>> locale.data2 = AttributeInheritance()
      >>> locale.data2.dict = InheritingDictionary({1: 'I'})

      Here is a dictionary lookup directly from the locale ...

      >>> locale.data[1]
      'eins'
      >>> locale.data[2]
      'two'

      ... however, we can also have any amount of nesting.

      >>> locale.data2.dict[1]
      'I'
      >>> locale.data2.dict[2]
      'ii'

      We also have to overwrite 'get()', 'keys()' and 'items()' since we want
      to make sure that all upper locales are consulted before returning the
      default or to construct the list of elements, respectively.

      >>> locale.data2.dict.get(2)
      'ii'
      >>> locale.data2.dict.get(4) is None
      True
      >>> locale.data.keys()
      [1, 2, 3]
      >>> locale.data.items()
      [(1, 'eins'), (2, 'two'), (3, 'three')]
    """

    implements(IDictionaryInheritance)

    def __setitem__(self, name, value):
        """See zope.i18n.interfaces.locales.ILocaleInheritance"""
        if ILocaleInheritance.isImplementedBy(value):
            value.__parent__ = self
            value.__name__ = name
        super(InheritingDictionary, self).__setitem__(name, value)

    def __getitem__(self, name):
        """See zope.i18n.interfaces.locales.ILocaleInheritance"""
        if not self.has_key(name):
            try: 
                selfUp = self.getInheritedSelf()
            except NoParentException:
                pass
            else:
                return selfUp.__getitem__(name)
        return super(InheritingDictionary, self).__getitem__(name)

    def get(self, name, default=None):
        """See zope.i18n.interfaces.locales.ILocaleInheritance"""
        try:
            return self[name]
        except KeyError:
            return default

    def items(self):
        try:
            d = dict(self.getInheritedSelf())
        except NoParentException:
            d = {}
        d.update(self)
        return d.items()

    def keys(self):
        return [item[0] for item in self.items()]

    def value(self):
        return [item[1] for item in self.items()]
        
        


=== Added File Zope3/src/zope/i18n/locales/provider.py ===
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Locale Provider

The Locale Provider looks up locales and loads them from the XML data, if
necessary.

$Id: provider.py,v 1.1 2004/02/05 22:52:24 srichter Exp $
"""
import os
from zope.interface import implements
from zope.i18n.interfaces.locales import ILocaleProvider

class LoadLocaleError(Exception):
    """This error is raised if a locale cannot be loaded."""


class LocaleProvider(object):
    """A locale provider that get's its data from the XML data."""

    implements(ILocaleProvider)

    def __init__(self, locale_dir):
        self._locales = {}
        self._locale_dir = locale_dir

    def loadLocale(self, language=None, country=None, variant=None):
        "See ZopeProducts.LocaleProvider.interfaces.ILocaleProvider"
        # Creating the filename
        if language == None and country == None and variant == None:
            filename = 'root.xml'
        else:
            filename = language
            if country is not None:
                filename += '_'+country
            if variant is not None:
                if '_' not in filename:
                    filename += '_'
                filename += '_'+variant
            filename += '.xml'

        # Making sure we have this locale
        path = os.path.join(self._locale_dir, filename)
        if not os.path.exists(path):
            raise LoadLocaleError, \
                  'The desired locale is not available.\nPath: %s' %path

        # Import here to avoid circular imports
        from zope.i18n.locales.xmlfactory import LocaleFactory

        # Let's get it!
        locale = LocaleFactory(path)()
        self._locales[(language, country, variant)] = locale

    def getLocale(self, language=None, country=None, variant=None):
        "See ZopeProducts.LocaleProvider.interfaces.ILocaleProvider"
        # We want to be liberal in what we accept, but the standard is lower
        # case language codes, upper case country codes, and upper case
        # variants, so coerce case here.
        if language:
            language = language.lower()
        if country:
            country = country.upper()
        if variant:
            variant = variant.upper()
        if not self._locales.has_key((language, country, variant)):
            self.loadLocale(language, country, variant)
        return self._locales[(language, country, variant)]


=== Added File Zope3/src/zope/i18n/locales/xmlfactory.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""XML Locale-related objects and functions

$Id: xmlfactory.py,v 1.1 2004/02/05 22:52:24 srichter Exp $
"""
from datetime import datetime, date, time
from xml.dom.minidom import parse as parseXML
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.inheritance import InheritingDictionary

class LocaleFactory:
    """This class creates a Locale object from an ICU XML file."""

    def __init__(self, path):
        """Initialize factory."""
        self._path = path
        # Mainly for testing
        if path:
            self._data = parseXML(path).documentElement

    def _getText(self, nodelist):
        rc = u''
        for node in nodelist:
            if node.nodeType == node.TEXT_NODE:
                rc = rc + node.data
        return rc


    def _extractVersion(self, identity_node):
        """Extract the Locale's version info based on data from the DOM
        tree.

        Example::

          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <identity>
          ...   <version number="1.0">Some notes</version>
          ...   <generation date="2003-12-19" />
          ...   <language type="de" /> 
          ...   <territory type="DE" /> 
          ... </identity>'''
          >>> dom = parseString(xml)

          >>> version = factory._extractVersion(dom.documentElement)
          >>> version.number
          u'1.0'
          >>> version.generationDate
          datetime.date(2003, 12, 19)
          >>> version.notes
          u'Some notes'
        """
        number = generationDate = notes = None
        # Retrieve the version number and notes of the locale
        nodes = identity_node.getElementsByTagName('version')
        if nodes:
            number = nodes[0].getAttribute('number')
            notes = self._getText(nodes[0].childNodes)
        # Retrieve the generationDate of the locale
        nodes = identity_node.getElementsByTagName('generation')
        if nodes:
            year, month, day = nodes[0].getAttribute('date').split('-')
            generationDate = date(int(year), int(month), int(day))

        return LocaleVersion(number, generationDate, notes)
    

    def _extractIdentity(self):
        """Extract the Locale's identity object based on info from the DOM
        tree.

        Example::

          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <ldml>
          ...   <identity>
          ...     <version number="1.0"/>
          ...     <generation date="2003-12-19" />
          ...     <language type="en" /> 
          ...     <territory type="US" /> 
          ...     <variant type="POSIX" /> 
          ...   </identity>
          ... </ldml>'''
          >>> factory = LocaleFactory(None)
          >>> factory._data = parseString(xml).documentElement

          >>> id = factory._extractIdentity()
          >>> id.language
          u'en'
          >>> id.script is None
          True
          >>> id.territory
          u'US'
          >>> id.variant
          u'POSIX'
          >>> id.version.number
          u'1.0'
        """
        id = LocaleIdentity()
        identity = self._data.getElementsByTagName('identity')[0]
        # Retrieve the language of the locale
        nodes = identity.getElementsByTagName('language')
        if nodes != []:
            id.language = nodes[0].getAttribute('type')  or None
        # Retrieve the territory of the locale
        nodes = identity.getElementsByTagName('territory')
        if nodes != []:
            id.territory = nodes[0].getAttribute('type') or None
        # Retrieve the varriant of the locale
        nodes = identity.getElementsByTagName('variant')
        if nodes != []:
            id.variant = nodes[0].getAttribute('type') or None

        id.version = self._extractVersion(identity)
        return id
    

    def _extractTypes(self, names_node):
        """Extract all types from the names_node.

        Example::

          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <displayNames>
          ...   <types>
          ...     <type type="Fallback" key="calendar"></type>
          ...     <type type="buddhist" key="calendar">BUDDHIST</type>
          ...     <type type="chinese" key="calendar">CHINESE</type>
          ...     <type type="gregorian" key="calendar">GREGORIAN</type>
          ...     <type type="stroke" key="collation">STROKE</type>
          ...     <type type="traditional" key="collation">TRADITIONAL</type>
          ...   </types>
          ... </displayNames>'''
          >>> dom = parseString(xml)

          >>> types = factory._extractTypes(dom.documentElement)
          >>> keys = types.keys()
          >>> keys.sort()
          >>> keys[:2]
          [(u'Fallback', u'calendar'), (u'buddhist', u'calendar')]
          >>> keys[2:4]
          [(u'chinese', u'calendar'), (u'gregorian', u'calendar')]
          >>> keys[4:]
          [(u'stroke', u'collation'), (u'traditional', u'collation')]
          >>> types[(u'chinese', u'calendar')]
          u'CHINESE'
          >>> types[(u'stroke', u'collation')]
          u'STROKE'
        """
        # 'types' node has not to exist 
        types_nodes = names_node.getElementsByTagName('types')
        if types_nodes == []:
            return 
        # Retrieve all types
        types = InheritingDictionary()
        for type_node in types_nodes[0].getElementsByTagName('type'):
            type = type_node.getAttribute('type')
            key = type_node.getAttribute('key')
            types[(type, key)] = self._getText(type_node.childNodes)
        return types


    def _extractDisplayNames(self):
        """Extract all display names from the DOM tree.

        Example::

          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <ldml>
          ...   <localeDisplayNames>
          ...     <languages>
          ...       <language type="Fallback"></language>
          ...       <language type="aa">aa</language>
          ...       <language type="ab">ab</language>
          ...     </languages>
          ...     <scripts>
          ...       <script type="Arab">Arab</script>
          ...       <script type="Armn">Armn</script>
          ...     </scripts>
          ...     <territories>
          ...       <territory type="AD">AD</territory>
          ...       <territory type="AE">AE</territory>
          ...     </territories>
          ...     <variants>
          ...       <variant type="Fallback"></variant>
          ...       <variant type="POSIX">POSIX</variant>
          ...     </variants>
          ...     <keys>
          ...       <key type="calendar">CALENDAR</key>
          ...       <key type="collation">COLLATION</key>
          ...     </keys>
          ...     <types>
          ...       <type type="buddhist" key="calendar">BUDDHIST</type>
          ...       <type type="stroke" key="collation">STROKE</type>
          ...     </types>
          ...   </localeDisplayNames>
          ... </ldml>'''
          >>> factory = LocaleFactory(None)
          >>> factory._data = parseString(xml).documentElement

          >>> names = factory._extractDisplayNames()

          >>> keys = names.languages.keys()
          >>> keys.sort()
          >>> keys
          [u'Fallback', u'aa', u'ab']
          >>> names.languages[u'aa']
          u'aa'

          >>> keys = names.scripts.keys()
          >>> keys.sort()
          >>> keys
          [u'Arab', u'Armn']
          >>> names.scripts[u'Arab']
          u'Arab'

          >>> keys = names.territories.keys()
          >>> keys.sort()
          >>> keys
          [u'AD', u'AE']
          >>> names.territories[u'AD']
          u'AD'

          >>> keys = names.variants.keys()
          >>> keys.sort()
          >>> keys
          [u'Fallback', u'POSIX']
          >>> names.variants[u'Fallback']
          u''

          >>> keys = names.keys.keys()
          >>> keys.sort()
          >>> keys
          [u'calendar', u'collation']
          >>> names.keys[u'calendar']
          u'CALENDAR'

          >>> names.types[(u'stroke', u'collation')]
          u'STROKE'
        """
        displayNames = LocaleDisplayNames()
        # Neither the 'localeDisplayNames' or 'scripts' node has to exist 
        names_nodes = self._data.getElementsByTagName('localeDisplayNames')
        if names_nodes == []:
            return displayNames

        for group_tag, single_tag in (('languages', 'language'),
                                      ('scripts', 'script'),
                                      ('territories', 'territory'),
                                      ('variants', 'variant'),
                                      ('keys', 'key')):
            group_nodes = names_nodes[0].getElementsByTagName(group_tag)
            if group_nodes == []:
                continue
            # Retrieve all children
            elements = InheritingDictionary()
            for element in group_nodes[0].getElementsByTagName(single_tag):
                type = element.getAttribute('type')
                elements[type] = self._getText(element.childNodes)
            setattr(displayNames, group_tag, elements)

        displayNames.types = self._extractTypes(names_nodes[0])
        return displayNames


    def _extractMonths(self, cal_node, calendar):
        """Extract all month entries from cal_node and store them in calendar.

        Example::

          >>> class CalendarStub(object):
          ...     months = None
          >>> calendar = CalendarStub()
          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <calendar type="gregorian">
          ...   <monthNames>
          ...     <month type="1">Januar</month>
          ...     <month type="2">Februar</month>
          ...     <month type="3">Maerz</month>
          ...     <month type="4">April</month>
          ...     <month type="5">Mai</month>
          ...     <month type="6">Juni</month>
          ...     <month type="7">Juli</month>
          ...     <month type="8">August</month>
          ...     <month type="9">September</month>
          ...     <month type="10">Oktober</month>
          ...     <month type="11">November</month>
          ...     <month type="12">Dezember</month>
          ...   </monthNames>
          ...   <monthAbbr>
          ...     <month type="1">Jan</month>
          ...     <month type="2">Feb</month>
          ...     <month type="3">Mrz</month>
          ...     <month type="4">Apr</month>
          ...     <month type="5">Mai</month>
          ...     <month type="6">Jun</month>
          ...     <month type="7">Jul</month>
          ...     <month type="8">Aug</month>
          ...     <month type="9">Sep</month>
          ...     <month type="10">Okt</month>
          ...     <month type="11">Nov</month>
          ...     <month type="12">Dez</month>
          ...   </monthAbbr>
          ... </calendar>'''
          >>> dom = parseString(xml)
          >>> factory._extractMonths(dom.documentElement, calendar)

          >>> names = [calendar.months.get(type, (None, None))[0]
          ...          for type in range(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 = [calendar.months.get(type, (None, None))[1]
          ...          for type in range(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']
        """
        # See whether we have month names and abbreviations
        names_nodes = cal_node.getElementsByTagName('monthNames')
        abbrs_nodes = cal_node.getElementsByTagName('monthAbbr')
        if not (names_nodes and abbrs_nodes):
            return
        
        # Get all month names
        names = {}
        for name_node in names_nodes[0].getElementsByTagName('month'):
            type = int(name_node.getAttribute('type'))
            names[type] = self._getText(name_node.childNodes)

        # Get all month abbrs
        abbrs = {}
        for abbr_node in abbrs_nodes[0].getElementsByTagName('month'):
            type = int(abbr_node.getAttribute('type'))
            abbrs[type] = self._getText(abbr_node.childNodes)

        # Put the info together
        calendar.months = InheritingDictionary()
        for type in range(1, 13):
            calendar.months[type] = (names.get(type, None),
                                     abbrs.get(type, None))


    def _extractDays(self, cal_node, calendar):
        """Extract all day entries from cal_node and store them in
        calendar.

        Example::

          >>> class CalendarStub(object):
          ...     days = None
          >>> calendar = CalendarStub()
          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <calendar type="gregorian">
          ...   <dayNames>
          ...     <day type="sun">Sonntag</day>
          ...     <day type="mon">Montag</day>
          ...     <day type="tue">Dienstag</day>
          ...     <day type="wed">Mittwoch</day>
          ...     <day type="thu">Donnerstag</day>
          ...     <day type="fri">Freitag</day>
          ...     <day type="sat">Samstag</day>
          ...   </dayNames>
          ...   <dayAbbr>
          ...     <day type="sun">So</day>
          ...     <day type="mon">Mo</day>
          ...     <day type="tue">Di</day>
          ...     <day type="wed">Mi</day>
          ...     <day type="thu">Do</day>
          ...     <day type="fri">Fr</day>
          ...     <day type="sat">Sa</day>
          ...   </dayAbbr>
          ... </calendar>'''
          >>> dom = parseString(xml)
          >>> factory._extractDays(dom.documentElement, calendar)

          >>> names = [calendar.days.get(type, (None, None))[0]
          ...          for type in range(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)]
          >>> abbrs
          [u'Mo', u'Di', u'Mi', u'Do', u'Fr', u'Sa', u'So']
        """
        # See whether we have weekday names and abbreviations
        names_nodes = cal_node.getElementsByTagName('dayNames')
        abbrs_nodes = cal_node.getElementsByTagName('dayAbbr')
        if not (names_nodes and abbrs_nodes):
            return

        # Get all weekday names
        names = {}
        for name_node in names_nodes[0].getElementsByTagName('day'):
            type = dayMapping[name_node.getAttribute('type')]
            names[type] = self._getText(name_node.childNodes)
        # Get all weekday abbreviations
        abbrs = {}
        for abbr_node in abbrs_nodes[0].getElementsByTagName('day'):
            type = dayMapping[abbr_node.getAttribute('type')]
            abbrs[type] = self._getText(abbr_node.childNodes)

        # Put the info together
        calendar.days = InheritingDictionary()
        for type in range(1, 13):
            calendar.days[type] = (names.get(type, None),
                                   abbrs.get(type, None))


    def _extractWeek(self, cal_node, calendar):
        """Extract all week entries from cal_node and store them in
        calendar.

        Example::

          >>> class CalendarStub(object):
          ...     week = None
          >>> calendar = CalendarStub()
          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <calendar type="gregorian">
          ...   <week>
          ...     <minDays count="1"/>
          ...     <firstDay day="sun"/>
          ...     <weekendStart day="fri" time="18:00"/>
          ...     <weekendEnd day="sun" time="18:00"/>
          ...   </week>
          ... </calendar>'''
          >>> dom = parseString(xml)
          >>> factory._extractWeek(dom.documentElement, calendar)

          >>> calendar.week['minDays']
          1
          >>> calendar.week['firstDay']
          7
          >>> calendar.week['weekendStart']
          (5, datetime.time(18, 0))
          >>> calendar.week['weekendEnd']
          (7, datetime.time(18, 0))
        """
        # See whether we have week entries
        week_nodes = cal_node.getElementsByTagName('week')
        if not week_nodes:
            return

        calendar.week = InheritingDictionary()

        # Get the 'minDays' value if available
        for node in week_nodes[0].getElementsByTagName('minDays'):
            calendar.week['minDays'] = int(node.getAttribute('count'))

        # Get the 'firstDay' value if available
        for node in week_nodes[0].getElementsByTagName('firstDay'):
            calendar.week['firstDay'] = dayMapping[node.getAttribute('day')]

        # Get the 'weekendStart' value if available
        for node in week_nodes[0].getElementsByTagName('weekendStart'):
            day = dayMapping[node.getAttribute('day')]
            time_args = map(int, node.getAttribute('time').split(':'))
            calendar.week['weekendStart'] = (day, time(*time_args))

            # Get the 'weekendEnd' value if available
        for node in week_nodes[0].getElementsByTagName('weekendEnd'):
            day = dayMapping[node.getAttribute('day')]
            time_args = map(int, node.getAttribute('time').split(':'))
            calendar.week['weekendEnd'] = (day, time(*time_args))


    def _extractEras(self, cal_node, calendar):
        """Extract all era entries from cal_node and store them in
        calendar.

        Example::

          >>> class CalendarStub(object):
          ...     days = None
          >>> calendar = CalendarStub()
          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <calendar type="gregorian">
          ...   <eras>
          ...      <eraAbbr>
          ...       <era type="0">BC</era>
          ...       <era type="1">AD</era>
          ...      </eraAbbr>
          ...      <eraName>
          ...       <era type="0">Before Christ</era>
          ...      </eraName>
          ...   </eras>
          ... </calendar>'''
          >>> dom = parseString(xml)
          >>> factory._extractEras(dom.documentElement, calendar)

          >>> names = [calendar.eras.get(type, (None, None))[0]
          ...          for type in range(2)]
          >>> names
          [u'Before Christ', None]

          >>> abbrs = [calendar.eras.get(type, (None, None))[1]
          ...          for type in range(2)]
          >>> abbrs
          [u'BC', u'AD']
        """
        # See whether we have era names and abbreviations
        eras_nodes = cal_node.getElementsByTagName('eras')
        if not eras_nodes:
            return
        names_nodes = eras_nodes[0].getElementsByTagName('eraName')
        abbrs_nodes = eras_nodes[0].getElementsByTagName('eraAbbr')

        # Get all era names
        names = {}
        if names_nodes:
            for name_node in names_nodes[0].getElementsByTagName('era'):
                type = int(name_node.getAttribute('type'))
                names[type] = self._getText(name_node.childNodes)
        # Get all era abbreviations
        abbrs = {}
        if abbrs_nodes:
            for abbr_node in abbrs_nodes[0].getElementsByTagName('era'):
                type = int(abbr_node.getAttribute('type'))
                abbrs[type] = self._getText(abbr_node.childNodes)

        calendar.eras = InheritingDictionary()
        for type in abbrs.keys():
            calendar.eras[type] = (names.get(type, None), abbrs.get(type, None))


    def _extractFormats(self, formats_node, lengthNodeName, formatNodeName):
        """Extract all format entries from formats_node and return a
        tuple of the form (defaultFormatType, [LocaleFormatLength, ...]).

        Example::

          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <dateFormats>
          ...   <default type="medium"/>
          ...   <dateFormatLength type="full">
          ...     <dateFormat>
          ...       <pattern>EEEE, MMMM d, yyyy</pattern>
          ...     </dateFormat>
          ...   </dateFormatLength>
          ...   <dateFormatLength type="medium">
          ...     <default type="DateFormatsKey2"/>
          ...     <dateFormat type="DateFormatsKey2">
          ...       <displayName>Standard Date</displayName>
          ...       <pattern>MMM d, yyyy</pattern>
          ...     </dateFormat>
          ...     <dateFormat type="DateFormatsKey3">
          ...       <pattern>MMM dd, yyyy</pattern>
          ...     </dateFormat>
          ...   </dateFormatLength>
          ... </dateFormats>'''
          >>> dom = parseString(xml)

          >>> default, lengths = factory._extractFormats(
          ...     dom.documentElement, 'dateFormatLength', 'dateFormat')
          >>> default
          u'medium'
          >>> lengths[u'full'].formats[None].pattern
          u'EEEE, MMMM d, yyyy'
          >>> lengths[u'medium'].default
          u'DateFormatsKey2'
          >>> lengths[u'medium'].formats['DateFormatsKey3'].pattern
          u'MMM dd, yyyy'
          >>> lengths[u'medium'].formats['DateFormatsKey2'].displayName
          u'Standard Date'
        """
        formats_default = None
        default_nodes = formats_node.getElementsByTagName('default')
        if default_nodes:
            formats_default = default_nodes[0].getAttribute('type')

        lengths = InheritingDictionary()
        for length_node in formats_node.getElementsByTagName(lengthNodeName):
            type = length_node.getAttribute('type') or None
            length = LocaleFormatLength(type)
            
            default_nodes = length_node.getElementsByTagName('default')
            if default_nodes:
                length.default = default_nodes[0].getAttribute('type')

            if length_node.getElementsByTagName(formatNodeName):
                length.formats = InheritingDictionary()
                
            for format_node in length_node.getElementsByTagName(formatNodeName):
                format = LocaleFormat()
                format.type = format_node.getAttribute('type') or None
                pattern_node = format_node.getElementsByTagName('pattern')[0]
                format.pattern = self._getText(pattern_node.childNodes)
                name_nodes = format_node.getElementsByTagName('displayName')
                if name_nodes:
                    format.displayName = self._getText(name_nodes[0].childNodes)
                length.formats[format.type] = format

            lengths[length.type] = length

        return (formats_default, lengths)

    def _extractCalendars(self, dates_node):
        """Extract all calendars and their specific information from the
        Locale's DOM tree.

        Example::

          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <dates>
          ...   <calendars>
          ...     <calendar type="gregorian">
          ...       <monthNames>
          ...         <month type="1">January</month>
          ...         <month type="12">December</month>
          ...       </monthNames>
          ...       <monthAbbr>
          ...         <month type="1">Jan</month>
          ...         <month type="12">Dec</month>
          ...       </monthAbbr>
          ...       <dayNames>
          ...         <day type="sun">Sunday</day>
          ...         <day type="sat">Saturday</day>
          ...       </dayNames>
          ...       <dayAbbr>
          ...         <day type="sun">Sun</day>
          ...         <day type="sat">Sat</day>
          ...       </dayAbbr>
          ...       <week>
          ...         <minDays count="1"/>
          ...         <firstDay day="sun"/>
          ...       </week>
          ...       <am>AM</am>
          ...       <pm>PM</pm>
          ...       <eras>
          ...         <eraAbbr>
          ...           <era type="0">BC</era>
          ...           <era type="1">AD</era>
          ...         </eraAbbr>
          ...       </eras>
          ...       <dateFormats>
          ...         <dateFormatLength type="full">
          ...           <dateFormat>
          ...             <pattern>EEEE, MMMM d, yyyy</pattern>
          ...           </dateFormat>
          ...         </dateFormatLength>
          ...       </dateFormats>
          ...       <timeFormats>
          ...         <default type="medium"/>
          ...         <timeFormatLength type="medium">
          ...           <timeFormat>
          ...             <pattern>h:mm:ss a</pattern>
          ...           </timeFormat>
          ...         </timeFormatLength>
          ...       </timeFormats>
          ...       <dateTimeFormats>
          ...         <dateTimeFormatLength>
          ...           <dateTimeFormat>
          ...             <pattern>{0} {1}</pattern>
          ...           </dateTimeFormat>
          ...         </dateTimeFormatLength>
          ...       </dateTimeFormats>
          ...     </calendar>
          ...     <calendar type="thai-buddhist">
          ...       <eras>
          ...         <era type="0">BE</era>
          ...       </eras>
          ...     </calendar>
          ...   </calendars>
          ... </dates>'''
          >>> dom = parseString(xml)

          >>> calendars = factory._extractCalendars(dom.documentElement)
          >>> keys = calendars.keys()
          >>> keys.sort()
          >>> keys
          [u'gregorian', u'thai-buddhist']
        """
        cals_nodes = dates_node.getElementsByTagName('calendars')
        # no calendar node
        if cals_nodes == []:
            return

        calendars = InheritingDictionary()
        for cal_node in cals_nodes[0].getElementsByTagName('calendar'):
            # get the calendar type
            type = cal_node.getAttribute('type')
            calendar = LocaleCalendar(type)
            # get month names and abbreviations
            self._extractMonths(cal_node, calendar)
            # get weekday names and abbreviations
            self._extractDays(cal_node, calendar)

            # get am/pm designation values
            nodes = cal_node.getElementsByTagName('am')
            if nodes:
                calendar.am = self._getText(nodes[0].childNodes)
            nodes = cal_node.getElementsByTagName('pm')
            if nodes:
                calendar.pm = self._getText(nodes[0].childNodes)

            # get era names and abbreviations
            self._extractEras(cal_node, calendar)

            for formatsName, lengthName, formatName in (
                ('dateFormats', 'dateFormatLength', 'dateFormat'),
                ('timeFormats', 'timeFormatLength', 'timeFormat'),
                ('dateTimeFormats', 'dateTimeFormatLength', 'dateTimeFormat')):

                formats_nodes = cal_node.getElementsByTagName(formatsName)
                if formats_nodes:
                    default, formats = self._extractFormats(
                        formats_nodes[0], lengthName, formatName)
                    setattr(calendar,
                            'default'+formatName[0].upper()+formatName[1:],
                            default)
                    setattr(calendar, formatsName, formats)

            calendars[calendar.type] = calendar

        return calendars


    def _extractTimeZones(self, dates_node):
        """Extract all timezone information for the locale from the DOM
        tree.

        Example::

          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <dates>
          ...   <timeZoneNames>
          ...     <zone type="America/Los_Angeles" >
          ...       <long>
          ...         <generic>Pacific Time</generic>
          ...         <standard>Pacific Standard Time</standard>
          ...         <daylight>Pacific Daylight Time</daylight>
          ...       </long>
          ...       <short>
          ...         <generic>PT</generic>
          ...         <standard>PST</standard>
          ...         <daylight>PDT</daylight>
          ...       </short>
          ...       <exemplarCity>San Francisco</exemplarCity>
          ...     </zone>
          ...     <zone type="Europe/London">
          ...       <long>
          ...         <generic>British Time</generic>
          ...         <standard>British Standard Time</standard>
          ...         <daylight>British Daylight Time</daylight>
          ...       </long>
          ...       <exemplarCity>York</exemplarCity>
          ...     </zone>
          ...   </timeZoneNames>
          ... </dates>'''
          >>> dom = parseString(xml)
          >>> zones = factory._extractTimeZones(dom.documentElement)

          >>> keys = zones.keys()
          >>> keys.sort()
          >>> keys
          [u'America/Los_Angeles', u'Europe/London']
          >>> zones[u'Europe/London'].names[u'generic']
          (u'British Time', None)
          >>> zones[u'Europe/London'].cities
          [u'York']
          >>> zones[u'America/Los_Angeles'].names[u'generic']
          (u'Pacific Time', u'PT')
        """
        tz_names = dates_node.getElementsByTagName('timeZoneNames')
        if not tz_names:
            return

        zones = InheritingDictionary()
        for node in tz_names[0].getElementsByTagName('zone'):
            type = node.getAttribute('type')
            zone = LocaleTimeZone(type)

            # get the short and long name node
            long = node.getElementsByTagName('long')
            short = node.getElementsByTagName('short')
            for type in (u'generic', u'standard', u'daylight'):
                # get long name
                long_desc = None
                if long:
                    long_nodes = long[0].getElementsByTagName(type)
                    if long_nodes:
                        long_desc = self._getText(long_nodes[0].childNodes)
                # get short name
                short_desc = None
                if short:
                    short_nodes = short[0].getElementsByTagName(type)
                    if short_nodes:
                        short_desc = self._getText(short_nodes[0].childNodes)
                if long_desc is not None or short_desc is not None:
                    zone.names[type] = (long_desc, short_desc)

            for city in node.getElementsByTagName('exemplarCity'):
                zone.cities.append(self._getText(city.childNodes))

            zones[zone.type] = zone

        return zones


    def _extractDates(self):
        """Extract all date information from the DOM tree"""
        dates_nodes = self._data.getElementsByTagName('dates')
        if dates_nodes == []:
            return

        dates = LocaleDates()
        dates.calendars = self._extractCalendars(dates_nodes[0])
        dates.timezones = self._extractTimeZones(dates_nodes[0])
        return dates


    def _extractSymbols(self, numbers_node):
        """Extract all week entries from cal_node and store them in
        calendar.

        Example::

          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <numbers>
          ...   <symbols>
          ...     <decimal>.</decimal>
          ...     <group>,</group>
          ...     <list>;</list>
          ...     <percentSign>%</percentSign>
          ...     <nativeZeroDigit>0</nativeZeroDigit>
          ...     <patternDigit>#</patternDigit>
          ...     <plusSign>+</plusSign>
          ...     <minusSign>-</minusSign>
          ...     <exponential>E</exponential>
          ...     <perMille>o/oo</perMille>
          ...     <infinity>oo</infinity>
          ...     <nan>NaN</nan>
          ...   </symbols>
          ... </numbers>'''
          >>> dom = parseString(xml)
          >>> symbols = factory._extractSymbols(dom.documentElement)

          >>> symbols['list']
          u';'
          >>> keys = symbols.keys()
          >>> keys.sort()
          >>> keys[:5]
          [u'decimal', u'exponential', u'group', u'infinity', u'list']
          >>> keys[5:9]
          [u'minusSign', u'nan', u'nativeZeroDigit', u'patternDigit']
          >>> keys[9:]
          [u'perMille', u'percentSign', u'plusSign']
        """
        # See whether we have symbols entries
        symbols_nodes = numbers_node.getElementsByTagName('symbols')
        if not symbols_nodes:
            return

        symbols = InheritingDictionary()
        for name in (u'decimal', u'group', u'list', u'percentSign',
                     u'nativeZeroDigit', u'patternDigit', u'plusSign',
                     u'minusSign', u'exponential', u'perMille',
                     u'infinity', u'nan'):
            nodes = symbols_nodes[0].getElementsByTagName(name)
            if nodes:
                symbols[name] = self._getText(nodes[0].childNodes)

        return symbols


    def _extractNumberFormats(self, numbers_node, numbers):
        """Extract all number formats from the numbers_node and save the data
        in numbers.

        Example::

          >>> class Numbers(object):
          ...     defaultDecimalFormat = None
          ...     decimalFormats = None
          ...     defaultScientificFormat = None
          ...     scientificFormats = None
          ...     defaultPercentFormat = None
          ...     percentFormats = None
          ...     defaultCurrencyFormat = None
          ...     currencyFormats = None
          >>> numbers = Numbers()
          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <numbers>
          ...   <decimalFormats>
          ...     <decimalFormatLength type="long">
          ...       <decimalFormat>
          ...         <pattern>#,##0.###</pattern>
          ...       </decimalFormat>
          ...     </decimalFormatLength>
          ...   </decimalFormats>
          ...   <scientificFormats>
          ...     <default type="long"/>
          ...     <scientificFormatLength type="long">
          ...       <scientificFormat>
          ...         <pattern>0.000###E+00</pattern>
          ...       </scientificFormat>
          ...     </scientificFormatLength>
          ...     <scientificFormatLength type="medium">
          ...       <scientificFormat>
          ...         <pattern>0.00##E+00</pattern>
          ...       </scientificFormat>
          ...     </scientificFormatLength>
          ...   </scientificFormats>
          ...   <percentFormats>
          ...     <percentFormatLength type="long">
          ...       <percentFormat>
          ...         <pattern>#,##0%</pattern>
          ...       </percentFormat>
          ...     </percentFormatLength>
          ...   </percentFormats>
          ...   <currencyFormats>
          ...     <currencyFormatLength type="long">
          ...       <currencyFormat>
          ...         <pattern>$ #,##0.00;($ #,##0.00)</pattern>
          ...       </currencyFormat>
          ...     </currencyFormatLength>
          ...   </currencyFormats>
          ... </numbers>'''
          >>> dom = parseString(xml)
          >>> factory._extractNumberFormats(dom.documentElement, numbers)

          >>> numbers.decimalFormats[u'long'].formats[None].pattern
          u'#,##0.###'

          >>> numbers.defaultScientificFormat
          u'long'
          >>> numbers.scientificFormats[u'long'].formats[None].pattern
          u'0.000###E+00'
          >>> numbers.scientificFormats[u'medium'].formats[None].pattern
          u'0.00##E+00'

          >>> numbers.percentFormats[u'long'].formats[None].pattern
          u'#,##0%'
          >>> numbers.percentFormats.get(u'medium', None) is None
          True

          >>> numbers.currencyFormats[u'long'].formats[None].pattern
          u'$ #,##0.00;($ #,##0.00)'
          >>> numbers.currencyFormats.get(u'medium', None) is None
          True
        """

        for category in ('decimal', 'scientific', 'percent', 'currency'):
            formatsName = category+'Formats'
            lengthName = category+'FormatLength'
            formatName = category+'Format'
            defaultName = 'default'+formatName[0].upper()+formatName[1:]

            formats_nodes = numbers_node.getElementsByTagName(formatsName)
            if formats_nodes:
                default, formats = self._extractFormats(
                    formats_nodes[0], lengthName, formatName)
                setattr(numbers, defaultName, default)
                setattr(numbers, formatsName, formats)


    def _extractCurrencies(self, numbers_node):
        """Extract all currency definitions and their information from the
        Locale's DOM tree.

        Example::

          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <numbers>
          ...   <currencies>
          ...     <currency type="USD">
          ...       <displayName>Dollar</displayName>
          ...       <symbol>$</symbol>
          ...     </currency>
          ...     <currency type ="JPY">
          ...       <displayName>Yen</displayName>
          ...       <symbol>Y</symbol>
          ...     </currency>
          ...     <currency type ="INR">
          ...       <displayName>Rupee</displayName>
          ...       <symbol choice="true">0&lt;=Rf|1&lt;=Ru|1&lt;Rf</symbol>
          ...     </currency>
          ...     <currency type="PTE">
          ...       <displayName>Escudo</displayName>
          ...       <symbol>$</symbol>
          ...     </currency>
          ...   </currencies>
          ... </numbers>'''
          >>> dom = parseString(xml)
          >>> currencies = factory._extractCurrencies(dom.documentElement)

          >>> keys = currencies.keys()
          >>> keys.sort()
          >>> keys
          [u'INR', u'JPY', u'PTE', u'USD']

          >>> currencies['USD'].symbol
          u'$'
          >>> currencies['USD'].displayName
          u'Dollar'
          >>> currencies['USD'].symbolChoice
          False
        """
        currs_nodes = numbers_node.getElementsByTagName('currencies')
        if not currs_nodes:
            return

        currencies = InheritingDictionary()
        for curr_node in currs_nodes[0].getElementsByTagName('currency'):
            type = curr_node.getAttribute('type')
            currency = LocaleCurrency(type)

            nodes = curr_node.getElementsByTagName('symbol')
            if nodes:
                currency.symbol = self._getText(nodes[0].childNodes)
                currency.symbolChoice = \
                                      nodes[0].getAttribute('choice') == u'true' 

            nodes = curr_node.getElementsByTagName('displayName')
            if nodes:
                currency.displayName = self._getText(nodes[0].childNodes)

            currencies[type] = currency

        return currencies


    def _extractNumbers(self):
        """Extract all number information from the DOM tree"""
        numbers_nodes = self._data.getElementsByTagName('numbers')
        if not numbers_nodes:
            return

        numbers = LocaleNumbers()
        numbers.symbols = self._extractSymbols(numbers_nodes[0])
        self._extractNumberFormats(numbers_nodes[0], numbers)
        numbers.currencies = self._extractCurrencies(numbers_nodes[0])
        return numbers
    

    def _extractDelimiters(self):
        """Extract all delimiter entries from the DOM tree.

        Example::

          >>> factory = LocaleFactory(None)
          >>> from xml.dom.minidom import parseString
          >>> xml = u'''
          ... <ldml>
          ...   <delimiters>
          ...     <quotationStart>``</quotationStart>
          ...     <quotationEnd>''</quotationEnd>
          ...     <alternateQuotationStart>`</alternateQuotationStart>
          ...     <alternateQuotationEnd>'</alternateQuotationEnd>
          ...   </delimiters>
          ... </ldml>'''
          >>> dom = parseString(xml)
          >>> factory._data = parseString(xml).documentElement
          >>> delimiters = factory._extractDelimiters()

          >>> delimiters[u'quotationStart']
          u'``'
          >>> delimiters[u'quotationEnd']
          u"''"
          >>> delimiters[u'alternateQuotationStart']
          u'`'
          >>> delimiters[u'alternateQuotationEnd'] 
          u"'"

          Escape: "'"
        """
        # See whether we have symbols entries
        delimiters_nodes = self._data.getElementsByTagName('delimiters')
        if not delimiters_nodes:
            return

        delimiters = InheritingDictionary()
        for name in (u'quotationStart', u'quotationEnd',
                     u'alternateQuotationStart', u'alternateQuotationEnd'):
            nodes = delimiters_nodes[0].getElementsByTagName(name)
            if nodes:
                delimiters[name] = self._getText(nodes[0].childNodes)

        return delimiters


    def __call__(self):
        """Create the Locale."""
        locale = Locale(self._extractIdentity())
        locale.displayNames = self._extractDisplayNames()
        locale.dates = self._extractDates()
        locale.numbers = self._extractNumbers()
        locale.delimiters = self._extractDelimiters
        
        # Unmapped:
        #
        #   - <characters>
        #   - <layout>
        #   - <measurement>
        #   - <collations>, <collation>

        return locale

=== Removed File Zope3/src/zope/i18n/locales/af.xml ===

=== Removed File Zope3/src/zope/i18n/locales/af_ZA.xml ===

=== Removed File Zope3/src/zope/i18n/locales/am.xml ===

=== Removed File Zope3/src/zope/i18n/locales/am_ET.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_AE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_BH.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_DZ.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_EG.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_IQ.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_JO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_KW.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_LB.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_LY.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_MA.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_OM.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_QA.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_SA.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_SD.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_SY.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_TN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ar_YE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/az.xml ===

=== Removed File Zope3/src/zope/i18n/locales/az_AZ.xml ===

=== Removed File Zope3/src/zope/i18n/locales/be.xml ===

=== Removed File Zope3/src/zope/i18n/locales/be_BY.xml ===

=== Removed File Zope3/src/zope/i18n/locales/bg.xml ===

=== Removed File Zope3/src/zope/i18n/locales/bg_BG.xml ===

=== Removed File Zope3/src/zope/i18n/locales/bn.xml ===

=== Removed File Zope3/src/zope/i18n/locales/bn_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ca.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ca_ES.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ca_ES_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/cs.xml ===

=== Removed File Zope3/src/zope/i18n/locales/cs_CZ.xml ===

=== Removed File Zope3/src/zope/i18n/locales/da.xml ===

=== Removed File Zope3/src/zope/i18n/locales/da_DK.xml ===

=== Removed File Zope3/src/zope/i18n/locales/de.xml ===

=== Removed File Zope3/src/zope/i18n/locales/de_AT.xml ===

=== Removed File Zope3/src/zope/i18n/locales/de_AT_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/de_BE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/de_CH.xml ===

=== Removed File Zope3/src/zope/i18n/locales/de_DE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/de_DE_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/de_LI.xml ===

=== Removed File Zope3/src/zope/i18n/locales/de_LU.xml ===

=== Removed File Zope3/src/zope/i18n/locales/de_LU_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/de__PHONEBOOK.xml ===

=== Removed File Zope3/src/zope/i18n/locales/div.xml ===

=== Removed File Zope3/src/zope/i18n/locales/div_MV.xml ===

=== Removed File Zope3/src/zope/i18n/locales/el.xml ===

=== Removed File Zope3/src/zope/i18n/locales/el_GR.xml ===

=== Removed File Zope3/src/zope/i18n/locales/el_GR_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_AS.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_AU.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_BE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_BE_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_BW.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_BZ.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_CA.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_GB.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_GB_EURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_GU.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_HK.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_IE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_IE_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_JM.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_MH.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_MP.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_MT.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_NZ.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_PH.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_SG.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_TT.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_UM.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_US.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_US_POSIX.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_VI.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_ZA.xml ===

=== Removed File Zope3/src/zope/i18n/locales/en_ZW.xml ===

=== Removed File Zope3/src/zope/i18n/locales/eo.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_AR.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_BO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_CL.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_CO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_CR.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_DO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_EC.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_ES.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_ES_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_GT.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_HN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_MX.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_NI.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_PA.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_PE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_PR.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_PY.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_SV.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_US.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_UY.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es_VE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/es__TRADITIONAL.xml ===

=== Removed File Zope3/src/zope/i18n/locales/et.xml ===

=== Removed File Zope3/src/zope/i18n/locales/et_EE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/eu.xml ===

=== Removed File Zope3/src/zope/i18n/locales/eu_ES.xml ===

=== Removed File Zope3/src/zope/i18n/locales/eu_ES_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fa.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fa_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fa_IR.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fi.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fi_FI.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fi_FI_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fo.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fo_FO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fr.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fr_BE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fr_BE_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fr_CA.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fr_CH.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fr_FR.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fr_FR_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fr_LU.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fr_LU_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/fr_MC.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ga.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ga_IE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ga_IE_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/gl.xml ===

=== Removed File Zope3/src/zope/i18n/locales/gl_ES.xml ===

=== Removed File Zope3/src/zope/i18n/locales/gl_ES_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/gu.xml ===

=== Removed File Zope3/src/zope/i18n/locales/gu_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/gv.xml ===

=== Removed File Zope3/src/zope/i18n/locales/gv_GB.xml ===

=== Removed File Zope3/src/zope/i18n/locales/he.xml ===

=== Removed File Zope3/src/zope/i18n/locales/he_IL.xml ===

=== Removed File Zope3/src/zope/i18n/locales/hi.xml ===

=== Removed File Zope3/src/zope/i18n/locales/hi_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/hi__DIRECT.xml ===

=== Removed File Zope3/src/zope/i18n/locales/hr.xml ===

=== Removed File Zope3/src/zope/i18n/locales/hr_HR.xml ===

=== Removed File Zope3/src/zope/i18n/locales/hu.xml ===

=== Removed File Zope3/src/zope/i18n/locales/hu_HU.xml ===

=== Removed File Zope3/src/zope/i18n/locales/hy.xml ===

=== Removed File Zope3/src/zope/i18n/locales/hy_AM.xml ===

=== Removed File Zope3/src/zope/i18n/locales/hy_AM_REVISED.xml ===

=== Removed File Zope3/src/zope/i18n/locales/id.xml ===

=== Removed File Zope3/src/zope/i18n/locales/id_ID.xml ===

=== Removed File Zope3/src/zope/i18n/locales/index.xml ===

=== Removed File Zope3/src/zope/i18n/locales/is.xml ===

=== Removed File Zope3/src/zope/i18n/locales/is_IS.xml ===

=== Removed File Zope3/src/zope/i18n/locales/it.xml ===

=== Removed File Zope3/src/zope/i18n/locales/it_CH.xml ===

=== Removed File Zope3/src/zope/i18n/locales/it_IT.xml ===

=== Removed File Zope3/src/zope/i18n/locales/it_IT_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/iw.xml ===

=== Removed File Zope3/src/zope/i18n/locales/iw_IL.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ja.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ja_JP.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ka.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ka_GE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/kk.xml ===

=== Removed File Zope3/src/zope/i18n/locales/kk_KZ.xml ===

=== Removed File Zope3/src/zope/i18n/locales/kl.xml ===

=== Removed File Zope3/src/zope/i18n/locales/kl_GL.xml ===

=== Removed File Zope3/src/zope/i18n/locales/kn.xml ===

=== Removed File Zope3/src/zope/i18n/locales/kn_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ko.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ko_KR.xml ===

=== Removed File Zope3/src/zope/i18n/locales/kok.xml ===

=== Removed File Zope3/src/zope/i18n/locales/kok_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/kw.xml ===

=== Removed File Zope3/src/zope/i18n/locales/kw_GB.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ky.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ky_KG.xml ===

=== Removed File Zope3/src/zope/i18n/locales/license.html ===

=== Removed File Zope3/src/zope/i18n/locales/lt.xml ===

=== Removed File Zope3/src/zope/i18n/locales/lt_LT.xml ===

=== Removed File Zope3/src/zope/i18n/locales/lv.xml ===

=== Removed File Zope3/src/zope/i18n/locales/lv_LV.xml ===

=== Removed File Zope3/src/zope/i18n/locales/mk.xml ===

=== Removed File Zope3/src/zope/i18n/locales/mk_MK.xml ===

=== Removed File Zope3/src/zope/i18n/locales/mn.xml ===

=== Removed File Zope3/src/zope/i18n/locales/mn_MN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/mr.xml ===

=== Removed File Zope3/src/zope/i18n/locales/mr_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ms.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ms_BN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ms_MY.xml ===

=== Removed File Zope3/src/zope/i18n/locales/mt.xml ===

=== Removed File Zope3/src/zope/i18n/locales/mt_MT.xml ===

=== Removed File Zope3/src/zope/i18n/locales/nb.xml ===

=== Removed File Zope3/src/zope/i18n/locales/nb_NO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/nl.xml ===

=== Removed File Zope3/src/zope/i18n/locales/nl_BE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/nl_BE_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/nl_NL.xml ===

=== Removed File Zope3/src/zope/i18n/locales/nl_NL_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/nn.xml ===

=== Removed File Zope3/src/zope/i18n/locales/nn_NO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/no.xml ===

=== Removed File Zope3/src/zope/i18n/locales/no_NO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/no_NO_NY.xml ===

=== Removed File Zope3/src/zope/i18n/locales/om.xml ===

=== Removed File Zope3/src/zope/i18n/locales/om_ET.xml ===

=== Removed File Zope3/src/zope/i18n/locales/om_KE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/pa.xml ===

=== Removed File Zope3/src/zope/i18n/locales/pa_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/pl.xml ===

=== Removed File Zope3/src/zope/i18n/locales/pl_PL.xml ===

=== Removed File Zope3/src/zope/i18n/locales/pt.xml ===

=== Removed File Zope3/src/zope/i18n/locales/pt_BR.xml ===

=== Removed File Zope3/src/zope/i18n/locales/pt_PT.xml ===

=== Removed File Zope3/src/zope/i18n/locales/pt_PT_PREEURO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ro.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ro_RO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/root.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ru.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ru_RU.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ru_UA.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sa.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sa_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sh.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sh_YU.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sk.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sk_SK.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sl.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sl_SI.xml ===

=== Removed File Zope3/src/zope/i18n/locales/so.xml ===

=== Removed File Zope3/src/zope/i18n/locales/so_DJ.xml ===

=== Removed File Zope3/src/zope/i18n/locales/so_ET.xml ===

=== Removed File Zope3/src/zope/i18n/locales/so_KE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/so_SO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sq.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sq_AL.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sr.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sr_YU.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sv.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sv_FI.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sv_SE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sw.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sw_KE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/sw_TZ.xml ===

=== Removed File Zope3/src/zope/i18n/locales/syr.xml ===

=== Removed File Zope3/src/zope/i18n/locales/syr_SY.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ta.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ta_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/te.xml ===

=== Removed File Zope3/src/zope/i18n/locales/te_IN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/th.xml ===

=== Removed File Zope3/src/zope/i18n/locales/th_TH.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ti.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ti_ER.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ti_ET.xml ===

=== Removed File Zope3/src/zope/i18n/locales/tr.xml ===

=== Removed File Zope3/src/zope/i18n/locales/tr_TR.xml ===

=== Removed File Zope3/src/zope/i18n/locales/tt.xml ===

=== Removed File Zope3/src/zope/i18n/locales/tt_RU.xml ===

=== Removed File Zope3/src/zope/i18n/locales/uk.xml ===

=== Removed File Zope3/src/zope/i18n/locales/uk_UA.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ur.xml ===

=== Removed File Zope3/src/zope/i18n/locales/ur_PK.xml ===

=== Removed File Zope3/src/zope/i18n/locales/uz.xml ===

=== Removed File Zope3/src/zope/i18n/locales/uz_UZ.xml ===

=== Removed File Zope3/src/zope/i18n/locales/vi.xml ===

=== Removed File Zope3/src/zope/i18n/locales/vi_VN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/zh.xml ===

=== Removed File Zope3/src/zope/i18n/locales/zh_CN.xml ===

=== Removed File Zope3/src/zope/i18n/locales/zh_HK.xml ===

=== Removed File Zope3/src/zope/i18n/locales/zh_MO.xml ===

=== Removed File Zope3/src/zope/i18n/locales/zh_SG.xml ===

=== Removed File Zope3/src/zope/i18n/locales/zh_TW.xml ===

=== Removed File Zope3/src/zope/i18n/locales/zh_TW_STROKE.xml ===

=== Removed File Zope3/src/zope/i18n/locales/zh__PINYIN.xml ===




More information about the Zope3-Checkins mailing list