Codebase list flask-babel / 19021cf
New upstream version 2.0.0 intrigeri 2 years ago
25 changed file(s) with 993 addition(s) and 1026 deletion(s). Raw diff Collapse all Expand all
00 Metadata-Version: 2.1
11 Name: Flask-Babel
2 Version: 0.12.2
2 Version: 2.0.0
33 Summary: Adds i18n/l10n support to Flask applications
44 Home-page: http://github.com/python-babel/flask-babel
55 Author: Armin Ronacher
66 Author-email: armin.ronacher@active-4.com
7 Maintainer: Tyler Kennedy
8 Maintainer-email: tk@tkte.ch
79 License: BSD
8 Description: # Flask Babel - 0.12.2
10 Description: # Flask Babel
911
10 [![Build Status](https://travis-ci.org/python-babel/flask-babel.svg?branch=master)](https://travis-ci.org/python-babel/flask-babel)
12 ![Tests](https://github.com/python-babel/flask-babel/workflows/Tests/badge.svg?branch=master)
1113 [![PyPI](https://img.shields.io/pypi/v/flask-babel.svg?maxAge=2592000)](https://pypi.python.org/pypi/Flask-Babel)
12 ![license](https://img.shields.io/github/license/python-babel/flask-babel.svg?maxAge=2592000)
13 ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/flask-babel.svg)
1414
1515 Implements i18n and l10n support for Flask. This is based on the Python
1616 [babel][] module as well as [pytz][] both of which are installed automatically
2222
2323 [babel]: https://github.com/python-babel/babel
2424 [pytz]: https://pypi.python.org/pypi/pytz/
25 [docs]: https://pythonhosted.org/Flask-Babel/
25 [docs]: https://flask-babel.tkte.ch/
26 [semver]: https://semver.org/
2627
27 Platform: any
28 Classifier: Development Status :: 4 - Beta
28 Platform: UNKNOWN
29 Classifier: Development Status :: 5 - Production/Stable
2930 Classifier: Environment :: Web Environment
3031 Classifier: Intended Audience :: Developers
3132 Classifier: License :: OSI Approved :: BSD License
3233 Classifier: Operating System :: OS Independent
33 Classifier: Programming Language :: Python :: 2.7
34 Classifier: Programming Language :: Python :: 3.5
3435 Classifier: Programming Language :: Python :: 3.6
36 Classifier: Programming Language :: Python :: 3.7
37 Classifier: Programming Language :: Python :: 3.8
38 Classifier: Programming Language :: Python :: 3.9
3539 Classifier: Programming Language :: Python :: Implementation :: CPython
3640 Classifier: Programming Language :: Python :: Implementation :: PyPy
3741 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
3842 Classifier: Topic :: Software Development :: Libraries :: Python Modules
3943 Description-Content-Type: text/markdown
44 Provides-Extra: dev
00 LICENSE
11 MANIFEST.in
2 Makefile
32 README.md
4 setup.cfg
53 setup.py
64 Flask_Babel.egg-info/PKG-INFO
75 Flask_Babel.egg-info/SOURCES.txt
1311 docs/conf.py
1412 docs/index.rst
1513 docs/make.bat
16 docs/_static/flask-babel.png
1714 flask_babel/__init__.py
18 flask_babel/_compat.py
1915 flask_babel/speaklater.py
2016 tests/babel.cfg
21 tests/tests.py
17 tests/test_date_formatting.py
18 tests/test_gettext.py
19 tests/test_integration.py
20 tests/test_number_formatting.py
2221 tests/renamed_translations/messages.pot
2322 tests/renamed_translations/de/LC_MESSAGES/messages.mo
2423 tests/renamed_translations/de/LC_MESSAGES/messages.po
24 tests/renamed_translations/de/LC_MESSAGES/myapp.mo
25 tests/renamed_translations/de/LC_MESSAGES/myapp.po
2526 tests/translations/messages.pot
2627 tests/translations/de/LC_MESSAGES/messages.mo
2728 tests/translations/de/LC_MESSAGES/messages.po
29 tests/translations/de/LC_MESSAGES/test.mo
30 tests/translations/de/LC_MESSAGES/test.po
2831 tests/translations_different_domain/myapp.pot
2932 tests/translations_different_domain/de/LC_MESSAGES/myapp.mo
3033 tests/translations_different_domain/de/LC_MESSAGES/myapp.po
0 pytz
01 Flask
12 Babel>=2.3
23 Jinja2>=2.5
4
5 [dev]
6 pytest
7 pytest-mock
8 bumpversion
9 ghp-import
10 sphinx
11 Pallets-Sphinx-Themes
+0
-22
Makefile less more
0 .PHONY: clean-pyc test upload-docs
1
2 all: clean-pyc test
3
4 test:
5 @cd tests; python tests.py
6
7 tox-test:
8 @tox
9
10 clean-pyc:
11 find . -name '*.pyc' -exec rm -f {} +
12 find . -name '*.pyo' -exec rm -f {} +
13 find . -name '*~' -exec rm -f {} +
14
15 clean: clean-pyc
16
17 upload-docs:
18 $(MAKE) -C docs html
19 python setup.py upload_docs
20
21 .PHONY: upload-docs clean-pyc clean tox-test test all
00 Metadata-Version: 2.1
11 Name: Flask-Babel
2 Version: 0.12.2
2 Version: 2.0.0
33 Summary: Adds i18n/l10n support to Flask applications
44 Home-page: http://github.com/python-babel/flask-babel
55 Author: Armin Ronacher
66 Author-email: armin.ronacher@active-4.com
7 Maintainer: Tyler Kennedy
8 Maintainer-email: tk@tkte.ch
79 License: BSD
8 Description: # Flask Babel - 0.12.2
10 Description: # Flask Babel
911
10 [![Build Status](https://travis-ci.org/python-babel/flask-babel.svg?branch=master)](https://travis-ci.org/python-babel/flask-babel)
12 ![Tests](https://github.com/python-babel/flask-babel/workflows/Tests/badge.svg?branch=master)
1113 [![PyPI](https://img.shields.io/pypi/v/flask-babel.svg?maxAge=2592000)](https://pypi.python.org/pypi/Flask-Babel)
12 ![license](https://img.shields.io/github/license/python-babel/flask-babel.svg?maxAge=2592000)
13 ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/flask-babel.svg)
1414
1515 Implements i18n and l10n support for Flask. This is based on the Python
1616 [babel][] module as well as [pytz][] both of which are installed automatically
2222
2323 [babel]: https://github.com/python-babel/babel
2424 [pytz]: https://pypi.python.org/pypi/pytz/
25 [docs]: https://pythonhosted.org/Flask-Babel/
25 [docs]: https://flask-babel.tkte.ch/
26 [semver]: https://semver.org/
2627
27 Platform: any
28 Classifier: Development Status :: 4 - Beta
28 Platform: UNKNOWN
29 Classifier: Development Status :: 5 - Production/Stable
2930 Classifier: Environment :: Web Environment
3031 Classifier: Intended Audience :: Developers
3132 Classifier: License :: OSI Approved :: BSD License
3233 Classifier: Operating System :: OS Independent
33 Classifier: Programming Language :: Python :: 2.7
34 Classifier: Programming Language :: Python :: 3.5
3435 Classifier: Programming Language :: Python :: 3.6
36 Classifier: Programming Language :: Python :: 3.7
37 Classifier: Programming Language :: Python :: 3.8
38 Classifier: Programming Language :: Python :: 3.9
3539 Classifier: Programming Language :: Python :: Implementation :: CPython
3640 Classifier: Programming Language :: Python :: Implementation :: PyPy
3741 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
3842 Classifier: Topic :: Software Development :: Libraries :: Python Modules
3943 Description-Content-Type: text/markdown
44 Provides-Extra: dev
0 # Flask Babel - 0.12.2
0 # Flask Babel
11
2 [![Build Status](https://travis-ci.org/python-babel/flask-babel.svg?branch=master)](https://travis-ci.org/python-babel/flask-babel)
2 ![Tests](https://github.com/python-babel/flask-babel/workflows/Tests/badge.svg?branch=master)
33 [![PyPI](https://img.shields.io/pypi/v/flask-babel.svg?maxAge=2592000)](https://pypi.python.org/pypi/Flask-Babel)
4 ![license](https://img.shields.io/github/license/python-babel/flask-babel.svg?maxAge=2592000)
5 ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/flask-babel.svg)
64
75 Implements i18n and l10n support for Flask. This is based on the Python
86 [babel][] module as well as [pytz][] both of which are installed automatically
1412
1513 [babel]: https://github.com/python-babel/babel
1614 [pytz]: https://pypi.python.org/pypi/pytz/
17 [docs]: https://pythonhosted.org/Flask-Babel/
15 [docs]: https://flask-babel.tkte.ch/
16 [semver]: https://semver.org/
0 # Makefile for Sphinx documentation
0 # Minimal makefile for Sphinx documentation
11 #
22
3 # You can set these variables from the command line.
4 SPHINXOPTS =
5 SPHINXBUILD = sphinx-build
6 PAPER =
3 # You can set these variables from the command line, and also
4 # from the environment for the first two.
5 SPHINXOPTS ?=
6 SPHINXBUILD ?= sphinx-build
7 SOURCEDIR = .
78 BUILDDIR = _build
89
9 # Internal variables.
10 PAPEROPT_a4 = -D latex_paper_size=a4
11 PAPEROPT_letter = -D latex_paper_size=letter
12 ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
10 # Put it first so that "make" without argument is like "make help".
11 help:
12 @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
1313
14 .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
14 import:
15 ghp-import -n -c flask-babel.tkte.ch "$(BUILDDIR)/html"
1516
16 help:
17 @echo "Please use \`make <target>' where <target> is one of"
18 @echo " html to make standalone HTML files"
19 @echo " dirhtml to make HTML files named index.html in directories"
20 @echo " singlehtml to make a single large HTML file"
21 @echo " pickle to make pickle files"
22 @echo " json to make JSON files"
23 @echo " htmlhelp to make HTML files and a HTML help project"
24 @echo " qthelp to make HTML files and a qthelp project"
25 @echo " devhelp to make HTML files and a Devhelp project"
26 @echo " epub to make an epub"
27 @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
28 @echo " latexpdf to make LaTeX files and run them through pdflatex"
29 @echo " text to make text files"
30 @echo " man to make manual pages"
31 @echo " changes to make an overview of all changed/added/deprecated items"
32 @echo " linkcheck to check all external links for integrity"
33 @echo " doctest to run all doctests embedded in the documentation (if enabled)"
17 .PHONY: help Makefile
3418
35 clean:
36 -rm -rf $(BUILDDIR)/*
37
38 html:
39 $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
40 @echo
41 @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
42
43 dirhtml:
44 $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
45 @echo
46 @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
47
48 singlehtml:
49 $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
50 @echo
51 @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
52
53 pickle:
54 $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
55 @echo
56 @echo "Build finished; now you can process the pickle files."
57
58 json:
59 $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
60 @echo
61 @echo "Build finished; now you can process the JSON files."
62
63 htmlhelp:
64 $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
65 @echo
66 @echo "Build finished; now you can run HTML Help Workshop with the" \
67 ".hhp project file in $(BUILDDIR)/htmlhelp."
68
69 qthelp:
70 $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
71 @echo
72 @echo "Build finished; now you can run "qcollectiongenerator" with the" \
73 ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
74 @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/FlaskBabel.qhcp"
75 @echo "To view the help file:"
76 @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/FlaskBabel.qhc"
77
78 devhelp:
79 $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
80 @echo
81 @echo "Build finished."
82 @echo "To view the help file:"
83 @echo "# mkdir -p $$HOME/.local/share/devhelp/FlaskBabel"
84 @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/FlaskBabel"
85 @echo "# devhelp"
86
87 epub:
88 $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
89 @echo
90 @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
91
92 latex:
93 $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
94 @echo
95 @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
96 @echo "Run \`make' in that directory to run these through (pdf)latex" \
97 "(use \`make latexpdf' here to do that automatically)."
98
99 latexpdf: latex
100 $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
101 @echo "Running LaTeX files through pdflatex..."
102 make -C $(BUILDDIR)/latex all-pdf
103 @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
104
105 text:
106 $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
107 @echo
108 @echo "Build finished. The text files are in $(BUILDDIR)/text."
109
110 man:
111 $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
112 @echo
113 @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
114
115 changes:
116 $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
117 @echo
118 @echo "The overview file is in $(BUILDDIR)/changes."
119
120 linkcheck:
121 $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
122 @echo
123 @echo "Link check complete; look for any errors in the above output " \
124 "or in $(BUILDDIR)/linkcheck/output.txt."
125
126 doctest:
127 $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
128 @echo "Testing of doctests in the sources finished, look at the " \
129 "results in $(BUILDDIR)/doctest/output.txt."
19 # Catch-all target: route all unknown targets to Sphinx using the new
20 # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
21 %: Makefile
22 @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
docs/_static/flask-babel.png less more
Binary diff not shown
0 # -*- coding: utf-8 -*-
0 # Configuration file for the Sphinx documentation builder.
11 #
2 # Flask Babel documentation build configuration file, created by
3 # sphinx-quickstart on Sat May 29 13:52:12 2010.
4 #
5 # This file is execfile()d with the current directory set to its containing dir.
6 #
7 # Note that not all possible configuration values are present in this
8 # autogenerated file.
9 #
10 # All configuration values have a default; values that are commented out
11 # serve to show the default.
2 # This file only contains a selection of the most common options. For a full
3 # list see the documentation:
4 # https://www.sphinx-doc.org/en/master/usage/configuration.html
125
13 import sys, os
6 # -- Path setup --------------------------------------------------------------
147
158 # If extensions (or modules to document with autodoc) are in another directory,
169 # add these directories to sys.path here. If the directory is relative to the
1710 # documentation root, use os.path.abspath to make it absolute, like shown here.
18 sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
19 sys.path.append(os.path.abspath('_themes'))
11 #
12 # import os
13 # import sys
14 # sys.path.insert(0, os.path.abspath('.'))
2015
21 # -- General configuration -----------------------------------------------------
2216
23 # If your documentation needs a minimal Sphinx version, state it here.
24 #needs_sphinx = '1.0'
17 # -- Project information -----------------------------------------------------
2518
26 # Add any Sphinx extension module names here, as strings. They can be extensions
27 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
28 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx']
19 project = 'Flask-Babel'
20 copyright = '2020, Armin Ronacher'
21 author = 'Armin Ronacher'
22
23 # The full version, including alpha/beta/rc tags
24 release = '2.0.0'
25
26
27 # -- General configuration ---------------------------------------------------
28
29 # Add any Sphinx extension module names here, as strings. They can be
30 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
31 # ones.
32 extensions = [
33 'sphinx.ext.autodoc',
34 'sphinx.ext.viewcode',
35 'pallets_sphinx_themes'
36 ]
2937
3038 # Add any paths that contain templates here, relative to this directory.
3139 templates_path = ['_templates']
3240
33 # The suffix of source filenames.
34 source_suffix = '.rst'
35
36 # The encoding of source files.
37 #source_encoding = 'utf-8-sig'
38
39 # The master toctree document.
40 master_doc = 'index'
41
42 # General information about the project.
43 project = u'Flask Babel'
44 copyright = u'2010, Armin Ronacher'
45
46 # The version info for the project you're documenting, acts as replacement for
47 # |version| and |release|, also used in various other places throughout the
48 # built documents.
49 #
50 # The short X.Y version.
51 version = '0.12.2'
52 # The full version, including alpha/beta/rc tags.
53 release = '0.12.2'
54
55 # The language for content autogenerated by Sphinx. Refer to documentation
56 # for a list of supported languages.
57 #language = None
58
59 # There are two options for replacing |today|: either, you set today to some
60 # non-false value, then it is used:
61 #today = ''
62 # Else, today_fmt is used as the format for a strftime call.
63 #today_fmt = '%B %d, %Y'
64
6541 # List of patterns, relative to source directory, that match files and
6642 # directories to ignore when looking for source files.
67 exclude_patterns = ['_build']
68
69 # The reST default role (used for this markup: `text`) to use for all documents.
70 #default_role = None
71
72 # If true, '()' will be appended to :func: etc. cross-reference text.
73 #add_function_parentheses = True
74
75 # If true, the current module name will be prepended to all description
76 # unit titles (such as .. function::).
77 #add_module_names = True
78
79 # If true, sectionauthor and moduleauthor directives will be shown in the
80 # output. They are ignored by default.
81 #show_authors = False
82
83 # The name of the Pygments (syntax highlighting) style to use.
84 #pygments_style = 'sphinx'
85
86 # A list of ignored prefixes for module index sorting.
87 #modindex_common_prefix = []
43 # This pattern also affects html_static_path and html_extra_path.
44 exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
8845
8946
90 # -- Options for HTML output ---------------------------------------------------
47 # -- Options for HTML output -------------------------------------------------
9148
92 # The theme to use for HTML and HTML Help pages. Major themes that come with
93 # Sphinx are currently 'default' and 'sphinxdoc'.
94 html_theme = 'flask_small'
95
96 # Theme options are theme-specific and customize the look and feel of a theme
97 # further. For a list of options available for each theme, see the
98 # documentation.
99 html_theme_options = {
100 'index_logo': 'flask-babel.png',
101 'github_fork': 'mitsuhiko/flask-babel'
102 }
103
104 # Add any paths that contain custom themes here, relative to this directory.
105 html_theme_path = ['_themes']
106
107 # The name for this set of Sphinx documents. If None, it defaults to
108 # "<project> v<release> documentation".
109 #html_title = None
110
111 # A shorter title for the navigation bar. Default is the same as html_title.
112 #html_short_title = None
113
114 # The name of an image file (relative to this directory) to place at the top
115 # of the sidebar.
116 #html_logo = None
117
118 # The name of an image file (within the static path) to use as favicon of the
119 # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
120 # pixels large.
121 #html_favicon = None
49 # The theme to use for HTML and HTML Help pages. See the documentation for
50 # a list of builtin themes.
51 #
52 html_theme = 'flask'
12253
12354 # Add any paths that contain custom static files (such as style sheets) here,
12455 # relative to this directory. They are copied after the builtin static files,
12556 # so a file named "default.css" will overwrite the builtin "default.css".
12657 html_static_path = ['_static']
127
128 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
129 # using the given strftime format.
130 #html_last_updated_fmt = '%b %d, %Y'
131
132 # If true, SmartyPants will be used to convert quotes and dashes to
133 # typographically correct entities.
134 #html_use_smartypants = True
135
136 # Custom sidebar templates, maps document names to template names.
137 #html_sidebars = {}
138
139 # Additional templates that should be rendered to pages, maps page names to
140 # template names.
141 #html_additional_pages = {}
142
143 # If false, no module index is generated.
144 #html_domain_indices = True
145
146 # If false, no index is generated.
147 #html_use_index = True
148
149 # If true, the index is split into individual pages for each letter.
150 #html_split_index = False
151
152 # If true, links to the reST sources are added to the pages.
153 #html_show_sourcelink = True
154
155 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
156 #html_show_sphinx = True
157
158 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
159 #html_show_copyright = True
160
161 # If true, an OpenSearch description file will be output, and all pages will
162 # contain a <link> tag referring to it. The value of this option must be the
163 # base URL from which the finished HTML is served.
164 #html_use_opensearch = ''
165
166 # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
167 #html_file_suffix = ''
168
169 # Output file base name for HTML help builder.
170 htmlhelp_basename = 'FlaskBabeldoc'
171
172
173 # -- Options for LaTeX output --------------------------------------------------
174
175 # The paper size ('letter' or 'a4').
176 #latex_paper_size = 'letter'
177
178 # The font size ('10pt', '11pt' or '12pt').
179 #latex_font_size = '10pt'
180
181 # Grouping the document tree into LaTeX files. List of tuples
182 # (source start file, target name, title, author, documentclass [howto/manual]).
183 latex_documents = [
184 ('index', 'FlaskBabel.tex', u'Flask Babel Documentation',
185 u'Armin Ronacher', 'manual'),
186 ]
187
188 # The name of an image file (relative to this directory) to place at the top of
189 # the title page.
190 #latex_logo = None
191
192 # For "manual" documents, if this is true, then toplevel headings are parts,
193 # not chapters.
194 #latex_use_parts = False
195
196 # If true, show page references after internal links.
197 #latex_show_pagerefs = False
198
199 # If true, show URL addresses after external links.
200 #latex_show_urls = False
201
202 # Additional stuff for the LaTeX preamble.
203 #latex_preamble = ''
204
205 # Documents to append as an appendix to all manuals.
206 #latex_appendices = []
207
208 # If false, no module index is generated.
209 #latex_domain_indices = True
210
211
212 # -- Options for manual page output --------------------------------------------
213
214 # One entry per manual page. List of tuples
215 # (source start file, name, description, authors, manual section).
216 man_pages = [
217 ('index', 'flaskbabel', u'Flask Babel Documentation',
218 [u'Armin Ronacher'], 1)
219 ]
220
221 intersphinx_mapping = {'http://docs.python.org/': None,
222 'http://flask.pocoo.org/docs/': None}
1111 Installation
1212 ------------
1313
14 Install the extension with one of the following commands::
15
16 $ easy_install Flask-Babel
17
18 or alternatively if you have pip installed::
14 Install the extension from PyPi::
1915
2016 $ pip install Flask-Babel
2117
22 Please note that Flask-Babel requires Jinja 2.5. If you are using an
18 Please note that Flask-Babel requires Jinja >=2.5. If you are using an
2319 older version you will have to upgrade or disable the Jinja support
2420 (see configuration).
2521
2723 Configuration
2824 -------------
2925
30 To get started all you need to do is to instanciate a :class:`Babel`
26 To get started all you need to do is to instantiate a :class:`Babel`
3127 object after configuring the application::
3228
3329 from flask import Flask
5046 This defaults to ``'UTC'`` which also is the
5147 timezone your application must use internally.
5248 `BABEL_TRANSLATION_DIRECTORIES` A semi-colon (``;``) separated string of
53 absolute and relative (to the app root) paths
54 to translation folders. Defaults to
55 ``translations``.
49 absolute and relative (to the `root_path` of
50 the application object) paths to translation
51 folders. Defaults to ``translations``.
5652 `BABEL_DOMAIN` The message domain used by the application.
5753 Defaults to ``messages``.
5854 =============================== =============================================
5955
6056 For more complex applications you might want to have multiple applications
6157 for different users which is where selector functions come in handy. The
62 first time the babel extension needs the locale (language code) of the
58 first time the babel extension needs the locale (locale code/ID) of the
6359 current user it will call a :meth:`~Babel.localeselector` function, and
6460 the first time the timezone is needed it will call a
6561 :meth:`~Babel.timezoneselector` function.
9389
9490 The example above assumes that the current user is stored on the
9591 :data:`flask.g` object.
92
93 Jinja Filters
94 -------------
95
96 Several commonly used formatters are added as jinja template filters after
97 calling `init_app().` For dates and times, these are:
98
99 - `<datetime>|datetimeformat` -> `format_datetime`
100 - `<date>|dateformat` -> `format_date`
101 - `<time>|timeformat` -> `format_time`
102 - `<timedelta>|timedeltaformat` -> `format_timedelta`
103
104 And for numbers, these are:
105
106 - `<number>|numberformat` -> `format_number`
107 - `<number>|decimalformat` -> `format_decimal`
108 - `<number>|currencyformat` -> `format_currency`
109 - `<number>|percentformat` -> `format_percent`
110 - `<number>|scientificformat` -> `format_scientific`
96111
97112 Formatting Dates
98113 ----------------
233248 and is the template for a ``.po`` file which contains the translated
234249 strings. Babel can do all that for you.
235250
236 First of all you have to get into the folder where you have your
237 application and create a mapping file. For typical Flask applications, this
238 is what you want in there:
251 First of all you have to create a mapping file. For typical Flask applications,
252 this is what you want in there:
239253
240254 .. sourcecode:: ini
241255
260274
261275 $ pybabel init -i messages.pot -d translations -l de
262276
263 ``-d translations`` tells pybabel to store the translations in this
264 folder. This is where Flask-Babel will look for translations. Put it
265 next to your template folder.
277 ``-d translations`` tells pybabel to store the translations in a directory
278 called "translations". This is the default folder where Flask-Babel will look
279 for translations unless you changed `BABEL_TRANSLATION_DIRECTORIES` and should
280 be at the root of your application.
266281
267282 Now edit the ``translations/de/LC_MESSAGES/messages.po`` file as needed.
268283 Check out some gettext tutorials if you feel lost.
0 @ECHO OFF
1
2 REM Command file for Sphinx documentation
3
4 if "%SPHINXBUILD%" == "" (
5 set SPHINXBUILD=sphinx-build
6 )
7 set BUILDDIR=_build
8 set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
9 if NOT "%PAPER%" == "" (
10 set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
11 )
12
13 if "%1" == "" goto help
14
15 if "%1" == "help" (
16 :help
17 echo.Please use `make ^<target^>` where ^<target^> is one of
18 echo. html to make standalone HTML files
19 echo. dirhtml to make HTML files named index.html in directories
20 echo. singlehtml to make a single large HTML file
21 echo. pickle to make pickle files
22 echo. json to make JSON files
23 echo. htmlhelp to make HTML files and a HTML help project
24 echo. qthelp to make HTML files and a qthelp project
25 echo. devhelp to make HTML files and a Devhelp project
26 echo. epub to make an epub
27 echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
28 echo. text to make text files
29 echo. man to make manual pages
30 echo. changes to make an overview over all changed/added/deprecated items
31 echo. linkcheck to check all external links for integrity
32 echo. doctest to run all doctests embedded in the documentation if enabled
33 goto end
34 )
35
36 if "%1" == "clean" (
37 for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
38 del /q /s %BUILDDIR%\*
39 goto end
40 )
41
42 if "%1" == "html" (
43 %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
44 echo.
45 echo.Build finished. The HTML pages are in %BUILDDIR%/html.
46 goto end
47 )
48
49 if "%1" == "dirhtml" (
50 %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
51 echo.
52 echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
53 goto end
54 )
55
56 if "%1" == "singlehtml" (
57 %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
58 echo.
59 echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
60 goto end
61 )
62
63 if "%1" == "pickle" (
64 %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
65 echo.
66 echo.Build finished; now you can process the pickle files.
67 goto end
68 )
69
70 if "%1" == "json" (
71 %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
72 echo.
73 echo.Build finished; now you can process the JSON files.
74 goto end
75 )
76
77 if "%1" == "htmlhelp" (
78 %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
79 echo.
80 echo.Build finished; now you can run HTML Help Workshop with the ^
81 .hhp project file in %BUILDDIR%/htmlhelp.
82 goto end
83 )
84
85 if "%1" == "qthelp" (
86 %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
87 echo.
88 echo.Build finished; now you can run "qcollectiongenerator" with the ^
89 .qhcp project file in %BUILDDIR%/qthelp, like this:
90 echo.^> qcollectiongenerator %BUILDDIR%\qthelp\FlaskBabel.qhcp
91 echo.To view the help file:
92 echo.^> assistant -collectionFile %BUILDDIR%\qthelp\FlaskBabel.ghc
93 goto end
94 )
95
96 if "%1" == "devhelp" (
97 %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
98 echo.
99 echo.Build finished.
100 goto end
101 )
102
103 if "%1" == "epub" (
104 %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
105 echo.
106 echo.Build finished. The epub file is in %BUILDDIR%/epub.
107 goto end
108 )
109
110 if "%1" == "latex" (
111 %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
112 echo.
113 echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
114 goto end
115 )
116
117 if "%1" == "text" (
118 %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
119 echo.
120 echo.Build finished. The text files are in %BUILDDIR%/text.
121 goto end
122 )
123
124 if "%1" == "man" (
125 %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
126 echo.
127 echo.Build finished. The manual pages are in %BUILDDIR%/man.
128 goto end
129 )
130
131 if "%1" == "changes" (
132 %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
133 echo.
134 echo.The overview file is in %BUILDDIR%/changes.
135 goto end
136 )
137
138 if "%1" == "linkcheck" (
139 %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
140 echo.
141 echo.Link check complete; look for any errors in the above output ^
142 or in %BUILDDIR%/linkcheck/output.txt.
143 goto end
144 )
145
146 if "%1" == "doctest" (
147 %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
148 echo.
149 echo.Testing of doctests in the sources finished, look at the ^
150 results in %BUILDDIR%/doctest/output.txt.
151 goto end
152 )
153
154 :end
0 @ECHO OFF
1
2 pushd %~dp0
3
4 REM Command file for Sphinx documentation
5
6 if "%SPHINXBUILD%" == "" (
7 set SPHINXBUILD=sphinx-build
8 )
9 set SOURCEDIR=.
10 set BUILDDIR=_build
11
12 if "%1" == "" goto help
13
14 %SPHINXBUILD% >NUL 2>NUL
15 if errorlevel 9009 (
16 echo.
17 echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
18 echo.installed, then set the SPHINXBUILD environment variable to point
19 echo.to the full path of the 'sphinx-build' executable. Alternatively you
20 echo.may add the Sphinx directory to PATH.
21 echo.
22 echo.If you don't have Sphinx installed, grab it from
23 echo.http://sphinx-doc.org/
24 exit /b 1
25 )
26
27 %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
28 goto end
29
30 :help
31 %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
32
33 :end
34 popd
0 # -*- coding: utf-8 -*-
10 """
21 flaskext.babel
32 ~~~~~~~~~~~~~~
1413 from contextlib import contextmanager
1514 from flask import current_app, request
1615 from flask.ctx import has_request_context
16 from flask.helpers import locked_cached_property
1717 from babel import dates, numbers, support, Locale
18 from werkzeug import ImmutableDict
19 try:
20 from pytz.gae import pytz
21 except ImportError:
22 from pytz import timezone, UTC
23 else:
24 timezone = pytz.timezone
25 UTC = pytz.UTC
26
27 from flask_babel._compat import string_types
18 from pytz import timezone, UTC
19 from werkzeug.datastructures import ImmutableDict
20
2821 from flask_babel.speaklater import LazyString
2922
3023
125118
126119 This has to return the locale as string (eg: ``'de_AT'``, ``'en_US'``)
127120 """
128 assert self.locale_selector_func is None, \
129 'a localeselector function is already registered'
130121 self.locale_selector_func = f
131122 return f
132123
138129
139130 This has to return the timezone as string (eg: ``'Europe/Vienna'``)
140131 """
141 assert self.timezone_selector_func is None, \
142 'a timezoneselector function is already registered'
143132 self.timezone_selector_func = f
144133 return f
145134
189178 """The message domain for the translations as a string.
190179 """
191180 return self.app.config['BABEL_DOMAIN']
181
182 @locked_cached_property
183 def domain_instance(self):
184 """The message domain for the translations.
185 """
186 return Domain(domain=self.app.config['BABEL_DOMAIN'])
192187
193188 @property
194189 def translation_directories(self):
210205 object if used outside of the request or if a translation cannot be
211206 found.
212207 """
213 ctx = _get_current_context()
214
215 if ctx is None:
216 return support.NullTranslations()
217
218 translations = getattr(ctx, 'babel_translations', None)
219 if translations is None:
220 translations = support.Translations()
221
222 babel = current_app.extensions['babel']
223 for dirname in babel.translation_directories:
224 catalog = support.Translations.load(
225 dirname,
226 [get_locale()],
227 babel.domain
228 )
229 translations.merge(catalog)
230 # FIXME: Workaround for merge() being really, really stupid. It
231 # does not copy _info, plural(), or any other instance variables
232 # populated by GNUTranslations. We probably want to stop using
233 # `support.Translations.merge` entirely.
234 if hasattr(catalog, 'plural'):
235 translations.plural = catalog.plural
236
237 ctx.babel_translations = translations
238
239 return translations
208 return get_domain().get_translations()
240209
241210
242211 def get_locale():
278247 if rv is None:
279248 tzinfo = babel.default_timezone
280249 else:
281 if isinstance(rv, string_types):
282 tzinfo = timezone(rv)
283 else:
284 tzinfo = rv
250 tzinfo = timezone(rv) if isinstance(rv, str) else rv
285251 ctx.babel_tzinfo = tzinfo
286252 return tzinfo
287253
304270 if hasattr(ctx, key):
305271 delattr(ctx, key)
306272
273 if hasattr(ctx, 'forced_babel_locale'):
274 ctx.babel_locale = ctx.forced_babel_locale
275
307276
308277 @contextmanager
309278 def force_locale(locale):
324293 yield
325294 return
326295
327 babel = current_app.extensions['babel']
328
329 orig_locale_selector_func = babel.locale_selector_func
330296 orig_attrs = {}
331297 for key in ('babel_translations', 'babel_locale'):
332298 orig_attrs[key] = getattr(ctx, key, None)
333299
334300 try:
335 babel.locale_selector_func = lambda: locale
336 for key in orig_attrs:
337 setattr(ctx, key, None)
301 ctx.babel_locale = Locale.parse(locale)
302 ctx.forced_babel_locale = ctx.babel_locale
303 ctx.babel_translations = None
338304 yield
339305 finally:
340 babel.locale_selector_func = orig_locale_selector_func
306 if hasattr(ctx, 'forced_babel_locale'):
307 del ctx.forced_babel_locale
308
341309 for key, value in orig_attrs.items():
342310 setattr(ctx, key, value)
343311
475443 :rtype: unicode
476444 """
477445 locale = get_locale()
478 return numbers.format_number(number, locale=locale)
446 return numbers.format_decimal(number, locale=locale)
479447
480448
481449 def format_decimal(number, format=None):
539507 return numbers.format_scientific(number, format=format, locale=locale)
540508
541509
542 def gettext(string, **variables):
543 """Translates a string with the current locale and passes in the
544 given keyword arguments as mapping to a string formatting string.
545
546 ::
547
548 gettext(u'Hello World!')
549 gettext(u'Hello %(name)s!', name='World')
550 """
551 t = get_translations()
552 if t is None:
553 return string if not variables else string % variables
554 s = t.ugettext(string)
555 return s if not variables else s % variables
556 _ = gettext
557
558
559 def ngettext(singular, plural, num, **variables):
560 """Translates a string with the current locale and passes in the
561 given keyword arguments as mapping to a string formatting string.
562 The `num` parameter is used to dispatch between singular and various
563 plural forms of the message. It is available in the format string
564 as ``%(num)d`` or ``%(num)s``. The source language should be
565 English or a similar language which only has one plural form.
566
567 ::
568
569 ngettext(u'%(num)d Apple', u'%(num)d Apples', num=len(apples))
570 """
571 variables.setdefault('num', num)
572 t = get_translations()
573 if t is None:
574 s = singular if num == 1 else plural
510 class Domain(object):
511 """Localization domain. By default will use look for tranlations in Flask
512 application directory and "messages" domain - all message catalogs should
513 be called ``messages.mo``.
514 """
515
516 def __init__(self, translation_directories=None, domain='messages'):
517 if isinstance(translation_directories, str):
518 translation_directories = [translation_directories]
519 self._translation_directories = translation_directories
520 self.domain = domain
521 self.cache = {}
522
523 def __repr__(self):
524 return '<Domain({!r}, {!r})>'.format(self._translation_directories, self.domain)
525
526 @property
527 def translation_directories(self):
528 if self._translation_directories is not None:
529 return self._translation_directories
530 babel = current_app.extensions['babel']
531 return babel.translation_directories
532
533 def as_default(self):
534 """Set this domain as default for the current request"""
535 ctx = _get_current_context()
536
537 if ctx is None:
538 raise RuntimeError("No request context")
539
540 ctx.babel_domain = self
541
542 def get_translations_cache(self, ctx):
543 """Returns dictionary-like object for translation caching"""
544 return self.cache
545
546 def get_translations(self):
547 ctx = _get_current_context()
548
549 if ctx is None:
550 return support.NullTranslations()
551
552 cache = self.get_translations_cache(ctx)
553 locale = get_locale()
554 try:
555 return cache[str(locale), self.domain]
556 except KeyError:
557 translations = support.Translations()
558
559 for dirname in self.translation_directories:
560 catalog = support.Translations.load(
561 dirname,
562 [locale],
563 self.domain
564 )
565 translations.merge(catalog)
566 # FIXME: Workaround for merge() being really, really stupid. It
567 # does not copy _info, plural(), or any other instance variables
568 # populated by GNUTranslations. We probably want to stop using
569 # `support.Translations.merge` entirely.
570 if hasattr(catalog, 'plural'):
571 translations.plural = catalog.plural
572
573 cache[str(locale), self.domain] = translations
574 return translations
575
576 def gettext(self, string, **variables):
577 """Translates a string with the current locale and passes in the
578 given keyword arguments as mapping to a string formatting string.
579
580 ::
581
582 gettext(u'Hello World!')
583 gettext(u'Hello %(name)s!', name='World')
584 """
585 t = self.get_translations()
586 s = t.ugettext(string)
575587 return s if not variables else s % variables
576588
577 s = t.ungettext(singular, plural, num)
578 return s if not variables else s % variables
579
580
581 def pgettext(context, string, **variables):
582 """Like :func:`gettext` but with a context.
583
584 .. versionadded:: 0.7
585 """
586 t = get_translations()
587 if t is None:
588 return string if not variables else string % variables
589 s = t.upgettext(context, string)
590 return s if not variables else s % variables
591
592
593 def npgettext(context, singular, plural, num, **variables):
594 """Like :func:`ngettext` but with a context.
595
596 .. versionadded:: 0.7
597 """
598 variables.setdefault('num', num)
599 t = get_translations()
600 if t is None:
601 s = singular if num == 1 else plural
589 def ngettext(self, singular, plural, num, **variables):
590 """Translates a string with the current locale and passes in the
591 given keyword arguments as mapping to a string formatting string.
592 The `num` parameter is used to dispatch between singular and various
593 plural forms of the message. It is available in the format string
594 as ``%(num)d`` or ``%(num)s``. The source language should be
595 English or a similar language which only has one plural form.
596
597 ::
598
599 ngettext(u'%(num)d Apple', u'%(num)d Apples', num=len(apples))
600 """
601 variables.setdefault('num', num)
602 t = self.get_translations()
603 s = t.ungettext(singular, plural, num)
602604 return s if not variables else s % variables
603 s = t.unpgettext(context, singular, plural, num)
604 return s if not variables else s % variables
605
606
607 def lazy_gettext(string, **variables):
608 """Like :func:`gettext` but the string returned is lazy which means
609 it will be translated when it is used as an actual string.
610
611 Example::
612
613 hello = lazy_gettext(u'Hello World')
614
615 @app.route('/')
616 def index():
617 return unicode(hello)
618 """
619 return LazyString(gettext, string, **variables)
620
621
622 def lazy_pgettext(context, string, **variables):
623 """Like :func:`pgettext` but the string returned is lazy which means
624 it will be translated when it is used as an actual string.
625
626 .. versionadded:: 0.7
627 """
628 return LazyString(pgettext, context, string, **variables)
605
606 def pgettext(self, context, string, **variables):
607 """Like :func:`gettext` but with a context.
608
609 .. versionadded:: 0.7
610 """
611 t = self.get_translations()
612 s = t.upgettext(context, string)
613 return s if not variables else s % variables
614
615 def npgettext(self, context, singular, plural, num, **variables):
616 """Like :func:`ngettext` but with a context.
617
618 .. versionadded:: 0.7
619 """
620 variables.setdefault('num', num)
621 t = self.get_translations()
622 s = t.unpgettext(context, singular, plural, num)
623 return s if not variables else s % variables
624
625 def lazy_gettext(self, string, **variables):
626 """Like :func:`gettext` but the string returned is lazy which means
627 it will be translated when it is used as an actual string.
628
629 Example::
630
631 hello = lazy_gettext(u'Hello World')
632
633 @app.route('/')
634 def index():
635 return unicode(hello)
636 """
637 return LazyString(self.gettext, string, **variables)
638
639 def lazy_ngettext(self, singular, plural, num, **variables):
640 """Like :func:`ngettext` but the string returned is lazy which means
641 it will be translated when it is used as an actual string.
642
643 Example::
644
645 apples = lazy_ngettext(u'%(num)d Apple', u'%(num)d Apples', num=len(apples))
646
647 @app.route('/')
648 def index():
649 return unicode(apples)
650 """
651 return LazyString(self.ngettext, singular, plural, num, **variables)
652
653 def lazy_pgettext(self, context, string, **variables):
654 """Like :func:`pgettext` but the string returned is lazy which means
655 it will be translated when it is used as an actual string.
656
657 .. versionadded:: 0.7
658 """
659 return LazyString(self.pgettext, context, string, **variables)
629660
630661
631662 def _get_current_context():
634665
635666 if current_app:
636667 return current_app
668
669
670 def get_domain():
671 ctx = _get_current_context()
672 if ctx is None:
673 # this will use NullTranslations
674 return Domain()
675
676 try:
677 return ctx.babel_domain
678 except AttributeError:
679 pass
680
681 babel = current_app.extensions['babel']
682 ctx.babel_domain = babel.domain_instance
683 return ctx.babel_domain
684
685
686 # Create shortcuts for the default Flask domain
687 def gettext(*args, **kwargs):
688 return get_domain().gettext(*args, **kwargs)
689 _ = gettext
690
691
692 def ngettext(*args, **kwargs):
693 return get_domain().ngettext(*args, **kwargs)
694
695
696 def pgettext(*args, **kwargs):
697 return get_domain().pgettext(*args, **kwargs)
698
699
700 def npgettext(*args, **kwargs):
701 return get_domain().npgettext(*args, **kwargs)
702
703
704 def lazy_gettext(*args, **kwargs):
705 return LazyString(gettext, *args, **kwargs)
706
707
708 def lazy_pgettext(*args, **kwargs):
709 return LazyString(pgettext, *args, **kwargs)
710
711
712 def lazy_ngettext(*args, **kwargs):
713 return LazyString(ngettext, *args, **kwargs)
+0
-20
flask_babel/_compat.py less more
0 # -*- coding: utf-8 -*-
1 """
2 flask.ext.babel._compat
3 ~~~~~~~~~~~~~~~~~~~~~~~
4
5 :copyright: (c) 2013 by Armin Ronacher, Daniel Neuhäuser.
6 :license: BSD, see LICENSE for more details.
7 """
8 import sys
9
10
11 PY2 = sys.version_info[0] == 2
12
13
14 if PY2:
15 text_type = unicode
16 string_types = (str, unicode)
17 else:
18 text_type = str
19 string_types = (str, )
0 # -*- coding: utf-8 -*-
1 from flask_babel._compat import text_type
2
3
40 class LazyString(object):
51 def __init__(self, func, *args, **kwargs):
62 self._func = func
106 def __getattr__(self, attr):
117 if attr == "__setstate__":
128 raise AttributeError(attr)
13 string = text_type(self)
9
10 string = str(self)
1411 if hasattr(string, attr):
1512 return getattr(string, attr)
13
1614 raise AttributeError(attr)
1715
1816 def __repr__(self):
19 return "l'{0}'".format(text_type(self))
17 return "l'{0}'".format(str(self))
2018
2119 def __str__(self):
22 return text_type(self._func(*self._args, **self._kwargs))
20 return str(self._func(*self._args, **self._kwargs))
2321
2422 def __len__(self):
25 return len(text_type(self))
23 return len(str(self))
2624
2725 def __getitem__(self, key):
28 return text_type(self)[key]
26 return str(self)[key]
2927
3028 def __iter__(self):
31 return iter(text_type(self))
29 return iter(str(self))
3230
3331 def __contains__(self, item):
34 return item in text_type(self)
32 return item in str(self)
3533
3634 def __add__(self, other):
37 return text_type(self) + other
35 return str(self) + other
3836
3937 def __radd__(self, other):
40 return other + text_type(self)
38 return other + str(self)
4139
4240 def __mul__(self, other):
43 return text_type(self) * other
41 return str(self) * other
4442
4543 def __rmul__(self, other):
46 return other * text_type(self)
44 return other * str(self)
4745
4846 def __lt__(self, other):
49 return text_type(self) < other
47 return str(self) < other
5048
5149 def __le__(self, other):
52 return text_type(self) <= other
50 return str(self) <= other
5351
5452 def __eq__(self, other):
55 return text_type(self) == other
53 return str(self) == other
5654
5755 def __ne__(self, other):
58 return text_type(self) != other
56 return str(self) != other
5957
6058 def __gt__(self, other):
61 return text_type(self) > other
59 return str(self) > other
6260
6361 def __ge__(self, other):
64 return text_type(self) >= other
62 return str(self) >= other
6563
6664 def __html__(self):
67 return text_type(self)
65 return str(self)
6866
6967 def __hash__(self):
70 return hash(text_type(self))
68 return hash(str(self))
7169
7270 def __mod__(self, other):
73 return text_type(self) % other
71 return str(self) % other
7472
7573 def __rmod__(self, other):
76 return other + text_type(self)
74 return other + str(self)
0 [upload_docs]
1 upload-dir = docs/_build/html
2
30 [egg_info]
41 tag_build =
52 tag_date = 0
77
88 setup(
99 name='Flask-Babel',
10 version='0.12.2',
10 version='2.0.0',
1111 url='http://github.com/python-babel/flask-babel',
1212 license='BSD',
1313 author='Armin Ronacher',
1414 author_email='armin.ronacher@active-4.com',
15 maintainer='Tyler Kennedy',
16 maintainer_email='tk@tkte.ch',
1517 description='Adds i18n/l10n support to Flask applications',
1618 long_description=long_description,
1719 long_description_content_type='text/markdown',
1820 packages=['flask_babel'],
1921 zip_safe=False,
20 platforms='any',
2122 install_requires=[
23 'pytz',
2224 'Flask',
2325 'Babel>=2.3',
2426 'Jinja2>=2.5'
2527 ],
2628 classifiers=[
27 'Development Status :: 4 - Beta',
29 'Development Status :: 5 - Production/Stable',
2830 'Environment :: Web Environment',
2931 'Intended Audience :: Developers',
3032 'License :: OSI Approved :: BSD License',
3133 'Operating System :: OS Independent',
32 'Programming Language :: Python :: 2.7',
34 'Programming Language :: Python :: 3.5',
3335 'Programming Language :: Python :: 3.6',
36 'Programming Language :: Python :: 3.7',
37 'Programming Language :: Python :: 3.8',
38 'Programming Language :: Python :: 3.9',
3439 'Programming Language :: Python :: Implementation :: CPython',
3540 'Programming Language :: Python :: Implementation :: PyPy',
3641 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
3742 'Topic :: Software Development :: Libraries :: Python Modules'
38 ]
43 ],
44 extras_require={
45 'dev': [
46 'pytest',
47 'pytest-mock',
48 'bumpversion',
49 'ghp-import',
50 'sphinx',
51 'Pallets-Sphinx-Themes'
52 ]
53 }
3954 )
0 # German translations for PROJECT.
1 # Copyright (C) 2010 ORGANIZATION
2 # This file is distributed under the same license as the PROJECT project.
3 # FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
4 #
5 msgid ""
6 msgstr ""
7 "Project-Id-Version: PROJECT VERSION\n"
8 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
9 "POT-Creation-Date: 2010-05-29 17:00+0200\n"
10 "PO-Revision-Date: 2010-05-30 12:56+0200\n"
11 "Last-Translator: Armin Ronacher <armin.ronacher@active-4.com>\n"
12 "Language-Team: de <LL@li.org>\n"
13 "Plural-Forms: nplurals=2; plural=(n != 1)\n"
14 "MIME-Version: 1.0\n"
15 "Content-Type: text/plain; charset=utf-8\n"
16 "Content-Transfer-Encoding: 8bit\n"
17 "Generated-By: Babel 0.9.5\n"
18
19 #: tests.py:94
20 #, python-format
21 msgid "Hello %(name)s!"
22 msgstr "Hallo %(name)s!"
23
24 #: tests.py:95 tests.py:96
25 #, python-format
26 msgid "%(num)s Apple"
27 msgid_plural "%(num)s Apples"
28 msgstr[0] "%(num)s Apfel"
29 msgstr[1] "%(num)s Äpfel"
30
31 #: tests.py:119
32 msgid "Yes"
33 msgstr "Ja"
34
0 # -*- coding: utf-8 -*-
1 from __future__ import with_statement
2
3 from datetime import datetime, timedelta
4 from threading import Semaphore, Thread
5
6 import flask
7
8 import flask_babel as babel
9
10
11 def test_basics():
12 app = flask.Flask(__name__)
13 babel.Babel(app)
14 d = datetime(2010, 4, 12, 13, 46)
15 delta = timedelta(days=6)
16
17 with app.test_request_context():
18 assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM'
19 assert babel.format_date(d) == 'Apr 12, 2010'
20 assert babel.format_time(d) == '1:46:00 PM'
21 assert babel.format_timedelta(delta) == '1 week'
22 assert babel.format_timedelta(delta, threshold=1) == '6 days'
23
24 with app.test_request_context():
25 app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Vienna'
26 assert babel.format_datetime(d) == 'Apr 12, 2010, 3:46:00 PM'
27 assert babel.format_date(d) == 'Apr 12, 2010'
28 assert babel.format_time(d) == '3:46:00 PM'
29
30 with app.test_request_context():
31 app.config['BABEL_DEFAULT_LOCALE'] = 'de_DE'
32 assert babel.format_datetime(d, 'long') == \
33 '12. April 2010 um 15:46:00 MESZ'
34
35
36 def test_init_app():
37 b = babel.Babel()
38 app = flask.Flask(__name__)
39 b.init_app(app)
40 d = datetime(2010, 4, 12, 13, 46)
41
42 with app.test_request_context():
43 assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM'
44 assert babel.format_date(d) == 'Apr 12, 2010'
45 assert babel.format_time(d) == '1:46:00 PM'
46
47 with app.test_request_context():
48 app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Vienna'
49 assert babel.format_datetime(d) == 'Apr 12, 2010, 3:46:00 PM'
50 assert babel.format_date(d) == 'Apr 12, 2010'
51 assert babel.format_time(d) == '3:46:00 PM'
52
53 with app.test_request_context():
54 app.config['BABEL_DEFAULT_LOCALE'] = 'de_DE'
55 assert babel.format_datetime(d, 'long') == \
56 '12. April 2010 um 15:46:00 MESZ'
57
58
59 def test_custom_formats():
60 app = flask.Flask(__name__)
61 app.config.update(
62 BABEL_DEFAULT_LOCALE='en_US',
63 BABEL_DEFAULT_TIMEZONE='Pacific/Johnston'
64 )
65 b = babel.Babel(app)
66 b.date_formats['datetime'] = 'long'
67 b.date_formats['datetime.long'] = 'MMMM d, yyyy h:mm:ss a'
68 d = datetime(2010, 4, 12, 13, 46)
69
70 with app.test_request_context():
71 assert babel.format_datetime(d) == 'April 12, 2010 3:46:00 AM'
72
73
74 def test_custom_locale_selector():
75 app = flask.Flask(__name__)
76 b = babel.Babel(app)
77 d = datetime(2010, 4, 12, 13, 46)
78
79 the_timezone = 'UTC'
80 the_locale = 'en_US'
81
82 @b.localeselector
83 def select_locale():
84 return the_locale
85
86 @b.timezoneselector
87 def select_timezone():
88 return the_timezone
89
90 with app.test_request_context():
91 assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM'
92
93 the_locale = 'de_DE'
94 the_timezone = 'Europe/Vienna'
95
96 with app.test_request_context():
97 assert babel.format_datetime(d) == '12.04.2010, 15:46:00'
98
99
100 def test_refreshing():
101 app = flask.Flask(__name__)
102 babel.Babel(app)
103 d = datetime(2010, 4, 12, 13, 46)
104 with app.test_request_context():
105 assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM'
106 app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Vienna'
107 babel.refresh()
108 assert babel.format_datetime(d) == 'Apr 12, 2010, 3:46:00 PM'
109
110
111 def test_force_locale():
112 app = flask.Flask(__name__)
113 b = babel.Babel(app)
114
115 @b.localeselector
116 def select_locale():
117 return 'de_DE'
118
119 with app.test_request_context():
120 assert str(babel.get_locale()) == 'de_DE'
121 with babel.force_locale('en_US'):
122 assert str(babel.get_locale()) == 'en_US'
123 assert str(babel.get_locale()) == 'de_DE'
124
125
126 def test_force_locale_with_threading():
127 app = flask.Flask(__name__)
128 b = babel.Babel(app)
129
130 @b.localeselector
131 def select_locale():
132 return 'de_DE'
133
134 semaphore = Semaphore(value=0)
135
136 def first_request():
137 with app.test_request_context():
138 with babel.force_locale('en_US'):
139 assert str(babel.get_locale()) == 'en_US'
140 semaphore.acquire()
141
142 thread = Thread(target=first_request)
143 thread.start()
144
145 try:
146 with app.test_request_context():
147 assert str(babel.get_locale()) == 'de_DE'
148 finally:
149 semaphore.release()
150 thread.join()
151
152
153 def test_refresh_during_force_locale():
154 app = flask.Flask(__name__)
155 b = babel.Babel(app)
156
157 @b.localeselector
158 def select_locale():
159 return 'de_DE'
160
161 with app.test_request_context():
162 with babel.force_locale('en_US'):
163 assert str(babel.get_locale()) == 'en_US'
164 babel.refresh()
165 assert str(babel.get_locale()) == 'en_US'
0 # -*- coding: utf-8 -*-
1 from __future__ import with_statement
2
3 import flask
4
5 import flask_babel as babel
6 from flask_babel import gettext, lazy_gettext, lazy_ngettext, ngettext
7
8
9 def test_basics():
10 app = flask.Flask(__name__)
11 babel.Babel(app, default_locale='de_DE')
12
13 with app.test_request_context():
14 assert gettext(u'Hello %(name)s!', name='Peter') == 'Hallo Peter!'
15 assert ngettext(u'%(num)s Apple', u'%(num)s Apples', 3) == \
16 u'3 Äpfel'
17 assert ngettext(u'%(num)s Apple', u'%(num)s Apples', 1) == \
18 u'1 Apfel'
19
20
21 def test_template_basics():
22 app = flask.Flask(__name__)
23 babel.Babel(app, default_locale='de_DE')
24
25 t = lambda x: flask.render_template_string('{{ %s }}' % x)
26
27 with app.test_request_context():
28 assert t("gettext('Hello %(name)s!', name='Peter')") == \
29 u'Hallo Peter!'
30 assert t("ngettext('%(num)s Apple', '%(num)s Apples', 3)") == \
31 u'3 Äpfel'
32 assert t("ngettext('%(num)s Apple', '%(num)s Apples', 1)") == \
33 u'1 Apfel'
34 assert flask.render_template_string('''
35 {% trans %}Hello {{ name }}!{% endtrans %}
36 ''', name='Peter').strip() == 'Hallo Peter!'
37 assert flask.render_template_string('''
38 {% trans num=3 %}{{ num }} Apple
39 {%- pluralize %}{{ num }} Apples{% endtrans %}
40 ''', name='Peter').strip() == u'3 Äpfel'
41
42
43 def test_lazy_gettext():
44 app = flask.Flask(__name__)
45 babel.Babel(app, default_locale='de_DE')
46 yes = lazy_gettext(u'Yes')
47 with app.test_request_context():
48 assert str(yes) == 'Ja'
49 assert yes.__html__() == 'Ja'
50
51 app.config['BABEL_DEFAULT_LOCALE'] = 'en_US'
52 with app.test_request_context():
53 assert str(yes) == 'Yes'
54 assert yes.__html__() == 'Yes'
55
56
57 def test_lazy_ngettext():
58 app = flask.Flask(__name__)
59 babel.Babel(app, default_locale='de_DE')
60 one_apple = lazy_ngettext(u'%(num)s Apple', u'%(num)s Apples', 1)
61 with app.test_request_context():
62 assert str(one_apple) == '1 Apfel'
63 assert one_apple.__html__() == '1 Apfel'
64 two_apples = lazy_ngettext(u'%(num)s Apple', u'%(num)s Apples', 2)
65 with app.test_request_context():
66 assert str(two_apples) == u'2 Äpfel'
67 assert two_apples.__html__() == u'2 Äpfel'
68
69
70 def test_lazy_gettext_defaultdomain():
71 app = flask.Flask(__name__)
72 b = babel.Babel(app, default_locale='de_DE', default_domain='test')
73 first = lazy_gettext('first')
74 with app.test_request_context():
75 assert str(first) == 'erste'
76 app.config['BABEL_DEFAULT_LOCALE'] = 'en_US'
77 with app.test_request_context():
78 assert str(first) == 'first'
79
80
81 def test_list_translations():
82 app = flask.Flask(__name__)
83 b = babel.Babel(app, default_locale='de_DE')
84 translations = b.list_translations()
85 assert len(translations) == 1
86 assert str(translations[0]) == 'de'
87
88
89 def test_no_formatting():
90 """
91 Ensure we don't format strings unless a variable is passed.
92 """
93 app = flask.Flask(__name__)
94 babel.Babel(app)
95
96 with app.test_request_context():
97 assert gettext(u'Test %s') == u'Test %s'
98 assert gettext(u'Test %(name)s', name=u'test') == u'Test test'
99 assert gettext(u'Test %s') % 'test' == u'Test test'
100
101
102 def test_domain():
103 app = flask.Flask(__name__)
104 b = babel.Babel(app, default_locale='de_DE')
105 domain = babel.Domain(domain='test')
106
107 with app.test_request_context():
108 assert domain.gettext('first') == 'erste'
109 assert babel.gettext('first') == 'first'
110
111
112 def test_as_default():
113 app = flask.Flask(__name__)
114 b = babel.Babel(app, default_locale='de_DE')
115 domain = babel.Domain(domain='test')
116
117 with app.test_request_context():
118 assert babel.gettext('first') == 'first'
119 domain.as_default()
120 assert babel.gettext('first') == 'erste'
121
122
123 def test_default_domain():
124 app = flask.Flask(__name__)
125 b = babel.Babel(app, default_locale='de_DE', default_domain='test')
126
127 with app.test_request_context():
128 assert babel.gettext('first') == 'erste'
129
130
131 def test_multiple_apps():
132 app1 = flask.Flask(__name__)
133 b1 = babel.Babel(app1, default_locale='de_DE')
134
135 app2 = flask.Flask(__name__)
136 b2 = babel.Babel(app2, default_locale='de_DE')
137
138 with app1.test_request_context() as ctx:
139 assert babel.gettext('Yes') == 'Ja'
140
141 assert ('de_DE', 'messages') in b1.domain_instance.get_translations_cache(ctx)
142
143 with app2.test_request_context() as ctx:
144 assert 'de_DE', 'messages' not in b2.domain_instance.get_translations_cache(ctx)
145
146
147 def test_cache(mocker):
148 load_mock = mocker.patch(
149 "babel.support.Translations.load", side_effect=babel.support.Translations.load
150 )
151
152 app = flask.Flask(__name__)
153 b = babel.Babel(app, default_locale="de_DE")
154
155 @b.localeselector
156 def select_locale():
157 return the_locale
158
159 # first request, should load en_US
160 the_locale = "en_US"
161 with app.test_request_context() as ctx:
162 assert b.domain_instance.get_translations_cache(ctx) == {}
163 assert babel.gettext("Yes") == "Yes"
164 assert load_mock.call_count == 1
165
166 # second request, should use en_US from cache
167 with app.test_request_context() as ctx:
168 assert set(b.domain_instance.get_translations_cache(ctx)) == {
169 ("en_US", "messages")
170 }
171 assert babel.gettext("Yes") == "Yes"
172 assert load_mock.call_count == 1
173
174 # third request, should load de_DE from cache
175 the_locale = "de_DE"
176 with app.test_request_context() as ctx:
177 assert set(b.domain_instance.get_translations_cache(ctx)) == {
178 ("en_US", "messages")
179 }
180 assert babel.gettext("Yes") == "Ja"
181 assert load_mock.call_count == 2
182
183 # now everything is cached, so no more loads should happen!
184 the_locale = "en_US"
185 with app.test_request_context() as ctx:
186 assert set(b.domain_instance.get_translations_cache(ctx)) == {
187 ("en_US", "messages"),
188 ("de_DE", "messages"),
189 }
190 assert babel.gettext("Yes") == "Yes"
191 assert load_mock.call_count == 2
192
193 the_locale = "de_DE"
194 with app.test_request_context() as ctx:
195 assert set(b.domain_instance.get_translations_cache(ctx)) == {
196 ("en_US", "messages"),
197 ("de_DE", "messages"),
198 }
199 assert babel.gettext("Yes") == "Ja"
200 assert load_mock.call_count == 2
0 # -*- coding: utf-8 -*-
1 from __future__ import with_statement
2
3 import pickle
4
5 import flask
6 from babel.support import NullTranslations
7
8 import flask_babel as babel
9 from flask_babel import get_translations, gettext, lazy_gettext
10
11
12 def test_no_request_context():
13 b = babel.Babel()
14 app = flask.Flask(__name__)
15 b.init_app(app)
16
17 with app.app_context():
18 assert isinstance(get_translations(), NullTranslations)
19
20
21 def test_multiple_directories():
22 """
23 Ensure we can load translations from multiple directories.
24 """
25 b = babel.Babel()
26 app = flask.Flask(__name__)
27
28 app.config.update({
29 'BABEL_TRANSLATION_DIRECTORIES': ';'.join((
30 'translations',
31 'renamed_translations'
32 )),
33 'BABEL_DEFAULT_LOCALE': 'de_DE'
34 })
35
36 b.init_app(app)
37
38 with app.test_request_context():
39 translations = b.list_translations()
40
41 assert(len(translations) == 2)
42 assert(str(translations[0]) == 'de')
43 assert(str(translations[1]) == 'de')
44
45 assert gettext(
46 u'Hello %(name)s!',
47 name='Peter'
48 ) == 'Hallo Peter!'
49
50
51 def test_multiple_directories_different_domain():
52 """
53 Ensure we can load translations from multiple directories with a
54 custom domain.
55 """
56 b = babel.Babel()
57 app = flask.Flask(__name__)
58
59 app.config.update({
60 'BABEL_TRANSLATION_DIRECTORIES': ';'.join((
61 'translations_different_domain',
62 'renamed_translations'
63 )),
64 'BABEL_DEFAULT_LOCALE': 'de_DE',
65 'BABEL_DOMAIN': 'myapp'
66 })
67
68 b.init_app(app)
69
70 with app.test_request_context():
71 translations = b.list_translations()
72
73 assert(len(translations) == 2)
74 assert(str(translations[0]) == 'de')
75 assert(str(translations[1]) == 'de')
76
77 assert gettext(
78 u'Hello %(name)s!',
79 name='Peter'
80 ) == 'Hallo Peter!'
81 assert gettext(u'Good bye') == 'Auf Wiedersehen'
82
83
84 def test_different_domain():
85 """
86 Ensure we can load translations from multiple directories.
87 """
88 b = babel.Babel()
89 app = flask.Flask(__name__)
90
91 app.config.update({
92 'BABEL_TRANSLATION_DIRECTORIES': 'translations_different_domain',
93 'BABEL_DEFAULT_LOCALE': 'de_DE',
94 'BABEL_DOMAIN': 'myapp'
95 })
96
97 b.init_app(app)
98
99 with app.test_request_context():
100 translations = b.list_translations()
101
102 assert(len(translations) == 1)
103 assert(str(translations[0]) == 'de')
104
105 assert gettext(u'Good bye') == 'Auf Wiedersehen'
106
107
108 def test_lazy_old_style_formatting():
109 lazy_string = lazy_gettext(u'Hello %(name)s')
110 assert lazy_string % {u'name': u'test'} == u'Hello test'
111
112 lazy_string = lazy_gettext(u'test')
113 assert u'Hello %s' % lazy_string == u'Hello test'
114
115
116 def test_lazy_pickling():
117 lazy_string = lazy_gettext(u'Foo')
118 pickled = pickle.dumps(lazy_string)
119 unpickled = pickle.loads(pickled)
120
121 assert unpickled == lazy_string
0 # -*- coding: utf-8 -*-
1 from __future__ import with_statement
2
3 from decimal import Decimal
4
5 import flask
6
7 import flask_babel as babel
8
9
10 def test_basics():
11 app = flask.Flask(__name__)
12 babel.Babel(app)
13 n = 1099
14
15 with app.test_request_context():
16 assert babel.format_number(n) == u'1,099'
17 assert babel.format_decimal(Decimal('1010.99')) == u'1,010.99'
18 assert babel.format_currency(n, 'USD') == '$1,099.00'
19 assert babel.format_percent(0.19) == '19%'
20 assert babel.format_scientific(10000) == u'1E4'
+0
-290
tests/tests.py less more
0 # -*- coding: utf-8 -*-
1 from __future__ import with_statement
2
3 import sys
4 import os
5 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
6
7 import pickle
8
9 import unittest
10 from decimal import Decimal
11 import flask
12 from datetime import datetime, timedelta
13 import flask_babel as babel
14 from flask_babel import gettext, ngettext, lazy_gettext, get_translations
15 from babel.support import NullTranslations
16 from flask_babel._compat import text_type
17
18
19 class IntegrationTestCase(unittest.TestCase):
20 def test_no_request_context(self):
21 b = babel.Babel()
22 app = flask.Flask(__name__)
23 b.init_app(app)
24
25 with app.app_context():
26 assert isinstance(get_translations(), NullTranslations)
27
28 def test_multiple_directories(self):
29 """
30 Ensure we can load translations from multiple directories.
31 """
32 b = babel.Babel()
33 app = flask.Flask(__name__)
34
35 app.config.update({
36 'BABEL_TRANSLATION_DIRECTORIES': ';'.join((
37 'translations',
38 'renamed_translations'
39 )),
40 'BABEL_DEFAULT_LOCALE': 'de_DE'
41 })
42
43 b.init_app(app)
44
45 with app.test_request_context():
46 translations = b.list_translations()
47
48 assert(len(translations) == 2)
49 assert(str(translations[0]) == 'de')
50 assert(str(translations[1]) == 'de')
51
52 assert gettext(
53 u'Hello %(name)s!',
54 name='Peter'
55 ) == 'Hallo Peter!'
56
57 def test_different_domain(self):
58 """
59 Ensure we can load translations from multiple directories.
60 """
61 b = babel.Babel()
62 app = flask.Flask(__name__)
63
64 app.config.update({
65 'BABEL_TRANSLATION_DIRECTORIES': 'translations_different_domain',
66 'BABEL_DEFAULT_LOCALE': 'de_DE',
67 'BABEL_DOMAIN': 'myapp'
68 })
69
70 b.init_app(app)
71
72 with app.test_request_context():
73 translations = b.list_translations()
74
75 assert(len(translations) == 1)
76 assert(str(translations[0]) == 'de')
77
78 assert gettext(u'Good bye') == 'Auf Wiedersehen'
79
80 def test_lazy_old_style_formatting(self):
81 lazy_string = lazy_gettext(u'Hello %(name)s')
82 assert lazy_string % {u'name': u'test'} == u'Hello test'
83
84 lazy_string = lazy_gettext(u'test')
85 assert u'Hello %s' % lazy_string == u'Hello test'
86
87 def test_lazy_pickling(self):
88 lazy_string = lazy_gettext(u'Foo')
89 pickled = pickle.dumps(lazy_string)
90 unpickled = pickle.loads(pickled)
91
92 assert unpickled == lazy_string
93
94
95 class DateFormattingTestCase(unittest.TestCase):
96
97 def test_basics(self):
98 app = flask.Flask(__name__)
99 babel.Babel(app)
100 d = datetime(2010, 4, 12, 13, 46)
101 delta = timedelta(days=6)
102
103 with app.test_request_context():
104 assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM'
105 assert babel.format_date(d) == 'Apr 12, 2010'
106 assert babel.format_time(d) == '1:46:00 PM'
107 assert babel.format_timedelta(delta) == '1 week'
108 assert babel.format_timedelta(delta, threshold=1) == '6 days'
109
110 with app.test_request_context():
111 app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Vienna'
112 assert babel.format_datetime(d) == 'Apr 12, 2010, 3:46:00 PM'
113 assert babel.format_date(d) == 'Apr 12, 2010'
114 assert babel.format_time(d) == '3:46:00 PM'
115
116 with app.test_request_context():
117 app.config['BABEL_DEFAULT_LOCALE'] = 'de_DE'
118 assert babel.format_datetime(d, 'long') == \
119 '12. April 2010 um 15:46:00 MESZ'
120
121 def test_init_app(self):
122 b = babel.Babel()
123 app = flask.Flask(__name__)
124 b.init_app(app)
125 d = datetime(2010, 4, 12, 13, 46)
126
127 with app.test_request_context():
128 assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM'
129 assert babel.format_date(d) == 'Apr 12, 2010'
130 assert babel.format_time(d) == '1:46:00 PM'
131
132 with app.test_request_context():
133 app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Vienna'
134 assert babel.format_datetime(d) == 'Apr 12, 2010, 3:46:00 PM'
135 assert babel.format_date(d) == 'Apr 12, 2010'
136 assert babel.format_time(d) == '3:46:00 PM'
137
138 with app.test_request_context():
139 app.config['BABEL_DEFAULT_LOCALE'] = 'de_DE'
140 assert babel.format_datetime(d, 'long') == \
141 '12. April 2010 um 15:46:00 MESZ'
142
143 def test_custom_formats(self):
144 app = flask.Flask(__name__)
145 app.config.update(
146 BABEL_DEFAULT_LOCALE='en_US',
147 BABEL_DEFAULT_TIMEZONE='Pacific/Johnston'
148 )
149 b = babel.Babel(app)
150 b.date_formats['datetime'] = 'long'
151 b.date_formats['datetime.long'] = 'MMMM d, yyyy h:mm:ss a'
152 d = datetime(2010, 4, 12, 13, 46)
153
154 with app.test_request_context():
155 assert babel.format_datetime(d) == 'April 12, 2010 3:46:00 AM'
156
157 def test_custom_locale_selector(self):
158 app = flask.Flask(__name__)
159 b = babel.Babel(app)
160 d = datetime(2010, 4, 12, 13, 46)
161
162 the_timezone = 'UTC'
163 the_locale = 'en_US'
164
165 @b.localeselector
166 def select_locale():
167 return the_locale
168
169 @b.timezoneselector
170 def select_timezone():
171 return the_timezone
172
173 with app.test_request_context():
174 assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM'
175
176 the_locale = 'de_DE'
177 the_timezone = 'Europe/Vienna'
178
179 with app.test_request_context():
180 assert babel.format_datetime(d) == '12.04.2010, 15:46:00'
181
182 def test_refreshing(self):
183 app = flask.Flask(__name__)
184 babel.Babel(app)
185 d = datetime(2010, 4, 12, 13, 46)
186 with app.test_request_context():
187 assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM'
188 app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Vienna'
189 babel.refresh()
190 assert babel.format_datetime(d) == 'Apr 12, 2010, 3:46:00 PM'
191
192 def test_force_locale(self):
193 app = flask.Flask(__name__)
194 b = babel.Babel(app)
195
196 @b.localeselector
197 def select_locale():
198 return 'de_DE'
199
200 with app.test_request_context():
201 assert str(babel.get_locale()) == 'de_DE'
202 with babel.force_locale('en_US'):
203 assert str(babel.get_locale()) == 'en_US'
204 assert str(babel.get_locale()) == 'de_DE'
205
206
207 class NumberFormattingTestCase(unittest.TestCase):
208
209 def test_basics(self):
210 app = flask.Flask(__name__)
211 babel.Babel(app)
212 n = 1099
213
214 with app.test_request_context():
215 assert babel.format_number(n) == u'1,099'
216 assert babel.format_decimal(Decimal('1010.99')) == u'1,010.99'
217 assert babel.format_currency(n, 'USD') == '$1,099.00'
218 assert babel.format_percent(0.19) == '19%'
219 assert babel.format_scientific(10000) == u'1E4'
220
221
222 class GettextTestCase(unittest.TestCase):
223
224 def test_basics(self):
225 app = flask.Flask(__name__)
226 babel.Babel(app, default_locale='de_DE')
227
228 with app.test_request_context():
229 assert gettext(u'Hello %(name)s!', name='Peter') == 'Hallo Peter!'
230 assert ngettext(u'%(num)s Apple', u'%(num)s Apples', 3) == \
231 u'3 Äpfel'
232 assert ngettext(u'%(num)s Apple', u'%(num)s Apples', 1) == \
233 u'1 Apfel'
234
235 def test_template_basics(self):
236 app = flask.Flask(__name__)
237 babel.Babel(app, default_locale='de_DE')
238
239 t = lambda x: flask.render_template_string('{{ %s }}' % x)
240
241 with app.test_request_context():
242 assert t("gettext('Hello %(name)s!', name='Peter')") == \
243 u'Hallo Peter!'
244 assert t("ngettext('%(num)s Apple', '%(num)s Apples', 3)") == \
245 u'3 Äpfel'
246 assert t("ngettext('%(num)s Apple', '%(num)s Apples', 1)") == \
247 u'1 Apfel'
248 assert flask.render_template_string('''
249 {% trans %}Hello {{ name }}!{% endtrans %}
250 ''', name='Peter').strip() == 'Hallo Peter!'
251 assert flask.render_template_string('''
252 {% trans num=3 %}{{ num }} Apple
253 {%- pluralize %}{{ num }} Apples{% endtrans %}
254 ''', name='Peter').strip() == u'3 Äpfel'
255
256 def test_lazy_gettext(self):
257 app = flask.Flask(__name__)
258 babel.Babel(app, default_locale='de_DE')
259 yes = lazy_gettext(u'Yes')
260 with app.test_request_context():
261 assert text_type(yes) == 'Ja'
262 assert yes.__html__() == 'Ja'
263 app.config['BABEL_DEFAULT_LOCALE'] = 'en_US'
264 with app.test_request_context():
265 assert text_type(yes) == 'Yes'
266 assert yes.__html__() == 'Yes'
267
268 def test_list_translations(self):
269 app = flask.Flask(__name__)
270 b = babel.Babel(app, default_locale='de_DE')
271 translations = b.list_translations()
272 assert len(translations) == 1
273 assert str(translations[0]) == 'de'
274
275 def test_no_formatting(self):
276 """
277 Ensure we don't format strings unless a variable is passed.
278 """
279 app = flask.Flask(__name__)
280 babel.Babel(app)
281
282 with app.test_request_context():
283 assert gettext(u'Test %s') == u'Test %s'
284 assert gettext(u'Test %(name)s', name=u'test') == u'Test test'
285 assert gettext(u'Test %s') % 'test' == u'Test test'
286
287
288 if __name__ == '__main__':
289 unittest.main()
0 # Translations template for PROJECT.
1 # Copyright (C) 2010 ORGANIZATION
2 # This file is distributed under the same license as the PROJECT project.
3 # FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
4 #
5 msgid ""
6 msgstr ""
7 "Project-Id-Version: PROJECT VERSION\n"
8 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
9 "POT-Creation-Date: 2010-05-30 12:56+0200\n"
10 "PO-Revision-Date: 2012-04-11 15:18+0200\n"
11 "Last-Translator: Serge S. Koval <serge.koval+github@gmail.com>\n"
12 "Language-Team: LANGUAGE <LL@li.org>\n"
13 "MIME-Version: 1.0\n"
14 "Content-Type: text/plain; charset=utf-8\n"
15 "Content-Transfer-Encoding: 8bit\n"
16 "Generated-By: Babel 0.9.5\n"
17
18 #: tests.py:94
19 #, python-format
20 msgid "first"
21 msgstr "erste"
22