зеркало из https://github.com/mozilla/kitsune.git
[bug 1035319] Removed /packages and /src in vendor.
Also removed kitsune.path and addsubmodules.sh. The .gitmodules file was updated to reflect these changes as well.
This commit is contained in:
Родитель
26d305416a
Коммит
096f9689ab
|
@ -1,171 +1,3 @@
|
|||
[submodule "vendor/src/bleach"]
|
||||
path = vendor/src/bleach
|
||||
url = https://github.com/jsocol/bleach.git
|
||||
[submodule "vendor/src/cache-panel"]
|
||||
path = vendor/src/cache-panel
|
||||
url = https://github.com/jbalogh/django-debug-cache-panel
|
||||
[submodule "vendor/src/check"]
|
||||
path = vendor/src/check
|
||||
url = https://github.com/jbalogh/check.git
|
||||
[submodule "vendor/src/commonware"]
|
||||
path = vendor/src/commonware
|
||||
url = https://github.com/jsocol/commonware.git
|
||||
[submodule "vendor/src/django-cache-machine"]
|
||||
path = vendor/src/django-cache-machine
|
||||
url = https://github.com/jbalogh/django-cache-machine.git
|
||||
[submodule "vendor/src/django-cronjobs"]
|
||||
path = vendor/src/django-cronjobs
|
||||
url = https://github.com/jsocol/django-cronjobs.git
|
||||
[submodule "vendor/src/django-extensions"]
|
||||
path = vendor/src/django-extensions
|
||||
url = https://github.com/django-extensions/django-extensions.git
|
||||
[submodule "vendor/src/django-mozilla-product-details"]
|
||||
path = vendor/src/django-mozilla-product-details
|
||||
url = https://github.com/fwenzel/django-mozilla-product-details
|
||||
[submodule "vendor/src/django-multidb-router"]
|
||||
path = vendor/src/django-multidb-router
|
||||
url = https://github.com/jbalogh/django-multidb-router.git
|
||||
[submodule "vendor/src/django-nose"]
|
||||
path = vendor/src/django-nose
|
||||
url = https://github.com/jbalogh/django-nose.git
|
||||
[submodule "vendor/src/jingo"]
|
||||
path = vendor/src/jingo
|
||||
url = https://github.com/jbalogh/jingo.git
|
||||
[submodule "vendor/src/jingo-minify"]
|
||||
path = vendor/src/jingo-minify
|
||||
url = https://github.com/jsocol/jingo-minify.git
|
||||
[submodule "vendor/src/py-wikimarkup"]
|
||||
path = vendor/src/py-wikimarkup
|
||||
url = https://github.com/pcraciunoiu/py-wikimarkup.git
|
||||
[submodule "vendor/src/schematic"]
|
||||
path = vendor/src/schematic
|
||||
url = https://github.com/jbalogh/schematic.git
|
||||
[submodule "vendor/src/test-utils"]
|
||||
path = vendor/src/test-utils
|
||||
url = https://github.com/jbalogh/test-utils.git
|
||||
[submodule "vendor/src/tower"]
|
||||
path = vendor/src/tower
|
||||
url = https://github.com/clouserw/tower.git
|
||||
[submodule "vendor/src/django"]
|
||||
path = vendor/src/django
|
||||
url = https://github.com/django/django
|
||||
[submodule "vendor/src/django-authority"]
|
||||
path = vendor/src/django-authority
|
||||
url = https://github.com/jsocol/django-authority
|
||||
[submodule "vendor/src/django-csp"]
|
||||
path = vendor/src/django-csp
|
||||
url = https://github.com/mozilla/django-csp.git
|
||||
[submodule "vendor/src/django-timezones"]
|
||||
path = vendor/src/django-timezones
|
||||
url = https://github.com/brosner/django-timezones.git
|
||||
[submodule "vendor/src/django-waffle"]
|
||||
path = vendor/src/django-waffle
|
||||
url = https://github.com/jsocol/django-waffle.git
|
||||
[submodule "vendor/src/django-mobility"]
|
||||
path = vendor/src/django-mobility
|
||||
url = https://github.com/jbalogh/django-mobility
|
||||
[submodule "vendor/src/django-qunit"]
|
||||
path = vendor/src/django-qunit
|
||||
url = https://github.com/rlr/django-qunit.git
|
||||
[submodule "vendor/src/django-adminplus"]
|
||||
path = vendor/src/django-adminplus
|
||||
url = https://github.com/jsocol/django-adminplus
|
||||
[submodule "vendor/src/celery"]
|
||||
path = vendor/src/celery
|
||||
url = https://github.com/celery/celery
|
||||
[submodule "vendor/src/django-celery"]
|
||||
path = vendor/src/django-celery
|
||||
url = https://github.com/celery/django-celery
|
||||
[submodule "vendor/src/kombu"]
|
||||
path = vendor/src/kombu
|
||||
url = https://github.com/celery/kombu
|
||||
[submodule "vendor/src/django-tidings"]
|
||||
path = vendor/src/django-tidings
|
||||
url = https://github.com/erikrose/django-tidings.git
|
||||
[submodule "vendor/src/pystatsd"]
|
||||
path = vendor/src/pystatsd
|
||||
url = https://github.com/jsocol/pystatsd
|
||||
[submodule "vendor/src/django-session-csrf"]
|
||||
path = vendor/src/django-session-csrf
|
||||
url = https://github.com/mozilla/django-session-csrf.git
|
||||
[submodule "vendor/src/redis-py"]
|
||||
path = vendor/src/redis-py
|
||||
url = https://github.com/andymccurdy/redis-py.git
|
||||
[submodule "vendor/src/django-picklefield"]
|
||||
path = vendor/src/django-picklefield
|
||||
url = https://github.com/gintas/django-picklefield.git
|
||||
[submodule "vendor/src/django-ratelimit"]
|
||||
path = vendor/src/django-ratelimit
|
||||
url = https://github.com/jsocol/django-ratelimit
|
||||
[submodule "vendor/src/django-recaptcha"]
|
||||
path = vendor/src/django-recaptcha
|
||||
url = https://github.com/mozilla/django-recaptcha
|
||||
[submodule "vendor/src/python-recaptcha"]
|
||||
path = vendor/src/python-recaptcha
|
||||
url = https://github.com/bltravis/python-recaptcha.git
|
||||
[submodule "vendor/src/elasticutils"]
|
||||
path = vendor/src/elasticutils
|
||||
url = git://github.com/mozilla/elasticutils.git
|
||||
[submodule "vendor/src/zendesk"]
|
||||
path = vendor/src/zendesk
|
||||
url = git://github.com/eventbrite/zendesk.git
|
||||
[submodule "vendor/src/django-eadred"]
|
||||
path = vendor/src/django-eadred
|
||||
url = git://github.com/willkg/django-eadred.git
|
||||
[submodule "vendor/src/raven-python"]
|
||||
path = vendor/src/raven-python
|
||||
url = git://github.com/getsentry/raven-python.git
|
||||
[submodule "vendor/src/django-statsd"]
|
||||
path = vendor/src/django-statsd
|
||||
url = git://github.com/andymckay/django-statsd.git
|
||||
[submodule "vendor/src/requests"]
|
||||
path = vendor/src/requests
|
||||
url = git://github.com/kennethreitz/requests.git
|
||||
[submodule "vendor/src/premailer"]
|
||||
path = vendor/src/premailer
|
||||
url = git://github.com/peterbe/premailer.git
|
||||
[submodule "kitsune/sumo/static/js/libs/ace"]
|
||||
path = kitsune/sumo/static/js/libs/ace
|
||||
url = git://github.com/ajaxorg/ace-builds.git
|
||||
[submodule "vendor/src/twython"]
|
||||
path = vendor/src/twython
|
||||
url = https://github.com/ryanmcgrath/twython.git
|
||||
[submodule "vendor/src/requests-oauthlib"]
|
||||
path = vendor/src/requests-oauthlib
|
||||
url = https://github.com/requests/requests-oauthlib.git
|
||||
[submodule "vendor/src/oauthlib"]
|
||||
path = vendor/src/oauthlib
|
||||
url = https://github.com/idan/oauthlib.git
|
||||
[submodule "vendor/src/html5lib-python"]
|
||||
path = vendor/src/html5lib-python
|
||||
url = https://github.com/html5lib/html5lib-python.git
|
||||
[submodule "vendor/src/django-rest-framework"]
|
||||
path = vendor/src/django-rest-framework
|
||||
url = https://github.com/tomchristie/django-rest-framework.git
|
||||
[submodule "vendor/src/django-filter"]
|
||||
path = vendor/src/django-filter
|
||||
url = https://github.com/alex/django-filter.git
|
||||
[submodule "vendor/src/django-badger"]
|
||||
path = vendor/src/django-badger
|
||||
url = https://github.com/mozilla/django-badger
|
||||
[submodule "vendor/src/dennis"]
|
||||
path = vendor/src/dennis
|
||||
url = https://github.com/willkg/dennis.git
|
||||
[submodule "vendor/src/billiard"]
|
||||
path = vendor/src/billiard
|
||||
url = https://github.com/celery/billiard.git
|
||||
[submodule "vendor/src/django-statici18n"]
|
||||
path = vendor/src/django-statici18n
|
||||
url = https://github.com/zyegfryed/django-statici18n.git
|
||||
[submodule "vendor/src/django-appconf"]
|
||||
path = vendor/src/django-appconf
|
||||
url = https://github.com/jezdez/django-appconf.git
|
||||
[submodule "vendor/src/django-axes"]
|
||||
path = vendor/src/django-axes
|
||||
url = https://github.com/django-security/django-axes.git
|
||||
[submodule "vendor/src/django-taggit"]
|
||||
path = vendor/src/django-taggit
|
||||
url = https://github.com/alex/django-taggit.git
|
||||
[submodule "vendor/src/elasticsearch-py"]
|
||||
path = vendor/src/elasticsearch-py
|
||||
url = https://github.com/elasticsearch/elasticsearch-py.git
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
for f in vendor/src/*; do
|
||||
pushd $f > /dev/null && REPO=$(git config remote.origin.url) && popd > /dev/null && git submodule add $REPO $f
|
||||
done
|
|
@ -1,99 +0,0 @@
|
|||
packages
|
||||
packages/pytz
|
||||
packages/coverage
|
||||
packages/sqlparse
|
||||
packages/GitPython/lib
|
||||
packages/Werkzeug
|
||||
packages/Babel
|
||||
packages/python-dateutil
|
||||
packages/pylint
|
||||
packages/ipython
|
||||
packages/pyflakes
|
||||
packages/amqp
|
||||
packages/anyjson
|
||||
packages/carrot
|
||||
packages/pyquery
|
||||
packages/setuptools
|
||||
packages/pep8
|
||||
packages/logilab-astng
|
||||
packages/importlib
|
||||
packages/python-memcached
|
||||
packages/selenium
|
||||
packages/mock
|
||||
packages/logilab-common
|
||||
packages/pyparsing
|
||||
packages/sqlalchemy
|
||||
packages/translate-toolkit
|
||||
packages/nose
|
||||
packages/httplib2/python2
|
||||
packages/polib
|
||||
packages/pyes
|
||||
packages/mimeparse
|
||||
packages/simplejson
|
||||
packages/six
|
||||
packages/South
|
||||
src
|
||||
src/dennis
|
||||
src/django-cronjobs
|
||||
src/django-cache-machine
|
||||
src/django-nose
|
||||
src/django-authority
|
||||
src/django-picklefield/src
|
||||
src/django-timezones
|
||||
src/commonware
|
||||
src/jingo
|
||||
src/cache-panel
|
||||
src/jingo-minify
|
||||
src/check
|
||||
src/django-mozilla-product-details
|
||||
src/test-utils
|
||||
src/schematic
|
||||
src/py-wikimarkup
|
||||
src/django-multidb-router
|
||||
src/bleach
|
||||
src/tower
|
||||
src/django-extensions
|
||||
src/django
|
||||
src/tweepy
|
||||
src/django-csp
|
||||
src/django-waffle
|
||||
src/sphinxapi
|
||||
src/django-mobility
|
||||
src/django-qunit
|
||||
src/django-adminplus
|
||||
src/celery
|
||||
src/kombu
|
||||
src/django-celery
|
||||
src/django-tidings
|
||||
src/pystatsd
|
||||
src/django-session-csrf
|
||||
src/redis-py
|
||||
src/django-ratelimit
|
||||
src/django-recaptcha
|
||||
src/python-recaptcha
|
||||
src/oedipus
|
||||
src/elasticutils
|
||||
src/elasticsearch-py
|
||||
src/zendesk
|
||||
packages/ordereddict
|
||||
src/django-eadred
|
||||
src/raven-python
|
||||
packages/google-api-python-client
|
||||
packages/python-gflags
|
||||
src/django-statsd
|
||||
src/requests
|
||||
src/premailer
|
||||
src/oauthlib
|
||||
src/requests-oauthlib
|
||||
src/twython
|
||||
packages/selenium/py
|
||||
packages/urllib3
|
||||
src/html5lib-python
|
||||
src/django-rest-framework
|
||||
src/django-filter
|
||||
src/django-badger
|
||||
src/billiard
|
||||
src/django-statici18n/src
|
||||
src/django-appconf
|
||||
src/django-axes
|
||||
src/django-taggit
|
|
@ -1,18 +0,0 @@
|
|||
Metadata-Version: 1.0
|
||||
Name: Babel
|
||||
Version: 0.9.6
|
||||
Summary: Internationalization utilities
|
||||
Home-page: http://babel.edgewall.org/
|
||||
Author: Edgewall Software
|
||||
Author-email: info@edgewall.org
|
||||
License: BSD
|
||||
Download-URL: http://babel.edgewall.org/wiki/Download
|
||||
Description: A collection of tools for internationalizing Python applications.
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 4 - Beta
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
@ -1,539 +0,0 @@
|
|||
COPYING
|
||||
ChangeLog
|
||||
INSTALL.txt
|
||||
MANIFEST.in
|
||||
README.txt
|
||||
setup.cfg
|
||||
setup.py
|
||||
Babel.egg-info/PKG-INFO
|
||||
Babel.egg-info/SOURCES.txt
|
||||
Babel.egg-info/dependency_links.txt
|
||||
Babel.egg-info/entry_points.txt
|
||||
Babel.egg-info/not-zip-safe
|
||||
Babel.egg-info/top_level.txt
|
||||
babel/__init__.py
|
||||
babel/core.py
|
||||
babel/dates.py
|
||||
babel/global.dat
|
||||
babel/localedata.py
|
||||
babel/numbers.py
|
||||
babel/support.py
|
||||
babel/util.py
|
||||
babel/localedata/aa.dat
|
||||
babel/localedata/aa_DJ.dat
|
||||
babel/localedata/aa_ER.dat
|
||||
babel/localedata/aa_ER_SAAHO.dat
|
||||
babel/localedata/aa_ET.dat
|
||||
babel/localedata/af.dat
|
||||
babel/localedata/af_NA.dat
|
||||
babel/localedata/af_ZA.dat
|
||||
babel/localedata/ak.dat
|
||||
babel/localedata/ak_GH.dat
|
||||
babel/localedata/am.dat
|
||||
babel/localedata/am_ET.dat
|
||||
babel/localedata/ar.dat
|
||||
babel/localedata/ar_AE.dat
|
||||
babel/localedata/ar_BH.dat
|
||||
babel/localedata/ar_DZ.dat
|
||||
babel/localedata/ar_EG.dat
|
||||
babel/localedata/ar_IQ.dat
|
||||
babel/localedata/ar_JO.dat
|
||||
babel/localedata/ar_KW.dat
|
||||
babel/localedata/ar_LB.dat
|
||||
babel/localedata/ar_LY.dat
|
||||
babel/localedata/ar_MA.dat
|
||||
babel/localedata/ar_OM.dat
|
||||
babel/localedata/ar_QA.dat
|
||||
babel/localedata/ar_SA.dat
|
||||
babel/localedata/ar_SD.dat
|
||||
babel/localedata/ar_SY.dat
|
||||
babel/localedata/ar_TN.dat
|
||||
babel/localedata/ar_YE.dat
|
||||
babel/localedata/as.dat
|
||||
babel/localedata/as_IN.dat
|
||||
babel/localedata/az.dat
|
||||
babel/localedata/az_AZ.dat
|
||||
babel/localedata/az_Cyrl.dat
|
||||
babel/localedata/az_Cyrl_AZ.dat
|
||||
babel/localedata/az_Latn.dat
|
||||
babel/localedata/az_Latn_AZ.dat
|
||||
babel/localedata/be.dat
|
||||
babel/localedata/be_BY.dat
|
||||
babel/localedata/bg.dat
|
||||
babel/localedata/bg_BG.dat
|
||||
babel/localedata/bn.dat
|
||||
babel/localedata/bn_BD.dat
|
||||
babel/localedata/bn_IN.dat
|
||||
babel/localedata/bs.dat
|
||||
babel/localedata/bs_BA.dat
|
||||
babel/localedata/byn.dat
|
||||
babel/localedata/byn_ER.dat
|
||||
babel/localedata/ca.dat
|
||||
babel/localedata/ca_ES.dat
|
||||
babel/localedata/cch.dat
|
||||
babel/localedata/cch_NG.dat
|
||||
babel/localedata/cop.dat
|
||||
babel/localedata/cs.dat
|
||||
babel/localedata/cs_CZ.dat
|
||||
babel/localedata/cy.dat
|
||||
babel/localedata/cy_GB.dat
|
||||
babel/localedata/da.dat
|
||||
babel/localedata/da_DK.dat
|
||||
babel/localedata/de.dat
|
||||
babel/localedata/de_AT.dat
|
||||
babel/localedata/de_BE.dat
|
||||
babel/localedata/de_CH.dat
|
||||
babel/localedata/de_DE.dat
|
||||
babel/localedata/de_LI.dat
|
||||
babel/localedata/de_LU.dat
|
||||
babel/localedata/dv.dat
|
||||
babel/localedata/dv_MV.dat
|
||||
babel/localedata/dz.dat
|
||||
babel/localedata/dz_BT.dat
|
||||
babel/localedata/ee.dat
|
||||
babel/localedata/ee_GH.dat
|
||||
babel/localedata/ee_TG.dat
|
||||
babel/localedata/el.dat
|
||||
babel/localedata/el_CY.dat
|
||||
babel/localedata/el_GR.dat
|
||||
babel/localedata/el_POLYTON.dat
|
||||
babel/localedata/en.dat
|
||||
babel/localedata/en_AS.dat
|
||||
babel/localedata/en_AU.dat
|
||||
babel/localedata/en_BE.dat
|
||||
babel/localedata/en_BW.dat
|
||||
babel/localedata/en_BZ.dat
|
||||
babel/localedata/en_CA.dat
|
||||
babel/localedata/en_Dsrt.dat
|
||||
babel/localedata/en_Dsrt_US.dat
|
||||
babel/localedata/en_GB.dat
|
||||
babel/localedata/en_GU.dat
|
||||
babel/localedata/en_HK.dat
|
||||
babel/localedata/en_IE.dat
|
||||
babel/localedata/en_IN.dat
|
||||
babel/localedata/en_JM.dat
|
||||
babel/localedata/en_MH.dat
|
||||
babel/localedata/en_MP.dat
|
||||
babel/localedata/en_MT.dat
|
||||
babel/localedata/en_NA.dat
|
||||
babel/localedata/en_NZ.dat
|
||||
babel/localedata/en_PH.dat
|
||||
babel/localedata/en_PK.dat
|
||||
babel/localedata/en_SG.dat
|
||||
babel/localedata/en_Shaw.dat
|
||||
babel/localedata/en_TT.dat
|
||||
babel/localedata/en_UM.dat
|
||||
babel/localedata/en_US.dat
|
||||
babel/localedata/en_US_POSIX.dat
|
||||
babel/localedata/en_VI.dat
|
||||
babel/localedata/en_ZA.dat
|
||||
babel/localedata/en_ZW.dat
|
||||
babel/localedata/eo.dat
|
||||
babel/localedata/es.dat
|
||||
babel/localedata/es_AR.dat
|
||||
babel/localedata/es_BO.dat
|
||||
babel/localedata/es_CL.dat
|
||||
babel/localedata/es_CO.dat
|
||||
babel/localedata/es_CR.dat
|
||||
babel/localedata/es_DO.dat
|
||||
babel/localedata/es_EC.dat
|
||||
babel/localedata/es_ES.dat
|
||||
babel/localedata/es_GT.dat
|
||||
babel/localedata/es_HN.dat
|
||||
babel/localedata/es_MX.dat
|
||||
babel/localedata/es_NI.dat
|
||||
babel/localedata/es_PA.dat
|
||||
babel/localedata/es_PE.dat
|
||||
babel/localedata/es_PR.dat
|
||||
babel/localedata/es_PY.dat
|
||||
babel/localedata/es_SV.dat
|
||||
babel/localedata/es_US.dat
|
||||
babel/localedata/es_UY.dat
|
||||
babel/localedata/es_VE.dat
|
||||
babel/localedata/et.dat
|
||||
babel/localedata/et_EE.dat
|
||||
babel/localedata/eu.dat
|
||||
babel/localedata/eu_ES.dat
|
||||
babel/localedata/fa.dat
|
||||
babel/localedata/fa_AF.dat
|
||||
babel/localedata/fa_IR.dat
|
||||
babel/localedata/fi.dat
|
||||
babel/localedata/fi_FI.dat
|
||||
babel/localedata/fil.dat
|
||||
babel/localedata/fil_PH.dat
|
||||
babel/localedata/fo.dat
|
||||
babel/localedata/fo_FO.dat
|
||||
babel/localedata/fr.dat
|
||||
babel/localedata/fr_BE.dat
|
||||
babel/localedata/fr_CA.dat
|
||||
babel/localedata/fr_CH.dat
|
||||
babel/localedata/fr_FR.dat
|
||||
babel/localedata/fr_LU.dat
|
||||
babel/localedata/fr_MC.dat
|
||||
babel/localedata/fr_SN.dat
|
||||
babel/localedata/fur.dat
|
||||
babel/localedata/fur_IT.dat
|
||||
babel/localedata/ga.dat
|
||||
babel/localedata/ga_IE.dat
|
||||
babel/localedata/gaa.dat
|
||||
babel/localedata/gaa_GH.dat
|
||||
babel/localedata/gez.dat
|
||||
babel/localedata/gez_ER.dat
|
||||
babel/localedata/gez_ET.dat
|
||||
babel/localedata/gl.dat
|
||||
babel/localedata/gl_ES.dat
|
||||
babel/localedata/gu.dat
|
||||
babel/localedata/gu_IN.dat
|
||||
babel/localedata/gv.dat
|
||||
babel/localedata/gv_GB.dat
|
||||
babel/localedata/ha.dat
|
||||
babel/localedata/ha_Arab.dat
|
||||
babel/localedata/ha_Arab_NG.dat
|
||||
babel/localedata/ha_Arab_SD.dat
|
||||
babel/localedata/ha_GH.dat
|
||||
babel/localedata/ha_Latn.dat
|
||||
babel/localedata/ha_Latn_GH.dat
|
||||
babel/localedata/ha_Latn_NE.dat
|
||||
babel/localedata/ha_Latn_NG.dat
|
||||
babel/localedata/ha_NE.dat
|
||||
babel/localedata/ha_NG.dat
|
||||
babel/localedata/ha_SD.dat
|
||||
babel/localedata/haw.dat
|
||||
babel/localedata/haw_US.dat
|
||||
babel/localedata/he.dat
|
||||
babel/localedata/he_IL.dat
|
||||
babel/localedata/hi.dat
|
||||
babel/localedata/hi_IN.dat
|
||||
babel/localedata/hr.dat
|
||||
babel/localedata/hr_HR.dat
|
||||
babel/localedata/hu.dat
|
||||
babel/localedata/hu_HU.dat
|
||||
babel/localedata/hy.dat
|
||||
babel/localedata/hy_AM.dat
|
||||
babel/localedata/hy_AM_REVISED.dat
|
||||
babel/localedata/ia.dat
|
||||
babel/localedata/id.dat
|
||||
babel/localedata/id_ID.dat
|
||||
babel/localedata/ig.dat
|
||||
babel/localedata/ig_NG.dat
|
||||
babel/localedata/ii.dat
|
||||
babel/localedata/ii_CN.dat
|
||||
babel/localedata/in.dat
|
||||
babel/localedata/is.dat
|
||||
babel/localedata/is_IS.dat
|
||||
babel/localedata/it.dat
|
||||
babel/localedata/it_CH.dat
|
||||
babel/localedata/it_IT.dat
|
||||
babel/localedata/iu.dat
|
||||
babel/localedata/iw.dat
|
||||
babel/localedata/ja.dat
|
||||
babel/localedata/ja_JP.dat
|
||||
babel/localedata/ka.dat
|
||||
babel/localedata/ka_GE.dat
|
||||
babel/localedata/kaj.dat
|
||||
babel/localedata/kaj_NG.dat
|
||||
babel/localedata/kam.dat
|
||||
babel/localedata/kam_KE.dat
|
||||
babel/localedata/kcg.dat
|
||||
babel/localedata/kcg_NG.dat
|
||||
babel/localedata/kfo.dat
|
||||
babel/localedata/kfo_CI.dat
|
||||
babel/localedata/kk.dat
|
||||
babel/localedata/kk_Cyrl.dat
|
||||
babel/localedata/kk_Cyrl_KZ.dat
|
||||
babel/localedata/kk_KZ.dat
|
||||
babel/localedata/kl.dat
|
||||
babel/localedata/kl_GL.dat
|
||||
babel/localedata/km.dat
|
||||
babel/localedata/km_KH.dat
|
||||
babel/localedata/kn.dat
|
||||
babel/localedata/kn_IN.dat
|
||||
babel/localedata/ko.dat
|
||||
babel/localedata/ko_KR.dat
|
||||
babel/localedata/kok.dat
|
||||
babel/localedata/kok_IN.dat
|
||||
babel/localedata/kpe.dat
|
||||
babel/localedata/kpe_GN.dat
|
||||
babel/localedata/kpe_LR.dat
|
||||
babel/localedata/ku.dat
|
||||
babel/localedata/ku_Arab.dat
|
||||
babel/localedata/ku_Latn.dat
|
||||
babel/localedata/ku_Latn_TR.dat
|
||||
babel/localedata/ku_TR.dat
|
||||
babel/localedata/kw.dat
|
||||
babel/localedata/kw_GB.dat
|
||||
babel/localedata/ky.dat
|
||||
babel/localedata/ky_KG.dat
|
||||
babel/localedata/ln.dat
|
||||
babel/localedata/ln_CD.dat
|
||||
babel/localedata/ln_CG.dat
|
||||
babel/localedata/lo.dat
|
||||
babel/localedata/lo_LA.dat
|
||||
babel/localedata/lt.dat
|
||||
babel/localedata/lt_LT.dat
|
||||
babel/localedata/lv.dat
|
||||
babel/localedata/lv_LV.dat
|
||||
babel/localedata/mk.dat
|
||||
babel/localedata/mk_MK.dat
|
||||
babel/localedata/ml.dat
|
||||
babel/localedata/ml_IN.dat
|
||||
babel/localedata/mn.dat
|
||||
babel/localedata/mn_CN.dat
|
||||
babel/localedata/mn_Cyrl.dat
|
||||
babel/localedata/mn_Cyrl_MN.dat
|
||||
babel/localedata/mn_MN.dat
|
||||
babel/localedata/mn_Mong.dat
|
||||
babel/localedata/mn_Mong_CN.dat
|
||||
babel/localedata/mo.dat
|
||||
babel/localedata/mr.dat
|
||||
babel/localedata/mr_IN.dat
|
||||
babel/localedata/ms.dat
|
||||
babel/localedata/ms_BN.dat
|
||||
babel/localedata/ms_MY.dat
|
||||
babel/localedata/mt.dat
|
||||
babel/localedata/mt_MT.dat
|
||||
babel/localedata/my.dat
|
||||
babel/localedata/my_MM.dat
|
||||
babel/localedata/nb.dat
|
||||
babel/localedata/nb_NO.dat
|
||||
babel/localedata/ne.dat
|
||||
babel/localedata/ne_IN.dat
|
||||
babel/localedata/ne_NP.dat
|
||||
babel/localedata/nl.dat
|
||||
babel/localedata/nl_BE.dat
|
||||
babel/localedata/nl_NL.dat
|
||||
babel/localedata/nn.dat
|
||||
babel/localedata/nn_NO.dat
|
||||
babel/localedata/no.dat
|
||||
babel/localedata/nr.dat
|
||||
babel/localedata/nr_ZA.dat
|
||||
babel/localedata/nso.dat
|
||||
babel/localedata/nso_ZA.dat
|
||||
babel/localedata/ny.dat
|
||||
babel/localedata/ny_MW.dat
|
||||
babel/localedata/om.dat
|
||||
babel/localedata/om_ET.dat
|
||||
babel/localedata/om_KE.dat
|
||||
babel/localedata/or.dat
|
||||
babel/localedata/or_IN.dat
|
||||
babel/localedata/pa.dat
|
||||
babel/localedata/pa_Arab.dat
|
||||
babel/localedata/pa_Arab_PK.dat
|
||||
babel/localedata/pa_Guru.dat
|
||||
babel/localedata/pa_Guru_IN.dat
|
||||
babel/localedata/pa_IN.dat
|
||||
babel/localedata/pa_PK.dat
|
||||
babel/localedata/pl.dat
|
||||
babel/localedata/pl_PL.dat
|
||||
babel/localedata/ps.dat
|
||||
babel/localedata/ps_AF.dat
|
||||
babel/localedata/pt.dat
|
||||
babel/localedata/pt_BR.dat
|
||||
babel/localedata/pt_PT.dat
|
||||
babel/localedata/ro.dat
|
||||
babel/localedata/ro_MD.dat
|
||||
babel/localedata/ro_RO.dat
|
||||
babel/localedata/root.dat
|
||||
babel/localedata/ru.dat
|
||||
babel/localedata/ru_RU.dat
|
||||
babel/localedata/ru_UA.dat
|
||||
babel/localedata/rw.dat
|
||||
babel/localedata/rw_RW.dat
|
||||
babel/localedata/sa.dat
|
||||
babel/localedata/sa_IN.dat
|
||||
babel/localedata/se.dat
|
||||
babel/localedata/se_FI.dat
|
||||
babel/localedata/se_NO.dat
|
||||
babel/localedata/sh.dat
|
||||
babel/localedata/sh_BA.dat
|
||||
babel/localedata/sh_CS.dat
|
||||
babel/localedata/sh_YU.dat
|
||||
babel/localedata/si.dat
|
||||
babel/localedata/si_LK.dat
|
||||
babel/localedata/sid.dat
|
||||
babel/localedata/sid_ET.dat
|
||||
babel/localedata/sk.dat
|
||||
babel/localedata/sk_SK.dat
|
||||
babel/localedata/sl.dat
|
||||
babel/localedata/sl_SI.dat
|
||||
babel/localedata/so.dat
|
||||
babel/localedata/so_DJ.dat
|
||||
babel/localedata/so_ET.dat
|
||||
babel/localedata/so_KE.dat
|
||||
babel/localedata/so_SO.dat
|
||||
babel/localedata/sq.dat
|
||||
babel/localedata/sq_AL.dat
|
||||
babel/localedata/sr.dat
|
||||
babel/localedata/sr_BA.dat
|
||||
babel/localedata/sr_CS.dat
|
||||
babel/localedata/sr_Cyrl.dat
|
||||
babel/localedata/sr_Cyrl_BA.dat
|
||||
babel/localedata/sr_Cyrl_CS.dat
|
||||
babel/localedata/sr_Cyrl_ME.dat
|
||||
babel/localedata/sr_Cyrl_RS.dat
|
||||
babel/localedata/sr_Cyrl_YU.dat
|
||||
babel/localedata/sr_Latn.dat
|
||||
babel/localedata/sr_Latn_BA.dat
|
||||
babel/localedata/sr_Latn_CS.dat
|
||||
babel/localedata/sr_Latn_ME.dat
|
||||
babel/localedata/sr_Latn_RS.dat
|
||||
babel/localedata/sr_Latn_YU.dat
|
||||
babel/localedata/sr_ME.dat
|
||||
babel/localedata/sr_RS.dat
|
||||
babel/localedata/sr_YU.dat
|
||||
babel/localedata/ss.dat
|
||||
babel/localedata/ss_SZ.dat
|
||||
babel/localedata/ss_ZA.dat
|
||||
babel/localedata/st.dat
|
||||
babel/localedata/st_LS.dat
|
||||
babel/localedata/st_ZA.dat
|
||||
babel/localedata/sv.dat
|
||||
babel/localedata/sv_FI.dat
|
||||
babel/localedata/sv_SE.dat
|
||||
babel/localedata/sw.dat
|
||||
babel/localedata/sw_KE.dat
|
||||
babel/localedata/sw_TZ.dat
|
||||
babel/localedata/syr.dat
|
||||
babel/localedata/syr_SY.dat
|
||||
babel/localedata/ta.dat
|
||||
babel/localedata/ta_IN.dat
|
||||
babel/localedata/te.dat
|
||||
babel/localedata/te_IN.dat
|
||||
babel/localedata/tg.dat
|
||||
babel/localedata/tg_Cyrl.dat
|
||||
babel/localedata/tg_Cyrl_TJ.dat
|
||||
babel/localedata/tg_TJ.dat
|
||||
babel/localedata/th.dat
|
||||
babel/localedata/th_TH.dat
|
||||
babel/localedata/ti.dat
|
||||
babel/localedata/ti_ER.dat
|
||||
babel/localedata/ti_ET.dat
|
||||
babel/localedata/tig.dat
|
||||
babel/localedata/tig_ER.dat
|
||||
babel/localedata/tl.dat
|
||||
babel/localedata/tn.dat
|
||||
babel/localedata/tn_ZA.dat
|
||||
babel/localedata/to.dat
|
||||
babel/localedata/to_TO.dat
|
||||
babel/localedata/tr.dat
|
||||
babel/localedata/tr_TR.dat
|
||||
babel/localedata/trv.dat
|
||||
babel/localedata/ts.dat
|
||||
babel/localedata/ts_ZA.dat
|
||||
babel/localedata/tt.dat
|
||||
babel/localedata/tt_RU.dat
|
||||
babel/localedata/ug.dat
|
||||
babel/localedata/ug_Arab.dat
|
||||
babel/localedata/ug_Arab_CN.dat
|
||||
babel/localedata/ug_CN.dat
|
||||
babel/localedata/uk.dat
|
||||
babel/localedata/uk_UA.dat
|
||||
babel/localedata/ur.dat
|
||||
babel/localedata/ur_IN.dat
|
||||
babel/localedata/ur_PK.dat
|
||||
babel/localedata/uz.dat
|
||||
babel/localedata/uz_AF.dat
|
||||
babel/localedata/uz_Arab.dat
|
||||
babel/localedata/uz_Arab_AF.dat
|
||||
babel/localedata/uz_Cyrl.dat
|
||||
babel/localedata/uz_Cyrl_UZ.dat
|
||||
babel/localedata/uz_Latn.dat
|
||||
babel/localedata/uz_Latn_UZ.dat
|
||||
babel/localedata/uz_UZ.dat
|
||||
babel/localedata/ve.dat
|
||||
babel/localedata/ve_ZA.dat
|
||||
babel/localedata/vi.dat
|
||||
babel/localedata/vi_VN.dat
|
||||
babel/localedata/wal.dat
|
||||
babel/localedata/wal_ET.dat
|
||||
babel/localedata/wo.dat
|
||||
babel/localedata/wo_Latn.dat
|
||||
babel/localedata/wo_Latn_SN.dat
|
||||
babel/localedata/wo_SN.dat
|
||||
babel/localedata/xh.dat
|
||||
babel/localedata/xh_ZA.dat
|
||||
babel/localedata/yo.dat
|
||||
babel/localedata/yo_NG.dat
|
||||
babel/localedata/zh.dat
|
||||
babel/localedata/zh_CN.dat
|
||||
babel/localedata/zh_HK.dat
|
||||
babel/localedata/zh_Hans.dat
|
||||
babel/localedata/zh_Hans_CN.dat
|
||||
babel/localedata/zh_Hans_HK.dat
|
||||
babel/localedata/zh_Hans_MO.dat
|
||||
babel/localedata/zh_Hans_SG.dat
|
||||
babel/localedata/zh_Hant.dat
|
||||
babel/localedata/zh_Hant_HK.dat
|
||||
babel/localedata/zh_Hant_MO.dat
|
||||
babel/localedata/zh_Hant_TW.dat
|
||||
babel/localedata/zh_MO.dat
|
||||
babel/localedata/zh_SG.dat
|
||||
babel/localedata/zh_TW.dat
|
||||
babel/localedata/zu.dat
|
||||
babel/localedata/zu_ZA.dat
|
||||
babel/messages/__init__.py
|
||||
babel/messages/catalog.py
|
||||
babel/messages/checkers.py
|
||||
babel/messages/extract.py
|
||||
babel/messages/frontend.py
|
||||
babel/messages/jslexer.py
|
||||
babel/messages/mofile.py
|
||||
babel/messages/plurals.py
|
||||
babel/messages/pofile.py
|
||||
babel/messages/tests/__init__.py
|
||||
babel/messages/tests/catalog.py
|
||||
babel/messages/tests/checkers.py
|
||||
babel/messages/tests/extract.py
|
||||
babel/messages/tests/frontend.py
|
||||
babel/messages/tests/mofile.py
|
||||
babel/messages/tests/plurals.py
|
||||
babel/messages/tests/pofile.py
|
||||
babel/messages/tests/data/mapping.cfg
|
||||
babel/messages/tests/data/setup.cfg
|
||||
babel/messages/tests/data/setup.py
|
||||
babel/messages/tests/data/project/__init__.py
|
||||
babel/messages/tests/data/project/file1.py
|
||||
babel/messages/tests/data/project/file2.py
|
||||
babel/messages/tests/data/project/i18n/messages.pot
|
||||
babel/messages/tests/data/project/i18n/messages_non_fuzzy.pot
|
||||
babel/messages/tests/data/project/i18n/de_DE/LC_MESSAGES/messages.po
|
||||
babel/messages/tests/data/project/i18n/ru_RU/LC_MESSAGES/messages.po
|
||||
babel/messages/tests/data/project/ignored/a_test_file.txt
|
||||
babel/messages/tests/data/project/ignored/an_example.txt
|
||||
babel/messages/tests/data/project/ignored/this_wont_normally_be_here.py
|
||||
babel/tests/__init__.py
|
||||
babel/tests/core.py
|
||||
babel/tests/dates.py
|
||||
babel/tests/localedata.py
|
||||
babel/tests/numbers.py
|
||||
babel/tests/support.py
|
||||
babel/tests/util.py
|
||||
contrib/babel.js
|
||||
doc/cmdline.txt
|
||||
doc/dates.txt
|
||||
doc/display.txt
|
||||
doc/index.txt
|
||||
doc/intro.txt
|
||||
doc/logo.pdf
|
||||
doc/logo.png
|
||||
doc/logo_small.png
|
||||
doc/messages.txt
|
||||
doc/numbers.txt
|
||||
doc/setup.txt
|
||||
doc/support.txt
|
||||
doc/common/COPYING
|
||||
doc/common/README.txt
|
||||
doc/common/doctools.py
|
||||
doc/common/template.html
|
||||
doc/common/conf/docutils.ini
|
||||
doc/common/conf/epydoc.ini
|
||||
doc/common/style/bkgnd_pattern.png
|
||||
doc/common/style/docutils.css
|
||||
doc/common/style/edgewall.css
|
||||
doc/common/style/epydoc.css
|
||||
doc/common/style/pygments.css
|
||||
doc/common/style/shadow.gif
|
||||
doc/common/style/vertbars.png
|
||||
scripts/dump_data.py
|
||||
scripts/dump_global.py
|
||||
scripts/import_cldr.py
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
[console_scripts]
|
||||
pybabel = babel.messages.frontend:main
|
||||
|
||||
[distutils.commands]
|
||||
compile_catalog = babel.messages.frontend:compile_catalog
|
||||
extract_messages = babel.messages.frontend:extract_messages
|
||||
init_catalog = babel.messages.frontend:init_catalog
|
||||
update_catalog = babel.messages.frontend:update_catalog
|
||||
|
||||
[distutils.setup_keywords]
|
||||
message_extractors = babel.messages.frontend:check_message_extractors
|
||||
|
||||
[babel.checkers]
|
||||
num_plurals = babel.messages.checkers:num_plurals
|
||||
python_format = babel.messages.checkers:python_format
|
||||
|
||||
[babel.extractors]
|
||||
ignore = babel.messages.extract:extract_nothing
|
||||
python = babel.messages.extract:extract_python
|
||||
javascript = babel.messages.extract:extract_javascript
|
||||
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1 +0,0 @@
|
|||
babel
|
|
@ -1,28 +0,0 @@
|
|||
Copyright (C) 2007 Edgewall Software
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,181 +0,0 @@
|
|||
Version 0.9.6
|
||||
http://svn.edgewall.org/repos/babel/tags/0.9.6/
|
||||
(Mar 17 2011, from branches/stable/0.9.x)
|
||||
|
||||
* Backport r493-494: documentation typo fixes.
|
||||
* Make the CLDR import script work with Python 2.7.
|
||||
* Fix various typos.
|
||||
* Fixed Python 2.3 compatibility (ticket #146, #233).
|
||||
* Sort output of list-locales.
|
||||
* Make the POT-Creation-Date of the catalog being updated equal to
|
||||
POT-Creation-Date of the template used to update (ticket #148).
|
||||
* Use a more explicit error message if no option or argument (command) is
|
||||
passed to pybabel (ticket #81).
|
||||
* Keep the PO-Revision-Date if it is not the default value (ticket #148).
|
||||
* Make --no-wrap work by reworking --width's default and mimic xgettext's
|
||||
behaviour of always wrapping comments (ticket #145).
|
||||
* Fixed negative offset handling of Catalog._set_mime_headers (ticket #165).
|
||||
* Add --project and --version options for commandline (ticket #173).
|
||||
* Add a __ne__() method to the Local class.
|
||||
* Explicitly sort instead of using sorted() and don't assume ordering
|
||||
(Python 2.3 and Jython compatibility).
|
||||
* Removed ValueError raising for string formatting message checkers if the
|
||||
string does not contain any string formattings (ticket #150).
|
||||
* Fix Serbian plural forms (ticket #213).
|
||||
* Small speed improvement in format_date() (ticket #216).
|
||||
* Fix number formatting for locales where CLDR specifies alt or draft
|
||||
items (ticket #217)
|
||||
* Fix bad check in format_time (ticket #257, reported with patch and tests by
|
||||
jomae)
|
||||
* Fix so frontend.CommandLineInterface.run does not accumulate logging
|
||||
handlers (#227, reported with initial patch by dfraser)
|
||||
* Fix exception if environment contains an invalid locale setting (#200)
|
||||
|
||||
|
||||
Version 0.9.5
|
||||
http://svn.edgewall.org/repos/babel/tags/0.9.5/
|
||||
(Apr 6 2010, from branches/stable/0.9.x)
|
||||
|
||||
* Fixed the case where messages containing square brackets would break with
|
||||
an unpack error.
|
||||
* Backport of r467: Fuzzy matching regarding plurals should *NOT* be checked
|
||||
against len(message.id) because this is always 2, instead, it's should be
|
||||
checked against catalog.num_plurals (ticket #212).
|
||||
|
||||
|
||||
Version 0.9.4
|
||||
http://svn.edgewall.org/repos/babel/tags/0.9.4/
|
||||
(Aug 25 2008, from branches/stable/0.9.x)
|
||||
|
||||
* Currency symbol definitions that is defined with choice patterns in the
|
||||
CLDR data are no longer imported, so the symbol code will be used instead.
|
||||
* Fixed quarter support in date formatting.
|
||||
* Fixed a serious memory leak that was introduces by the support for CLDR
|
||||
aliases in 0.9.3 (ticket #128).
|
||||
* Locale modifiers such as "@euro" are now stripped from locale identifiers
|
||||
when parsing (ticket #136).
|
||||
* The system locales "C" and "POSIX" are now treated as aliases for
|
||||
"en_US_POSIX", for which the CLDR provides the appropriate data. Thanks to
|
||||
Manlio Perillo for the suggestion.
|
||||
* Fixed JavaScript extraction for regular expression literals (ticket #138)
|
||||
and concatenated strings.
|
||||
* The `Translation` class in `babel.support` can now manage catalogs with
|
||||
different message domains, and exposes the family of `d*gettext` functions
|
||||
(ticket #137).
|
||||
|
||||
|
||||
Version 0.9.3
|
||||
http://svn.edgewall.org/repos/babel/tags/0.9.3/
|
||||
(Jul 9 2008, from branches/stable/0.9.x)
|
||||
|
||||
* Fixed invalid message extraction methods causing an UnboundLocalError.
|
||||
* Extraction method specification can now use a dot instead of the colon to
|
||||
separate module and function name (ticket #105).
|
||||
* Fixed message catalog compilation for locales with more than two plural
|
||||
forms (ticket #95).
|
||||
* Fixed compilation of message catalogs for locales with more than two plural
|
||||
forms where the translations were empty (ticket #97).
|
||||
* The stripping of the comment tags in comments is optional now and
|
||||
is done for each line in a comment.
|
||||
* Added a JavaScript message extractor.
|
||||
* Updated to CLDR 1.6.
|
||||
* Fixed timezone calculations when formatting datetime and time values.
|
||||
* Added a `get_plural` function into the plurals module that returns the
|
||||
correct plural forms for a locale as tuple.
|
||||
* Added support for alias definitions in the CLDR data files, meaning that
|
||||
the chance for items missing in certain locales should be greatly reduced
|
||||
(ticket #68).
|
||||
|
||||
|
||||
Version 0.9.2
|
||||
http://svn.edgewall.org/repos/babel/tags/0.9.2/
|
||||
(Feb 4 2008, from branches/stable/0.9.x)
|
||||
|
||||
* Fixed catalogs' charset values not being recognized (ticket #66).
|
||||
* Numerous improvements to the default plural forms.
|
||||
* Fixed fuzzy matching when updating message catalogs (ticket #82).
|
||||
* Fixed bug in catalog updating, that in some cases pulled in translations
|
||||
from different catalogs based on the same template.
|
||||
* Location lines in PO files do no longer get wrapped at hyphens in file
|
||||
names (ticket #79).
|
||||
* Fixed division by zero error in catalog compilation on empty catalogs
|
||||
(ticket #60).
|
||||
|
||||
|
||||
Version 0.9.1
|
||||
http://svn.edgewall.org/repos/babel/tags/0.9.1/
|
||||
(Sep 7 2007, from branches/stable/0.9.x)
|
||||
|
||||
* Fixed catalog updating when a message is merged that was previously simple
|
||||
but now has a plural form, for example by moving from `gettext` to
|
||||
`ngettext`, or vice versa.
|
||||
* Fixed time formatting for 12 am and 12 pm.
|
||||
* Fixed output encoding of the `pybabel --list-locales` command.
|
||||
* MO files are now written in binary mode on windows (ticket #61).
|
||||
|
||||
|
||||
Version 0.9
|
||||
http://svn.edgewall.org/repos/babel/tags/0.9.0/
|
||||
(Aug 20 2007, from branches/stable/0.9.x)
|
||||
|
||||
* The `new_catalog` distutils command has been renamed to `init_catalog` for
|
||||
consistency with the command-line frontend.
|
||||
* Added compilation of message catalogs to MO files (ticket #21).
|
||||
* Added updating of message catalogs from POT files (ticket #22).
|
||||
* Support for significant digits in number formatting.
|
||||
* Apply proper "banker's rounding" in number formatting in a cross-platform
|
||||
manner.
|
||||
* The number formatting functions now also work with numbers represented by
|
||||
Python `Decimal` objects (ticket #53).
|
||||
* Added extensible infrastructure for validating translation catalogs.
|
||||
* Fixed the extractor not filtering out messages that didn't validate against
|
||||
the keyword's specification (ticket #39).
|
||||
* Fixed the extractor raising an exception when encountering an empty string
|
||||
msgid. It now emits a warning to stderr.
|
||||
* Numerous Python message extractor fixes: it now handles nested function
|
||||
calls within a gettext function call correctly, uses the correct line number
|
||||
for multi-line function calls, and other small fixes (tickets #38 and #39).
|
||||
* Improved support for detecting Python string formatting fields in message
|
||||
strings (ticket #57).
|
||||
* CLDR upgraded to the 1.5 release.
|
||||
* Improved timezone formatting.
|
||||
* Implemented scientific number formatting.
|
||||
* Added mechanism to lookup locales by alias, for cases where browsers insist
|
||||
on including only the language code in the `Accept-Language` header, and
|
||||
sometimes even the incorrect language code.
|
||||
|
||||
|
||||
Version 0.8.1
|
||||
http://svn.edgewall.org/repos/babel/tags/0.8.1/
|
||||
(Jul 2 2007, from branches/stable/0.8.x)
|
||||
|
||||
* `default_locale()` would fail when the value of the `LANGUAGE` environment
|
||||
variable contained multiple language codes separated by colon, as is
|
||||
explicitly allowed by the GNU gettext tools. As the `default_locale()`
|
||||
function is called at the module level in some modules, this bug would
|
||||
completely break importing these modules on systems where `LANGUAGE` is set
|
||||
that way.
|
||||
* The character set specified in PO template files is now respected when
|
||||
creating new catalog files based on that template. This allows the use of
|
||||
characters outside the ASCII range in POT files (ticket #17).
|
||||
* The default ordering of messages in generated POT files, which is based on
|
||||
the order those messages are found when walking the source tree, is no
|
||||
longer subject to differences between platforms; directory and file names
|
||||
are now always sorted alphabetically.
|
||||
* The Python message extractor now respects the special encoding comment to be
|
||||
able to handle files containing non-ASCII characters (ticket #23).
|
||||
* Added 'N_' (gettext noop) to the extractor's default keywords.
|
||||
* Made locale string parsing more robust, and also take the script part into
|
||||
account (ticket #27).
|
||||
* Added a function to list all locales for which locale data is available.
|
||||
* Added a command-line option to the `pybabel` command which prints out all
|
||||
available locales (ticket #24).
|
||||
* The name of the command-line script has been changed from just `babel` to
|
||||
`pybabel` to avoid a conflict with the OpenBabel project (ticket #34).
|
||||
|
||||
|
||||
Version 0.8
|
||||
http://svn.edgewall.org/repos/babel/tags/0.8.0/
|
||||
(Jun 20 2007, from branches/stable/0.8.x)
|
||||
|
||||
* First public release
|
|
@ -1,39 +0,0 @@
|
|||
Installing Babel
|
||||
================
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
* Python 2.3 or later (2.4 or later is recommended)
|
||||
* Optional: setuptools 0.6b1 or later
|
||||
* Optional: pytz (strongly recommended for real time-zone support, mandatory
|
||||
to run the automated test suite)
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Once you've downloaded and unpacked a Babel source release, enter the
|
||||
directory where the archive was unpacked, and run:
|
||||
|
||||
$ python setup.py install
|
||||
|
||||
Note that you may need administrator/root privileges for this step, as
|
||||
this command will by default attempt to install Babel to the Python
|
||||
site-packages directory on your system.
|
||||
|
||||
For advanced options, please refer to the easy_install and/or the distutils
|
||||
documentation:
|
||||
|
||||
http://peak.telecommunity.com/DevCenter/EasyInstall
|
||||
http://docs.python.org/inst/inst.html
|
||||
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
If you encounter any problems with Babel, please don't hesitate to ask
|
||||
questions on the Babel mailing list or IRC channel:
|
||||
|
||||
http://babel.edgewall.org/wiki/MailingList
|
||||
http://babel.edgewall.org/wiki/IrcChannel
|
|
@ -1,4 +0,0 @@
|
|||
include babel/global.dat
|
||||
include babel/localedata/*.dat
|
||||
include doc/api/*.*
|
||||
include doc/*.html
|
|
@ -1,18 +0,0 @@
|
|||
Metadata-Version: 1.0
|
||||
Name: Babel
|
||||
Version: 0.9.6
|
||||
Summary: Internationalization utilities
|
||||
Home-page: http://babel.edgewall.org/
|
||||
Author: Edgewall Software
|
||||
Author-email: info@edgewall.org
|
||||
License: BSD
|
||||
Download-URL: http://babel.edgewall.org/wiki/Download
|
||||
Description: A collection of tools for internationalizing Python applications.
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 4 - Beta
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
@ -1,12 +0,0 @@
|
|||
About Babel
|
||||
===========
|
||||
|
||||
Babel is a Python library that provides an integrated collection of
|
||||
utilities that assist with internationalizing and localizing Python
|
||||
applications (in particular web-based applications.)
|
||||
|
||||
Details can be found in the HTML files in the `doc` folder.
|
||||
|
||||
For more information please visit the Babel web site:
|
||||
|
||||
<http://babel.edgewall.org/>
|
|
@ -1,39 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2007-2008 Edgewall Software
|
||||
# All rights reserved.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at http://babel.edgewall.org/wiki/License.
|
||||
#
|
||||
# This software consists of voluntary contributions made by many
|
||||
# individuals. For the exact contribution history, see the revision
|
||||
# history and logs, available at http://babel.edgewall.org/log/.
|
||||
|
||||
"""Integrated collection of utilities that assist in internationalizing and
|
||||
localizing applications.
|
||||
|
||||
This package is basically composed of two major parts:
|
||||
|
||||
* tools to build and work with ``gettext`` message catalogs
|
||||
* a Python interface to the CLDR (Common Locale Data Repository), providing
|
||||
access to various locale display names, localized number and date
|
||||
formatting, etc.
|
||||
|
||||
:see: http://www.gnu.org/software/gettext/
|
||||
:see: http://docs.python.org/lib/module-gettext.html
|
||||
:see: http://www.unicode.org/cldr/
|
||||
"""
|
||||
|
||||
from babel.core import *
|
||||
|
||||
__docformat__ = 'restructuredtext en'
|
||||
try:
|
||||
from pkg_resources import get_distribution, ResolutionError
|
||||
try:
|
||||
__version__ = get_distribution('Babel').version
|
||||
except ResolutionError:
|
||||
__version__ = None # unknown
|
||||
except ImportError:
|
||||
__version__ = None # unknown
|
|
@ -1,790 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2007 Edgewall Software
|
||||
# All rights reserved.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at http://babel.edgewall.org/wiki/License.
|
||||
#
|
||||
# This software consists of voluntary contributions made by many
|
||||
# individuals. For the exact contribution history, see the revision
|
||||
# history and logs, available at http://babel.edgewall.org/log/.
|
||||
|
||||
"""Core locale representation and locale data access."""
|
||||
|
||||
import os
|
||||
import pickle
|
||||
|
||||
from babel import localedata
|
||||
|
||||
__all__ = ['UnknownLocaleError', 'Locale', 'default_locale', 'negotiate_locale',
|
||||
'parse_locale']
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
_global_data = None
|
||||
|
||||
def get_global(key):
|
||||
"""Return the dictionary for the given key in the global data.
|
||||
|
||||
The global data is stored in the ``babel/global.dat`` file and contains
|
||||
information independent of individual locales.
|
||||
|
||||
>>> get_global('zone_aliases')['UTC']
|
||||
'Etc/GMT'
|
||||
>>> get_global('zone_territories')['Europe/Berlin']
|
||||
'DE'
|
||||
|
||||
:param key: the data key
|
||||
:return: the dictionary found in the global data under the given key
|
||||
:rtype: `dict`
|
||||
:since: version 0.9
|
||||
"""
|
||||
global _global_data
|
||||
if _global_data is None:
|
||||
dirname = os.path.join(os.path.dirname(__file__))
|
||||
filename = os.path.join(dirname, 'global.dat')
|
||||
fileobj = open(filename, 'rb')
|
||||
try:
|
||||
_global_data = pickle.load(fileobj)
|
||||
finally:
|
||||
fileobj.close()
|
||||
return _global_data.get(key, {})
|
||||
|
||||
|
||||
LOCALE_ALIASES = {
|
||||
'ar': 'ar_SY', 'bg': 'bg_BG', 'bs': 'bs_BA', 'ca': 'ca_ES', 'cs': 'cs_CZ',
|
||||
'da': 'da_DK', 'de': 'de_DE', 'el': 'el_GR', 'en': 'en_US', 'es': 'es_ES',
|
||||
'et': 'et_EE', 'fa': 'fa_IR', 'fi': 'fi_FI', 'fr': 'fr_FR', 'gl': 'gl_ES',
|
||||
'he': 'he_IL', 'hu': 'hu_HU', 'id': 'id_ID', 'is': 'is_IS', 'it': 'it_IT',
|
||||
'ja': 'ja_JP', 'km': 'km_KH', 'ko': 'ko_KR', 'lt': 'lt_LT', 'lv': 'lv_LV',
|
||||
'mk': 'mk_MK', 'nl': 'nl_NL', 'nn': 'nn_NO', 'no': 'nb_NO', 'pl': 'pl_PL',
|
||||
'pt': 'pt_PT', 'ro': 'ro_RO', 'ru': 'ru_RU', 'sk': 'sk_SK', 'sl': 'sl_SI',
|
||||
'sv': 'sv_SE', 'th': 'th_TH', 'tr': 'tr_TR', 'uk': 'uk_UA'
|
||||
}
|
||||
|
||||
|
||||
class UnknownLocaleError(Exception):
|
||||
"""Exception thrown when a locale is requested for which no locale data
|
||||
is available.
|
||||
"""
|
||||
|
||||
def __init__(self, identifier):
|
||||
"""Create the exception.
|
||||
|
||||
:param identifier: the identifier string of the unsupported locale
|
||||
"""
|
||||
Exception.__init__(self, 'unknown locale %r' % identifier)
|
||||
self.identifier = identifier
|
||||
|
||||
|
||||
class Locale(object):
|
||||
"""Representation of a specific locale.
|
||||
|
||||
>>> locale = Locale('en', 'US')
|
||||
>>> repr(locale)
|
||||
'<Locale "en_US">'
|
||||
>>> locale.display_name
|
||||
u'English (United States)'
|
||||
|
||||
A `Locale` object can also be instantiated from a raw locale string:
|
||||
|
||||
>>> locale = Locale.parse('en-US', sep='-')
|
||||
>>> repr(locale)
|
||||
'<Locale "en_US">'
|
||||
|
||||
`Locale` objects provide access to a collection of locale data, such as
|
||||
territory and language names, number and date format patterns, and more:
|
||||
|
||||
>>> locale.number_symbols['decimal']
|
||||
u'.'
|
||||
|
||||
If a locale is requested for which no locale data is available, an
|
||||
`UnknownLocaleError` is raised:
|
||||
|
||||
>>> Locale.parse('en_DE')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
UnknownLocaleError: unknown locale 'en_DE'
|
||||
|
||||
:see: `IETF RFC 3066 <http://www.ietf.org/rfc/rfc3066.txt>`_
|
||||
"""
|
||||
|
||||
def __init__(self, language, territory=None, script=None, variant=None):
|
||||
"""Initialize the locale object from the given identifier components.
|
||||
|
||||
>>> locale = Locale('en', 'US')
|
||||
>>> locale.language
|
||||
'en'
|
||||
>>> locale.territory
|
||||
'US'
|
||||
|
||||
:param language: the language code
|
||||
:param territory: the territory (country or region) code
|
||||
:param script: the script code
|
||||
:param variant: the variant code
|
||||
:raise `UnknownLocaleError`: if no locale data is available for the
|
||||
requested locale
|
||||
"""
|
||||
self.language = language
|
||||
self.territory = territory
|
||||
self.script = script
|
||||
self.variant = variant
|
||||
self.__data = None
|
||||
|
||||
identifier = str(self)
|
||||
if not localedata.exists(identifier):
|
||||
raise UnknownLocaleError(identifier)
|
||||
|
||||
def default(cls, category=None, aliases=LOCALE_ALIASES):
|
||||
"""Return the system default locale for the specified category.
|
||||
|
||||
>>> for name in ['LANGUAGE', 'LC_ALL', 'LC_CTYPE']:
|
||||
... os.environ[name] = ''
|
||||
>>> os.environ['LANG'] = 'fr_FR.UTF-8'
|
||||
>>> Locale.default('LC_MESSAGES')
|
||||
<Locale "fr_FR">
|
||||
|
||||
:param category: one of the ``LC_XXX`` environment variable names
|
||||
:param aliases: a dictionary of aliases for locale identifiers
|
||||
:return: the value of the variable, or any of the fallbacks
|
||||
(``LANGUAGE``, ``LC_ALL``, ``LC_CTYPE``, and ``LANG``)
|
||||
:rtype: `Locale`
|
||||
:see: `default_locale`
|
||||
"""
|
||||
return cls(default_locale(category, aliases=aliases))
|
||||
default = classmethod(default)
|
||||
|
||||
def negotiate(cls, preferred, available, sep='_', aliases=LOCALE_ALIASES):
|
||||
"""Find the best match between available and requested locale strings.
|
||||
|
||||
>>> Locale.negotiate(['de_DE', 'en_US'], ['de_DE', 'de_AT'])
|
||||
<Locale "de_DE">
|
||||
>>> Locale.negotiate(['de_DE', 'en_US'], ['en', 'de'])
|
||||
<Locale "de">
|
||||
>>> Locale.negotiate(['de_DE', 'de'], ['en_US'])
|
||||
|
||||
You can specify the character used in the locale identifiers to separate
|
||||
the differnet components. This separator is applied to both lists. Also,
|
||||
case is ignored in the comparison:
|
||||
|
||||
>>> Locale.negotiate(['de-DE', 'de'], ['en-us', 'de-de'], sep='-')
|
||||
<Locale "de_DE">
|
||||
|
||||
:param preferred: the list of locale identifers preferred by the user
|
||||
:param available: the list of locale identifiers available
|
||||
:param aliases: a dictionary of aliases for locale identifiers
|
||||
:return: the `Locale` object for the best match, or `None` if no match
|
||||
was found
|
||||
:rtype: `Locale`
|
||||
:see: `negotiate_locale`
|
||||
"""
|
||||
identifier = negotiate_locale(preferred, available, sep=sep,
|
||||
aliases=aliases)
|
||||
if identifier:
|
||||
return Locale.parse(identifier, sep=sep)
|
||||
negotiate = classmethod(negotiate)
|
||||
|
||||
def parse(cls, identifier, sep='_'):
|
||||
"""Create a `Locale` instance for the given locale identifier.
|
||||
|
||||
>>> l = Locale.parse('de-DE', sep='-')
|
||||
>>> l.display_name
|
||||
u'Deutsch (Deutschland)'
|
||||
|
||||
If the `identifier` parameter is not a string, but actually a `Locale`
|
||||
object, that object is returned:
|
||||
|
||||
>>> Locale.parse(l)
|
||||
<Locale "de_DE">
|
||||
|
||||
:param identifier: the locale identifier string
|
||||
:param sep: optional component separator
|
||||
:return: a corresponding `Locale` instance
|
||||
:rtype: `Locale`
|
||||
:raise `ValueError`: if the string does not appear to be a valid locale
|
||||
identifier
|
||||
:raise `UnknownLocaleError`: if no locale data is available for the
|
||||
requested locale
|
||||
:see: `parse_locale`
|
||||
"""
|
||||
if isinstance(identifier, basestring):
|
||||
return cls(*parse_locale(identifier, sep=sep))
|
||||
return identifier
|
||||
parse = classmethod(parse)
|
||||
|
||||
def __eq__(self, other):
|
||||
return str(self) == str(other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __repr__(self):
|
||||
return '<Locale "%s">' % str(self)
|
||||
|
||||
def __str__(self):
|
||||
return '_'.join(filter(None, [self.language, self.script,
|
||||
self.territory, self.variant]))
|
||||
|
||||
def _data(self):
|
||||
if self.__data is None:
|
||||
self.__data = localedata.LocaleDataDict(localedata.load(str(self)))
|
||||
return self.__data
|
||||
_data = property(_data)
|
||||
|
||||
def get_display_name(self, locale=None):
|
||||
"""Return the display name of the locale using the given locale.
|
||||
|
||||
The display name will include the language, territory, script, and
|
||||
variant, if those are specified.
|
||||
|
||||
>>> Locale('zh', 'CN', script='Hans').get_display_name('en')
|
||||
u'Chinese (Simplified Han, China)'
|
||||
|
||||
:param locale: the locale to use
|
||||
:return: the display name
|
||||
"""
|
||||
if locale is None:
|
||||
locale = self
|
||||
locale = Locale.parse(locale)
|
||||
retval = locale.languages.get(self.language)
|
||||
if self.territory or self.script or self.variant:
|
||||
details = []
|
||||
if self.script:
|
||||
details.append(locale.scripts.get(self.script))
|
||||
if self.territory:
|
||||
details.append(locale.territories.get(self.territory))
|
||||
if self.variant:
|
||||
details.append(locale.variants.get(self.variant))
|
||||
details = filter(None, details)
|
||||
if details:
|
||||
retval += ' (%s)' % u', '.join(details)
|
||||
return retval
|
||||
|
||||
display_name = property(get_display_name, doc="""\
|
||||
The localized display name of the locale.
|
||||
|
||||
>>> Locale('en').display_name
|
||||
u'English'
|
||||
>>> Locale('en', 'US').display_name
|
||||
u'English (United States)'
|
||||
>>> Locale('sv').display_name
|
||||
u'svenska'
|
||||
|
||||
:type: `unicode`
|
||||
""")
|
||||
|
||||
def english_name(self):
|
||||
return self.get_display_name(Locale('en'))
|
||||
english_name = property(english_name, doc="""\
|
||||
The english display name of the locale.
|
||||
|
||||
>>> Locale('de').english_name
|
||||
u'German'
|
||||
>>> Locale('de', 'DE').english_name
|
||||
u'German (Germany)'
|
||||
|
||||
:type: `unicode`
|
||||
""")
|
||||
|
||||
#{ General Locale Display Names
|
||||
|
||||
def languages(self):
|
||||
return self._data['languages']
|
||||
languages = property(languages, doc="""\
|
||||
Mapping of language codes to translated language names.
|
||||
|
||||
>>> Locale('de', 'DE').languages['ja']
|
||||
u'Japanisch'
|
||||
|
||||
:type: `dict`
|
||||
:see: `ISO 639 <http://www.loc.gov/standards/iso639-2/>`_
|
||||
""")
|
||||
|
||||
def scripts(self):
|
||||
return self._data['scripts']
|
||||
scripts = property(scripts, doc="""\
|
||||
Mapping of script codes to translated script names.
|
||||
|
||||
>>> Locale('en', 'US').scripts['Hira']
|
||||
u'Hiragana'
|
||||
|
||||
:type: `dict`
|
||||
:see: `ISO 15924 <http://www.evertype.com/standards/iso15924/>`_
|
||||
""")
|
||||
|
||||
def territories(self):
|
||||
return self._data['territories']
|
||||
territories = property(territories, doc="""\
|
||||
Mapping of script codes to translated script names.
|
||||
|
||||
>>> Locale('es', 'CO').territories['DE']
|
||||
u'Alemania'
|
||||
|
||||
:type: `dict`
|
||||
:see: `ISO 3166 <http://www.iso.org/iso/en/prods-services/iso3166ma/>`_
|
||||
""")
|
||||
|
||||
def variants(self):
|
||||
return self._data['variants']
|
||||
variants = property(variants, doc="""\
|
||||
Mapping of script codes to translated script names.
|
||||
|
||||
>>> Locale('de', 'DE').variants['1901']
|
||||
u'Alte deutsche Rechtschreibung'
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
#{ Number Formatting
|
||||
|
||||
def currencies(self):
|
||||
return self._data['currency_names']
|
||||
currencies = property(currencies, doc="""\
|
||||
Mapping of currency codes to translated currency names.
|
||||
|
||||
>>> Locale('en').currencies['COP']
|
||||
u'Colombian Peso'
|
||||
>>> Locale('de', 'DE').currencies['COP']
|
||||
u'Kolumbianischer Peso'
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def currency_symbols(self):
|
||||
return self._data['currency_symbols']
|
||||
currency_symbols = property(currency_symbols, doc="""\
|
||||
Mapping of currency codes to symbols.
|
||||
|
||||
>>> Locale('en', 'US').currency_symbols['USD']
|
||||
u'$'
|
||||
>>> Locale('es', 'CO').currency_symbols['USD']
|
||||
u'US$'
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def number_symbols(self):
|
||||
return self._data['number_symbols']
|
||||
number_symbols = property(number_symbols, doc="""\
|
||||
Symbols used in number formatting.
|
||||
|
||||
>>> Locale('fr', 'FR').number_symbols['decimal']
|
||||
u','
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def decimal_formats(self):
|
||||
return self._data['decimal_formats']
|
||||
decimal_formats = property(decimal_formats, doc="""\
|
||||
Locale patterns for decimal number formatting.
|
||||
|
||||
>>> Locale('en', 'US').decimal_formats[None]
|
||||
<NumberPattern u'#,##0.###'>
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def currency_formats(self):
|
||||
return self._data['currency_formats']
|
||||
currency_formats = property(currency_formats, doc=r"""\
|
||||
Locale patterns for currency number formatting.
|
||||
|
||||
>>> print Locale('en', 'US').currency_formats[None]
|
||||
<NumberPattern u'\xa4#,##0.00'>
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def percent_formats(self):
|
||||
return self._data['percent_formats']
|
||||
percent_formats = property(percent_formats, doc="""\
|
||||
Locale patterns for percent number formatting.
|
||||
|
||||
>>> Locale('en', 'US').percent_formats[None]
|
||||
<NumberPattern u'#,##0%'>
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def scientific_formats(self):
|
||||
return self._data['scientific_formats']
|
||||
scientific_formats = property(scientific_formats, doc="""\
|
||||
Locale patterns for scientific number formatting.
|
||||
|
||||
>>> Locale('en', 'US').scientific_formats[None]
|
||||
<NumberPattern u'#E0'>
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
#{ Calendar Information and Date Formatting
|
||||
|
||||
def periods(self):
|
||||
return self._data['periods']
|
||||
periods = property(periods, doc="""\
|
||||
Locale display names for day periods (AM/PM).
|
||||
|
||||
>>> Locale('en', 'US').periods['am']
|
||||
u'AM'
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def days(self):
|
||||
return self._data['days']
|
||||
days = property(days, doc="""\
|
||||
Locale display names for weekdays.
|
||||
|
||||
>>> Locale('de', 'DE').days['format']['wide'][3]
|
||||
u'Donnerstag'
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def months(self):
|
||||
return self._data['months']
|
||||
months = property(months, doc="""\
|
||||
Locale display names for months.
|
||||
|
||||
>>> Locale('de', 'DE').months['format']['wide'][10]
|
||||
u'Oktober'
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def quarters(self):
|
||||
return self._data['quarters']
|
||||
quarters = property(quarters, doc="""\
|
||||
Locale display names for quarters.
|
||||
|
||||
>>> Locale('de', 'DE').quarters['format']['wide'][1]
|
||||
u'1. Quartal'
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def eras(self):
|
||||
return self._data['eras']
|
||||
eras = property(eras, doc="""\
|
||||
Locale display names for eras.
|
||||
|
||||
>>> Locale('en', 'US').eras['wide'][1]
|
||||
u'Anno Domini'
|
||||
>>> Locale('en', 'US').eras['abbreviated'][0]
|
||||
u'BC'
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def time_zones(self):
|
||||
return self._data['time_zones']
|
||||
time_zones = property(time_zones, doc="""\
|
||||
Locale display names for time zones.
|
||||
|
||||
>>> Locale('en', 'US').time_zones['Europe/London']['long']['daylight']
|
||||
u'British Summer Time'
|
||||
>>> Locale('en', 'US').time_zones['America/St_Johns']['city']
|
||||
u"St. John's"
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def meta_zones(self):
|
||||
return self._data['meta_zones']
|
||||
meta_zones = property(meta_zones, doc="""\
|
||||
Locale display names for meta time zones.
|
||||
|
||||
Meta time zones are basically groups of different Olson time zones that
|
||||
have the same GMT offset and daylight savings time.
|
||||
|
||||
>>> Locale('en', 'US').meta_zones['Europe_Central']['long']['daylight']
|
||||
u'Central European Summer Time'
|
||||
|
||||
:type: `dict`
|
||||
:since: version 0.9
|
||||
""")
|
||||
|
||||
def zone_formats(self):
|
||||
return self._data['zone_formats']
|
||||
zone_formats = property(zone_formats, doc=r"""\
|
||||
Patterns related to the formatting of time zones.
|
||||
|
||||
>>> Locale('en', 'US').zone_formats['fallback']
|
||||
u'%(1)s (%(0)s)'
|
||||
>>> Locale('pt', 'BR').zone_formats['region']
|
||||
u'Hor\xe1rio %s'
|
||||
|
||||
:type: `dict`
|
||||
:since: version 0.9
|
||||
""")
|
||||
|
||||
def first_week_day(self):
|
||||
return self._data['week_data']['first_day']
|
||||
first_week_day = property(first_week_day, doc="""\
|
||||
The first day of a week, with 0 being Monday.
|
||||
|
||||
>>> Locale('de', 'DE').first_week_day
|
||||
0
|
||||
>>> Locale('en', 'US').first_week_day
|
||||
6
|
||||
|
||||
:type: `int`
|
||||
""")
|
||||
|
||||
def weekend_start(self):
|
||||
return self._data['week_data']['weekend_start']
|
||||
weekend_start = property(weekend_start, doc="""\
|
||||
The day the weekend starts, with 0 being Monday.
|
||||
|
||||
>>> Locale('de', 'DE').weekend_start
|
||||
5
|
||||
|
||||
:type: `int`
|
||||
""")
|
||||
|
||||
def weekend_end(self):
|
||||
return self._data['week_data']['weekend_end']
|
||||
weekend_end = property(weekend_end, doc="""\
|
||||
The day the weekend ends, with 0 being Monday.
|
||||
|
||||
>>> Locale('de', 'DE').weekend_end
|
||||
6
|
||||
|
||||
:type: `int`
|
||||
""")
|
||||
|
||||
def min_week_days(self):
|
||||
return self._data['week_data']['min_days']
|
||||
min_week_days = property(min_week_days, doc="""\
|
||||
The minimum number of days in a week so that the week is counted as the
|
||||
first week of a year or month.
|
||||
|
||||
>>> Locale('de', 'DE').min_week_days
|
||||
4
|
||||
|
||||
:type: `int`
|
||||
""")
|
||||
|
||||
def date_formats(self):
|
||||
return self._data['date_formats']
|
||||
date_formats = property(date_formats, doc="""\
|
||||
Locale patterns for date formatting.
|
||||
|
||||
>>> Locale('en', 'US').date_formats['short']
|
||||
<DateTimePattern u'M/d/yy'>
|
||||
>>> Locale('fr', 'FR').date_formats['long']
|
||||
<DateTimePattern u'd MMMM yyyy'>
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def time_formats(self):
|
||||
return self._data['time_formats']
|
||||
time_formats = property(time_formats, doc="""\
|
||||
Locale patterns for time formatting.
|
||||
|
||||
>>> Locale('en', 'US').time_formats['short']
|
||||
<DateTimePattern u'h:mm a'>
|
||||
>>> Locale('fr', 'FR').time_formats['long']
|
||||
<DateTimePattern u'HH:mm:ss z'>
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
def datetime_formats(self):
|
||||
return self._data['datetime_formats']
|
||||
datetime_formats = property(datetime_formats, doc="""\
|
||||
Locale patterns for datetime formatting.
|
||||
|
||||
>>> Locale('en').datetime_formats[None]
|
||||
u'{1} {0}'
|
||||
>>> Locale('th').datetime_formats[None]
|
||||
u'{1}, {0}'
|
||||
|
||||
:type: `dict`
|
||||
""")
|
||||
|
||||
|
||||
def default_locale(category=None, aliases=LOCALE_ALIASES):
|
||||
"""Returns the system default locale for a given category, based on
|
||||
environment variables.
|
||||
|
||||
>>> for name in ['LANGUAGE', 'LC_ALL', 'LC_CTYPE']:
|
||||
... os.environ[name] = ''
|
||||
>>> os.environ['LANG'] = 'fr_FR.UTF-8'
|
||||
>>> default_locale('LC_MESSAGES')
|
||||
'fr_FR'
|
||||
|
||||
The "C" or "POSIX" pseudo-locales are treated as aliases for the
|
||||
"en_US_POSIX" locale:
|
||||
|
||||
>>> os.environ['LC_MESSAGES'] = 'POSIX'
|
||||
>>> default_locale('LC_MESSAGES')
|
||||
'en_US_POSIX'
|
||||
|
||||
:param category: one of the ``LC_XXX`` environment variable names
|
||||
:param aliases: a dictionary of aliases for locale identifiers
|
||||
:return: the value of the variable, or any of the fallbacks (``LANGUAGE``,
|
||||
``LC_ALL``, ``LC_CTYPE``, and ``LANG``)
|
||||
:rtype: `str`
|
||||
"""
|
||||
varnames = (category, 'LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LANG')
|
||||
for name in filter(None, varnames):
|
||||
locale = os.getenv(name)
|
||||
if locale:
|
||||
if name == 'LANGUAGE' and ':' in locale:
|
||||
# the LANGUAGE variable may contain a colon-separated list of
|
||||
# language codes; we just pick the language on the list
|
||||
locale = locale.split(':')[0]
|
||||
if locale in ('C', 'POSIX'):
|
||||
locale = 'en_US_POSIX'
|
||||
elif aliases and locale in aliases:
|
||||
locale = aliases[locale]
|
||||
try:
|
||||
return '_'.join(filter(None, parse_locale(locale)))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def negotiate_locale(preferred, available, sep='_', aliases=LOCALE_ALIASES):
|
||||
"""Find the best match between available and requested locale strings.
|
||||
|
||||
>>> negotiate_locale(['de_DE', 'en_US'], ['de_DE', 'de_AT'])
|
||||
'de_DE'
|
||||
>>> negotiate_locale(['de_DE', 'en_US'], ['en', 'de'])
|
||||
'de'
|
||||
|
||||
Case is ignored by the algorithm, the result uses the case of the preferred
|
||||
locale identifier:
|
||||
|
||||
>>> negotiate_locale(['de_DE', 'en_US'], ['de_de', 'de_at'])
|
||||
'de_DE'
|
||||
|
||||
>>> negotiate_locale(['de_DE', 'en_US'], ['de_de', 'de_at'])
|
||||
'de_DE'
|
||||
|
||||
By default, some web browsers unfortunately do not include the territory
|
||||
in the locale identifier for many locales, and some don't even allow the
|
||||
user to easily add the territory. So while you may prefer using qualified
|
||||
locale identifiers in your web-application, they would not normally match
|
||||
the language-only locale sent by such browsers. To workaround that, this
|
||||
function uses a default mapping of commonly used langauge-only locale
|
||||
identifiers to identifiers including the territory:
|
||||
|
||||
>>> negotiate_locale(['ja', 'en_US'], ['ja_JP', 'en_US'])
|
||||
'ja_JP'
|
||||
|
||||
Some browsers even use an incorrect or outdated language code, such as "no"
|
||||
for Norwegian, where the correct locale identifier would actually be "nb_NO"
|
||||
(Bokmål) or "nn_NO" (Nynorsk). The aliases are intended to take care of
|
||||
such cases, too:
|
||||
|
||||
>>> negotiate_locale(['no', 'sv'], ['nb_NO', 'sv_SE'])
|
||||
'nb_NO'
|
||||
|
||||
You can override this default mapping by passing a different `aliases`
|
||||
dictionary to this function, or you can bypass the behavior althogher by
|
||||
setting the `aliases` parameter to `None`.
|
||||
|
||||
:param preferred: the list of locale strings preferred by the user
|
||||
:param available: the list of locale strings available
|
||||
:param sep: character that separates the different parts of the locale
|
||||
strings
|
||||
:param aliases: a dictionary of aliases for locale identifiers
|
||||
:return: the locale identifier for the best match, or `None` if no match
|
||||
was found
|
||||
:rtype: `str`
|
||||
"""
|
||||
available = [a.lower() for a in available if a]
|
||||
for locale in preferred:
|
||||
ll = locale.lower()
|
||||
if ll in available:
|
||||
return locale
|
||||
if aliases:
|
||||
alias = aliases.get(ll)
|
||||
if alias:
|
||||
alias = alias.replace('_', sep)
|
||||
if alias.lower() in available:
|
||||
return alias
|
||||
parts = locale.split(sep)
|
||||
if len(parts) > 1 and parts[0].lower() in available:
|
||||
return parts[0]
|
||||
return None
|
||||
|
||||
def parse_locale(identifier, sep='_'):
|
||||
"""Parse a locale identifier into a tuple of the form::
|
||||
|
||||
``(language, territory, script, variant)``
|
||||
|
||||
>>> parse_locale('zh_CN')
|
||||
('zh', 'CN', None, None)
|
||||
>>> parse_locale('zh_Hans_CN')
|
||||
('zh', 'CN', 'Hans', None)
|
||||
|
||||
The default component separator is "_", but a different separator can be
|
||||
specified using the `sep` parameter:
|
||||
|
||||
>>> parse_locale('zh-CN', sep='-')
|
||||
('zh', 'CN', None, None)
|
||||
|
||||
If the identifier cannot be parsed into a locale, a `ValueError` exception
|
||||
is raised:
|
||||
|
||||
>>> parse_locale('not_a_LOCALE_String')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: 'not_a_LOCALE_String' is not a valid locale identifier
|
||||
|
||||
Encoding information and locale modifiers are removed from the identifier:
|
||||
|
||||
>>> parse_locale('it_IT@euro')
|
||||
('it', 'IT', None, None)
|
||||
>>> parse_locale('en_US.UTF-8')
|
||||
('en', 'US', None, None)
|
||||
>>> parse_locale('de_DE.iso885915@euro')
|
||||
('de', 'DE', None, None)
|
||||
|
||||
:param identifier: the locale identifier string
|
||||
:param sep: character that separates the different components of the locale
|
||||
identifier
|
||||
:return: the ``(language, territory, script, variant)`` tuple
|
||||
:rtype: `tuple`
|
||||
:raise `ValueError`: if the string does not appear to be a valid locale
|
||||
identifier
|
||||
|
||||
:see: `IETF RFC 4646 <http://www.ietf.org/rfc/rfc4646.txt>`_
|
||||
"""
|
||||
if '.' in identifier:
|
||||
# this is probably the charset/encoding, which we don't care about
|
||||
identifier = identifier.split('.', 1)[0]
|
||||
if '@' in identifier:
|
||||
# this is a locale modifier such as @euro, which we don't care about
|
||||
# either
|
||||
identifier = identifier.split('@', 1)[0]
|
||||
|
||||
parts = identifier.split(sep)
|
||||
lang = parts.pop(0).lower()
|
||||
if not lang.isalpha():
|
||||
raise ValueError('expected only letters, got %r' % lang)
|
||||
|
||||
script = territory = variant = None
|
||||
if parts:
|
||||
if len(parts[0]) == 4 and parts[0].isalpha():
|
||||
script = parts.pop(0).title()
|
||||
|
||||
if parts:
|
||||
if len(parts[0]) == 2 and parts[0].isalpha():
|
||||
territory = parts.pop(0).upper()
|
||||
elif len(parts[0]) == 3 and parts[0].isdigit():
|
||||
territory = parts.pop(0)
|
||||
|
||||
if parts:
|
||||
if len(parts[0]) == 4 and parts[0][0].isdigit() or \
|
||||
len(parts[0]) >= 5 and parts[0][0].isalpha():
|
||||
variant = parts.pop()
|
||||
|
||||
if parts:
|
||||
raise ValueError('%r is not a valid locale identifier' % identifier)
|
||||
|
||||
return lang, territory, script, variant
|
|
@ -1,991 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2007 Edgewall Software
|
||||
# All rights reserved.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at http://babel.edgewall.org/wiki/License.
|
||||
#
|
||||
# This software consists of voluntary contributions made by many
|
||||
# individuals. For the exact contribution history, see the revision
|
||||
# history and logs, available at http://babel.edgewall.org/log/.
|
||||
|
||||
"""Locale dependent formatting and parsing of dates and times.
|
||||
|
||||
The default locale for the functions in this module is determined by the
|
||||
following environment variables, in that order:
|
||||
|
||||
* ``LC_TIME``,
|
||||
* ``LC_ALL``, and
|
||||
* ``LANG``
|
||||
"""
|
||||
|
||||
from datetime import date, datetime, time, timedelta, tzinfo
|
||||
import re
|
||||
|
||||
from babel.core import default_locale, get_global, Locale
|
||||
from babel.util import UTC
|
||||
|
||||
__all__ = ['format_date', 'format_datetime', 'format_time',
|
||||
'get_timezone_name', 'parse_date', 'parse_datetime', 'parse_time']
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
LC_TIME = default_locale('LC_TIME')
|
||||
|
||||
# Aliases for use in scopes where the modules are shadowed by local variables
|
||||
date_ = date
|
||||
datetime_ = datetime
|
||||
time_ = time
|
||||
|
||||
def get_period_names(locale=LC_TIME):
|
||||
"""Return the names for day periods (AM/PM) used by the locale.
|
||||
|
||||
>>> get_period_names(locale='en_US')['am']
|
||||
u'AM'
|
||||
|
||||
:param locale: the `Locale` object, or a locale string
|
||||
:return: the dictionary of period names
|
||||
:rtype: `dict`
|
||||
"""
|
||||
return Locale.parse(locale).periods
|
||||
|
||||
def get_day_names(width='wide', context='format', locale=LC_TIME):
|
||||
"""Return the day names used by the locale for the specified format.
|
||||
|
||||
>>> get_day_names('wide', locale='en_US')[1]
|
||||
u'Tuesday'
|
||||
>>> get_day_names('abbreviated', locale='es')[1]
|
||||
u'mar'
|
||||
>>> get_day_names('narrow', context='stand-alone', locale='de_DE')[1]
|
||||
u'D'
|
||||
|
||||
:param width: the width to use, one of "wide", "abbreviated", or "narrow"
|
||||
:param context: the context, either "format" or "stand-alone"
|
||||
:param locale: the `Locale` object, or a locale string
|
||||
:return: the dictionary of day names
|
||||
:rtype: `dict`
|
||||
"""
|
||||
return Locale.parse(locale).days[context][width]
|
||||
|
||||
def get_month_names(width='wide', context='format', locale=LC_TIME):
|
||||
"""Return the month names used by the locale for the specified format.
|
||||
|
||||
>>> get_month_names('wide', locale='en_US')[1]
|
||||
u'January'
|
||||
>>> get_month_names('abbreviated', locale='es')[1]
|
||||
u'ene'
|
||||
>>> get_month_names('narrow', context='stand-alone', locale='de_DE')[1]
|
||||
u'J'
|
||||
|
||||
:param width: the width to use, one of "wide", "abbreviated", or "narrow"
|
||||
:param context: the context, either "format" or "stand-alone"
|
||||
:param locale: the `Locale` object, or a locale string
|
||||
:return: the dictionary of month names
|
||||
:rtype: `dict`
|
||||
"""
|
||||
return Locale.parse(locale).months[context][width]
|
||||
|
||||
def get_quarter_names(width='wide', context='format', locale=LC_TIME):
|
||||
"""Return the quarter names used by the locale for the specified format.
|
||||
|
||||
>>> get_quarter_names('wide', locale='en_US')[1]
|
||||
u'1st quarter'
|
||||
>>> get_quarter_names('abbreviated', locale='de_DE')[1]
|
||||
u'Q1'
|
||||
|
||||
:param width: the width to use, one of "wide", "abbreviated", or "narrow"
|
||||
:param context: the context, either "format" or "stand-alone"
|
||||
:param locale: the `Locale` object, or a locale string
|
||||
:return: the dictionary of quarter names
|
||||
:rtype: `dict`
|
||||
"""
|
||||
return Locale.parse(locale).quarters[context][width]
|
||||
|
||||
def get_era_names(width='wide', locale=LC_TIME):
|
||||
"""Return the era names used by the locale for the specified format.
|
||||
|
||||
>>> get_era_names('wide', locale='en_US')[1]
|
||||
u'Anno Domini'
|
||||
>>> get_era_names('abbreviated', locale='de_DE')[1]
|
||||
u'n. Chr.'
|
||||
|
||||
:param width: the width to use, either "wide", "abbreviated", or "narrow"
|
||||
:param locale: the `Locale` object, or a locale string
|
||||
:return: the dictionary of era names
|
||||
:rtype: `dict`
|
||||
"""
|
||||
return Locale.parse(locale).eras[width]
|
||||
|
||||
def get_date_format(format='medium', locale=LC_TIME):
|
||||
"""Return the date formatting patterns used by the locale for the specified
|
||||
format.
|
||||
|
||||
>>> get_date_format(locale='en_US')
|
||||
<DateTimePattern u'MMM d, yyyy'>
|
||||
>>> get_date_format('full', locale='de_DE')
|
||||
<DateTimePattern u'EEEE, d. MMMM yyyy'>
|
||||
|
||||
:param format: the format to use, one of "full", "long", "medium", or
|
||||
"short"
|
||||
:param locale: the `Locale` object, or a locale string
|
||||
:return: the date format pattern
|
||||
:rtype: `DateTimePattern`
|
||||
"""
|
||||
return Locale.parse(locale).date_formats[format]
|
||||
|
||||
def get_datetime_format(format='medium', locale=LC_TIME):
|
||||
"""Return the datetime formatting patterns used by the locale for the
|
||||
specified format.
|
||||
|
||||
>>> get_datetime_format(locale='en_US')
|
||||
u'{1} {0}'
|
||||
|
||||
:param format: the format to use, one of "full", "long", "medium", or
|
||||
"short"
|
||||
:param locale: the `Locale` object, or a locale string
|
||||
:return: the datetime format pattern
|
||||
:rtype: `unicode`
|
||||
"""
|
||||
patterns = Locale.parse(locale).datetime_formats
|
||||
if format not in patterns:
|
||||
format = None
|
||||
return patterns[format]
|
||||
|
||||
def get_time_format(format='medium', locale=LC_TIME):
|
||||
"""Return the time formatting patterns used by the locale for the specified
|
||||
format.
|
||||
|
||||
>>> get_time_format(locale='en_US')
|
||||
<DateTimePattern u'h:mm:ss a'>
|
||||
>>> get_time_format('full', locale='de_DE')
|
||||
<DateTimePattern u'HH:mm:ss v'>
|
||||
|
||||
:param format: the format to use, one of "full", "long", "medium", or
|
||||
"short"
|
||||
:param locale: the `Locale` object, or a locale string
|
||||
:return: the time format pattern
|
||||
:rtype: `DateTimePattern`
|
||||
"""
|
||||
return Locale.parse(locale).time_formats[format]
|
||||
|
||||
def get_timezone_gmt(datetime=None, width='long', locale=LC_TIME):
|
||||
"""Return the timezone associated with the given `datetime` object formatted
|
||||
as string indicating the offset from GMT.
|
||||
|
||||
>>> dt = datetime(2007, 4, 1, 15, 30)
|
||||
>>> get_timezone_gmt(dt, locale='en')
|
||||
u'GMT+00:00'
|
||||
|
||||
>>> from pytz import timezone
|
||||
>>> tz = timezone('America/Los_Angeles')
|
||||
>>> dt = datetime(2007, 4, 1, 15, 30, tzinfo=tz)
|
||||
>>> get_timezone_gmt(dt, locale='en')
|
||||
u'GMT-08:00'
|
||||
>>> get_timezone_gmt(dt, 'short', locale='en')
|
||||
u'-0800'
|
||||
|
||||
The long format depends on the locale, for example in France the acronym
|
||||
UTC string is used instead of GMT:
|
||||
|
||||
>>> get_timezone_gmt(dt, 'long', locale='fr_FR')
|
||||
u'UTC-08:00'
|
||||
|
||||
:param datetime: the ``datetime`` object; if `None`, the current date and
|
||||
time in UTC is used
|
||||
:param width: either "long" or "short"
|
||||
:param locale: the `Locale` object, or a locale string
|
||||
:return: the GMT offset representation of the timezone
|
||||
:rtype: `unicode`
|
||||
:since: version 0.9
|
||||
"""
|
||||
if datetime is None:
|
||||
datetime = datetime_.utcnow()
|
||||
elif isinstance(datetime, (int, long)):
|
||||
datetime = datetime_.utcfromtimestamp(datetime).time()
|
||||
if datetime.tzinfo is None:
|
||||
datetime = datetime.replace(tzinfo=UTC)
|
||||
locale = Locale.parse(locale)
|
||||
|
||||
offset = datetime.tzinfo.utcoffset(datetime)
|
||||
seconds = offset.days * 24 * 60 * 60 + offset.seconds
|
||||
hours, seconds = divmod(seconds, 3600)
|
||||
if width == 'short':
|
||||
pattern = u'%+03d%02d'
|
||||
else:
|
||||
pattern = locale.zone_formats['gmt'] % '%+03d:%02d'
|
||||
return pattern % (hours, seconds // 60)
|
||||
|
||||
def get_timezone_location(dt_or_tzinfo=None, locale=LC_TIME):
|
||||
"""Return a representation of the given timezone using "location format".
|
||||
|
||||
The result depends on both the local display name of the country and the
|
||||
city associated with the time zone:
|
||||
|
||||
>>> from pytz import timezone
|
||||
>>> tz = timezone('America/St_Johns')
|
||||
>>> get_timezone_location(tz, locale='de_DE')
|
||||
u"Kanada (St. John's)"
|
||||
>>> tz = timezone('America/Mexico_City')
|
||||
>>> get_timezone_location(tz, locale='de_DE')
|
||||
u'Mexiko (Mexiko-Stadt)'
|
||||
|
||||
If the timezone is associated with a country that uses only a single
|
||||
timezone, just the localized country name is returned:
|
||||
|
||||
>>> tz = timezone('Europe/Berlin')
|
||||
>>> get_timezone_name(tz, locale='de_DE')
|
||||
u'Deutschland'
|
||||
|
||||
:param dt_or_tzinfo: the ``datetime`` or ``tzinfo`` object that determines
|
||||
the timezone; if `None`, the current date and time in
|
||||
UTC is assumed
|
||||
:param locale: the `Locale` object, or a locale string
|
||||
:return: the localized timezone name using location format
|
||||
:rtype: `unicode`
|
||||
:since: version 0.9
|
||||
"""
|
||||
if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, (int, long)):
|
||||
dt = None
|
||||
tzinfo = UTC
|
||||
elif isinstance(dt_or_tzinfo, (datetime, time)):
|
||||
dt = dt_or_tzinfo
|
||||
if dt.tzinfo is not None:
|
||||
tzinfo = dt.tzinfo
|
||||
else:
|
||||
tzinfo = UTC
|
||||
else:
|
||||
dt = None
|
||||
tzinfo = dt_or_tzinfo
|
||||
locale = Locale.parse(locale)
|
||||
|
||||
if hasattr(tzinfo, 'zone'):
|
||||
zone = tzinfo.zone
|
||||
else:
|
||||
zone = tzinfo.tzname(dt or datetime.utcnow())
|
||||
|
||||
# Get the canonical time-zone code
|
||||
zone = get_global('zone_aliases').get(zone, zone)
|
||||
|
||||
info = locale.time_zones.get(zone, {})
|
||||
|
||||
# Otherwise, if there is only one timezone for the country, return the
|
||||
# localized country name
|
||||
region_format = locale.zone_formats['region']
|
||||
territory = get_global('zone_territories').get(zone)
|
||||
if territory not in locale.territories:
|
||||
territory = 'ZZ' # invalid/unknown
|
||||
territory_name = locale.territories[territory]
|
||||
if territory and len(get_global('territory_zones').get(territory, [])) == 1:
|
||||
return region_format % (territory_name)
|
||||
|
||||
# Otherwise, include the city in the output
|
||||
fallback_format = locale.zone_formats['fallback']
|
||||
if 'city' in info:
|
||||
city_name = info['city']
|
||||
else:
|
||||
metazone = get_global('meta_zones').get(zone)
|
||||
metazone_info = locale.meta_zones.get(metazone, {})
|
||||
if 'city' in metazone_info:
|
||||
city_name = metainfo['city']
|
||||
elif '/' in zone:
|
||||
city_name = zone.split('/', 1)[1].replace('_', ' ')
|
||||
else:
|
||||
city_name = zone.replace('_', ' ')
|
||||
|
||||
return region_format % (fallback_format % {
|
||||
'0': city_name,
|
||||
'1': territory_name
|
||||
})
|
||||
|
||||
def get_timezone_name(dt_or_tzinfo=None, width='long', uncommon=False,
|
||||
locale=LC_TIME):
|
||||
r"""Return the localized display name for the given timezone. The timezone
|
||||
may be specified using a ``datetime`` or `tzinfo` object.
|
||||
|
||||
>>> from pytz import timezone
|
||||
>>> dt = time(15, 30, tzinfo=timezone('America/Los_Angeles'))
|
||||
>>> get_timezone_name(dt, locale='en_US')
|
||||
u'Pacific Standard Time'
|
||||
>>> get_timezone_name(dt, width='short', locale='en_US')
|
||||
u'PST'
|
||||
|
||||
If this function gets passed only a `tzinfo` object and no concrete
|
||||
`datetime`, the returned display name is indenpendent of daylight savings
|
||||
time. This can be used for example for selecting timezones, or to set the
|
||||
time of events that recur across DST changes:
|
||||
|
||||
>>> tz = timezone('America/Los_Angeles')
|
||||
>>> get_timezone_name(tz, locale='en_US')
|
||||
u'Pacific Time'
|
||||
>>> get_timezone_name(tz, 'short', locale='en_US')
|
||||
u'PT'
|
||||
|
||||
If no localized display name for the timezone is available, and the timezone
|
||||
is associated with a country that uses only a single timezone, the name of
|
||||
that country is returned, formatted according to the locale:
|
||||
|
||||
>>> tz = timezone('Europe/Berlin')
|
||||
>>> get_timezone_name(tz, locale='de_DE')
|
||||
u'Deutschland'
|
||||
>>> get_timezone_name(tz, locale='pt_BR')
|
||||
u'Hor\xe1rio Alemanha'
|
||||
|
||||
On the other hand, if the country uses multiple timezones, the city is also
|
||||
included in the representation:
|
||||
|
||||
>>> tz = timezone('America/St_Johns')
|
||||
>>> get_timezone_name(tz, locale='de_DE')
|
||||
u"Kanada (St. John's)"
|
||||
|
||||
The `uncommon` parameter can be set to `True` to enable the use of timezone
|
||||
representations that are not commonly used by the requested locale. For
|
||||
example, while in French the central European timezone is usually
|
||||
abbreviated as "HEC", in Canadian French, this abbreviation is not in
|
||||
common use, so a generic name would be chosen by default:
|
||||
|
||||
>>> tz = timezone('Europe/Paris')
|
||||
>>> get_timezone_name(tz, 'short', locale='fr_CA')
|
||||
u'France'
|
||||
>>> get_timezone_name(tz, 'short', uncommon=True, locale='fr_CA')
|
||||
u'HEC'
|
||||
|
||||
:param dt_or_tzinfo: the ``datetime`` or ``tzinfo`` object that determines
|
||||
the timezone; if a ``tzinfo`` object is used, the
|
||||
resulting display name will be generic, i.e.
|
||||
independent of daylight savings time; if `None`, the
|
||||
current date in UTC is assumed
|
||||
:param width: either "long" or "short"
|
||||
:param uncommon: whether even uncommon timezone abbreviations should be used
|
||||
:param locale: the `Locale` object, or a locale string
|
||||
:return: the timezone display name
|
||||
:rtype: `unicode`
|
||||
:since: version 0.9
|
||||
:see: `LDML Appendix J: Time Zone Display Names
|
||||
<http://www.unicode.org/reports/tr35/#Time_Zone_Fallback>`_
|
||||
"""
|
||||
if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, (int, long)):
|
||||
dt = None
|
||||
tzinfo = UTC
|
||||
elif isinstance(dt_or_tzinfo, (datetime, time)):
|
||||
dt = dt_or_tzinfo
|
||||
if dt.tzinfo is not None:
|
||||
tzinfo = dt.tzinfo
|
||||
else:
|
||||
tzinfo = UTC
|
||||
else:
|
||||
dt = None
|
||||
tzinfo = dt_or_tzinfo
|
||||
locale = Locale.parse(locale)
|
||||
|
||||
if hasattr(tzinfo, 'zone'):
|
||||
zone = tzinfo.zone
|
||||
else:
|
||||
zone = tzinfo.tzname(dt)
|
||||
|
||||
# Get the canonical time-zone code
|
||||
zone = get_global('zone_aliases').get(zone, zone)
|
||||
|
||||
info = locale.time_zones.get(zone, {})
|
||||
# Try explicitly translated zone names first
|
||||
if width in info:
|
||||
if dt is None:
|
||||
field = 'generic'
|
||||
else:
|
||||
dst = tzinfo.dst(dt)
|
||||
if dst is None:
|
||||
field = 'generic'
|
||||
elif dst == 0:
|
||||
field = 'standard'
|
||||
else:
|
||||
field = 'daylight'
|
||||
if field in info[width]:
|
||||
return info[width][field]
|
||||
|
||||
metazone = get_global('meta_zones').get(zone)
|
||||
if metazone:
|
||||
metazone_info = locale.meta_zones.get(metazone, {})
|
||||
if width in metazone_info and (uncommon or metazone_info.get('common')):
|
||||
if dt is None:
|
||||
field = 'generic'
|
||||
else:
|
||||
field = tzinfo.dst(dt) and 'daylight' or 'standard'
|
||||
if field in metazone_info[width]:
|
||||
return metazone_info[width][field]
|
||||
|
||||
# If we have a concrete datetime, we assume that the result can't be
|
||||
# independent of daylight savings time, so we return the GMT offset
|
||||
if dt is not None:
|
||||
return get_timezone_gmt(dt, width=width, locale=locale)
|
||||
|
||||
return get_timezone_location(dt_or_tzinfo, locale=locale)
|
||||
|
||||
def format_date(date=None, format='medium', locale=LC_TIME):
|
||||
"""Return a date formatted according to the given pattern.
|
||||
|
||||
>>> d = date(2007, 04, 01)
|
||||
>>> format_date(d, locale='en_US')
|
||||
u'Apr 1, 2007'
|
||||
>>> format_date(d, format='full', locale='de_DE')
|
||||
u'Sonntag, 1. April 2007'
|
||||
|
||||
If you don't want to use the locale default formats, you can specify a
|
||||
custom date pattern:
|
||||
|
||||
>>> format_date(d, "EEE, MMM d, ''yy", locale='en')
|
||||
u"Sun, Apr 1, '07"
|
||||
|
||||
:param date: the ``date`` or ``datetime`` object; if `None`, the current
|
||||
date is used
|
||||
:param format: one of "full", "long", "medium", or "short", or a custom
|
||||
date/time pattern
|
||||
:param locale: a `Locale` object or a locale identifier
|
||||
:rtype: `unicode`
|
||||
|
||||
:note: If the pattern contains time fields, an `AttributeError` will be
|
||||
raised when trying to apply the formatting. This is also true if
|
||||
the value of ``date`` parameter is actually a ``datetime`` object,
|
||||
as this function automatically converts that to a ``date``.
|
||||
"""
|
||||
if date is None:
|
||||
date = date_.today()
|
||||
elif isinstance(date, datetime):
|
||||
date = date.date()
|
||||
|
||||
locale = Locale.parse(locale)
|
||||
if format in ('full', 'long', 'medium', 'short'):
|
||||
format = get_date_format(format, locale=locale)
|
||||
pattern = parse_pattern(format)
|
||||
return pattern.apply(date, locale)
|
||||
|
||||
def format_datetime(datetime=None, format='medium', tzinfo=None,
|
||||
locale=LC_TIME):
|
||||
"""Return a date formatted according to the given pattern.
|
||||
|
||||
>>> dt = datetime(2007, 04, 01, 15, 30)
|
||||
>>> format_datetime(dt, locale='en_US')
|
||||
u'Apr 1, 2007 3:30:00 PM'
|
||||
|
||||
For any pattern requiring the display of the time-zone, the third-party
|
||||
``pytz`` package is needed to explicitly specify the time-zone:
|
||||
|
||||
>>> from pytz import timezone
|
||||
>>> format_datetime(dt, 'full', tzinfo=timezone('Europe/Paris'),
|
||||
... locale='fr_FR')
|
||||
u'dimanche 1 avril 2007 17:30:00 HEC'
|
||||
>>> format_datetime(dt, "yyyy.MM.dd G 'at' HH:mm:ss zzz",
|
||||
... tzinfo=timezone('US/Eastern'), locale='en')
|
||||
u'2007.04.01 AD at 11:30:00 EDT'
|
||||
|
||||
:param datetime: the `datetime` object; if `None`, the current date and
|
||||
time is used
|
||||
:param format: one of "full", "long", "medium", or "short", or a custom
|
||||
date/time pattern
|
||||
:param tzinfo: the timezone to apply to the time for display
|
||||
:param locale: a `Locale` object or a locale identifier
|
||||
:rtype: `unicode`
|
||||
"""
|
||||
if datetime is None:
|
||||
datetime = datetime_.utcnow()
|
||||
elif isinstance(datetime, (int, long)):
|
||||
datetime = datetime_.utcfromtimestamp(datetime)
|
||||
elif isinstance(datetime, time):
|
||||
datetime = datetime_.combine(date.today(), datetime)
|
||||
if datetime.tzinfo is None:
|
||||
datetime = datetime.replace(tzinfo=UTC)
|
||||
if tzinfo is not None:
|
||||
datetime = datetime.astimezone(tzinfo)
|
||||
if hasattr(tzinfo, 'normalize'): # pytz
|
||||
datetime = tzinfo.normalize(datetime)
|
||||
|
||||
locale = Locale.parse(locale)
|
||||
if format in ('full', 'long', 'medium', 'short'):
|
||||
return get_datetime_format(format, locale=locale) \
|
||||
.replace('{0}', format_time(datetime, format, tzinfo=None,
|
||||
locale=locale)) \
|
||||
.replace('{1}', format_date(datetime, format, locale=locale))
|
||||
else:
|
||||
return parse_pattern(format).apply(datetime, locale)
|
||||
|
||||
def format_time(time=None, format='medium', tzinfo=None, locale=LC_TIME):
|
||||
"""Return a time formatted according to the given pattern.
|
||||
|
||||
>>> t = time(15, 30)
|
||||
>>> format_time(t, locale='en_US')
|
||||
u'3:30:00 PM'
|
||||
>>> format_time(t, format='short', locale='de_DE')
|
||||
u'15:30'
|
||||
|
||||
If you don't want to use the locale default formats, you can specify a
|
||||
custom time pattern:
|
||||
|
||||
>>> format_time(t, "hh 'o''clock' a", locale='en')
|
||||
u"03 o'clock PM"
|
||||
|
||||
For any pattern requiring the display of the time-zone, the third-party
|
||||
``pytz`` package is needed to explicitly specify the time-zone:
|
||||
|
||||
>>> from pytz import timezone
|
||||
>>> t = datetime(2007, 4, 1, 15, 30)
|
||||
>>> tzinfo = timezone('Europe/Paris')
|
||||
>>> t = tzinfo.localize(t)
|
||||
>>> format_time(t, format='full', tzinfo=tzinfo, locale='fr_FR')
|
||||
u'15:30:00 HEC'
|
||||
>>> format_time(t, "hh 'o''clock' a, zzzz", tzinfo=timezone('US/Eastern'),
|
||||
... locale='en')
|
||||
u"09 o'clock AM, Eastern Daylight Time"
|
||||
|
||||
As that example shows, when this function gets passed a
|
||||
``datetime.datetime`` value, the actual time in the formatted string is
|
||||
adjusted to the timezone specified by the `tzinfo` parameter. If the
|
||||
``datetime`` is "naive" (i.e. it has no associated timezone information),
|
||||
it is assumed to be in UTC.
|
||||
|
||||
These timezone calculations are **not** performed if the value is of type
|
||||
``datetime.time``, as without date information there's no way to determine
|
||||
what a given time would translate to in a different timezone without
|
||||
information about whether daylight savings time is in effect or not. This
|
||||
means that time values are left as-is, and the value of the `tzinfo`
|
||||
parameter is only used to display the timezone name if needed:
|
||||
|
||||
>>> t = time(15, 30)
|
||||
>>> format_time(t, format='full', tzinfo=timezone('Europe/Paris'),
|
||||
... locale='fr_FR')
|
||||
u'15:30:00 HEC'
|
||||
>>> format_time(t, format='full', tzinfo=timezone('US/Eastern'),
|
||||
... locale='en_US')
|
||||
u'3:30:00 PM ET'
|
||||
|
||||
:param time: the ``time`` or ``datetime`` object; if `None`, the current
|
||||
time in UTC is used
|
||||
:param format: one of "full", "long", "medium", or "short", or a custom
|
||||
date/time pattern
|
||||
:param tzinfo: the time-zone to apply to the time for display
|
||||
:param locale: a `Locale` object or a locale identifier
|
||||
:rtype: `unicode`
|
||||
|
||||
:note: If the pattern contains date fields, an `AttributeError` will be
|
||||
raised when trying to apply the formatting. This is also true if
|
||||
the value of ``time`` parameter is actually a ``datetime`` object,
|
||||
as this function automatically converts that to a ``time``.
|
||||
"""
|
||||
if time is None:
|
||||
time = datetime.utcnow()
|
||||
elif isinstance(time, (int, long)):
|
||||
time = datetime.utcfromtimestamp(time)
|
||||
if time.tzinfo is None:
|
||||
time = time.replace(tzinfo=UTC)
|
||||
if isinstance(time, datetime):
|
||||
if tzinfo is not None:
|
||||
time = time.astimezone(tzinfo)
|
||||
if hasattr(tzinfo, 'normalize'): # pytz
|
||||
time = tzinfo.normalize(time)
|
||||
time = time.timetz()
|
||||
elif tzinfo is not None:
|
||||
time = time.replace(tzinfo=tzinfo)
|
||||
|
||||
locale = Locale.parse(locale)
|
||||
if format in ('full', 'long', 'medium', 'short'):
|
||||
format = get_time_format(format, locale=locale)
|
||||
return parse_pattern(format).apply(time, locale)
|
||||
|
||||
def parse_date(string, locale=LC_TIME):
|
||||
"""Parse a date from a string.
|
||||
|
||||
This function uses the date format for the locale as a hint to determine
|
||||
the order in which the date fields appear in the string.
|
||||
|
||||
>>> parse_date('4/1/04', locale='en_US')
|
||||
datetime.date(2004, 4, 1)
|
||||
>>> parse_date('01.04.2004', locale='de_DE')
|
||||
datetime.date(2004, 4, 1)
|
||||
|
||||
:param string: the string containing the date
|
||||
:param locale: a `Locale` object or a locale identifier
|
||||
:return: the parsed date
|
||||
:rtype: `date`
|
||||
"""
|
||||
# TODO: try ISO format first?
|
||||
format = get_date_format(locale=locale).pattern.lower()
|
||||
year_idx = format.index('y')
|
||||
month_idx = format.index('m')
|
||||
if month_idx < 0:
|
||||
month_idx = format.index('l')
|
||||
day_idx = format.index('d')
|
||||
|
||||
indexes = [(year_idx, 'Y'), (month_idx, 'M'), (day_idx, 'D')]
|
||||
indexes.sort()
|
||||
indexes = dict([(item[1], idx) for idx, item in enumerate(indexes)])
|
||||
|
||||
# FIXME: this currently only supports numbers, but should also support month
|
||||
# names, both in the requested locale, and english
|
||||
|
||||
numbers = re.findall('(\d+)', string)
|
||||
year = numbers[indexes['Y']]
|
||||
if len(year) == 2:
|
||||
year = 2000 + int(year)
|
||||
else:
|
||||
year = int(year)
|
||||
month = int(numbers[indexes['M']])
|
||||
day = int(numbers[indexes['D']])
|
||||
if month > 12:
|
||||
month, day = day, month
|
||||
return date(year, month, day)
|
||||
|
||||
def parse_datetime(string, locale=LC_TIME):
|
||||
"""Parse a date and time from a string.
|
||||
|
||||
This function uses the date and time formats for the locale as a hint to
|
||||
determine the order in which the time fields appear in the string.
|
||||
|
||||
:param string: the string containing the date and time
|
||||
:param locale: a `Locale` object or a locale identifier
|
||||
:return: the parsed date/time
|
||||
:rtype: `datetime`
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def parse_time(string, locale=LC_TIME):
|
||||
"""Parse a time from a string.
|
||||
|
||||
This function uses the time format for the locale as a hint to determine
|
||||
the order in which the time fields appear in the string.
|
||||
|
||||
>>> parse_time('15:30:00', locale='en_US')
|
||||
datetime.time(15, 30)
|
||||
|
||||
:param string: the string containing the time
|
||||
:param locale: a `Locale` object or a locale identifier
|
||||
:return: the parsed time
|
||||
:rtype: `time`
|
||||
"""
|
||||
# TODO: try ISO format first?
|
||||
format = get_time_format(locale=locale).pattern.lower()
|
||||
hour_idx = format.index('h')
|
||||
if hour_idx < 0:
|
||||
hour_idx = format.index('k')
|
||||
min_idx = format.index('m')
|
||||
sec_idx = format.index('s')
|
||||
|
||||
indexes = [(hour_idx, 'H'), (min_idx, 'M'), (sec_idx, 'S')]
|
||||
indexes.sort()
|
||||
indexes = dict([(item[1], idx) for idx, item in enumerate(indexes)])
|
||||
|
||||
# FIXME: support 12 hour clock, and 0-based hour specification
|
||||
# and seconds should be optional, maybe minutes too
|
||||
# oh, and time-zones, of course
|
||||
|
||||
numbers = re.findall('(\d+)', string)
|
||||
hour = int(numbers[indexes['H']])
|
||||
minute = int(numbers[indexes['M']])
|
||||
second = int(numbers[indexes['S']])
|
||||
return time(hour, minute, second)
|
||||
|
||||
|
||||
class DateTimePattern(object):
|
||||
|
||||
def __init__(self, pattern, format):
|
||||
self.pattern = pattern
|
||||
self.format = format
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %r>' % (type(self).__name__, self.pattern)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.pattern
|
||||
|
||||
def __mod__(self, other):
|
||||
assert type(other) is DateTimeFormat
|
||||
return self.format % other
|
||||
|
||||
def apply(self, datetime, locale):
|
||||
return self % DateTimeFormat(datetime, locale)
|
||||
|
||||
|
||||
class DateTimeFormat(object):
|
||||
|
||||
def __init__(self, value, locale):
|
||||
assert isinstance(value, (date, datetime, time))
|
||||
if isinstance(value, (datetime, time)) and value.tzinfo is None:
|
||||
value = value.replace(tzinfo=UTC)
|
||||
self.value = value
|
||||
self.locale = Locale.parse(locale)
|
||||
|
||||
def __getitem__(self, name):
|
||||
char = name[0]
|
||||
num = len(name)
|
||||
if char == 'G':
|
||||
return self.format_era(char, num)
|
||||
elif char in ('y', 'Y', 'u'):
|
||||
return self.format_year(char, num)
|
||||
elif char in ('Q', 'q'):
|
||||
return self.format_quarter(char, num)
|
||||
elif char in ('M', 'L'):
|
||||
return self.format_month(char, num)
|
||||
elif char in ('w', 'W'):
|
||||
return self.format_week(char, num)
|
||||
elif char == 'd':
|
||||
return self.format(self.value.day, num)
|
||||
elif char == 'D':
|
||||
return self.format_day_of_year(num)
|
||||
elif char == 'F':
|
||||
return self.format_day_of_week_in_month()
|
||||
elif char in ('E', 'e', 'c'):
|
||||
return self.format_weekday(char, num)
|
||||
elif char == 'a':
|
||||
return self.format_period(char)
|
||||
elif char == 'h':
|
||||
if self.value.hour % 12 == 0:
|
||||
return self.format(12, num)
|
||||
else:
|
||||
return self.format(self.value.hour % 12, num)
|
||||
elif char == 'H':
|
||||
return self.format(self.value.hour, num)
|
||||
elif char == 'K':
|
||||
return self.format(self.value.hour % 12, num)
|
||||
elif char == 'k':
|
||||
if self.value.hour == 0:
|
||||
return self.format(24, num)
|
||||
else:
|
||||
return self.format(self.value.hour, num)
|
||||
elif char == 'm':
|
||||
return self.format(self.value.minute, num)
|
||||
elif char == 's':
|
||||
return self.format(self.value.second, num)
|
||||
elif char == 'S':
|
||||
return self.format_frac_seconds(num)
|
||||
elif char == 'A':
|
||||
return self.format_milliseconds_in_day(num)
|
||||
elif char in ('z', 'Z', 'v', 'V'):
|
||||
return self.format_timezone(char, num)
|
||||
else:
|
||||
raise KeyError('Unsupported date/time field %r' % char)
|
||||
|
||||
def format_era(self, char, num):
|
||||
width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[max(3, num)]
|
||||
era = int(self.value.year >= 0)
|
||||
return get_era_names(width, self.locale)[era]
|
||||
|
||||
def format_year(self, char, num):
|
||||
value = self.value.year
|
||||
if char.isupper():
|
||||
week = self.get_week_number(self.get_day_of_year())
|
||||
if week == 0:
|
||||
value -= 1
|
||||
year = self.format(value, num)
|
||||
if num == 2:
|
||||
year = year[-2:]
|
||||
return year
|
||||
|
||||
def format_quarter(self, char, num):
|
||||
quarter = (self.value.month - 1) // 3 + 1
|
||||
if num <= 2:
|
||||
return ('%%0%dd' % num) % quarter
|
||||
width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num]
|
||||
context = {'Q': 'format', 'q': 'stand-alone'}[char]
|
||||
return get_quarter_names(width, context, self.locale)[quarter]
|
||||
|
||||
def format_month(self, char, num):
|
||||
if num <= 2:
|
||||
return ('%%0%dd' % num) % self.value.month
|
||||
width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num]
|
||||
context = {'M': 'format', 'L': 'stand-alone'}[char]
|
||||
return get_month_names(width, context, self.locale)[self.value.month]
|
||||
|
||||
def format_week(self, char, num):
|
||||
if char.islower(): # week of year
|
||||
day_of_year = self.get_day_of_year()
|
||||
week = self.get_week_number(day_of_year)
|
||||
if week == 0:
|
||||
date = self.value - timedelta(days=day_of_year)
|
||||
week = self.get_week_number(self.get_day_of_year(date),
|
||||
date.weekday())
|
||||
return self.format(week, num)
|
||||
else: # week of month
|
||||
week = self.get_week_number(self.value.day)
|
||||
if week == 0:
|
||||
date = self.value - timedelta(days=self.value.day)
|
||||
week = self.get_week_number(date.day, date.weekday())
|
||||
pass
|
||||
return '%d' % week
|
||||
|
||||
def format_weekday(self, char, num):
|
||||
if num < 3:
|
||||
if char.islower():
|
||||
value = 7 - self.locale.first_week_day + self.value.weekday()
|
||||
return self.format(value % 7 + 1, num)
|
||||
num = 3
|
||||
weekday = self.value.weekday()
|
||||
width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num]
|
||||
context = {3: 'format', 4: 'format', 5: 'stand-alone'}[num]
|
||||
return get_day_names(width, context, self.locale)[weekday]
|
||||
|
||||
def format_day_of_year(self, num):
|
||||
return self.format(self.get_day_of_year(), num)
|
||||
|
||||
def format_day_of_week_in_month(self):
|
||||
return '%d' % ((self.value.day - 1) / 7 + 1)
|
||||
|
||||
def format_period(self, char):
|
||||
period = {0: 'am', 1: 'pm'}[int(self.value.hour >= 12)]
|
||||
return get_period_names(locale=self.locale)[period]
|
||||
|
||||
def format_frac_seconds(self, num):
|
||||
value = str(self.value.microsecond)
|
||||
return self.format(round(float('.%s' % value), num) * 10**num, num)
|
||||
|
||||
def format_milliseconds_in_day(self, num):
|
||||
msecs = self.value.microsecond // 1000 + self.value.second * 1000 + \
|
||||
self.value.minute * 60000 + self.value.hour * 3600000
|
||||
return self.format(msecs, num)
|
||||
|
||||
def format_timezone(self, char, num):
|
||||
width = {3: 'short', 4: 'long'}[max(3, num)]
|
||||
if char == 'z':
|
||||
return get_timezone_name(self.value, width, locale=self.locale)
|
||||
elif char == 'Z':
|
||||
return get_timezone_gmt(self.value, width, locale=self.locale)
|
||||
elif char == 'v':
|
||||
return get_timezone_name(self.value.tzinfo, width,
|
||||
locale=self.locale)
|
||||
elif char == 'V':
|
||||
if num == 1:
|
||||
return get_timezone_name(self.value.tzinfo, width,
|
||||
uncommon=True, locale=self.locale)
|
||||
return get_timezone_location(self.value.tzinfo, locale=self.locale)
|
||||
|
||||
def format(self, value, length):
|
||||
return ('%%0%dd' % length) % value
|
||||
|
||||
def get_day_of_year(self, date=None):
|
||||
if date is None:
|
||||
date = self.value
|
||||
return (date - date_(date.year, 1, 1)).days + 1
|
||||
|
||||
def get_week_number(self, day_of_period, day_of_week=None):
|
||||
"""Return the number of the week of a day within a period. This may be
|
||||
the week number in a year or the week number in a month.
|
||||
|
||||
Usually this will return a value equal to or greater than 1, but if the
|
||||
first week of the period is so short that it actually counts as the last
|
||||
week of the previous period, this function will return 0.
|
||||
|
||||
>>> format = DateTimeFormat(date(2006, 1, 8), Locale.parse('de_DE'))
|
||||
>>> format.get_week_number(6)
|
||||
1
|
||||
|
||||
>>> format = DateTimeFormat(date(2006, 1, 8), Locale.parse('en_US'))
|
||||
>>> format.get_week_number(6)
|
||||
2
|
||||
|
||||
:param day_of_period: the number of the day in the period (usually
|
||||
either the day of month or the day of year)
|
||||
:param day_of_week: the week day; if ommitted, the week day of the
|
||||
current date is assumed
|
||||
"""
|
||||
if day_of_week is None:
|
||||
day_of_week = self.value.weekday()
|
||||
first_day = (day_of_week - self.locale.first_week_day -
|
||||
day_of_period + 1) % 7
|
||||
if first_day < 0:
|
||||
first_day += 7
|
||||
week_number = (day_of_period + first_day - 1) / 7
|
||||
if 7 - first_day >= self.locale.min_week_days:
|
||||
week_number += 1
|
||||
return week_number
|
||||
|
||||
|
||||
PATTERN_CHARS = {
|
||||
'G': [1, 2, 3, 4, 5], # era
|
||||
'y': None, 'Y': None, 'u': None, # year
|
||||
'Q': [1, 2, 3, 4], 'q': [1, 2, 3, 4], # quarter
|
||||
'M': [1, 2, 3, 4, 5], 'L': [1, 2, 3, 4, 5], # month
|
||||
'w': [1, 2], 'W': [1], # week
|
||||
'd': [1, 2], 'D': [1, 2, 3], 'F': [1], 'g': None, # day
|
||||
'E': [1, 2, 3, 4, 5], 'e': [1, 2, 3, 4, 5], 'c': [1, 3, 4, 5], # week day
|
||||
'a': [1], # period
|
||||
'h': [1, 2], 'H': [1, 2], 'K': [1, 2], 'k': [1, 2], # hour
|
||||
'm': [1, 2], # minute
|
||||
's': [1, 2], 'S': None, 'A': None, # second
|
||||
'z': [1, 2, 3, 4], 'Z': [1, 2, 3, 4], 'v': [1, 4], 'V': [1, 4] # zone
|
||||
}
|
||||
|
||||
def parse_pattern(pattern):
|
||||
"""Parse date, time, and datetime format patterns.
|
||||
|
||||
>>> parse_pattern("MMMMd").format
|
||||
u'%(MMMM)s%(d)s'
|
||||
>>> parse_pattern("MMM d, yyyy").format
|
||||
u'%(MMM)s %(d)s, %(yyyy)s'
|
||||
|
||||
Pattern can contain literal strings in single quotes:
|
||||
|
||||
>>> parse_pattern("H:mm' Uhr 'z").format
|
||||
u'%(H)s:%(mm)s Uhr %(z)s'
|
||||
|
||||
An actual single quote can be used by using two adjacent single quote
|
||||
characters:
|
||||
|
||||
>>> parse_pattern("hh' o''clock'").format
|
||||
u"%(hh)s o'clock"
|
||||
|
||||
:param pattern: the formatting pattern to parse
|
||||
"""
|
||||
if type(pattern) is DateTimePattern:
|
||||
return pattern
|
||||
|
||||
result = []
|
||||
quotebuf = None
|
||||
charbuf = []
|
||||
fieldchar = ['']
|
||||
fieldnum = [0]
|
||||
|
||||
def append_chars():
|
||||
result.append(''.join(charbuf).replace('%', '%%'))
|
||||
del charbuf[:]
|
||||
|
||||
def append_field():
|
||||
limit = PATTERN_CHARS[fieldchar[0]]
|
||||
if limit and fieldnum[0] not in limit:
|
||||
raise ValueError('Invalid length for field: %r'
|
||||
% (fieldchar[0] * fieldnum[0]))
|
||||
result.append('%%(%s)s' % (fieldchar[0] * fieldnum[0]))
|
||||
fieldchar[0] = ''
|
||||
fieldnum[0] = 0
|
||||
|
||||
for idx, char in enumerate(pattern.replace("''", '\0')):
|
||||
if quotebuf is None:
|
||||
if char == "'": # quote started
|
||||
if fieldchar[0]:
|
||||
append_field()
|
||||
elif charbuf:
|
||||
append_chars()
|
||||
quotebuf = []
|
||||
elif char in PATTERN_CHARS:
|
||||
if charbuf:
|
||||
append_chars()
|
||||
if char == fieldchar[0]:
|
||||
fieldnum[0] += 1
|
||||
else:
|
||||
if fieldchar[0]:
|
||||
append_field()
|
||||
fieldchar[0] = char
|
||||
fieldnum[0] = 1
|
||||
else:
|
||||
if fieldchar[0]:
|
||||
append_field()
|
||||
charbuf.append(char)
|
||||
|
||||
elif quotebuf is not None:
|
||||
if char == "'": # end of quote
|
||||
charbuf.extend(quotebuf)
|
||||
quotebuf = None
|
||||
else: # inside quote
|
||||
quotebuf.append(char)
|
||||
|
||||
if fieldchar[0]:
|
||||
append_field()
|
||||
elif charbuf:
|
||||
append_chars()
|
||||
|
||||
return DateTimePattern(pattern, u''.join(result).replace('\0', "'"))
|
Двоичный файл не отображается.
|
@ -1,209 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2007 Edgewall Software
|
||||
# All rights reserved.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at http://babel.edgewall.org/wiki/License.
|
||||
#
|
||||
# This software consists of voluntary contributions made by many
|
||||
# individuals. For the exact contribution history, see the revision
|
||||
# history and logs, available at http://babel.edgewall.org/log/.
|
||||
|
||||
"""Low-level locale data access.
|
||||
|
||||
:note: The `Locale` class, which uses this module under the hood, provides a
|
||||
more convenient interface for accessing the locale data.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pickle
|
||||
try:
|
||||
import threading
|
||||
except ImportError:
|
||||
import dummy_threading as threading
|
||||
from UserDict import DictMixin
|
||||
|
||||
__all__ = ['exists', 'list', 'load']
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
_cache = {}
|
||||
_cache_lock = threading.RLock()
|
||||
_dirname = os.path.join(os.path.dirname(__file__), 'localedata')
|
||||
|
||||
|
||||
def exists(name):
|
||||
"""Check whether locale data is available for the given locale.
|
||||
|
||||
:param name: the locale identifier string
|
||||
:return: `True` if the locale data exists, `False` otherwise
|
||||
:rtype: `bool`
|
||||
"""
|
||||
if name in _cache:
|
||||
return True
|
||||
return os.path.exists(os.path.join(_dirname, '%s.dat' % name))
|
||||
|
||||
|
||||
def list():
|
||||
"""Return a list of all locale identifiers for which locale data is
|
||||
available.
|
||||
|
||||
:return: a list of locale identifiers (strings)
|
||||
:rtype: `list`
|
||||
:since: version 0.8.1
|
||||
"""
|
||||
return [stem for stem, extension in [
|
||||
os.path.splitext(filename) for filename in os.listdir(_dirname)
|
||||
] if extension == '.dat' and stem != 'root']
|
||||
|
||||
|
||||
def load(name, merge_inherited=True):
|
||||
"""Load the locale data for the given locale.
|
||||
|
||||
The locale data is a dictionary that contains much of the data defined by
|
||||
the Common Locale Data Repository (CLDR). This data is stored as a
|
||||
collection of pickle files inside the ``babel`` package.
|
||||
|
||||
>>> d = load('en_US')
|
||||
>>> d['languages']['sv']
|
||||
u'Swedish'
|
||||
|
||||
Note that the results are cached, and subsequent requests for the same
|
||||
locale return the same dictionary:
|
||||
|
||||
>>> d1 = load('en_US')
|
||||
>>> d2 = load('en_US')
|
||||
>>> d1 is d2
|
||||
True
|
||||
|
||||
:param name: the locale identifier string (or "root")
|
||||
:param merge_inherited: whether the inherited data should be merged into
|
||||
the data of the requested locale
|
||||
:return: the locale data
|
||||
:rtype: `dict`
|
||||
:raise `IOError`: if no locale data file is found for the given locale
|
||||
identifer, or one of the locales it inherits from
|
||||
"""
|
||||
_cache_lock.acquire()
|
||||
try:
|
||||
data = _cache.get(name)
|
||||
if not data:
|
||||
# Load inherited data
|
||||
if name == 'root' or not merge_inherited:
|
||||
data = {}
|
||||
else:
|
||||
parts = name.split('_')
|
||||
if len(parts) == 1:
|
||||
parent = 'root'
|
||||
else:
|
||||
parent = '_'.join(parts[:-1])
|
||||
data = load(parent).copy()
|
||||
filename = os.path.join(_dirname, '%s.dat' % name)
|
||||
fileobj = open(filename, 'rb')
|
||||
try:
|
||||
if name != 'root' and merge_inherited:
|
||||
merge(data, pickle.load(fileobj))
|
||||
else:
|
||||
data = pickle.load(fileobj)
|
||||
_cache[name] = data
|
||||
finally:
|
||||
fileobj.close()
|
||||
return data
|
||||
finally:
|
||||
_cache_lock.release()
|
||||
|
||||
|
||||
def merge(dict1, dict2):
|
||||
"""Merge the data from `dict2` into the `dict1` dictionary, making copies
|
||||
of nested dictionaries.
|
||||
|
||||
>>> d = {1: 'foo', 3: 'baz'}
|
||||
>>> merge(d, {1: 'Foo', 2: 'Bar'})
|
||||
>>> items = d.items(); items.sort(); items
|
||||
[(1, 'Foo'), (2, 'Bar'), (3, 'baz')]
|
||||
|
||||
:param dict1: the dictionary to merge into
|
||||
:param dict2: the dictionary containing the data that should be merged
|
||||
"""
|
||||
for key, val2 in dict2.items():
|
||||
if val2 is not None:
|
||||
val1 = dict1.get(key)
|
||||
if isinstance(val2, dict):
|
||||
if val1 is None:
|
||||
val1 = {}
|
||||
if isinstance(val1, Alias):
|
||||
val1 = (val1, val2)
|
||||
elif isinstance(val1, tuple):
|
||||
alias, others = val1
|
||||
others = others.copy()
|
||||
merge(others, val2)
|
||||
val1 = (alias, others)
|
||||
else:
|
||||
val1 = val1.copy()
|
||||
merge(val1, val2)
|
||||
else:
|
||||
val1 = val2
|
||||
dict1[key] = val1
|
||||
|
||||
|
||||
class Alias(object):
|
||||
"""Representation of an alias in the locale data.
|
||||
|
||||
An alias is a value that refers to some other part of the locale data,
|
||||
as specified by the `keys`.
|
||||
"""
|
||||
|
||||
def __init__(self, keys):
|
||||
self.keys = tuple(keys)
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %r>' % (type(self).__name__, self.keys)
|
||||
|
||||
def resolve(self, data):
|
||||
"""Resolve the alias based on the given data.
|
||||
|
||||
This is done recursively, so if one alias resolves to a second alias,
|
||||
that second alias will also be resolved.
|
||||
|
||||
:param data: the locale data
|
||||
:type data: `dict`
|
||||
"""
|
||||
base = data
|
||||
for key in self.keys:
|
||||
data = data[key]
|
||||
if isinstance(data, Alias):
|
||||
data = data.resolve(base)
|
||||
elif isinstance(data, tuple):
|
||||
alias, others = data
|
||||
data = alias.resolve(base)
|
||||
return data
|
||||
|
||||
|
||||
class LocaleDataDict(DictMixin, dict):
|
||||
"""Dictionary wrapper that automatically resolves aliases to the actual
|
||||
values.
|
||||
"""
|
||||
|
||||
def __init__(self, data, base=None):
|
||||
dict.__init__(self, data)
|
||||
if base is None:
|
||||
base = data
|
||||
self.base = base
|
||||
|
||||
def __getitem__(self, key):
|
||||
orig = val = dict.__getitem__(self, key)
|
||||
if isinstance(val, Alias): # resolve an alias
|
||||
val = val.resolve(self.base)
|
||||
if isinstance(val, tuple): # Merge a partial dict with an alias
|
||||
alias, others = val
|
||||
val = alias.resolve(self.base).copy()
|
||||
merge(val, others)
|
||||
if type(val) is dict: # Return a nested alias-resolving dict
|
||||
val = LocaleDataDict(val, base=self.base)
|
||||
if val is not orig:
|
||||
self[key] = val
|
||||
return val
|
||||
|
||||
def copy(self):
|
||||
return LocaleDataDict(dict.copy(self), base=self.base)
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче