summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2015-06-04 17:24:26 -0500
committerJason Madden <jamadden@gmail.com>2015-06-04 17:24:26 -0500
commite016951ed2c8f925b576052bdb20c8cccc91e3bd (patch)
tree47d9adabdfefff7b4427054ee1eb9a8f0bb6cbac
parent82281eb7ee9a2e71af6011053670648fdf31e938 (diff)
downloadzope-i18n-e016951ed2c8f925b576052bdb20c8cccc91e3bd.tar.gz
Add support for PyPy3 and Python3.2
-rw-r--r--.travis.yml2
-rw-r--r--CHANGES.rst5
-rw-r--r--setup.py1
-rw-r--r--src/zope/i18n/__init__.py25
-rw-r--r--src/zope/i18n/_compat.py32
-rw-r--r--src/zope/i18n/format.py44
-rw-r--r--src/zope/i18n/interfaces/__init__.py41
-rw-r--r--src/zope/i18n/interfaces/locales.py500
-rw-r--r--src/zope/i18n/locales/__init__.py75
-rw-r--r--src/zope/i18n/locales/fallbackcollator.txt17
-rw-r--r--src/zope/i18n/locales/xmlfactory.py231
-rw-r--r--src/zope/i18n/testmessagecatalog.py9
-rw-r--r--src/zope/i18n/testmessagecatalog.txt8
-rw-r--r--src/zope/i18n/tests/test_formats.py40
-rw-r--r--src/zope/i18n/tests/test_translationdomain.py38
-rw-r--r--src/zope/i18n/tests/test_zcml.py21
-rw-r--r--src/zope/i18n/translationdomain.py9
-rw-r--r--src/zope/i18n/zcml.py12
-rw-r--r--tox.ini2
19 files changed, 585 insertions, 527 deletions
diff --git a/.travis.yml b/.travis.yml
index e1ccd66..8cf9441 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,9 +4,11 @@ sudo: false
env:
- TOXENV=py26
- TOXENV=py27
+ - TOXENV=py32
- TOXENV=py33
- TOXENV=py34
- TOXENV=pypy
+ - TOXENV=pypy3
install:
- travis_retry pip install tox
diff --git a/CHANGES.rst b/CHANGES.rst
index a8e7cc1..6b185ae 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -2,6 +2,11 @@
CHANGES
=======
+4.0.1 (unreleased)
+--------------------
+
+- Added support for Python 3.2 and PyPy3.
+
4.0.0 (2014-12-20)
--------------------
diff --git a/setup.py b/setup.py
index a6cf22d..bc8effc 100644
--- a/setup.py
+++ b/setup.py
@@ -64,6 +64,7 @@ setup(
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: Implementation :: CPython',
diff --git a/src/zope/i18n/__init__.py b/src/zope/i18n/__init__.py
index ca4974e..6cb8443 100644
--- a/src/zope/i18n/__init__.py
+++ b/src/zope/i18n/__init__.py
@@ -24,6 +24,8 @@ from zope.i18n.interfaces import INegotiator
from zope.i18n.interfaces import ITranslationDomain
from zope.i18n.interfaces import IFallbackTranslationDomainFactory
+from ._compat import _u
+
PY3 = sys.version_info[0] == 3
if PY3:
unicode = str
@@ -69,14 +71,14 @@ def translate(msgid, domain=None, mapping=None, context=None,
Normally, the translation system will use a domain utility:
- >>> component.provideUtility(TestDomain(eek=u'ook'), name='my.domain')
- >>> translate(u'eek', 'my.domain')
+ >>> component.provideUtility(TestDomain(eek=_u("ook")), name='my.domain')
+ >>> translate(_u("eek"), 'my.domain')
u'ook'
Normally, if no domain is given, or if there is no domain utility
for the given domain, then the text isn't translated:
- >>> translate(u'eek')
+ >>> translate(_u("eek"))
u'eek'
Moreover the text will be converted to unicode:
@@ -87,8 +89,8 @@ def translate(msgid, domain=None, mapping=None, context=None,
A fallback domain factory can be provided. This is normally used
for testing:
- >>> def fallback(domain=u''):
- ... return TestDomain(eek=u'test-from-' + domain)
+ >>> def fallback(domain=_u("")):
+ ... return TestDomain(eek=_u("test-from-") + domain)
>>> interface.directlyProvides(
... fallback,
... zope.i18n.interfaces.IFallbackTranslationDomainFactory,
@@ -96,10 +98,10 @@ def translate(msgid, domain=None, mapping=None, context=None,
>>> component.provideUtility(fallback)
- >>> translate(u'eek')
+ >>> translate(_u("eek"))
u'test-from-'
- >>> translate(u'eek', 'your.domain')
+ >>> translate(_u("eek"), 'your.domain')
u'test-from-your.domain'
"""
@@ -139,23 +141,24 @@ def interpolate(text, mapping=None):
In the text we can use substitution slots like $varname or ${varname}:
- >>> interpolate(u"This is $name version ${version}.", mapping)
+ >>> from zope.i18n._compat import _u
+ >>> interpolate(_u("This is $name version ${version}."), mapping)
u'This is Zope version 3.'
Interpolation variables can be used more than once in the text:
- >>> interpolate(u"This is $name version ${version}. ${name} $version!",
+ >>> interpolate(_u("This is $name version ${version}. ${name} $version!"),
... mapping)
u'This is Zope version 3. Zope 3!'
In case if the variable wasn't found in the mapping or '$$' form
was used no substitution will happens:
- >>> interpolate(u"This is $name $version. $unknown $$name $${version}.",
+ >>> interpolate(_u("This is $name $version. $unknown $$name $${version}."),
... mapping)
u'This is Zope 3. $unknown $$name $${version}.'
- >>> interpolate(u"This is ${name}")
+ >>> interpolate(_u("This is ${name}"))
u'This is ${name}'
"""
diff --git a/src/zope/i18n/_compat.py b/src/zope/i18n/_compat.py
new file mode 100644
index 0000000..09b3f74
--- /dev/null
+++ b/src/zope/i18n/_compat.py
@@ -0,0 +1,32 @@
+##############################################################################
+#
+# Copyright (c) 2015 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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
+#
+##############################################################################
+import sys
+
+if sys.version_info[0] < 3: #pragma NO COVER Python2
+
+ PY2 = True
+ PY3 = False
+
+ def _u(s, encoding='unicode_escape'):
+ return unicode(s, encoding)
+
+else: #pragma NO COVER Python3
+
+ PY2 = False
+ PY3 = True
+
+ def _u(s, encoding=None):
+ if encoding is None:
+ return s
+ return str(s, encoding)
diff --git a/src/zope/i18n/format.py b/src/zope/i18n/format.py
index 51d64f1..7095ece 100644
--- a/src/zope/i18n/format.py
+++ b/src/zope/i18n/format.py
@@ -26,6 +26,8 @@ import pytz.reference
from zope.i18n.interfaces import IDateTimeFormat, INumberFormat
from zope.interface import implementer
+from ._compat import _u
+
PY3 = sys.version_info[0] == 3
if PY3:
unicode = str
@@ -199,7 +201,7 @@ class DateTimeFormat(object):
else:
bin_pattern = self._bin_pattern
- text = u''
+ text = _u("")
info = buildDateTimeInfo(obj, self.calendar, bin_pattern)
for elem in bin_pattern:
text += info.get(elem, elem)
@@ -222,18 +224,18 @@ class NumberFormat(object):
def __init__(self, pattern=None, symbols={}):
# setup default symbols
self.symbols = {
- u'decimal': u'.',
- u'group': u',',
- u'list': u';',
- u'percentSign': u'%',
- u'nativeZeroDigit': u'0',
- u'patternDigit': u'#',
- u'plusSign': u'+',
- u'minusSign': u'-',
- u'exponential': u'E',
- u'perMille': u'\xe2\x88\x9e',
- u'infinity': u'\xef\xbf\xbd',
- u'nan': '' }
+ _u("decimal"): _u("."),
+ _u("group"): _u(","),
+ _u("list"): _u(";"),
+ _u("percentSign"): _u("%"),
+ _u("nativeZeroDigit"): _u("0"),
+ _u("patternDigit"): _u("#"),
+ _u("plusSign"): _u("+"),
+ _u("minusSign"): _u("-"),
+ _u("exponential"): _u("E"),
+ _u("perMille"): _u("\xe2\x88\x9e"),
+ _u("infinity"): _u("\xef\xbf\xbd"),
+ _u("nan"): '' }
self.symbols.update(symbols)
self._pattern = pattern
self._bin_pattern = None
@@ -373,7 +375,7 @@ class NumberFormat(object):
# The exponential might have a mandatory sign; remove it from the
# bin_pattern and remember the setting
exp_bin_pattern = bin_pattern[EXPONENTIAL]
- plus_sign = u''
+ plus_sign = _u("")
if exp_bin_pattern.startswith('+'):
plus_sign = self.symbols['plusSign']
exp_bin_pattern = exp_bin_pattern[1:]
@@ -656,7 +658,7 @@ def buildDateTimeInfo(dt, calendar, pattern):
('S', dt.microsecond), ('w', int(dt.strftime('%W'))),
('W', week_in_month)):
for entry in _findFormattingCharacterInPattern(field, pattern):
- info[entry] = (u'%%.%ii' %entry[1]) %value
+ info[entry] = (_u("%%.%ii") %entry[1]) %value
# am/pm marker (Text)
for entry in _findFormattingCharacterInPattern('a', pattern):
@@ -670,9 +672,9 @@ def buildDateTimeInfo(dt, calendar, pattern):
# time zone (Text)
for entry in _findFormattingCharacterInPattern('z', pattern):
if entry[1] == 1:
- info[entry] = u"%s%i%.2i" %(tz_sign, tz_hours, tz_mins)
+ info[entry] = _u("%s%i%.2i") %(tz_sign, tz_hours, tz_mins)
elif entry[1] == 2:
- info[entry] = u"%s%.2i:%.2i" %(tz_sign, tz_hours, tz_mins)
+ info[entry] = _u("%s%.2i:%.2i") %(tz_sign, tz_hours, tz_mins)
elif entry[1] == 3:
info[entry] = tz_name
else:
@@ -681,9 +683,9 @@ def buildDateTimeInfo(dt, calendar, pattern):
# month in year (Text and Number)
for entry in _findFormattingCharacterInPattern('M', pattern):
if entry[1] == 1:
- info[entry] = u'%i' %dt.month
+ info[entry] = _u("%i") %dt.month
elif entry[1] == 2:
- info[entry] = u'%.2i' %dt.month
+ info[entry] = _u("%.2i") %dt.month
elif entry[1] == 3:
info[entry] = calendar.months[dt.month][1]
else:
@@ -692,9 +694,9 @@ def buildDateTimeInfo(dt, calendar, pattern):
# day in week (Text and Number)
for entry in _findFormattingCharacterInPattern('E', pattern):
if entry[1] == 1:
- info[entry] = u'%i' %weekday
+ info[entry] = _u("%i") %weekday
elif entry[1] == 2:
- info[entry] = u'%.2i' %weekday
+ info[entry] = _u("%.2i") %weekday
elif entry[1] == 3:
info[entry] = calendar.days[dt.weekday() + 1][1]
else:
diff --git a/src/zope/i18n/interfaces/__init__.py b/src/zope/i18n/interfaces/__init__.py
index 99944c2..9cee5c6 100644
--- a/src/zope/i18n/interfaces/__init__.py
+++ b/src/zope/i18n/interfaces/__init__.py
@@ -16,6 +16,7 @@
from zope.interface import Interface, Attribute
from zope.schema import TextLine, Dict, Choice, Field
+from .._compat import _u
class II18nAware(Interface):
"""Internationalization aware content object."""
@@ -68,13 +69,13 @@ class IMessageCatalog(Interface):
"""
language = TextLine(
- title=u"Language",
- description=u"The language the catalog translates to.",
+ title=_u("Language"),
+ description=_u("The language the catalog translates to."),
required=True)
domain = TextLine(
- title=u"Domain",
- description=u"The domain the catalog is registered for.",
+ title=_u("Domain"),
+ description=_u("The domain the catalog is registered for."),
required=True)
def getIdentifier():
@@ -128,8 +129,8 @@ class ITranslationDomain(Interface):
"""
domain = TextLine(
- title=u"Domain Name",
- description=u"The name of the domain this object represents.",
+ title=_u("Domain Name"),
+ description=_u("The name of the domain this object represents."),
required=True)
def translate(msgid, mapping=None, context=None, target_language=None,
@@ -154,8 +155,8 @@ class IFallbackTranslationDomainFactory(Interface):
debugging i18n.
"""
- def __call__(domain_id=u''):
- """Return a fallback translation domain for the given domain id.
+ def __call__(domain_id=_u("")):
+ """Return a fallback translation domain for the given domain id.
"""
class ITranslator(Interface):
@@ -302,7 +303,7 @@ class IFormat(Interface):
class INumberFormat(IFormat):
- u"""Specific number formatting interface. Here are the formatting
+ """Specific number formatting interface. Here are the formatting
rules (I modified the rules from ICU a bit, since I think they did not
agree well with the real world XML formatting strings):
@@ -356,22 +357,22 @@ class INumberFormat(IFormat):
"""
type = Field(
- title=u'Type',
- description=(u'The type into which a string is parsed. If ``None``, '
- u'then ``int`` will be used for whole numbers and '
- u'``float`` for decimals.'),
+ title=_u("Type"),
+ description=(_u("The type into which a string is parsed. If ``None``, "
+ "then ``int`` will be used for whole numbers and "
+ "``float`` for decimals.")),
default=None,
required=False)
symbols = Dict(
- title=u"Number Symbols",
+ title=_u("Number Symbols"),
key_type=Choice(
- title=u"Dictionary Class",
- values=(u'decimal', u'group', u'list', u'percentSign',
- u'nativeZeroDigit', u'patternDigit', u'plusSign',
- u'minusSign', u'exponential', u'perMille',
- u'infinity', u'nan')),
- value_type=TextLine(title=u"Symbol"))
+ title=_u("Dictionary Class"),
+ values=(_u("decimal"), _u("group"), _u("list"), _u("percentSign"),
+ _u("nativeZeroDigit"), _u("patternDigit"), _u("plusSign"),
+ _u("minusSign"), _u("exponential"), _u("perMille"),
+ _u("infinity"), _u("nan"))),
+ value_type=TextLine(title=_u("Symbol")))
class IDateTimeFormat(IFormat):
diff --git a/src/zope/i18n/interfaces/locales.py b/src/zope/i18n/interfaces/locales.py
index e054d08..25d64de 100644
--- a/src/zope/i18n/interfaces/locales.py
+++ b/src/zope/i18n/interfaces/locales.py
@@ -18,6 +18,7 @@ from zope.interface import Interface, Attribute
from zope.schema import \
Field, Text, TextLine, Int, Bool, Tuple, List, Dict, Date
from zope.schema import Container, Choice
+from .._compat import _u
class ILocaleProvider(Interface):
"""This interface is our connection to the Zope 3 service. From it
@@ -64,37 +65,37 @@ class ILocaleIdentity(Interface):
"""
language = TextLine(
- title = u"Language Type",
- description = u"The language for which a locale is applicable.",
+ title = _u("Language Type"),
+ description = _u("The language for which a locale is applicable."),
constraint = re.compile(r'[a-z]{2}').match,
required = True,
readonly = True)
script = TextLine(
- title = u"Script Type",
- description = u"""The script for which the language/locale is
- applicable.""",
+ title = _u("Script Type"),
+ description = _u("""The script for which the language/locale is
+ applicable."""),
constraint = re.compile(r'[a-z]*').match)
territory = TextLine(
- title = u"Territory Type",
- description = u"The territory for which a locale is applicable.",
+ title = _u("Territory Type"),
+ description = _u("The territory for which a locale is applicable."),
constraint = re.compile(r'[A-Z]{2}').match,
required = True,
readonly = True)
variant = TextLine(
- title = u"Variant Type",
- description = u"The variant for which a locale is applicable.",
+ title = _u("Variant Type"),
+ description = _u("The variant for which a locale is applicable."),
constraint = re.compile(r'[a-zA-Z]*').match,
required = True,
readonly = True)
version = Field(
- title = u"Locale Version",
- description = u"The value of this field is an ILocaleVersion object.",
+ title = _u("Locale Version"),
+ description = _u("The value of this field is an ILocaleVersion object."),
readonly = True)
-
+
def __repr__(self):
"""Defines the representation of the id, which should be a compact
string that references the language, country and variant."""
@@ -105,23 +106,23 @@ class ILocaleVersion(Interface):
The locale version is part of the ILocaleIdentity object.
"""
-
+
number = TextLine(
- title = u"Version Number",
- description = u"The version number of the locale.",
+ title = _u("Version Number"),
+ description = _u("The version number of the locale."),
constraint = re.compile(r'^([0-9].)*[0-9]$').match,
required = True,
readonly = True)
generationDate = Date(
- title = u"Generation Date",
- description = u"Specifies the creation date of the locale.",
+ title = _u("Generation Date"),
+ description = _u("Specifies the creation date of the locale."),
constraint = lambda date: date < datetime.now(),
readonly = True)
notes = Text(
- title = u"Notes",
- description = u"Some release notes for the version of this locale.",
+ title = _u("Notes"),
+ description = _u("Some release notes for the version of this locale."),
readonly = True)
@@ -132,36 +133,36 @@ class ILocaleDisplayNames(Interface):
language, script and territory names. But also keys and types used
throughout the locale object are localized here.
"""
-
+
languages = Dict(
- title = u"Language type to translated name",
- key_type = TextLine(title=u"Language Type"),
- value_type = TextLine(title=u"Language Name"))
+ title = _u("Language type to translated name"),
+ key_type = TextLine(title=_u("Language Type")),
+ value_type = TextLine(title=_u("Language Name")))
scripts = Dict(
- title = u"Script type to script name",
- key_type = TextLine(title=u"Script Type"),
- value_type = TextLine(title=u"Script Name"))
+ title = _u("Script type to script name"),
+ key_type = TextLine(title=_u("Script Type")),
+ value_type = TextLine(title=_u("Script Name")))
territories = Dict(
- title = u"Territory type to translated territory name",
- key_type = TextLine(title=u"Territory Type"),
- value_type = TextLine(title=u"Territory Name"))
+ title = _u("Territory type to translated territory name"),
+ key_type = TextLine(title=_u("Territory Type")),
+ value_type = TextLine(title=_u("Territory Name")))
variants = Dict(
- title = u"Variant type to name",
- key_type = TextLine(title=u"Variant Type"),
- value_type = TextLine(title=u"Variant Name"))
+ title = _u("Variant type to name"),
+ key_type = TextLine(title=_u("Variant Type")),
+ value_type = TextLine(title=_u("Variant Name")))
keys = Dict(
- title = u"Key type to name",
- key_type = TextLine(title=u"Key Type"),
- value_type = TextLine(title=u"Key Name"))
+ title = _u("Key type to name"),
+ key_type = TextLine(title=_u("Key Type")),
+ value_type = TextLine(title=_u("Key Name")))
types = Dict(
- title = u"Type type and key to localized name",
- key_type = Tuple(title=u"Type Type and Key"),
- value_type = TextLine(title=u"Type Name"))
+ title = _u("Type type and key to localized name"),
+ key_type = Tuple(title=_u("Type Type and Key")),
+ value_type = TextLine(title=_u("Type Name")))
class ILocaleTimeZone(Interface):
@@ -174,26 +175,26 @@ class ILocaleTimeZone(Interface):
"""
type = TextLine(
- title = u"Time Zone Type",
- description = u"Standard name of the timezone for unique referencing.",
+ title = _u("Time Zone Type"),
+ description = _u("Standard name of the timezone for unique referencing."),
required = True,
readonly = True)
cities = List(
- title = u"Cities",
- description = u"Cities in Timezone",
- value_type = TextLine(title=u"City Name"),
+ title = _u("Cities"),
+ description = _u("Cities in Timezone"),
+ value_type = TextLine(title=_u("City Name")),
required = True,
readonly = True)
names = Dict(
- title = u"Time Zone Names",
- description = u"Various names of the timezone.",
+ title = _u("Time Zone Names"),
+ description = _u("Various names of the timezone."),
key_type = Choice(
- title = u"Time Zone Name Type",
- values = (u'generic', u'standard', u'daylight')),
- value_type = Tuple(title=u"Time Zone Name and Abbreviation",
+ title = _u("Time Zone Name Type"),
+ values = (_u("generic"), _u("standard"), _u("daylight"))),
+ value_type = Tuple(title=_u("Time Zone Name and Abbreviation"),
min_length=2, max_length=2),
required = True,
readonly = True)
@@ -203,44 +204,44 @@ class ILocaleFormat(Interface):
"""Specifies a format for a particular type of data."""
type = TextLine(
- title=u"Format Type",
- description=u"The name of the format",
+ title=_u("Format Type"),
+ description=_u("The name of the format"),
required = False,
readonly = True)
displayName = TextLine(
- title = u"Display Name",
- description = u"Name of the calendar, for example 'gregorian'.",
+ title = _u("Display Name"),
+ description = _u("Name of the calendar, for example 'gregorian'."),
required = False,
readonly = True)
pattern = TextLine(
- title = u"Format Pattern",
- description = u"The pattern that is used to format the object.",
+ title = _u("Format Pattern"),
+ description = _u("The pattern that is used to format the object."),
required = True,
readonly = True)
class ILocaleFormatLength(Interface):
"""The format length describes a class of formats."""
-
+
type = Choice(
- title = u"Format Length Type",
- description = u"Name of the format length",
- values = (u'full', u'long', u'medium', u'short')
+ title = _u("Format Length Type"),
+ description = _u("Name of the format length"),
+ values = (_u("full"), _u("long"), _u("medium"), _u("short"))
)
default = TextLine(
- title=u"Default Format",
- description=u"The name of the defaulkt format.")
+ title=_u("Default Format"),
+ description=_u("The name of the defaulkt format."))
formats = Dict(
- title = u"Formats",
- description = u"Maps format types to format objects",
- key_type = TextLine(title = u"Format Type"),
+ title = _u("Formats"),
+ description = _u("Maps format types to format objects"),
+ key_type = TextLine(title = _u("Format Type")),
value_type = Field(
- title = u"Format Object",
- description = u"Values are ILocaleFormat objects."),
+ title = _u("Format Object"),
+ description = _u("Values are ILocaleFormat objects.")),
required = True,
readonly = True)
@@ -249,24 +250,24 @@ class ILocaleMonthContext(Interface):
"""Specifices a usage context for month names"""
type = TextLine(
- title=u'Month context type',
- description=u"Name of the month context, format or stand-alone.")
+ title=_u("Month context type"),
+ description=_u("Name of the month context, format or stand-alone."))
defaultWidth = TextLine(
- title=u'Default month name width',
- default=u'wide')
+ title=_u("Default month name width"),
+ default=_u("wide"))
months = Dict(
- title=u'Month Names',
- description=u'A mapping of month name widths to a mapping of'
- u'corresponding month names.',
+ title=_u("Month Names"),
+ description=_u("A mapping of month name widths to a mapping of"
+ "corresponding month names."),
key_type=Choice(
- title=u'Width type',
- values=(u'wide', u'abbreviated', u'narrow')),
+ title=_u("Width type"),
+ values=(_u("wide"), _u("abbreviated"), _u("narrow"))),
value_type=Dict(
- title=u'Month name',
- key_type=Int(title=u'Type', min=1, max=12),
- value_type=TextLine(title=u'Month Name'))
+ title=_u("Month name"),
+ key_type=Int(title=_u("Type"), min=1, max=12),
+ value_type=TextLine(title=_u("Month Name")))
)
@@ -274,27 +275,27 @@ class ILocaleDayContext(Interface):
"""Specifices a usage context for days names"""
type = TextLine(
- title=u'Day context type',
- description=u"Name of the day context, format or stand-alone.")
+ title=_u("Day context type"),
+ description=_u("Name of the day context, format or stand-alone."))
defaultWidth = TextLine(
- title=u'Default day name width',
- default=u'wide')
+ title=_u("Default day name width"),
+ default=_u("wide"))
days = Dict(
- title=u'Day Names',
- description=u'A mapping of day name widths to a mapping of'
- u'corresponding day names.',
+ title=_u("Day Names"),
+ description=_u("A mapping of day name widths to a mapping of"
+ "corresponding day names."),
key_type=Choice(
- title=u'Width type',
- values=(u'wide', u'abbreviated', u'narrow')),
+ title=_u("Width type"),
+ values=(_u("wide"), _u("abbreviated"), _u("narrow"))),
value_type=Dict(
- title=u'Day name',
+ title=_u("Day name"),
key_type=Choice(
- title=u"Type",
- values=(u'sun', u'mon', u'tue', u'wed',
- u'thu', u'fri', u'sat')),
- value_type=TextLine(title=u'Day Name'))
+ title=_u("Type"),
+ values=(_u("sun"), _u("mon"), _u("tue"), _u("wed"),
+ _u("thu"), _u("fri"), _u("sat"))),
+ value_type=TextLine(title=_u("Day Name")))
)
@@ -303,57 +304,57 @@ class ILocaleCalendar(Interface):
which made it attractive to be added."""
type = TextLine(
- title=u"Calendar Type",
- description=u"Name of the calendar, for example 'gregorian'.")
+ title=_u("Calendar Type"),
+ description=_u("Name of the calendar, for example 'gregorian'."))
defaultMonthContext = TextLine(
- title=u'Default month context',
- default=u'format')
-
+ title=_u("Default month context"),
+ default=_u("format"))
+
monthContexts = Dict(
- title=u'Month Contexts',
- description=u'A mapping of month context types to '
- u'ILocaleMonthContext objects',
- key_type=Choice(title=u'Type',
- values=(u'format', u'stand-alone')),
- value_type=Field(title=u'ILocaleMonthContext object'))
+ title=_u("Month Contexts"),
+ description=_u("A mapping of month context types to "
+ "ILocaleMonthContext objects"),
+ key_type=Choice(title=_u("Type"),
+ values=(_u("format"), _u("stand-alone"))),
+ value_type=Field(title=_u("ILocaleMonthContext object")))
# BBB: leftover from CLDR 1.0
months = Dict(
- title = u"Month Names",
- description = u"A mapping of all month names and abbreviations",
- key_type = Int(title=u"Type", min=1, max=12),
- value_type = Tuple(title=u"Month Name and Abbreviation",
+ title = _u("Month Names"),
+ description = _u("A mapping of all month names and abbreviations"),
+ key_type = Int(title=_u("Type"), min=1, max=12),
+ value_type = Tuple(title=_u("Month Name and Abbreviation"),
min_length=2, max_length=2))
defaultDayContext = TextLine(
- title=u'Default day context',
- default=u'format')
-
+ title=_u("Default day context"),
+ default=_u("format"))
+
dayContexts = Dict(
- title=u'Day Contexts',
- description=u'A mapping of day context types to '
- u'ILocaleDayContext objects',
- key_type=Choice(title=u'Type',
- values=(u'format', u'stand-alone')),
- value_type=Field(title=u'ILocaleDayContext object'))
+ title=_u("Day Contexts"),
+ description=_u("A mapping of day context types to "
+ "ILocaleDayContext objects"),
+ key_type=Choice(title=_u("Type"),
+ values=(_u("format"), _u("stand-alone"))),
+ value_type=Field(title=_u("ILocaleDayContext object")))
# BBB: leftover from CLDR 1.0
days = Dict(
- title=u"Weekdays Names",
- description = u"A mapping of all month names and abbreviations",
- key_type = Choice(title=u"Type",
- values=(u'sun', u'mon', u'tue', u'wed',
- u'thu', u'fri', u'sat')),
- value_type = Tuple(title=u"Weekdays Name and Abbreviation",
+ title=_u("Weekdays Names"),
+ description = _u("A mapping of all month names and abbreviations"),
+ key_type = Choice(title=_u("Type"),
+ values=(_u("sun"), _u("mon"), _u("tue"), _u("wed"),
+ _u("thu"), _u("fri"), _u("sat"))),
+ value_type = Tuple(title=_u("Weekdays Name and Abbreviation"),
min_length=2, max_length=2))
week = Dict(
- title=u"Week Information",
- description = u"Contains various week information",
+ title=_u("Week Information"),
+ description = _u("Contains various week information"),
key_type = Choice(
- title=u"Type",
- description=u"""
+ title=_u("Type"),
+ description=_u("""
Varies Week information:
- 'minDays' is just an integer between 1 and 7.
@@ -362,52 +363,52 @@ class ILocaleCalendar(Interface):
- The 'weekendStart' and 'weekendEnd' are tuples of the form
(weekDayNumber, datetime.time)
- """,
- values=(u'minDays', u'firstDay',
- u'weekendStart', u'weekendEnd')))
+ """),
+ values=(_u("minDays"), _u("firstDay"),
+ _u("weekendStart"), _u("weekendEnd"))))
- am = TextLine(title=u"AM String")
+ am = TextLine(title=_u("AM String"))
- pm = TextLine(title=u"PM String")
+ pm = TextLine(title=_u("PM String"))
eras = Dict(
- title = u"Era Names",
- key_type = Int(title=u"Type", min=0),
- value_type = Tuple(title=u"Era Name and Abbreviation",
+ title = _u("Era Names"),
+ key_type = Int(title=_u("Type"), min=0),
+ value_type = Tuple(title=_u("Era Name and Abbreviation"),
min_length=2, max_length=2))
- defaultDateFormat = TextLine(title=u"Default Date Format Type")
+ defaultDateFormat = TextLine(title=_u("Default Date Format Type"))
dateFormats = Dict(
- title=u"Date Formats",
- description = u"Contains various Date Formats.",
+ title=_u("Date Formats"),
+ description = _u("Contains various Date Formats."),
key_type = Choice(
- title=u"Type",
- description = u"Name of the format length",
- values = (u'full', u'long', u'medium', u'short')),
- value_type = Field(title=u"ILocaleFormatLength object"))
+ title=_u("Type"),
+ description = _u("Name of the format length"),
+ values = (_u("full"), _u("long"), _u("medium"), _u("short"))),
+ value_type = Field(title=_u("ILocaleFormatLength object")))
- defaultTimeFormat = TextLine(title=u"Default Time Format Type")
+ defaultTimeFormat = TextLine(title=_u("Default Time Format Type"))
timeFormats = Dict(
- title=u"Time Formats",
- description = u"Contains various Time Formats.",
+ title=_u("Time Formats"),
+ description = _u("Contains various Time Formats."),
key_type = Choice(
- title=u"Type",
- description = u"Name of the format length",
- values = (u'full', u'long', u'medium', u'short')),
- value_type = Field(title=u"ILocaleFormatLength object"))
+ title=_u("Type"),
+ description = _u("Name of the format length"),
+ values = (_u("full"), _u("long"), _u("medium"), _u("short"))),
+ value_type = Field(title=_u("ILocaleFormatLength object")))
- defaultDateTimeFormat = TextLine(title=u"Default Date-Time Format Type")
+ defaultDateTimeFormat = TextLine(title=_u("Default Date-Time Format Type"))
dateTimeFormats = Dict(
- title=u"Date-Time Formats",
- description = u"Contains various Date-Time Formats.",
+ title=_u("Date-Time Formats"),
+ description = _u("Contains various Date-Time Formats."),
key_type = Choice(
- title=u"Type",
- description = u"Name of the format length",
- values = (u'full', u'long', u'medium', u'short')),
- value_type = Field(title=u"ILocaleFormatLength object"))
+ title=_u("Type"),
+ description = _u("Name of the format length"),
+ values = (_u("full"), _u("long"), _u("medium"), _u("short"))),
+ value_type = Field(title=_u("ILocaleFormatLength object")))
def getMonthNames():
"""Return a list of month names."""
@@ -437,37 +438,37 @@ class ILocaleCalendar(Interface):
"""Determines whether a the argument lies in a weekend."""
def getFirstDayName():
- """Return the the type of the first day in the week."""
+ """Return the the type of the first day in the week."""
class ILocaleDates(Interface):
"""This object contains various data about dates, times and time zones."""
localizedPatternChars = TextLine(
- title = u"Localized Pattern Characters",
- description = u"Localized pattern characters used in dates and times")
+ title = _u("Localized Pattern Characters"),
+ description = _u("Localized pattern characters used in dates and times"))
calendars = Dict(
- title = u"Calendar type to ILocaleCalendar",
+ title = _u("Calendar type to ILocaleCalendar"),
key_type = Choice(
- title=u"Calendar Type",
- values=(u'gregorian',
- u'arabic',
- u'chinese',
- u'civil-arabic',
- u'hebrew',
- u'japanese',
- u'thai-buddhist')),
- value_type=Field(title=u"Calendar",
- description=u"This is a ILocaleCalendar object."))
+ title=_u("Calendar Type"),
+ values=(_u("gregorian"),
+ _u("arabic"),
+ _u("chinese"),
+ _u("civil-arabic"),
+ _u("hebrew"),
+ _u("japanese"),
+ _u("thai-buddhist"))),
+ value_type=Field(title=_u("Calendar"),
+ description=_u("This is a ILocaleCalendar object.")))
timezones = Dict(
- title=u"Time zone type to ILocaleTimezone",
- key_type=TextLine(title=u"Time Zone type"),
- value_type=Field(title=u"Time Zone",
- description=u"This is a ILocaleTimeZone object."))
+ title=_u("Time zone type to ILocaleTimezone"),
+ key_type=TextLine(title=_u("Time Zone type")),
+ value_type=Field(title=_u("Time Zone"),
+ description=_u("This is a ILocaleTimeZone object.")))
- def getFormatter(category, length=None, name=None, calendar=u'gregorian'):
+ def getFormatter(category, length=None, name=None, calendar=_u("gregorian")):
"""Get a date/time formatter.
`category` must be one of 'date', 'dateTime', 'time'.
@@ -481,81 +482,81 @@ class ILocaleDates(Interface):
class ILocaleCurrency(Interface):
"""Defines a particular currency."""
- type = TextLine(title=u'Type')
+ type = TextLine(title=_u("Type"))
- symbol = TextLine(title=u'Symbol')
+ symbol = TextLine(title=_u("Symbol"))
- displayName = TextLine(title=u'Official Name')
+ displayName = TextLine(title=_u("Official Name"))
- symbolChoice = Bool(title=u'Symbol Choice')
+ symbolChoice = Bool(title=_u("Symbol Choice"))
class ILocaleNumbers(Interface):
"""This object contains various data about numbers and currencies."""
symbols = Dict(
- title = u"Number Symbols",
+ title = _u("Number Symbols"),
key_type = Choice(
- title = u"Format Name",
- values = (u'decimal', u'group', u'list', u'percentSign',
- u'nativeZeroDigit', u'patternDigit', u'plusSign',
- u'minusSign', u'exponential', u'perMille',
- u'infinity', u'nan')),
- value_type=TextLine(title=u"Symbol"))
+ title = _u("Format Name"),
+ values = (_u("decimal"), _u("group"), _u("list"), _u("percentSign"),
+ _u("nativeZeroDigit"), _u("patternDigit"), _u("plusSign"),
+ _u("minusSign"), _u("exponential"), _u("perMille"),
+ _u("infinity"), _u("nan"))),
+ value_type=TextLine(title=_u("Symbol")))
- defaultDecimalFormat = TextLine(title=u"Default Decimal Format Type")
+ defaultDecimalFormat = TextLine(title=_u("Default Decimal Format Type"))
decimalFormats = Dict(
- title=u"Decimal Formats",
- description = u"Contains various Decimal Formats.",
+ title=_u("Decimal Formats"),
+ description = _u("Contains various Decimal Formats."),
key_type = Choice(
- title=u"Type",
- description = u"Name of the format length",
- values = (u'full', u'long', u'medium', u'short')),
- value_type = Field(title=u"ILocaleFormatLength object"))
+ title=_u("Type"),
+ description = _u("Name of the format length"),
+ values = (_u("full"), _u("long"), _u("medium"), _u("short"))),
+ value_type = Field(title=_u("ILocaleFormatLength object")))
- defaultScientificFormat = TextLine(title=u"Default Scientific Format Type")
+ defaultScientificFormat = TextLine(title=_u("Default Scientific Format Type"))
scientificFormats = Dict(
- title=u"Scientific Formats",
- description = u"Contains various Scientific Formats.",
+ title=_u("Scientific Formats"),
+ description = _u("Contains various Scientific Formats."),
key_type = Choice(
- title=u"Type",
- description = u"Name of the format length",
- values = (u'full', u'long', u'medium', u'short')),
- value_type = Field(title=u"ILocaleFormatLength object"))
+ title=_u("Type"),
+ description = _u("Name of the format length"),
+ values = (_u("full"), _u("long"), _u("medium"), _u("short"))),
+ value_type = Field(title=_u("ILocaleFormatLength object")))
- defaultPercentFormat = TextLine(title=u"Default Percent Format Type")
+ defaultPercentFormat = TextLine(title=_u("Default Percent Format Type"))
percentFormats = Dict(
- title=u"Percent Formats",
- description = u"Contains various Percent Formats.",
+ title=_u("Percent Formats"),
+ description = _u("Contains various Percent Formats."),
key_type = Choice(
- title=u"Type",
- description = u"Name of the format length",
- values = (u'full', u'long', u'medium', u'short')),
- value_type = Field(title=u"ILocaleFormatLength object"))
+ title=_u("Type"),
+ description = _u("Name of the format length"),
+ values = (_u("full"), _u("long"), _u("medium"), _u("short"))),
+ value_type = Field(title=_u("ILocaleFormatLength object")))
- defaultCurrencyFormat = TextLine(title=u"Default Currency Format Type")
+ defaultCurrencyFormat = TextLine(title=_u("Default Currency Format Type"))
currencyFormats = Dict(
- title=u"Currency Formats",
- description = u"Contains various Currency Formats.",
+ title=_u("Currency Formats"),
+ description = _u("Contains various Currency Formats."),
key_type = Choice(
- title=u"Type",
- description = u"Name of the format length",
- values = (u'full', u'long', u'medium', u'short')),
- value_type = Field(title=u"ILocaleFormatLength object"))
+ title=_u("Type"),
+ description = _u("Name of the format length"),
+ values = (_u("full"), _u("long"), _u("medium"), _u("short"))),
+ value_type = Field(title=_u("ILocaleFormatLength object")))
currencies = Dict(
- title=u"Currencies",
- description = u"Contains various Currency data.",
+ title=_u("Currencies"),
+ description = _u("Contains various Currency data."),
key_type = TextLine(
- title=u"Type",
- description = u"Name of the format length"),
- value_type = Field(title=u"ILocaleCurrency object"))
+ title=_u("Type"),
+ description = _u("Name of the format length")),
+ value_type = Field(title=_u("ILocaleCurrency object")))
- def getFormatter(category, length=None, name=u''):
+ def getFormatter(category, length=None, name=_u("")):
"""Get the NumberFormat based on the category, length and name of the
format.
@@ -575,23 +576,23 @@ class ILocaleNumbers(Interface):
def getDefaultCurrency():
"""Get the default currency."""
-_orientations = [u"left-to-right", u"right-to-left",
- u"top-to-bottom", u"bottom-to-top"]
+_orientations = [_u("left-to-right"), _u("right-to-left"),
+ _u("top-to-bottom"), _u("bottom-to-top")]
class ILocaleOrientation(Interface):
"""Information about the orientation of text."""
characters = Choice(
- title = u"Orientation of characters",
+ title = _u("Orientation of characters"),
values = _orientations,
- default = u"left-to-right"
+ default = _u("left-to-right")
)
lines = Choice(
- title = u"Orientation of characters",
+ title = _u("Orientation of characters"),
values = _orientations,
- default = u"top-to-bottom"
+ default = _u("top-to-bottom")
)
-
+
class ILocale(Interface):
"""This class contains all important information about the locale.
@@ -605,38 +606,39 @@ class ILocale(Interface):
"""
id = Field(
- title = u"Locale identity",
- description = u"ILocaleIdentity object identifying the locale.",
+ title = _u("Locale identity"),
+ description = _u("ILocaleIdentity object identifying the locale."),
required = True,
readonly = True)
displayNames = Field(
- title = u"Display Names",
- description = u"""ILocaleDisplayNames object that contains localized
- names.""")
+ title = _u("Display Names"),
+ description = _u("""ILocaleDisplayNames object that contains localized
+ names."""))
dates = Field(
- title = u"Dates",
- description = u"ILocaleDates object that contains date/time data.")
+ title = _u("Dates"),
+ description = _u("ILocaleDates object that contains date/time data."))
numbers = Field(
- title = u"Numbers",
- description = u"ILocaleNumbers object that contains number data.")
+ title = _u("Numbers"),
+ description = _u("ILocaleNumbers object that contains number data."))
orientation = Field(
- title = u"Orientation",
- description = u"ILocaleOrientation with text orientation info.")
+ title = _u("Orientation"),
+ description = _u("ILocaleOrientation with text orientation info."))
delimiters = Dict(
- title=u"Delimiters",
- description = u"Contains various Currency data.",
+ title=_u("Delimiters"),
+ description = _u("Contains various Currency data."),
key_type = Choice(
- title=u"Delimiter Type",
- description = u"Delimiter name.",
- values=(u'quotationStart', u'quotationEnd',
- u'alternateQuotationStart',
- u'alternateQuotationEnd')),
- value_type = Field(title=u"Delimiter symbol"))
+ title=_u("Delimiter Type"),
+ description = _u("Delimiter name."),
+ values=(_u("quotationStart"),
+ _u("quotationEnd"),
+ _u("alternateQuotationStart"),
+ _u("alternateQuotationEnd"))),
+ value_type = Field(title=_u("Delimiter symbol")))
def getLocaleID():
"""Return a locale id as specified in the LDML specification"""
@@ -647,15 +649,15 @@ class ILocaleInheritance(Interface):
Locale-related objects implementing this interface are able to ask for its
inherited self. For example, 'en_US.dates.monthNames' can call on itself
- 'getInheritedSelf()' and get the value for 'en.dates.monthNames'.
+ 'getInheritedSelf()' and get the value for 'en.dates.monthNames'.
"""
__parent__ = Attribute("The parent in the location hierarchy")
__name__ = TextLine(
- title = u"The name within the parent",
- description=u"""The parent can be traversed with this name to get
- the object.""")
+ title = _u("The name within the parent"),
+ description=_u("""The parent can be traversed with this name to get
+ the object."""))
def getInheritedSelf():
"""Return itself but in the next higher up Locale."""
@@ -712,5 +714,3 @@ class ICollator(Interface):
The return value is negative if text1 < text2, 0 is they are
equal, and positive if text1 > text2.
"""
-
-
diff --git a/src/zope/i18n/locales/__init__.py b/src/zope/i18n/locales/__init__.py
index da83db3..f36edd9 100644
--- a/src/zope/i18n/locales/__init__.py
+++ b/src/zope/i18n/locales/__init__.py
@@ -32,6 +32,7 @@ from zope.i18n.format import NumberFormat, DateTimeFormat
from zope.i18n.locales.inheritance import \
AttributeInheritance, InheritingDictionary, NoParentException
from zope.i18n.locales.provider import LocaleProvider, LoadLocaleError
+from .._compat import _u
# Setup the locale directory
from zope import i18n
@@ -223,8 +224,8 @@ class LocaleFormat(object):
def __init__(self, type=None):
"""Initialize the object."""
self.type = type
- self.displayName = u''
- self.pattern = u''
+ self.displayName = _u("")
+ self.pattern = _u("")
@implementer(ILocaleFormatLength)
@@ -245,7 +246,7 @@ class LocaleMonthContext(AttributeInheritance):
def __init__(self, type=None):
"""Initialize the object."""
self.type = type
- self.default = u'wide'
+ self.default = _u("wide")
@implementer(ILocaleDayContext)
@@ -254,7 +255,7 @@ class LocaleDayContext(AttributeInheritance):
def __init__(self, type=None):
"""Initialize the object."""
self.type = type
- self.default = u'wide'
+ self.default = _u("wide")
@implementer(ILocaleCalendar)
@@ -279,44 +280,44 @@ class LocaleCalendar(AttributeInheritance):
>>> locale.calendar = LocaleCalendar('gregorian')
>>> root.calendar.months = InheritingDictionary(
- ... {1: (u'January', u'Jan'), 2: (u'February', u'Feb')})
+ ... {1: (_u("January"), _u("Jan")), 2: (_u("February"), _u("Feb"))})
>>> locale.calendar.months = InheritingDictionary(
- ... {2: (u'Februar', u'Feb'), 3: (u'Maerz', u'Mrz')})
+ ... {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')
+ >>> locale.calendar.getMonthTypeFromName(_u("January"))
1
- >>> locale.calendar.getMonthTypeFromName(u'Februar')
+ >>> locale.calendar.getMonthTypeFromName(_u("Februar"))
2
>>> locale.calendar.getMonthAbbreviations()[:4]
[u'Jan', u'Feb', u'Mrz', None]
- >>> locale.calendar.getMonthTypeFromAbbreviation(u'Jan')
+ >>> locale.calendar.getMonthTypeFromAbbreviation(_u("Jan"))
1
- >>> locale.calendar.getMonthTypeFromAbbreviation(u'Mrz')
+ >>> locale.calendar.getMonthTypeFromAbbreviation(_u("Mrz"))
3
>>> root.calendar.days = InheritingDictionary(
- ... {1: (u'Monday', u'Mon'), 2: (u'Tuesday', u'Tue')})
+ ... {1: (_u("Monday"), _u("Mon")), 2: (_u("Tuesday"), _u("Tue"))})
>>> locale.calendar.days = InheritingDictionary(
- ... {2: (u'Dienstag', u'Die'), 3: (u'Mittwoch', u'Mit')})
+ ... {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')
+ >>> locale.calendar.getDayTypeFromName(_u("Monday"))
1
- >>> locale.calendar.getDayTypeFromName(u'Dienstag')
+ >>> locale.calendar.getDayTypeFromName(_u("Dienstag"))
2
>>> locale.calendar.getDayAbbreviations()[:4]
[u'Mon', u'Die', u'Mit', None]
- >>> locale.calendar.getDayTypeFromAbbreviation(u'Mon')
+ >>> locale.calendar.getDayTypeFromAbbreviation(_u("Mon"))
1
- >>> locale.calendar.getDayTypeFromAbbreviation(u'Die')
+ >>> locale.calendar.getDayTypeFromAbbreviation(_u("Die"))
2
Let's test the direct attribute access as well.
- >>> root.am = u'AM'
- >>> root.pm = u'PM'
- >>> locale.pm = u'nachm.'
+ >>> root.am = _u("AM")
+ >>> root.pm = _u("PM")
+ >>> locale.pm = _u("nachm.")
>>> locale.pm
u'nachm.'
>>> locale.am
@@ -403,12 +404,12 @@ class LocaleDates(AttributeInheritance):
>>> fulllength = LocaleFormatLength()
>>> format = LocaleFormat()
- >>> format.pattern = u'EEEE, d. MMMM yyyy'
+ >>> format.pattern = _u("EEEE, d. MMMM yyyy")
>>> fulllength.formats = {None: format}
>>> mediumlength = LocaleFormatLength()
>>> format = LocaleFormat()
- >>> format.pattern = u'dd.MM.yyyy'
+ >>> format.pattern = _u("dd.MM.yyyy")
>>> mediumlength.formats = {None: format}
>>> cal.dateFormats = {'full': fulllength, 'medium': mediumlength}
@@ -426,12 +427,12 @@ class LocaleDates(AttributeInheritance):
>>> fulllength = LocaleFormatLength()
>>> format = LocaleFormat()
- >>> format.pattern = u"H:mm' Uhr 'z"
+ >>> format.pattern = _u("H:mm' Uhr 'z")
>>> fulllength.formats = {None: format}
>>> mediumlength = LocaleFormatLength()
>>> format = LocaleFormat()
- >>> format.pattern = u'HH:mm:ss'
+ >>> format.pattern = _u("HH:mm:ss")
>>> mediumlength.formats = {None: format}
>>> cal.timeFormats = {'full': fulllength, 'medium': mediumlength}
@@ -450,7 +451,7 @@ class LocaleDates(AttributeInheritance):
>>> length = LocaleFormatLength()
>>> format = LocaleFormat()
- >>> format.pattern = u'{1} {0}'
+ >>> format.pattern = _u("{1} {0}")
>>> length.formats = {None: format}
>>> cal.dateTimeFormats = {None: length}
@@ -479,15 +480,15 @@ class LocaleDates(AttributeInheritance):
"""
def getFormatter(self, category, length=None, name=None,
- calendar=u'gregorian'):
+ calendar=_u("gregorian")):
"""See zope.i18n.interfaces.locales.ILocaleDates"""
- if category not in (u'date', u'time', u'dateTime'):
+ if category not in (_u("date"), _u("time"), _u("dateTime")):
raise ValueError('Invalid category: %s' % category)
- if calendar not in (u'gregorian', u'arabic', u'chinese',
- u'civil-arabic', u'hebrew', u'japanese',
- u'thai-buddhist'):
+ if calendar not in (_u("gregorian"), _u("arabic"), _u("chinese"),
+ _u("civil-arabic"), _u("hebrew"), _u("japanese"),
+ _u("thai-buddhist")):
raise ValueError('Invalid calendar: %s' % calendar)
- if length not in (u'short', u'medium', u'long', u'full', None):
+ if length not in (_u("short"), _u("medium"), _u("long"), _u("full"), None):
raise ValueError('Invalid format length: %s' % length)
cal = self.calendars[calendar]
@@ -555,7 +556,7 @@ class LocaleNumbers(AttributeInheritance):
>>> length = LocaleFormatLength()
>>> format = LocaleFormat()
- >>> format.pattern = u'#,##0.###;-#,##0.###'
+ >>> format.pattern = _u("#,##0.###;-#,##0.###")
>>> length.formats = {None: format}
>>> numbers.decimalFormats = {None: length}
>>> formatter = numbers.getFormatter('decimal')
@@ -570,11 +571,11 @@ class LocaleNumbers(AttributeInheritance):
>>> longlength = LocaleFormatLength('long')
>>> format = LocaleFormat()
- >>> format.pattern = u'0.000###E+00'
+ >>> format.pattern = _u("0.000###E+00")
>>> longlength.formats = {None: format}
>>> mediumlength = LocaleFormatLength('long')
>>> format = LocaleFormat()
- >>> format.pattern = u'0.00##E+00'
+ >>> format.pattern = _u("0.00##E+00")
>>> mediumlength.formats = {None: format}
>>> numbers.scientificFormats = {'long': longlength,
... 'medium': mediumlength}
@@ -591,9 +592,9 @@ class LocaleNumbers(AttributeInheritance):
>>> longlength = LocaleFormatLength('long')
>>> fooformat = LocaleFormat()
- >>> fooformat.pattern = u'0.##0%'
+ >>> fooformat.pattern = _u("0.##0%")
>>> barformat = LocaleFormat()
- >>> barformat.pattern = u'0%'
+ >>> barformat.pattern = _u("0%")
>>> longlength.formats = {None: fooformat, 'bar': barformat}
>>> numbers.percentFormats = {'long': longlength}
>>> numbers.defaultPercentFormat = 'long'
@@ -615,8 +616,8 @@ class LocaleNumbers(AttributeInheritance):
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)
+ 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:
diff --git a/src/zope/i18n/locales/fallbackcollator.txt b/src/zope/i18n/locales/fallbackcollator.txt
index 9457be2..727d6b1 100644
--- a/src/zope/i18n/locales/fallbackcollator.txt
+++ b/src/zope/i18n/locales/fallbackcollator.txt
@@ -10,7 +10,7 @@ true for English. :)
Text collation is a fairly involved process. Systems that need this,
will likely use something like ICU
-(http://www-306.ibm.com/software/globalization/icu,
+(http://www-306.ibm.com/software/globalization/icu,
http://pyicu.osafoundation.org/). We don't want to introduce a
dependency on ICU and this time, so we are providing a fallback
collator that:
@@ -31,7 +31,8 @@ application code should certainly *not* count on this.
Now, we can pass the collator's key method to sort functions to sort
strings in a slightly friendly way:
- >>> sorted([u'Sam', u'sally', u'Abe', u'alice', u'Terry', u'tim'],
+ >>> from zope.i18n._compat import _u
+ >>> sorted([_u("Sam"), _u("sally"), _u("Abe"), _u("alice"), _u("Terry"), _u("tim")],
... key=collator.key)
[u'Abe', u'alice', u'sally', u'Sam', u'Terry', u'tim']
@@ -41,23 +42,23 @@ then returns a tuple with the result of lower-casing the normalized
string and the normalized string. We can see this by calling the key
method, which converts unicode strings to collation keys:
- >>> collator.key(u'Sam')
+ >>> collator.key(_u("Sam"))
(u'sam', u'Sam')
- >>> collator.key(u'\xc6\xf8a\u030a')
+ >>> collator.key(_u("\xc6\xf8a\u030a"))
(u'\xe6\xf8\xe5', u'\xc6\xf8\xe5')
There is also a cmp function for comparing strings:
- >>> collator.cmp(u'Terry', u'sally')
+ >>> collator.cmp(_u("Terry"), _u("sally"))
1
- >>> collator.cmp(u'sally', u'Terry')
+ >>> collator.cmp(_u("sally"), _u("Terry"))
-1
- >>> collator.cmp(u'terry', u'Terry')
+ >>> collator.cmp(_u("terry"), _u("Terry"))
1
- >>> collator.cmp(u'terry', u'terry')
+ >>> collator.cmp(_u("terry"), _u("terry"))
0
diff --git a/src/zope/i18n/locales/xmlfactory.py b/src/zope/i18n/locales/xmlfactory.py
index 1276d7b..5d4fb3b 100644
--- a/src/zope/i18n/locales/xmlfactory.py
+++ b/src/zope/i18n/locales/xmlfactory.py
@@ -22,6 +22,9 @@ from zope.i18n.locales import LocaleFormat, LocaleFormatLength, dayMapping
from zope.i18n.locales import LocaleOrientation, LocaleDayContext
from zope.i18n.locales import LocaleMonthContext, calendarAliases
from zope.i18n.locales.inheritance import InheritingDictionary
+from .._compat import _u
+
+_BLANK = _u('')
class LocaleFactory(object):
"""This class creates a Locale object from an ICU XML file."""
@@ -34,7 +37,7 @@ class LocaleFactory(object):
self._data = parseXML(path).documentElement
def _getText(self, nodelist):
- rc = u''
+ rc = _BLANK
for node in nodelist:
if node.nodeType == node.TEXT_NODE:
rc = rc + node.data
@@ -49,13 +52,13 @@ class LocaleFactory(object):
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <identity>
... <version number="1.0">Some notes</version>
... <generation date="2003-12-19" />
- ... <language type="de" />
- ... <territory type="DE" />
- ... </identity>'''
+ ... <language type="de" />
+ ... <territory type="DE" />
+ ... </identity>''')
>>> dom = parseString(xml)
>>> version = factory._extractVersion(dom.documentElement)
@@ -79,7 +82,7 @@ class LocaleFactory(object):
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
@@ -88,16 +91,16 @@ class LocaleFactory(object):
Example::
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <ldml>
... <identity>
... <version number="1.0"/>
... <generation date="2003-12-19" />
- ... <language type="en" />
- ... <territory type="US" />
- ... <variant type="POSIX" />
+ ... <language type="en" />
+ ... <territory type="US" />
+ ... <variant type="POSIX" />
... </identity>
- ... </ldml>'''
+ ... </ldml>''')
>>> factory = LocaleFactory(None)
>>> factory._data = parseString(xml).documentElement
@@ -130,7 +133,7 @@ class LocaleFactory(object):
id.version = self._extractVersion(identity)
return id
-
+
def _extractTypes(self, names_node):
"""Extract all types from the names_node.
@@ -139,7 +142,7 @@ class LocaleFactory(object):
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <displayNames>
... <types>
... <type type="Fallback" key="calendar"></type>
@@ -149,7 +152,7 @@ class LocaleFactory(object):
... <type type="stroke" key="collation">STROKE</type>
... <type type="traditional" key="collation">TRADITIONAL</type>
... </types>
- ... </displayNames>'''
+ ... </displayNames>''')
>>> dom = parseString(xml)
>>> types = factory._extractTypes(dom.documentElement)
@@ -161,15 +164,15 @@ class LocaleFactory(object):
[(u'chinese', u'calendar'), (u'gregorian', u'calendar')]
>>> keys[4:]
[(u'stroke', u'collation'), (u'traditional', u'collation')]
- >>> types[(u'chinese', u'calendar')]
+ >>> types[(_u('chinese'), _u('calendar'))]
u'CHINESE'
- >>> types[(u'stroke', u'collation')]
+ >>> types[(_u('stroke'), _u('collation'))]
u'STROKE'
"""
- # 'types' node has not to exist
+ # 'types' node has not to exist
types_nodes = names_node.getElementsByTagName('types')
if types_nodes == []:
- return
+ return
# Retrieve all types
types = InheritingDictionary()
for type_node in types_nodes[0].getElementsByTagName('type'):
@@ -185,7 +188,7 @@ class LocaleFactory(object):
Example::
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <ldml>
... <localeDisplayNames>
... <languages>
@@ -214,7 +217,7 @@ class LocaleFactory(object):
... <type type="stroke" key="collation">STROKE</type>
... </types>
... </localeDisplayNames>
- ... </ldml>'''
+ ... </ldml>''')
>>> factory = LocaleFactory(None)
>>> factory._data = parseString(xml).documentElement
@@ -224,42 +227,42 @@ class LocaleFactory(object):
>>> keys.sort()
>>> keys
[u'Fallback', u'aa', u'ab']
- >>> names.languages[u'aa']
+ >>> names.languages[_u("aa")]
u'aa'
>>> keys = names.scripts.keys()
>>> keys.sort()
>>> keys
[u'Arab', u'Armn']
- >>> names.scripts[u'Arab']
+ >>> names.scripts[_u("Arab")]
u'Arab'
>>> keys = names.territories.keys()
>>> keys.sort()
>>> keys
[u'AD', u'AE']
- >>> names.territories[u'AD']
+ >>> names.territories[_u("AD")]
u'AD'
>>> keys = names.variants.keys()
>>> keys.sort()
>>> keys
[u'Fallback', u'POSIX']
- >>> names.variants[u'Fallback']
+ >>> names.variants[_u("Fallback")]
u''
>>> keys = names.keys.keys()
>>> keys.sort()
>>> keys
[u'calendar', u'collation']
- >>> names.keys[u'calendar']
+ >>> names.keys[_u("calendar")]
u'CALENDAR'
- >>> names.types[(u'stroke', u'collation')]
+ >>> names.types[(_u("stroke"), _u("collation"))]
u'STROKE'
"""
displayNames = LocaleDisplayNames()
- # Neither the 'localeDisplayNames' or 'scripts' node has to exist
+ # Neither the 'localeDisplayNames' or 'scripts' node has to exist
names_nodes = self._data.getElementsByTagName('localeDisplayNames')
if names_nodes == []:
return displayNames
@@ -295,7 +298,7 @@ class LocaleFactory(object):
>>> calendar = CalendarStub()
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <months>
... <default type="format" />
... <monthContext type="format">
@@ -329,27 +332,27 @@ class LocaleFactory(object):
... <month type="12">Dez</month>
... </monthWidth>
... </monthContext>
- ... </months>'''
+ ... </months>''')
>>> dom = parseString(xml)
>>> factory._extractMonths(dom.documentElement, calendar)
The contexts and widths were introduced in CLDR 1.1, the way
of getting month names is like this::
-
+
>>> calendar.defaultMonthContext
u'format'
-
- >>> ctx = calendar.monthContexts[u'format']
+
+ >>> ctx = calendar.monthContexts[_u("format")]
>>> ctx.defaultWidth
u'wide'
-
- >>> names = [ctx.months[u'wide'][type] for type in range(1,13)]
+
+ >>> names = [ctx.months[_u("wide")][type] 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 = [ctx.months[u'abbreviated'][type] for type in range(1,13)]
+
+ >>> abbrs = [ctx.months[_u("abbreviated")][type] for type in range(1,13)]
>>> abbrs[:6]
[u'Jan', u'Feb', u'Mrz', u'Apr', u'Mai', u'Jun']
>>> abbrs[6:]
@@ -370,21 +373,21 @@ class LocaleFactory(object):
[u'Jan', u'Feb', u'Mrz', u'Apr', u'Mai', u'Jun']
>>> abbrs[6:]
[u'Jul', u'Aug', u'Sep', u'Okt', u'Nov', u'Dez']
-
-
+
+
"""
-
+
defaultMonthContext_node = months_node.getElementsByTagName('default')
if defaultMonthContext_node:
calendar.defaultMonthContext = defaultMonthContext_node[0].getAttribute('type')
-
+
monthContext_nodes = months_node.getElementsByTagName('monthContext')
if not monthContext_nodes:
return
calendar.monthContexts = InheritingDictionary()
names_node = abbrs_node = None # BBB
-
+
for node in monthContext_nodes:
context_type = node.getAttribute('type')
mctx = LocaleMonthContext(context_type)
@@ -400,20 +403,20 @@ class LocaleFactory(object):
width_type = width_node.getAttribute('type')
width = InheritingDictionary()
widths[width_type] = width
-
+
for month_node in width_node.getElementsByTagName('month'):
mtype = int(month_node.getAttribute('type'))
width[mtype] = self._getText(month_node.childNodes)
-
+
if context_type == 'format':
if width_type == 'abbreviated':
abbrs_node = width_node
elif width_type == 'wide':
names_node = width_node
-
+
if not (names_node and abbrs_node):
return
-
+
# Get all month names
names = {}
for name_node in names_node.getElementsByTagName('month'):
@@ -444,7 +447,7 @@ class LocaleFactory(object):
>>> calendar = CalendarStub()
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <days>
... <default type="format" />
... <dayContext type="format">
@@ -468,30 +471,30 @@ class LocaleFactory(object):
... <day type="sat">Sa</day>
... </dayWidth>
... </dayContext>
- ... </days>'''
+ ... </days>''')
>>> dom = parseString(xml)
>>> factory._extractDays(dom.documentElement, calendar)
Day contexts and widths were introduced in CLDR 1.1, here's
how to use them::
-
+
>>> calendar.defaultDayContext
u'format'
-
- >>> ctx = calendar.dayContexts[u'format']
+
+ >>> ctx = calendar.dayContexts[_u("format")]
>>> ctx.defaultWidth
u'wide'
-
- >>> names = [ctx.days[u'wide'][type] for type in range(1,8)]
+
+ >>> names = [ctx.days[_u("wide")][type] 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 = [ctx.days[u'abbreviated'][type] for type in range(1,8)]
+ >>> abbrs = [ctx.days[_u("abbreviated")][type] for type in range(1,8)]
>>> abbrs
[u'Mo', u'Di', u'Mi', u'Do', u'Fr', u'Sa', u'So']
-
+
And here's the old CLDR 1.0 way of getting day names and
abbreviations::
@@ -511,14 +514,14 @@ class LocaleFactory(object):
defaultDayContext_node = days_node.getElementsByTagName('default')
if defaultDayContext_node:
calendar.defaultDayContext = defaultDayContext_node[0].getAttribute('type')
-
+
dayContext_nodes = days_node.getElementsByTagName('dayContext')
if not dayContext_nodes:
return
calendar.dayContexts = InheritingDictionary()
names_node = abbrs_node = None # BBB
-
+
for node in dayContext_nodes:
context_type = node.getAttribute('type')
dctx = LocaleDayContext(context_type)
@@ -534,11 +537,11 @@ class LocaleFactory(object):
width_type = width_node.getAttribute('type')
width = InheritingDictionary()
widths[width_type] = width
-
+
for day_node in width_node.getElementsByTagName('day'):
dtype = dayMapping[day_node.getAttribute('type')]
width[dtype] = self._getText(day_node.childNodes)
-
+
if context_type == 'format':
if width_type == 'abbreviated':
abbrs_node = width_node
@@ -577,7 +580,7 @@ class LocaleFactory(object):
>>> calendar = CalendarStub()
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <calendar type="gregorian">
... <week>
... <minDays count="1"/>
@@ -585,7 +588,7 @@ class LocaleFactory(object):
... <weekendStart day="fri" time="18:00"/>
... <weekendEnd day="sun" time="18:00"/>
... </week>
- ... </calendar>'''
+ ... </calendar>''')
>>> dom = parseString(xml)
>>> factory._extractWeek(dom.documentElement, calendar)
@@ -637,7 +640,7 @@ class LocaleFactory(object):
>>> calendar = CalendarStub()
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <calendar type="gregorian">
... <eras>
... <eraAbbr>
@@ -648,7 +651,7 @@ class LocaleFactory(object):
... <era type="0">Before Christ</era>
... </eraName>
... </eras>
- ... </calendar>'''
+ ... </calendar>''')
>>> dom = parseString(xml)
>>> factory._extractEras(dom.documentElement, calendar)
@@ -695,7 +698,7 @@ class LocaleFactory(object):
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <dateFormats>
... <default type="medium"/>
... <dateFormatLength type="full">
@@ -713,20 +716,20 @@ class LocaleFactory(object):
... <pattern>MMM dd, yyyy</pattern>
... </dateFormat>
... </dateFormatLength>
- ... </dateFormats>'''
+ ... </dateFormats>''')
>>> dom = parseString(xml)
>>> default, lengths = factory._extractFormats(
... dom.documentElement, 'dateFormatLength', 'dateFormat')
>>> default
u'medium'
- >>> lengths[u'full'].formats[None].pattern
+ >>> lengths[_u("full")].formats[None].pattern
u'EEEE, MMMM d, yyyy'
- >>> lengths[u'medium'].default
+ >>> lengths[_u("medium")].default
u'DateFormatsKey2'
- >>> lengths[u'medium'].formats['DateFormatsKey3'].pattern
+ >>> lengths[_u("medium")].formats['DateFormatsKey3'].pattern
u'MMM dd, yyyy'
- >>> lengths[u'medium'].formats['DateFormatsKey2'].displayName
+ >>> lengths[_u("medium")].formats['DateFormatsKey2'].displayName
u'Standard Date'
"""
formats_default = None
@@ -738,14 +741,14 @@ class LocaleFactory(object):
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
@@ -768,7 +771,7 @@ class LocaleFactory(object):
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <dates>
... <calendars>
... <calendar type="gregorian">
@@ -829,7 +832,7 @@ class LocaleFactory(object):
... </eras>
... </calendar>
... </calendars>
- ... </dates>'''
+ ... </dates>''')
>>> dom = parseString(xml)
>>> calendars = factory._extractCalendars(dom.documentElement)
@@ -837,12 +840,12 @@ class LocaleFactory(object):
>>> keys.sort()
>>> keys
[u'buddhist', u'gregorian', 'thai-buddhist']
-
+
Note that "thai-buddhist" are added as an alias to "buddhist".
-
+
>>> calendars['buddhist'] is calendars['thai-buddhist']
True
-
+
"""
cals_nodes = dates_node.getElementsByTagName('calendars')
# no calendar node
@@ -909,7 +912,7 @@ class LocaleFactory(object):
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <dates>
... <timeZoneNames>
... <zone type="America/Los_Angeles" >
@@ -934,7 +937,7 @@ class LocaleFactory(object):
... <exemplarCity>York</exemplarCity>
... </zone>
... </timeZoneNames>
- ... </dates>'''
+ ... </dates>''')
>>> dom = parseString(xml)
>>> zones = factory._extractTimeZones(dom.documentElement)
@@ -942,11 +945,11 @@ class LocaleFactory(object):
>>> keys.sort()
>>> keys
[u'America/Los_Angeles', u'Europe/London']
- >>> zones[u'Europe/London'].names[u'generic']
+ >>> zones[_u("Europe/London")].names[_u("generic")]
(u'British Time', None)
- >>> zones[u'Europe/London'].cities
+ >>> zones[_u("Europe/London")].cities
[u'York']
- >>> zones[u'America/Los_Angeles'].names[u'generic']
+ >>> zones[_u("America/Los_Angeles")].names[_u("generic")]
(u'Pacific Time', u'PT')
"""
tz_names = dates_node.getElementsByTagName('timeZoneNames')
@@ -961,7 +964,7 @@ class LocaleFactory(object):
# get the short and long name node
long = node.getElementsByTagName('long')
short = node.getElementsByTagName('short')
- for type in (u'generic', u'standard', u'daylight'):
+ for type in (_u("generic"), _u("standard"), _u("daylight")):
# get long name
long_desc = None
if long:
@@ -1009,7 +1012,7 @@ class LocaleFactory(object):
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <numbers>
... <symbols>
... <decimal>.</decimal>
@@ -1025,7 +1028,7 @@ class LocaleFactory(object):
... <infinity>oo</infinity>
... <nan>NaN</nan>
... </symbols>
- ... </numbers>'''
+ ... </numbers>''')
>>> dom = parseString(xml)
>>> symbols = factory._extractSymbols(dom.documentElement)
@@ -1046,10 +1049,10 @@ class LocaleFactory(object):
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'):
+ 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)
@@ -1075,7 +1078,7 @@ class LocaleFactory(object):
>>> numbers = Numbers()
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <numbers>
... <decimalFormats>
... <decimalFormatLength type="long">
@@ -1111,28 +1114,28 @@ class LocaleFactory(object):
... </currencyFormat>
... </currencyFormatLength>
... </currencyFormats>
- ... </numbers>'''
+ ... </numbers>''')
>>> dom = parseString(xml)
>>> factory._extractNumberFormats(dom.documentElement, numbers)
- >>> numbers.decimalFormats[u'long'].formats[None].pattern
+ >>> numbers.decimalFormats[_u("long")].formats[None].pattern
u'#,##0.###'
>>> numbers.defaultScientificFormat
u'long'
- >>> numbers.scientificFormats[u'long'].formats[None].pattern
+ >>> numbers.scientificFormats[_u("long")].formats[None].pattern
u'0.000###E+00'
- >>> numbers.scientificFormats[u'medium'].formats[None].pattern
+ >>> numbers.scientificFormats[_u("medium")].formats[None].pattern
u'0.00##E+00'
- >>> numbers.percentFormats[u'long'].formats[None].pattern
+ >>> numbers.percentFormats[_u("long")].formats[None].pattern
u'#,##0%'
- >>> numbers.percentFormats.get(u'medium', None) is None
+ >>> numbers.percentFormats.get(_u("medium"), None) is None
True
- >>> numbers.currencyFormats[u'long'].formats[None].pattern
+ >>> numbers.currencyFormats[_u("long")].formats[None].pattern
u'$ #,##0.00;($ #,##0.00)'
- >>> numbers.currencyFormats.get(u'medium', None) is None
+ >>> numbers.currencyFormats.get(_u("medium"), None) is None
True
"""
@@ -1158,7 +1161,7 @@ class LocaleFactory(object):
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <numbers>
... <currencies>
... <currency type="USD">
@@ -1178,7 +1181,7 @@ class LocaleFactory(object):
... <symbol>$</symbol>
... </currency>
... </currencies>
- ... </numbers>'''
+ ... </numbers>''')
>>> dom = parseString(xml)
>>> currencies = factory._extractCurrencies(dom.documentElement)
@@ -1207,7 +1210,7 @@ class LocaleFactory(object):
if nodes:
currency.symbol = self._getText(nodes[0].childNodes)
currency.symbolChoice = \
- nodes[0].getAttribute('choice') == u'true'
+ nodes[0].getAttribute('choice') == _u("true")
nodes = curr_node.getElementsByTagName('displayName')
if nodes:
@@ -1226,14 +1229,14 @@ class LocaleFactory(object):
numbers = LocaleNumbers()
symbols = self._extractSymbols(numbers_nodes[0])
- if symbols is not None:
+ if symbols is not None:
numbers.symbols = symbols
self._extractNumberFormats(numbers_nodes[0], numbers)
currencies = self._extractCurrencies(numbers_nodes[0])
if currencies is not None:
numbers.currencies = currencies
return numbers
-
+
def _extractDelimiters(self):
"""Extract all delimiter entries from the DOM tree.
@@ -1242,7 +1245,7 @@ class LocaleFactory(object):
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <ldml>
... <delimiters>
... <quotationStart>``</quotationStart>
@@ -1250,18 +1253,18 @@ class LocaleFactory(object):
... <alternateQuotationStart>`</alternateQuotationStart>
... <alternateQuotationEnd>'</alternateQuotationEnd>
... </delimiters>
- ... </ldml>'''
+ ... </ldml>''')
>>> dom = parseString(xml)
>>> factory._data = parseString(xml).documentElement
>>> delimiters = factory._extractDelimiters()
- >>> delimiters[u'quotationStart']
+ >>> delimiters[_u("quotationStart")]
u'``'
- >>> delimiters[u'quotationEnd']
+ >>> delimiters[_u("quotationEnd")]
u"''"
- >>> delimiters[u'alternateQuotationStart']
+ >>> delimiters[_u("alternateQuotationStart")]
u'`'
- >>> delimiters[u'alternateQuotationEnd']
+ >>> delimiters[_u("alternateQuotationEnd")]
u"'"
Escape: "'"
@@ -1272,8 +1275,8 @@ class LocaleFactory(object):
return
delimiters = InheritingDictionary()
- for name in (u'quotationStart', u'quotationEnd',
- u'alternateQuotationStart', u'alternateQuotationEnd'):
+ 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)
@@ -1286,12 +1289,12 @@ class LocaleFactory(object):
>>> factory = LocaleFactory(None)
>>> from xml.dom.minidom import parseString
- >>> xml = u'''
+ >>> xml = _u('''
... <ldml>
... <layout>
... <orientation lines="bottom-to-top" characters="right-to-left" />
... </layout>
- ... </ldml>'''
+ ... </ldml>''')
>>> dom = parseString(xml)
>>> factory._data = parseString(xml).documentElement
>>> orientation = factory._extractOrientation()
@@ -1304,7 +1307,7 @@ class LocaleFactory(object):
if not orientation_nodes:
return
orientation = LocaleOrientation()
- for name in (u'characters', u'lines'):
+ for name in (_u("characters"), _u("lines")):
value = orientation_nodes[0].getAttribute(name)
if value:
setattr(orientation, name, value)
@@ -1317,7 +1320,7 @@ class LocaleFactory(object):
names = self._extractDisplayNames()
if names is not None:
- locale.displayNames = names
+ locale.displayNames = names
dates = self._extractDates()
if dates is not None:
@@ -1334,7 +1337,7 @@ class LocaleFactory(object):
orientation = self._extractOrientation()
if orientation is not None:
locale.orientation = orientation
-
+
# Unmapped:
#
# - <characters>
diff --git a/src/zope/i18n/testmessagecatalog.py b/src/zope/i18n/testmessagecatalog.py
index f6104e5..4bebda2 100644
--- a/src/zope/i18n/testmessagecatalog.py
+++ b/src/zope/i18n/testmessagecatalog.py
@@ -17,6 +17,7 @@
from zope import interface
import zope.i18n.interfaces
from zope.i18n.translationdomain import TranslationDomain
+from ._compat import _u
@interface.implementer(zope.i18n.interfaces.IGlobalMessageCatalog)
class TestMessageCatalog:
@@ -29,11 +30,11 @@ class TestMessageCatalog:
def queryMessage(self, msgid, default=None):
default = getattr(msgid, 'default', default)
if default != None and default != msgid:
- msg = u"%s (%s)" % (msgid, default)
+ msg = _u("%s (%s)") % (msgid, default)
else:
msg = msgid
-
- return u'[[%s][%s]]' % (self.domain, msg)
+
+ return _u("[[%s][%s]]") % (self.domain, msg)
getMessage = queryMessage
@@ -44,7 +45,7 @@ class TestMessageCatalog:
pass
@interface.implementer(zope.i18n.interfaces.ITranslationDomain)
-def TestMessageFallbackDomain(domain_id=u''):
+def TestMessageFallbackDomain(domain_id=_u("")):
domain = TranslationDomain(domain_id)
domain.addCatalog(TestMessageCatalog(domain_id))
return domain
diff --git a/src/zope/i18n/testmessagecatalog.txt b/src/zope/i18n/testmessagecatalog.txt
index bd04ad8..dc1d9d0 100644
--- a/src/zope/i18n/testmessagecatalog.txt
+++ b/src/zope/i18n/testmessagecatalog.txt
@@ -51,16 +51,16 @@ that has the test catalog as it's only catalog:
>>> zope.i18n.interfaces.IFallbackTranslationDomainFactory.providedBy(
... factory)
True
-
+
>>> domain = factory('foo.bar')
- >>> domain.translate(u'eek')
+ >>> domain.translate('eek')
u'eek'
- >>> domain.translate(u'eek', target_language='test')
+ >>> domain.translate('eek', target_language='test')
u'[[foo.bar][eek]]'
Note that if a default is padded in, it will be included in test
output:
- >>> domain.translate(u'eek', target_language='test', default=u'Eek')
+ >>> domain.translate('eek', target_language='test', default='Eek')
u'[[foo.bar][eek (Eek)]]'
diff --git a/src/zope/i18n/tests/test_formats.py b/src/zope/i18n/tests/test_formats.py
index 74baeef..aa7910c 100644
--- a/src/zope/i18n/tests/test_formats.py
+++ b/src/zope/i18n/tests/test_formats.py
@@ -29,12 +29,14 @@ from zope.i18n.interfaces import INumberFormat
from zope.i18n.format import NumberFormat, NumberParseError
from zope.i18n.format import parseNumberPattern
+from .._compat import _u
+
class LocaleStub(object):
pass
class LocaleCalendarStub(object):
- type = u'gregorian'
+ type = _u("gregorian")
months = { 1: ('Januar', 'Jan'), 2: ('Februar', 'Feb'),
3: ('Maerz', 'Mrz'), 4: ('April', 'Apr'),
@@ -222,9 +224,9 @@ class TestBuildDateTimeParseInfo(TestCase):
self.assertEqual(self.info(('M', 2)), '([0-9]{2})')
def testMonthNames(self):
- names = [u'Januar', u'Februar', u'Maerz', u'April',
- u'Mai', u'Juni', u'Juli', u'August', u'September', u'Oktober',
- u'November', u'Dezember']
+ names = [_u("Januar"), _u("Februar"), _u("Maerz"), _u("April"),
+ _u("Mai"), _u("Juni"), _u("Juli"), _u("August"), _u("September"), _u("Oktober"),
+ _u("November"), _u("Dezember")]
self.assertEqual(self.info(('M', 4)), '('+'|'.join(names)+')')
def testMonthAbbr(self):
@@ -548,54 +550,54 @@ class TestDateTimeFormat(TestCase):
def testFormatDayInYear(self):
self.assertEqual(
self.format.format(datetime.date(2003, 1, 3), 'D'),
- u'3')
+ _u("3"))
self.assertEqual(
self.format.format(datetime.date(2003, 1, 3), 'DD'),
- u'03')
+ _u("03"))
self.assertEqual(
self.format.format(datetime.date(2003, 1, 3), 'DDD'),
- u'003')
+ _u("003"))
self.assertEqual(
self.format.format(datetime.date(2003, 12, 31), 'D'),
- u'365')
+ _u("365"))
self.assertEqual(
self.format.format(datetime.date(2003, 12, 31), 'DD'),
- u'365')
+ _u("365"))
self.assertEqual(
self.format.format(datetime.date(2003, 12, 31), 'DDD'),
- u'365')
+ _u("365"))
self.assertEqual(
self.format.format(datetime.date(2004, 12, 31), 'DDD'),
- u'366')
+ _u("366"))
def testFormatDayOfWeekInMOnth(self):
self.assertEqual(
self.format.format(datetime.date(2003, 1, 3), 'F'),
- u'1')
+ _u("1"))
self.assertEqual(
self.format.format(datetime.date(2003, 1, 10), 'F'),
- u'2')
+ _u("2"))
self.assertEqual(
self.format.format(datetime.date(2003, 1, 17), 'F'),
- u'3')
+ _u("3"))
self.assertEqual(
self.format.format(datetime.date(2003, 1, 24), 'F'),
- u'4')
+ _u("4"))
self.assertEqual(
self.format.format(datetime.date(2003, 1, 31), 'F'),
- u'5')
+ _u("5"))
self.assertEqual(
self.format.format(datetime.date(2003, 1, 6), 'F'),
- u'1')
+ _u("1"))
def testFormatUnusualFormats(self):
self.assertEqual(
self.format.format(datetime.date(2003, 1, 3), 'DDD-yyyy'),
- u'003-2003')
+ _u("003-2003"))
self.assertEqual(
self.format.format(datetime.date(2003, 1, 10),
"F. EEEE 'im' MMMM, yyyy"),
- u'2. Freitag im Januar, 2003')
+ _u("2. Freitag im Januar, 2003"))
diff --git a/src/zope/i18n/tests/test_translationdomain.py b/src/zope/i18n/tests/test_translationdomain.py
index 85e87af..baf6aa7 100644
--- a/src/zope/i18n/tests/test_translationdomain.py
+++ b/src/zope/i18n/tests/test_translationdomain.py
@@ -20,6 +20,7 @@ from zope.i18n.tests.test_itranslationdomain import \
TestITranslationDomain, Environment
from zope.i18nmessageid import MessageFactory
from zope.i18n.interfaces import ITranslationDomain
+from .._compat import _u
import zope.component
def testdir():
@@ -72,19 +73,19 @@ class TestGlobalTranslationDomain(unittest.TestCase, TestITranslationDomain):
def testEmptyStringTranslate(self):
translate = self._domain.translate
- self.assertEqual(translate(u'', target_language='en'), u'')
- self.assertEqual(translate(u'', target_language='foo'), u'')
+ self.assertEqual(translate(_u(""), target_language='en'), _u(""))
+ self.assertEqual(translate(_u(""), target_language='foo'), _u(""))
def testStringTranslate(self):
self.assertEqual(
- self._domain.translate(u'short_greeting', target_language='en'),
- u'Hello!')
+ self._domain.translate(_u("short_greeting"), target_language='en'),
+ _u("Hello!"))
def testMessageIDTranslate(self):
factory = MessageFactory('default')
translate = self._domain.translate
- msgid = factory(u'short_greeting', 'default')
- self.assertEqual(translate(msgid, target_language='en'), u'Hello!')
+ msgid = factory(_u("short_greeting"), 'default')
+ self.assertEqual(translate(msgid, target_language='en'), _u("Hello!"))
# MessageID attributes override arguments
msgid = factory('43-not-there', 'this ${that} the other',
mapping={'that': 'THAT'})
@@ -95,13 +96,13 @@ class TestGlobalTranslationDomain(unittest.TestCase, TestITranslationDomain):
def testMessageIDRecursiveTranslate(self):
factory = MessageFactory('default')
translate = self._domain.translate
- msgid_sub1 = factory(u'44-not-there', '${blue}',
+ msgid_sub1 = factory(_u("44-not-there"), '${blue}',
mapping = {'blue': 'BLUE'})
- msgid_sub2 = factory(u'45-not-there', '${yellow}',
+ msgid_sub2 = factory(_u("45-not-there"), '${yellow}',
mapping = {'yellow': 'YELLOW'})
mapping = {'color1': msgid_sub1,
'color2': msgid_sub2}
- msgid = factory(u'46-not-there', 'Color: ${color1}/${color2}',
+ msgid = factory(_u("46-not-there"), 'Color: ${color1}/${color2}',
mapping=mapping)
self.assertEqual(
translate(msgid, target_language='en', default="default"),
@@ -110,9 +111,9 @@ class TestGlobalTranslationDomain(unittest.TestCase, TestITranslationDomain):
self.assertEqual(msgid.mapping, {'color1': msgid_sub1,
'color2': msgid_sub2})
# A circular reference should not lead to crashes
- msgid1 = factory(u'47-not-there', 'Message 1 and $msg2',
+ msgid1 = factory(_u("47-not-there"), 'Message 1 and $msg2',
mapping = {})
- msgid2 = factory(u'48-not-there', 'Message 2 and $msg1',
+ msgid2 = factory(_u("48-not-there"), 'Message 2 and $msg1',
mapping = {})
msgid1.mapping['msg2'] = msgid2
msgid2.mapping['msg1'] = msgid1
@@ -121,16 +122,16 @@ class TestGlobalTranslationDomain(unittest.TestCase, TestITranslationDomain):
# Recusrive translations also work if the original message id wasn't a
# message id but a unicode with a directly passed mapping
self.assertEqual("Color: BLUE/YELLOW",
- translate(u'Color: ${color1}/${color2}', mapping=mapping,
+ translate(_u("Color: ${color1}/${color2}"), mapping=mapping,
target_language='en'))
# If we have mapping with a message id from a different domain, make sure
# we use that domain, not ours. If the message domain is not registered yet,
# we should return a defualt translation.
alt_factory = MessageFactory('alt')
- msgid_sub = alt_factory(u'special', default=u'oohhh')
+ msgid_sub = alt_factory(_u("special"), default=_u("oohhh"))
mapping = {'message': msgid_sub}
- msgid = factory(u'46-not-there', 'Message: ${message}',
+ msgid = factory(_u("46-not-there"), 'Message: ${message}',
mapping=mapping)
# test we get a default with no domain registerd
self.assertEqual(
@@ -161,9 +162,9 @@ class TestGlobalTranslationDomain(unittest.TestCase, TestITranslationDomain):
zope.component.provideUtility(domain, ITranslationDomain, 'alt')
factory = MessageFactory('alt')
- msgid = factory(u'special', 'default')
+ msgid = factory(_u("special"), 'default')
self.assertEqual(
- self._domain.translate(msgid, target_language='en'), u'Wow')
+ self._domain.translate(msgid, target_language='en'), _u("Wow"))
def testSimpleFallbackTranslation(self):
translate = self._domain.translate
@@ -171,11 +172,11 @@ class TestGlobalTranslationDomain(unittest.TestCase, TestITranslationDomain):
# Test that a translation in an unsupported language returns a
# translation in the fallback language (by default, English)
eq(translate('short_greeting', target_language='es'),
- u'Hello!')
+ _u("Hello!"))
# Same test, but use the context argument instead of target_language
context = Environment()
eq(translate('short_greeting', context=context),
- u'Hello!')
+ _u("Hello!"))
def testInterpolationWithoutTranslation(self):
translate = self._domain.translate
@@ -193,4 +194,3 @@ def test_suite():
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
-
diff --git a/src/zope/i18n/tests/test_zcml.py b/src/zope/i18n/tests/test_zcml.py
index 147456d..9693fe6 100644
--- a/src/zope/i18n/tests/test_zcml.py
+++ b/src/zope/i18n/tests/test_zcml.py
@@ -27,6 +27,7 @@ from zope.component.testing import PlacelessSetup
import zope.i18n.tests
from zope.i18n.interfaces import ITranslationDomain
from zope.i18n import config
+from .._compat import _u
PY3 = sys.version_info[0] == 3
if PY3:
@@ -110,14 +111,14 @@ class DirectivesTest(PlacelessSetup, unittest.TestCase):
self.assertEqual(util._catalogs.get('en'),
[unicode(path1), unicode(path2)])
- msg = util.translate(u'Additional message', target_language='en')
- self.assertEqual(msg, u'Additional message translated')
+ msg = util.translate(_u("Additional message"), target_language='en')
+ self.assertEqual(msg, _u("Additional message translated"))
- msg = util.translate(u'New Domain', target_language='en')
- self.assertEqual(msg, u'New Domain translated')
+ msg = util.translate(_u("New Domain"), target_language='en')
+ self.assertEqual(msg, _u("New Domain translated"))
- msg = util.translate(u'New Language', target_language='en')
- self.assertEqual(msg, u'New Language translated')
+ msg = util.translate(_u("New Language"), target_language='en')
+ self.assertEqual(msg, _u("New Language translated"))
def testRegisterAndCompileTranslations(self):
from zope.configuration import xmlconfig
@@ -148,12 +149,12 @@ class DirectivesTest(PlacelessSetup, unittest.TestCase):
self.assertEqual(util._catalogs,
{'test': ['test'], 'en': [unicode(path)]})
- msg = util.translate(u"I'm a newer file", target_language='en')
- self.assertEqual(msg, u"I'm a newer file translated")
+ msg = util.translate(_u("I'm a newer file"), target_language='en')
+ self.assertEqual(msg, _u("I'm a newer file translated"))
util = getUtility(ITranslationDomain, 'zope-i18n2')
- msg = util.translate(u"I'm a new file", target_language='en')
- self.assertEqual(msg, u"I'm a new file translated")
+ msg = util.translate(_u("I'm a new file"), target_language='en')
+ self.assertEqual(msg, _u("I'm a new file translated"))
# Reset the mtime of the mo file
os.utime(path, (path_atime, path_mtime))
diff --git a/src/zope/i18n/translationdomain.py b/src/zope/i18n/translationdomain.py
index 6629c9e..415f1ba 100644
--- a/src/zope/i18n/translationdomain.py
+++ b/src/zope/i18n/translationdomain.py
@@ -20,6 +20,7 @@ from zope.i18nmessageid import Message
from zope.i18n import translate, interpolate
from zope.i18n.simpletranslationdomain import SimpleTranslationDomain
from zope.i18n.interfaces import ITranslationDomain, INegotiator
+from ._compat import _u
# The configuration should specify a list of fallback languages for the
# site. If a particular catalog for a negotiated language is not available,
@@ -35,6 +36,8 @@ PY3 = sys.version_info[0] == 3
if PY3:
unicode = str
+_EMPTY = _u("")
+
class TranslationDomain(SimpleTranslationDomain):
def __init__(self, domain, fallbacks=None):
@@ -69,8 +72,8 @@ class TranslationDomain(SimpleTranslationDomain):
"""See zope.i18n.interfaces.ITranslationDomain"""
# if the msgid is empty, let's save a lot of calculations and return
# an empty string.
- if msgid == u'':
- return u''
+ if msgid == _EMPTY:
+ return _EMPTY
if target_language is None and context is not None:
langs = self._catalogs.keys()
@@ -129,7 +132,7 @@ class TranslationDomain(SimpleTranslationDomain):
# this is a slight optimization for the case when there is a
# single catalog. More importantly, it is extremely helpful
# when testing and the test language is used, because it
- # allows the test language to get the default.
+ # allows the test language to get the default.
text = self._data[catalog_names[0]].queryMessage(
msgid, default)
else:
diff --git a/src/zope/i18n/zcml.py b/src/zope/i18n/zcml.py
index 4ab9af1..959a58e 100644
--- a/src/zope/i18n/zcml.py
+++ b/src/zope/i18n/zcml.py
@@ -33,7 +33,7 @@ from zope.i18n.gettextmessagecatalog import GettextMessageCatalog
from zope.i18n.testmessagecatalog import TestMessageCatalog
from zope.i18n.translationdomain import TranslationDomain
from zope.i18n.interfaces import ITranslationDomain
-
+from ._compat import _u
logger = logging.getLogger("zope.i18n")
@@ -42,15 +42,15 @@ class IRegisterTranslationsDirective(Interface):
"""Register translations with the global site manager."""
directory = Path(
- title=u"Directory",
- description=u"Directory containing the translations",
+ title=_u("Directory"),
+ description=_u("Directory containing the translations"),
required=True
)
domain = TextLine(
- title=u"Domain",
- description=u"Translation domain to register. If not specified, "
- "all domains found in the directory are registered",
+ title=_u("Domain"),
+ description=_u("Translation domain to register. If not specified, "
+ "all domains found in the directory are registered"),
required=False
)
diff --git a/tox.ini b/tox.ini
index 4c956b4..2fe14a8 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py26,py27,py33,py34,pypy,coverage,docs
+envlist = py26,py27,py32,py33,py34,pypy,pypy3,coverage,docs
[testenv]
commands =