././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1581088622.4903545 Flask-BabelEx-0.9.4/0000755000175000017500000000000000000000000014321 5ustar00sergeserge00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1581088622.4870212 Flask-BabelEx-0.9.4/Flask_BabelEx.egg-info/0000755000175000017500000000000000000000000020435 5ustar00sergeserge00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088622.0 Flask-BabelEx-0.9.4/Flask_BabelEx.egg-info/PKG-INFO0000644000175000017500000000314200000000000021532 0ustar00sergeserge00000000000000Metadata-Version: 1.1 Name: Flask-BabelEx Version: 0.9.4 Summary: Adds i18n/l10n support to Flask applications Home-page: http://github.com/mrjoes/flask-babelex Author: Serge S. Koval Author-email: serge.koval+github@gmail.com License: BSD Description: Flask-BabelEx ------------- Adds i18n/l10n support to Flask applications with the help of the `Babel`_ library. This is fork of official Flask-Babel extension with following features: 1. It is possible to use multiple language catalogs in one Flask application; 2. Localization domains: your extension can package localization file(s) and use them if necessary; 3. Does not reload localizations for each request. Links ````` * `documentation `_ * `development version `_ * `original Flask-Babel extension `_. .. _Babel: http://babel.edgewall.org/ Platform: any 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: Programming Language :: Python :: 3 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088622.0 Flask-BabelEx-0.9.4/Flask_BabelEx.egg-info/SOURCES.txt0000644000175000017500000000124500000000000022323 0ustar00sergeserge00000000000000LICENSE MANIFEST.in Makefile README setup.cfg setup.py Flask_BabelEx.egg-info/PKG-INFO Flask_BabelEx.egg-info/SOURCES.txt Flask_BabelEx.egg-info/dependency_links.txt Flask_BabelEx.egg-info/not-zip-safe Flask_BabelEx.egg-info/requires.txt Flask_BabelEx.egg-info/top_level.txt docs/Makefile docs/conf.py docs/index.rst docs/make.bat docs/_static/flask-babel.png flask_babelex/__init__.py flask_babelex/_compat.py tests/babel.cfg tests/tests.py tests/translations/messages.pot tests/translations/test.pot tests/translations/de/LC_MESSAGES/messages.mo tests/translations/de/LC_MESSAGES/messages.po tests/translations/de/LC_MESSAGES/test.mo tests/translations/de/LC_MESSAGES/test.po././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088622.0 Flask-BabelEx-0.9.4/Flask_BabelEx.egg-info/dependency_links.txt0000644000175000017500000000000100000000000024503 0ustar00sergeserge00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088600.0 Flask-BabelEx-0.9.4/Flask_BabelEx.egg-info/not-zip-safe0000644000175000017500000000000100000000000022663 0ustar00sergeserge00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088622.0 Flask-BabelEx-0.9.4/Flask_BabelEx.egg-info/requires.txt0000644000175000017500000000005500000000000023035 0ustar00sergeserge00000000000000Flask Babel>=1.0 speaklater>=1.2 Jinja2>=2.5 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088622.0 Flask-BabelEx-0.9.4/Flask_BabelEx.egg-info/top_level.txt0000644000175000017500000000001600000000000023164 0ustar00sergeserge00000000000000flask_babelex ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/LICENSE0000644000175000017500000000272200000000000015331 0ustar00sergeserge00000000000000Copyright (c) 2013 by Serge S. Koval, Armin Ronacher and contributors. Some rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/MANIFEST.in0000644000175000017500000000035400000000000016061 0ustar00sergeserge00000000000000include Makefile LICENSE recursive-include tests * recursive-exclude tests *.pyc recursive-exclude tests *.pyo recursive-include docs * recursive-exclude docs *.pyc recursive-exclude docs *.pyo prune docs/_build prune docs/_themes/.git ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/Makefile0000644000175000017500000000056400000000000015766 0ustar00sergeserge00000000000000.PHONY: clean-pyc test upload-docs all: clean-pyc test test: @cd tests; python tests.py tox-test: @tox clean-pyc: find . -name '*.pyc' -exec rm -f {} + find . -name '*.pyo' -exec rm -f {} + find . -name '*~' -exec rm -f {} + clean: clean-pyc upload-docs: $(MAKE) -C docs html python setup.py upload_docs .PHONY: upload-docs clean-pyc clean tox-test test all ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1581088622.4903545 Flask-BabelEx-0.9.4/PKG-INFO0000644000175000017500000000314200000000000015416 0ustar00sergeserge00000000000000Metadata-Version: 1.1 Name: Flask-BabelEx Version: 0.9.4 Summary: Adds i18n/l10n support to Flask applications Home-page: http://github.com/mrjoes/flask-babelex Author: Serge S. Koval Author-email: serge.koval+github@gmail.com License: BSD Description: Flask-BabelEx ------------- Adds i18n/l10n support to Flask applications with the help of the `Babel`_ library. This is fork of official Flask-Babel extension with following features: 1. It is possible to use multiple language catalogs in one Flask application; 2. Localization domains: your extension can package localization file(s) and use them if necessary; 3. Does not reload localizations for each request. Links ````` * `documentation `_ * `development version `_ * `original Flask-Babel extension `_. .. _Babel: http://babel.edgewall.org/ Platform: any 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: Programming Language :: Python :: 3 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/README0000644000175000017500000000064500000000000015206 0ustar00sergeserge00000000000000Flask-BabelEx Implements i18n and l10n support for Flask. This is fork of the official Flask-Babel extension with additional features: 1. It is possible to use multiple language catalogs in one Flask application; 2. Localization domains: your extension can package localization file(s) and use them if necessary; 3. Does not reload localizations for each request. Flask-BabelEx is API-compatible with Flask-Babel. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1581088622.4870212 Flask-BabelEx-0.9.4/docs/0000755000175000017500000000000000000000000015251 5ustar00sergeserge00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/docs/Makefile0000644000175000017500000001100400000000000016705 0ustar00sergeserge00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/FlaskBabel.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/FlaskBabel.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/FlaskBabel" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/FlaskBabel" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: latex $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1581088622.4870212 Flask-BabelEx-0.9.4/docs/_static/0000755000175000017500000000000000000000000016677 5ustar00sergeserge00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/docs/_static/flask-babel.png0000644000175000017500000005005500000000000021555 0ustar00sergeserge00000000000000PNG  IHDR_osBIT|d pHYsa(atEXtSoftwarewww.inkscape.org< IDATxwbEh-c|vFkl`K,nTEE)J^/Ý;gs9^yg 3{޳^}-sw f<+Ѷ;q=p0,O;` `g`,OJ; qOx9z~J9rȑ#GSU3o=Jx q/0$@O0|H쨁 +\<63~bVC3 xw9r`ht+mgM닀~%_nf[Yg3`"ps{#3[̖1.f:rfV7upbfJEaA#G9r4[2H^XY bX xin3]cHrl}x'm#1 1{ж"e\#f0?ˑ#G k|f%rQݏ{ I=oxWCH>_4 /B2GX ~YZ9,qLo(23iP}3G9r(MN,-~]$"xRy$}o٧,TPHަ4@W+5RG ,4oy"+#ȳ2# g"W-Hwe͑#G92ќ|ˢTG#93߸f,_2"uw7 Zfv"2,7Q\_ 79@~!b =W:(4cĬ }}~O`N;f6ݯtsȑ#GI[/=3܄ (#; "37ن}!zs""-øC_K3 HPǹtW&#$ȑ#GUCs@[w?{#8ZH2̶@ysPS[Aҏ3 W vuy&if'}抙nDLif3c|wt'888#G9rTRp' 9{9 MP6>0B9LB?Gw Z"3DDE| !zg]EafmUdݿ#`9r 4W5fx]mP潉&,"mohf=H\k3߯TADܸpoۣȁ6aW)n.A指ͬaf/*`  !hBfv ȑy\c?$^BHQoBS:"F I~V2;r@7ڤ;PCbBҞi>kPiaI .t7ۛr#³> 9f֧9!;>7DHYQl݂] 9ȑc @s(]modlf[[b7Q|[m<7wr+ןa/Dl`zovff; fppbs 3[.B,j%Qh 3 1ؿ7~*GI4#_PDg!B~87ŵ/6a p1?1Hǁm}8?jf"fb2݊l|+k٣(N%lHMC L (ww3Hsc2vL49*D`OC,mJϑ af=۴kMFCUO|_G󨍣g(+^W,t#K 1 Km^B}{a-ސhI#_HҏX3wh-vD +Ά3ݽ\Gcͣ bf@&NELde+af1ҦlWFrgJYGHhP=awol:1x)%(<opqٮHo_J:𺙭GP#'fv"D#b) {>fɸ%݇ۇgEjFEʼnڄdv{No9CKao+2 c)M#)]&qQѾ ;~膒zE#fp;xs39}{vd&#`f#!Dz#+k U!s@gз9ȹe1蘍 ًvG?RcK8-o 3pB=%7l"f 3nԽm&o?n`B`p_j)a@n۲,:"f qǫm2;??Crb>..a"©0v34o$.rm4Ҡ4%7ecO\:@?xHY1ӑIo R,٠:!GBޤ$?>N_I7oQqg=3큤½2#ԦqxC¸QC+Ur[`&]@G 4bǏ˘sTzyQhw~2O5\;!JkB<MB(,GC۷}8pxsxDo?}ܽvLwݿ`TH"6u%X$.'":O 2w&rKFLCF;Qx;{kuBa}-im`C$n 삤还=w8 isI~ӛJ4]>8wq1k}灣7/{{wg@̹8ݟF" sMe{%q@ cS<82TlC  g(񹌶+B< mk"Knc4>IM=|6dYdsVDR)׶GGOL-o6 G7s}.mIr8 +h(#Z#G$VDkgSyHEJ<-3BIMOߘ ]w0|C j26+eJI?}G&+<[Y>3kRy9h\Drce*#( zh8FQyֶA}QF xI۟ aK2P5CH-GI~J?_Rp%Gow$Q/ǜl{~7tt ot uXH3!g+S\Z(8F#/$ZZakef"i>BAΊ(E.Ohm±.a7q>'U>-v(9AS lvgyUFI+!7"q~y$m7)L JȓD Id !/ҼXԃRϬ8NܟEGB Т7C3;^G",g5W@@v-Slc-P eUU+p ~q&e4$D w&F}ҸǨ\#сʄ9EjmD ER]4~!a0 <!M."!Z< nCa*bQO'_6T82F}Ҹk잍O'?IEi^7}oDRyw7 Bvi%p-@NYi >DjAf61PX_K0LFDd{?.Dz9,42"=Co^,UDZ!-\H9M'0ȑDe(*_¸D5P wETOIc~~p |m7URɽA$3[ l{D =Bw\g6r&\| B߈XKS_+/^&rmTgV38q~p?M*'C E l/T*w $@&H^Iᣀ#&|Ba$_a_C*"B~(fkw̺}m$n^GEu"& ~)#DD}`M cȧ31F]M9V.9c!:?P49(,wy`hިD?0{#~Vp03*Vi6'<c5o UC{ :d CP:&MDffHJMH# xw66HǦVp%`--@ez?cfˡtupl#!ܿEg뻢 ^нV`b&^16 HMChvGFXhD̶CeHh_E ݁ …==a?&.G V;3pz&N4ݳr5;̬?c}Eef qDJiKq~ԘE(= #= 7TTG({Z>+X,FBuU\KH}p.3Bh$w_Cyc8+ 3ى6VSqη2}~\y-njIe 7/3{1LT+}31CaN>!v;bpd򲆎*9Ҹ\̩}@j߹h,|)>?FiDZNfS-ʦKB8_H G W,x{da:P!h*{Hrf '27O=%Pϭ}S@^ mM䬷NF(adJx}@?h Ƈy?oX%WP80œi,1ȮNB|Uyͫ5FefW $`k."垾z;9~o$~C#6swD ~yڳ *TJVD9Ffo=/>$3io{"F]?!i?l}p=j Uf&UniI̺ dvrI?Aܡ^lĥG^ރwPDf@w?SlT@^7"ii ynf{0  }v7O̬ψAWsͬ (DBa}D#VD8x݇bf_kzVa>E\1[TE}\ofF%ѦC0~? څڐoUVTR8ig*"`Bͬ-Z]=f2an*ُPq5pM\N {a5307Mfڧ7-==5]*= dIȏ+ SWs3Iaf"I~i)wk6r;>CUo1-GL+OW{ fva(uc}ap\^ GHtmlB/J:4^'d 6˓(n("Ϋ7z#, w El"l8'P,\7pjq2#x5j#l梈6?Tg{8҈bx!'ƘWhf<~ͧ$uXJ\w6DE{X5$ipll%rwsdk>Sͬp03%ps'};9oYh,|iR$S)I|=-gJI|( 1m5d~&4Iab5]f4}_8"udc;F0ٺN&^ld1_&EjC w6" G}m }^7 x>;.LO>x?{TyY6}'LTyΨ$EͲ%s [\ M"mV|UZuCm˶##&Fx;!qeڲ8X#FpwZ;HĹ!avN9FײDvWlDjni,Ip 6s<3kSElƠxLBv&?2D},zˆ<$ &F!M]?s#MEh"9˘yx$h3L$5oTڞ-~n.HΧ3< Gz ƪ/~Z֊$ -8)8 $ͻѾ]9{"@سD>F?~o$mB5U |ii,>)cmJ:g?3? nrPM?L $.:aߘكHm*#J IDAT|3$׹u$ D9XҬj̧ˎ\8ȦF8V trx©H՜D%`06:Sږ۔DUnf@s-sdKmM(xy=u˷w>Ѧ$3Qv?WAO3ܠs)6ͬ >"&sעoG>cjK 12q~ ׭*ldB< \r\!<%f6)(rkOt%JDVD&G~V)OOj;]G{u.V6~D?C$܎9<+v r{=W ]O<8UKd쥷ggxHc"mQbN/oCP3B=- 2!eE*IO4r\\C,$mm2Jۥ X64} T77(z% cې $M֋/TfϏbΓ}q4"Ӧ>?lp_ٕfv2t&''QF’`2% 5@:N>f[o)CG=X^ L!cjUJuw?ݯtJnD ؔboIiJQ`Q裸>|2;fvi yc/h &=yl?9:0ވQ1~ҔudN+Z`?9XAa(S޸Y7&i(RX$ 57[o )itwűʇ|cWorG X*d6١zbI~QAI VEfњf0#5asb ݻ{[uF2ҲCgkMM+] wa*ү"cx ;&J'إ"rDED?0H$BG_–^7,vWD 6pűۅDhDnN>K K>X C<(,[᥸m6!J_\l'D 3t` })ukbL L}/"#02I$[TW{t>?qscdމci"Y~n}d9648(D]ez,;1i(f Ef FFPߗB>92zv%A52d0 7vttOGI1ߤj`zDIb_(+W[T@lf!9IeT&A3u3KǹTtlg$'F8#,KڵB,j'Y1LDse R/M]FhiR_ԧFs'zG_e$9Kֽ7\p2k3Ib!rVmCDl?=t࿦ BObh(_T Ac5tf3]׼Fݫf6>3l`ffv6lP%fit2E[dr1jN,Z$%}C6Q>\bo{%R۶BBc | DԶ5姏%ڰY3Ɣ^g쌤8%=SP̦ }1+tqUR#\w?03/ݽծg$Ìko~ڢFڛ!ik{({i4ZQ!aǚ]q`wfz~ f3Ѿa)Mw!zaUۣL#+Q)p"ybfS3ьa>A)o1ULݧ#083{N1!{f_N7QAe~ J&3twĩ_8u7PV^qt NC)/%=cT'i'  '] I̵zKC/,EDJz+yaBqdf砘᪥|'~,msAv/U(g'iA9fRbfpml<%:82%x"V\*L~ס\x!ڠ'+!+nf8pvn)wafyfv b G䰺x_0Y?3f9۝Qц0=9$hMU!kzX@ A!S /* QAr )(p38< M#H:$q5sKs0Jf7q8 )^͍H!]8jpnfF*.1I_ ifAuH4tp IZXDzg7I&S!Dzh10 ўHS6,h6FL+f;wOzɄQOcלڬzywDĿ;reѷP` jӏ>I}Q™oR<̣'Ji>XSQtϑ-׆Z#"j%4Dܓ~5-+[/Us;Ҥ]hJ{ dp,RHZ0%|lfVɉ\Df@V8ުsKS.mr7:G"SW;Jvvvn]wpM]f=lf}ѧџ鎈&< L *?wXe)0Áu|/>GWͷ %K/ B"o ~*8wCUSnΈE#T".-u iWdT)D6(T0- B[?J% uD?!+Tl4R-upKMIS$L@X2GVD}3cf6af)`"H۟Ta ! f֘RAjr#VEjP,'AzNO>CցENjVh̜$Ѿ^l+u[Rf+W̧]7@E%Iɾ09 ERCHVdfmCfvaf=xiH> 1ACZ oEMB!.|D?n+D""_1M:ƮET:DGR#7V2lyT%=+!̦XC9Gh)>wk$l]AV{=+>l7޴1W3wcfW\~ݛpUP`fD=;>>:9BT;IHÙ '%k,lʅWDZ~˲)=f6/]1ߡH+մ~L@>~_8b;"/EM-"跥 -:q2܎$9J#/?*ёv;oH !'@Z"g(]cptZ1}" óNG $Y&"|+>3X&L* GUN9*K+&b(foQ$T5kwVCO~Rj)#{NȆHwJc !5~3{[Wc׿0Q ~sgAe쏊a=gj*hݟ2hFksHSU@H#BUfv8r=b J"v,:,lf Hro>( H i"/ 0#05CuS̺ lB8 硏bR]6#L,BޔB0HB*iBa 梥,x r>-us&y8>f)MjP琊sx$Jj鶾&S%[QAu7&hV:pPif m̫}^Rwˀg Utg~w#vX|Qxpc`CR4!0<97if"GdQzmKa=,o~4VC5DV裹yƷF0"ˢq"pߚZ~v&,Ι8Ɣ93(83|lO;"nj_v>rz }03}Rƿ}W~'K@qR)FX~H}"b[FhYHZ}I]}9Ȧu?J#)8،mE6oK;Zlr Hs ÁȞsnXQýF0.O81mC<8;9vs>Ȝ{W[$\}qwkb\Y gk"Vb.7{t<pY#}~:% 18vnyo[/66vM 0dpxנ5g0N=R~Dۋmc'e<̖s-cܢ!5Hif"VH/kJa8+pCrTM I82!E}0&p?Oq-UJYPե.Lk?6̬יwPCKue=հ1aۙVhx/z@f.}͊oD9aGٕ1l""-+o}bwn84*eIǟPƻ=XGqsubI_}Wqn;"f(-yZx3Ff63q@ ueҤр"-Β .B?%1.9XT.J/"TWbOC{"P$wݏpc}uw_ݟvS8o(2DߔGT}KS psW=*;QEeCDDVʑzZ/>ocEW]nLkV_zƃeLsB Q$>AADx?T,}kY>,3]6gH:FqJ1:Z/Hy'%nfvt*E U8Nh쎲=(^zZy٪0i`5Js&r&i3+Y_ܔUYes\#ݟs3}Ow[ 6WoX),uE}J!x[UI.1%hP>;@@4:Ia_AoлI"9WLԻb✪mN3lM3F"5_щE2uG~i7LIGL,~ (9s33=ta[u_gLDJ^CN-q>݇&oOmj{kn4DZZ}UUs Rw6TsɒJ2Me(Ъd+w^qt32e=ѓ&B?[>'O@:}XT(:4F,?&!ڂ#&Hpqx&*6'"H=?%8C|b tq>KzrQf6>74$G!I Tlw@bZsl_4 ;R1)h-w`"܈lB}zmMu7#2>oLeM$&Bkճ,IxY{GTP8Z=Yȵr]ªq, 87 {FH+>X~T]ׯn([@RqԒv|]y .kοn@o"" 6ʉkPIچc)EJtJ~*|wգ#i1hFzֿ_fH7W@,@Ko| ([vmQU^w_7q~?ծ;"kG!1K-L"QaMq /}H4?D?$\>ܮ)mJqas{27@[d Evߴ.|$H&!UU|a6tXj2"}\b H(h{͊(|OW"F=୚g>jR6Fi)}=р,N kRl&l*$qnQqR]b\;*\;ERBcw@hD $10҉F=)N#|3I)"gܿsXzۓ|*V"1f=9B2|e|\ ipVEYF|f}df̫Dپij @E+سW>(s#C]: >RNE*(Xû?H^7*af9NDf=H#GވP ڡȡZY 1eHe|`Ĺ(o2k.wG$IZH0?ZO?1h A/3aJxףpX4#0<ñW:̓ͬ "2IaG9{M;QrвH7vu壎'xȷ0nH(0p|>,'UQj߮hỠ|!Zzz%t٘ڣ"$<3[SZb;Q6vd~8WqMSȎcm`}쿯c~nQh7`?3'"f]y'|XRpL!bX̲ t3{ !fzYIg.2 ]PB%_dfux$%IDAT?j})PO^q95)̬5bG`oW0OлVXm$ç{)?)rS:Hڿ177c ]LcG[큭p7dmE8i11ڣZ /K2 k\BիCg/sѐcV4~K1"!}:$W+c_ 8u2໒߇{ m'c4!I6CBQlk2{>"2ˆGE>T?a1~OO ٱHrZ6 7u^R0SM$<w'Rڮ> m>wri>=VU+}kdvXȄ0{8 *`OW[pLۑ`Kw{@qn iaة9acFW{⷏ bw/KeV~ b!xsdk0gfg (M>39W1cBj{7c/sXw(,wwLc$ o<=v\E%;T("e&;[!fpoB(\1YF~Aa$WCO yD}ry䏴opgdg9?jḃ &u$nVt! #$0$)ᵅoݑ8wud 䊵o0>_BWhMƅq;9o/ҞG2bDGaz_ 3aB#;AQ"C | 3 q׳bG ;'Bf2R,T:# PDUҪ1Qhbj ݳ9'ЧԜΦR#ݽ m6ٍdƍ;'5V^!1H Waۣ_k e,g+ݤ3ZiEj|$6u|I i~,{>Gqn&Hއv 1G5`h1QEe,^1F*͑Ss2L,ݨY%bz_z'-iУ)'B5`!̦ߚ٭HꆈgWp}ɓb[)N@j3=8T 3zw*H "F|0x;x8Ƽb}\5ݏIiⒿF8-(j׾/٠rA#$aZ1__xFF`:id HQBtKvz"=iN4@GREp SMih Ϡ:i 7s`Ը#uvvUr,C3Mco8'j TD's kM@kQ!K1PțIϧ1Α# ,9ƨyglqR.h,BHdvD[!5$SW]CK6f~ IF9KP?pP[rTC<2-$Hyjc3+YaѝՐK2c?+[|Rȑ#G*"__䜡#ǐ6-"^?QљS#;>umK BDߐ=E1̮0ϐCM5K6FK!џ3iC19 L@`Mbcsȑ#iE@ I4Aam6?J.$E]MV Ǟ4I!B[#ׇ3U)YX yGX²_#Oܕ#f›89N9rX:&Fx3%9;LGf ~z Jf;731fGD*BpO#qKvUJFEϟd2:Q1mLsȑ#G FD=q_%X$HJ?/@DiZb2qT#$9f4?X?εG p N, U!ORȔM@UZt bV69r}D+3ea 1DkH&q d`>b@u~O~Q1@(]aWaNISt›EarYV4Niȑ#G I"#`Ow_ՕZj7@aX*'[ a-(t\lQkQ&!(1gRX$%Z$30 1_qB!"Mu6B9rȱ-:w2놐fNP]?j5s94t 'z"%Anҡ^ZTs(d>&5OJ_#~Qd@:_͑#G?p$ n $(r J=Q<\ދZ~>HOw&2Z7r;LB&2' WJc*si}ʸȑ#G¹b7K/^aj"tGwRүqiXD!~2_>M:P ̠B0B7mZuC c9rȱ C("ŤՐ ?BgDun?J EM9+P/gfݢ=HxC8!{HC@oRwM~?>ZA5G9r|O'l?qߪԕ;{Dl;nN,>.Ad/DУ F#I彁luj[;8*6v j <1q(t.:sLEɄӢ#؆y^J$ <;Q2B9r#N#B_!"Hk̖An! wB f6ZjkOEtb*^@u>u*Uޢ1/+ _Y%1>ӄ3Г߆95Z9rȱtb1wA76@oU (ƟF%h`c#*SX>MzFb q-,%b!D-.{svgN_p%p:JL{3X _{c'<$z61ֱk!.#^%o7_.!7氡m v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'FlaskBabeldoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'FlaskBabel.tex', u'Flask Babel Documentation', u'Armin Ronacher', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'flaskbabel', u'Flask Babel Documentation', [u'Armin Ronacher'], 1) ] intersphinx_mapping = {'http://docs.python.org/': None, 'http://flask.pocoo.org/docs/': None} ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/docs/index.rst0000644000175000017500000002777700000000000017136 0ustar00sergeserge00000000000000Flask-BabelEx ============= .. module:: flask_babelex Flask-BabelEx is an extension to `Flask`_ that adds i18n and l10n support to any Flask application with the help of `babel`_, `pytz`_ and `speaklater`_. It has builtin support for date formatting with timezone support as well as a very simple and friendly interface to :mod:`gettext` translations. Installation ------------ Install the extension with one of the following commands:: $ easy_install Flask-BabelEx or alternatively if you have pip installed:: $ pip install Flask-BabelEx Please note that Flask-BabelEx requires Jinja 2.5. If you are using an older version you will have to upgrade or disable the Jinja support. Configuration ------------- To get started all you need to do is to instanciate a :class:`Babel` object after configuring the application:: from flask import Flask from flask_babelex import Babel app = Flask(__name__) app.config.from_pyfile('mysettings.cfg') babel = Babel(app) The babel object itself can be used to configure the babel support further. Babel has two configuration values that can be used to change some internal defaults: =========================== ============================================= `BABEL_DEFAULT_LOCALE` The default locale to use if no locale selector is registered. This defaults to ``'en'``. `BABEL_DEFAULT_TIMEZONE` The timezone to use for user facing dates. This defaults to ``'UTC'`` which also is the timezone your application must use internally. =========================== ============================================= For more complex applications you might want to have multiple applications for different users which is where selector functions come in handy. The first time the babel extension needs the locale (language code) of the current user it will call a :meth:`~Babel.localeselector` function, and the first time the timezone is needed it will call a :meth:`~Babel.timezoneselector` function. If any of these methods return `None` the extension will automatically fall back to what's in the config. Furthermore for efficiency that function is called only once and the return value then cached. If you need to switch the language between a request, you can :func:`refresh` the cache. Example selector functions:: from flask import g, request @babel.localeselector def get_locale(): # if a user is logged in, use the locale from the user settings user = getattr(g, 'user', None) if user is not None: return user.locale # otherwise try to guess the language from the user accept # header the browser transmits. We support de/fr/en in this # example. The best match wins. return request.accept_languages.best_match(['de', 'fr', 'en']) @babel.timezoneselector def get_timezone(): user = getattr(g, 'user', None) if user is not None: return user.timezone The example above assumes that the current user is stored on the :data:`flask.g` object. Formatting Dates ---------------- To format dates you can use the :func:`format_datetime`, :func:`format_date`, :func:`format_time` and :func:`format_timedelta` functions. They all accept a :class:`datetime.datetime` (or :class:`datetime.date`, :class:`datetime.time` and :class:`datetime.timedelta`) object as first parameter and then optionally a format string. The application should use naive datetime objects internally that use UTC as timezone. On formatting it will automatically convert into the user's timezone in case it differs from UTC. To play with the date formatting from the console, you can use the :meth:`~flask.Flask.test_request_context` method: >>> app.test_request_context().push() Here some examples: >>> from flask_babelex import format_datetime >>> from datetime import datetime >>> format_datetime(datetime(1987, 3, 5, 17, 12)) u'Mar 5, 1987 5:12:00 PM' >>> format_datetime(datetime(1987, 3, 5, 17, 12), 'full') u'Thursday, March 5, 1987 5:12:00 PM World (GMT) Time' >>> format_datetime(datetime(1987, 3, 5, 17, 12), 'short') u'3/5/87 5:12 PM' >>> format_datetime(datetime(1987, 3, 5, 17, 12), 'dd mm yyy') u'05 12 1987' >>> format_datetime(datetime(1987, 3, 5, 17, 12), 'dd mm yyyy') u'05 12 1987' And again with a different language: >>> app.config['BABEL_DEFAULT_LOCALE'] = 'de' >>> from flask_babelex import refresh; refresh() >>> format_datetime(datetime(1987, 3, 5, 17, 12), 'EEEE, d. MMMM yyyy H:mm') u'Donnerstag, 5. M\xe4rz 1987 17:12' For more format examples head over to the `babel`_ documentation. Using Translations ------------------ The other big part next to date formatting are translations. For that, Flask uses :mod:`gettext` together with Babel. The idea of gettext is that you can mark certain strings as translatable and a tool will pick all those app, collect them in a separate file for you to translate. At runtime the original strings (which should be English) will be replaced by the language you selected. There are two functions responsible for translating: :func:`gettext` and :func:`ngettext`. The first to translate singular strings and the second to translate strings that might become plural. Here some examples:: from flask_babelex import gettext, ngettext gettext(u'A simple string') gettext(u'Value: %(value)s', value=42) ngettext(u'%(num)s Apple', u'%(num)s Apples', number_of_apples) Additionally if you want to use constant strings somewhere in your application and define them outside of a request, you can use a lazy strings. Lazy strings will not be evaluated until they are actually used. To use such a lazy string, use the :func:`lazy_gettext` function:: from flask_babelex import lazy_gettext class MyForm(formlibrary.FormBase): success_message = lazy_gettext(u'The form was successfully saved.') So how does Flask-BabelEx find the translations? Well first you have to create some. Here is how you do it: Translating Applications ------------------------ First you need to mark all the strings you want to translate in your application with :func:`gettext` or :func:`ngettext`. After that, it's time to create a ``.pot`` file. A ``.pot`` file contains all the strings and is the template for a ``.po`` file which contains the translated strings. Babel can do all that for you. First of all you have to get into the folder where you have your application and create a mapping file. For typical Flask applications, this is what you want in there: .. sourcecode:: ini [python: **.py] [jinja2: **/templates/**.html] extensions=jinja2.ext.autoescape,jinja2.ext.with_ Save it as ``babel.cfg`` or something similar next to your application. Then it's time to run the `pybabel` command that comes with Babel to extract your strings:: $ pybabel extract -F babel.cfg -o messages.pot . If you are using the :func:`lazy_gettext` function you should tell pybabel that it should also look for such function calls:: $ pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot . This will use the mapping from the ``babel.cfg`` file and store the generated template in ``messages.pot``. Now we can create the first translation. For example to translate to German use this command:: $ pybabel init -i messages.pot -d translations -l de ``-d translations`` tells pybabel to store the translations in this folder. This is where Flask-BabelEx will look for translations. Put it next to your template folder. Now edit the ``translations/de/LC_MESSAGES/messages.po`` file as needed. Check out some gettext tutorials if you feel lost. To compile the translations for use, ``pybabel`` helps again:: $ pybabel compile -d translations What if the strings change? Create a new ``messages.pot`` like above and then let ``pybabel`` merge the changes:: $ pybabel update -i messages.pot -d translations Afterwards some strings might be marked as fuzzy (where it tried to figure out if a translation matched a changed key). If you have fuzzy entries, make sure to check them by hand and remove the fuzzy flag before compiling. Flask-BabelEx looks for message catalogs in ``translations`` directory which should be located under Flask application directory. Default domain is "messages". For example, if you want to have translations for German, Spanish and French, directory structure should look like this: translations/de/LC_MESSAGES/messages.mo translations/sp/LC_MESSAGES/messages.mo translations/fr/LC_MESSAGES/messages.mo Translation Domains ------------------- By default, Flask-BabelEx will use "messages" domain, which will make it use translations from the ``messages.mo`` file. It is not very convenient for third-party Flask extensions, which might want to localize themselves without requiring user to merge their translations into "messages" domain. Flask-BabelEx allows extension developers to specify which translation domain to use:: from flask_babelex import Domain mydomain = Domain(domain='myext') mydomain.lazy_gettext('Hello World!') :class:`Domain` contains all gettext-related methods (:meth:`~Domain.gettext`, :meth:`~Domain.ngettext`, etc). In previous example, localizations will be read from the ``myext.mo`` files, but they have to be located in ``translations`` directory under users Flask application. If extension is distributed with the localizations, it is possible to specify their location:: from flask_babelex import Domain from flask.ext.myext import translations mydomain = Domain(translations.__path__[0]) ``mydomain`` will look for translations in extension directory with default (messages) domain. It is also possible to change the translation domain used by default, either for each app or per request. To set the :class:`Domain` that will be used in an app, pass it to :class:`Babel` on initialization:: from flask import Flask from flask_babelex import Babel, Domain app = Flask(__name__) domain = Domain(domain='myext') babel = Babel(app, default_domain=domain) Translations will then come from the ``myext.mo`` files by default. To change the default domain in a request context, call the :meth:`~Domain.as_default` method from within the request context:: from flask import Flask from flask_babelex import Babel, Domain, gettext app = Flask(__name__) domain = Domain(domain='myext') babel = Babel(app) @app.route('/path') def demopage(): domain.as_default() return gettext('Hello World!') ``Hello World!`` will get translated using the ``myext.mo`` files, but other requests will use the default ``messages.mo``. Note that a :class:`Babel` must be initialized for the app for translations to work at all. Troubleshooting --------------- On Snow Leopard pybabel will most likely fail with an exception. If this happens, check if this command outputs UTF-8:: $ echo $LC_CTYPE UTF-8 This is a OS X bug unfortunately. To fix it, put the following lines into your ``~/.profile`` file:: export LC_CTYPE=en_US.utf-8 Then restart your terminal. API --- This part of the documentation documents each and every public class or function from Flask-BabelEx. Configuration ````````````` .. autoclass:: Babel :members: Context Functions ````````````````` .. autofunction:: get_locale .. autofunction:: get_timezone Translation domains ``````````````````` .. autoclass:: Domain :members: Datetime Functions `````````````````` .. autofunction:: to_user_timezone .. autofunction:: to_utc .. autofunction:: format_datetime .. autofunction:: format_date .. autofunction:: format_time .. autofunction:: format_timedelta Gettext Functions ````````````````` .. autofunction:: gettext .. autofunction:: ngettext .. autofunction:: pgettext .. autofunction:: npgettext .. autofunction:: lazy_gettext .. autofunction:: lazy_pgettext Low-Level API ````````````` .. autofunction:: refresh .. _Flask: http://flask.pocoo.org/ .. _babel: http://babel.edgewall.org/ .. _pytz: http://pytz.sourceforge.net/ .. _speaklater: http://pypi.python.org/pypi/speaklater ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/docs/make.bat0000644000175000017500000001002200000000000016651 0ustar00sergeserge00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\FlaskBabel.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\FlaskBabel.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1581088622.4870212 Flask-BabelEx-0.9.4/flask_babelex/0000755000175000017500000000000000000000000017103 5ustar00sergeserge00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/flask_babelex/__init__.py0000644000175000017500000005422400000000000021223 0ustar00sergeserge00000000000000# -*- coding: utf-8 -*- """ flask_babelex ~~~~~~~~~~~~~ Implements i18n/l10n support for Flask applications based on Babel. :copyright: (c) 2013 by Serge S. Koval, Armin Ronacher and contributors. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import os # this is a workaround for a snow leopard bug that babel does not # work around :) if os.environ.get('LC_CTYPE', '').lower() == 'utf-8': os.environ['LC_CTYPE'] = 'en_US.utf-8' from datetime import datetime from flask import _request_ctx_stack from babel import dates, numbers, support, Locale from babel.support import NullTranslations from werkzeug.datastructures import ImmutableDict try: from pytz.gae import pytz except ImportError: from pytz import timezone, UTC else: timezone = pytz.timezone UTC = pytz.UTC from flask_babelex._compat import string_types _DEFAULT_LOCALE = Locale.parse('en') class Babel(object): """Central controller class that can be used to configure how Flask-Babel behaves. Each application that wants to use Flask-Babel has to create, or run :meth:`init_app` on, an instance of this class after the configuration was initialized. """ default_date_formats = ImmutableDict({ 'time': 'medium', 'date': 'medium', 'datetime': 'medium', 'time.short': None, 'time.medium': None, 'time.full': None, 'time.long': None, 'date.short': None, 'date.medium': None, 'date.full': None, 'date.long': None, 'datetime.short': None, 'datetime.medium': None, 'datetime.full': None, 'datetime.long': None, }) def __init__(self, app=None, default_locale='en', default_timezone='UTC', date_formats=None, configure_jinja=True, default_domain=None): self._default_locale = default_locale self._default_timezone = default_timezone self._date_formats = date_formats self._configure_jinja = configure_jinja self.app = app self._locale_cache = dict() if default_domain is None: self._default_domain = Domain() else: self._default_domain = default_domain self.locale_selector_func = None self.timezone_selector_func = None if app is not None: self.init_app(app) def init_app(self, app): """Set up this instance for use with *app*, if no app was passed to the constructor. """ self.app = app app.babel_instance = self if not hasattr(app, 'extensions'): app.extensions = {} app.extensions['babel'] = self app.config.setdefault('BABEL_DEFAULT_LOCALE', self._default_locale) app.config.setdefault('BABEL_DEFAULT_TIMEZONE', self._default_timezone) if self._date_formats is None: self._date_formats = self.default_date_formats.copy() #: a mapping of Babel datetime format strings that can be modified #: to change the defaults. If you invoke :func:`format_datetime` #: and do not provide any format string Flask-Babel will do the #: following things: #: #: 1. look up ``date_formats['datetime']``. By default ``'medium'`` #: is returned to enforce medium length datetime formats. #: 2. ``date_formats['datetime.medium'] (if ``'medium'`` was #: returned in step one) is looked up. If the return value #: is anything but `None` this is used as new format string. #: otherwise the default for that language is used. self.date_formats = self._date_formats if self._configure_jinja: app.jinja_env.filters.update( datetimeformat=format_datetime, dateformat=format_date, timeformat=format_time, timedeltaformat=format_timedelta, numberformat=format_number, decimalformat=format_decimal, currencyformat=format_currency, percentformat=format_percent, scientificformat=format_scientific, ) app.jinja_env.add_extension('jinja2.ext.i18n') app.jinja_env.install_gettext_callables( lambda x: get_domain().get_translations().ugettext(x), lambda s, p, n: get_domain().get_translations().ungettext(s, p, n), newstyle=True ) def localeselector(self, f): """Registers a callback function for locale selection. The default behaves as if a function was registered that returns `None` all the time. If `None` is returned, the locale falls back to the one from the configuration. This has to return the locale as string (eg: ``'de_AT'``, ''`en_US`'') """ assert self.locale_selector_func is None, \ 'a localeselector function is already registered' self.locale_selector_func = f return f def timezoneselector(self, f): """Registers a callback function for timezone selection. The default behaves as if a function was registered that returns `None` all the time. If `None` is returned, the timezone falls back to the one from the configuration. This has to return the timezone as string (eg: ``'Europe/Vienna'``) """ assert self.timezone_selector_func is None, \ 'a timezoneselector function is already registered' self.timezone_selector_func = f return f def list_translations(self): """Returns a list of all the locales translations exist for. The list returned will be filled with actual locale objects and not just strings. .. versionadded:: 0.6 """ dirname = os.path.join(self.app.root_path, 'translations') if not os.path.isdir(dirname): return [] result = [] for folder in os.listdir(dirname): locale_dir = os.path.join(dirname, folder, 'LC_MESSAGES') if not os.path.isdir(locale_dir): continue if filter(lambda x: x.endswith('.mo'), os.listdir(locale_dir)): result.append(Locale.parse(folder)) if not result: result.append(Locale.parse(self._default_locale)) return result @property def default_locale(self): """The default locale from the configuration as instance of a `babel.Locale` object. """ return self.load_locale(self.app.config['BABEL_DEFAULT_LOCALE']) @property def default_timezone(self): """The default timezone from the configuration as instance of a `pytz.timezone` object. """ return timezone(self.app.config['BABEL_DEFAULT_TIMEZONE']) def load_locale(self, locale): """Load locale by name and cache it. Returns instance of a `babel.Locale` object. """ rv = self._locale_cache.get(locale) if rv is None: self._locale_cache[locale] = rv = Locale.parse(locale) return rv def get_locale(): """Returns the locale that should be used for this request as `babel.Locale` object. This returns `None` if used outside of a request. If flask-babel was not attached to the Flask application, will return 'en' locale. """ ctx = _request_ctx_stack.top if ctx is None: return None locale = getattr(ctx, 'babel_locale', None) if locale is None: babel = ctx.app.extensions.get('babel') if babel is None: locale = _DEFAULT_LOCALE else: if babel.locale_selector_func is not None: rv = babel.locale_selector_func() if rv is None: locale = babel.default_locale else: locale = babel.load_locale(rv) else: locale = babel.default_locale ctx.babel_locale = locale return locale def get_timezone(): """Returns the timezone that should be used for this request as `pytz.timezone` object. This returns `None` if used outside of a request. If flask-babel was not attached to application, will return UTC timezone object. """ ctx = _request_ctx_stack.top tzinfo = getattr(ctx, 'babel_tzinfo', None) if tzinfo is None: babel = ctx.app.extensions.get('babel') if babel is None: tzinfo = UTC else: if babel.timezone_selector_func is None: tzinfo = babel.default_timezone else: rv = babel.timezone_selector_func() if rv is None: tzinfo = babel.default_timezone else: if isinstance(rv, string_types): tzinfo = timezone(rv) else: tzinfo = rv ctx.babel_tzinfo = tzinfo return tzinfo def refresh(): """Refreshes the cached timezones and locale information. This can be used to switch a translation between a request and if you want the changes to take place immediately, not just with the next request:: user.timezone = request.form['timezone'] user.locale = request.form['locale'] refresh() flash(gettext('Language was changed')) Without that refresh, the :func:`~flask.flash` function would probably return English text and a now German page. """ ctx = _request_ctx_stack.top for key in 'babel_locale', 'babel_tzinfo': if hasattr(ctx, key): delattr(ctx, key) def _get_format(key, format): """A small helper for the datetime formatting functions. Looks up format defaults for different kinds. """ babel = _request_ctx_stack.top.app.extensions.get('babel') if babel is not None: formats = babel.date_formats else: formats = Babel.default_date_formats if format is None: format = formats[key] if format in ('short', 'medium', 'full', 'long'): rv = formats['%s.%s' % (key, format)] if rv is not None: format = rv return format def to_user_timezone(datetime): """Convert a datetime object to the user's timezone. This automatically happens on all date formatting unless rebasing is disabled. If you need to convert a :class:`datetime.datetime` object at any time to the user's timezone (as returned by :func:`get_timezone` this function can be used). """ if datetime.tzinfo is None: datetime = datetime.replace(tzinfo=UTC) tzinfo = get_timezone() return tzinfo.normalize(datetime.astimezone(tzinfo)) def to_utc(datetime): """Convert a datetime object to UTC and drop tzinfo. This is the opposite operation to :func:`to_user_timezone`. """ if datetime.tzinfo is None: datetime = get_timezone().localize(datetime) return datetime.astimezone(UTC).replace(tzinfo=None) def format_datetime(datetime=None, format=None, rebase=True): """Return a date formatted according to the given pattern. If no :class:`~datetime.datetime` object is passed, the current time is assumed. By default rebasing happens which causes the object to be converted to the users's timezone (as returned by :func:`to_user_timezone`). This function formats both date and time. The format parameter can either be ``'short'``, ``'medium'``, ``'long'`` or ``'full'`` (in which cause the language's default for that setting is used, or the default from the :attr:`Babel.date_formats` mapping is used) or a format string as documented by Babel. This function is also available in the template context as filter named `datetimeformat`. """ format = _get_format('datetime', format) return _date_format(dates.format_datetime, datetime, format, rebase) def format_date(date=None, format=None, rebase=True): """Return a date formatted according to the given pattern. If no :class:`~datetime.datetime` or :class:`~datetime.date` object is passed, the current time is assumed. By default rebasing happens which causes the object to be converted to the users's timezone (as returned by :func:`to_user_timezone`). This function only formats the date part of a :class:`~datetime.datetime` object. The format parameter can either be ``'short'``, ``'medium'``, ``'long'`` or ``'full'`` (in which cause the language's default for that setting is used, or the default from the :attr:`Babel.date_formats` mapping is used) or a format string as documented by Babel. This function is also available in the template context as filter named `dateformat`. """ if rebase and isinstance(date, datetime): date = to_user_timezone(date) format = _get_format('date', format) return _date_format(dates.format_date, date, format, rebase) def format_time(time=None, format=None, rebase=True): """Return a time formatted according to the given pattern. If no :class:`~datetime.datetime` object is passed, the current time is assumed. By default rebasing happens which causes the object to be converted to the users's timezone (as returned by :func:`to_user_timezone`). This function formats both date and time. The format parameter can either be ``'short'``, ``'medium'``, ``'long'`` or ``'full'`` (in which cause the language's default for that setting is used, or the default from the :attr:`Babel.date_formats` mapping is used) or a format string as documented by Babel. This function is also available in the template context as filter named `timeformat`. """ format = _get_format('time', format) return _date_format(dates.format_time, time, format, rebase) def format_timedelta(datetime_or_timedelta, granularity='second'): """Format the elapsed time from the given date to now or the given timedelta. This currently requires an unreleased development version of Babel. This function is also available in the template context as filter named `timedeltaformat`. """ if isinstance(datetime_or_timedelta, datetime): datetime_or_timedelta = datetime.utcnow() - datetime_or_timedelta return dates.format_timedelta(datetime_or_timedelta, granularity, locale=get_locale()) def _date_format(formatter, obj, format, rebase, **extra): """Internal helper that formats the date.""" locale = get_locale() extra = {} if formatter is not dates.format_date and rebase: extra['tzinfo'] = get_timezone() return formatter(obj, format, locale=locale, **extra) def format_number(number): """Return the given number formatted for the locale in request :param number: the number to format :return: the formatted number :rtype: unicode """ locale = get_locale() return numbers.format_number(number, locale=locale) def format_decimal(number, format=None): """Return the given decimal number formatted for the locale in request :param number: the number to format :param format: the format to use :return: the formatted number :rtype: unicode """ locale = get_locale() return numbers.format_decimal(number, format=format, locale=locale) def format_currency(number, currency, format=None): """Return the given number formatted for the locale in request :param number: the number to format :param currency: the currency code :param format: the format to use :return: the formatted number :rtype: unicode """ locale = get_locale() return numbers.format_currency( number, currency, format=format, locale=locale ) def format_percent(number, format=None): """Return formatted percent value for the locale in request :param number: the number to format :param format: the format to use :return: the formatted percent number :rtype: unicode """ locale = get_locale() return numbers.format_percent(number, format=format, locale=locale) def format_scientific(number, format=None): """Return value formatted in scientific notation for the locale in request :param number: the number to format :param format: the format to use :return: the formatted percent number :rtype: unicode """ locale = get_locale() return numbers.format_scientific(number, format=format, locale=locale) class Domain(object): """Localization domain. By default will use look for tranlations in Flask application directory and "messages" domain - all message catalogs should be called ``messages.mo``. """ def __init__(self, dirname=None, domain='messages'): self.dirname = dirname self.domain = domain self.cache = dict() def as_default(self): """Set this domain as default for the current request""" ctx = _request_ctx_stack.top if ctx is None: raise RuntimeError("No request context") ctx.babel_domain = self def get_translations_cache(self, ctx): """Returns dictionary-like object for translation caching""" return self.cache def get_translations_path(self, ctx): """Returns translations directory path. Override if you want to implement custom behavior. """ return self.dirname or os.path.join(ctx.app.root_path, 'translations') def get_translations(self): """Returns the correct gettext translations that should be used for this request. This will never fail and return a dummy translation object if used outside of the request or if a translation cannot be found. """ ctx = _request_ctx_stack.top if ctx is None: return NullTranslations() locale = get_locale() cache = self.get_translations_cache(ctx) translations = cache.get(str(locale)) if translations is None: dirname = self.get_translations_path(ctx) translations = support.Translations.load(dirname, locale, domain=self.domain) cache[str(locale)] = translations return translations def gettext(self, string, **variables): """Translates a string with the current locale and passes in the given keyword arguments as mapping to a string formatting string. :: gettext(u'Hello World!') gettext(u'Hello %(name)s!', name='World') """ t = self.get_translations() if variables: return t.ugettext(string) % variables else: return t.ugettext(string) def ngettext(self, singular, plural, num, **variables): """Translates a string with the current locale and passes in the given keyword arguments as mapping to a string formatting string. The `num` parameter is used to dispatch between singular and various plural forms of the message. It is available in the format string as ``%(num)d`` or ``%(num)s``. The source language should be English or a similar language which only has one plural form. :: ngettext(u'%(num)d Apple', u'%(num)d Apples', num=len(apples)) """ variables.setdefault('num', num) t = self.get_translations() return t.ungettext(singular, plural, num) % variables def pgettext(self, context, string, **variables): """Like :func:`gettext` but with a context. .. versionadded:: 0.7 """ t = self.get_translations() return t.upgettext(context, string) % variables def npgettext(self, context, singular, plural, num, **variables): """Like :func:`ngettext` but with a context. .. versionadded:: 0.7 """ variables.setdefault('num', num) t = self.get_translations() return t.unpgettext(context, singular, plural, num) % variables def lazy_gettext(self, string, **variables): """Like :func:`gettext` but the string returned is lazy which means it will be translated when it is used as an actual string. Example:: hello = lazy_gettext(u'Hello World') @app.route('/') def index(): return unicode(hello) """ from speaklater import make_lazy_string return make_lazy_string(self.gettext, string, **variables) def lazy_pgettext(self, context, string, **variables): """Like :func:`pgettext` but the string returned is lazy which means it will be translated when it is used as an actual string. .. versionadded:: 0.7 """ from speaklater import make_lazy_string return make_lazy_string(self.pgettext, context, string, **variables) # This is the domain that will be used if there is no request context (and thus no app) # or if the app isn't initialized for babel. Note that if there is no request context, # then the standard Domain will use NullTranslations domain = Domain() def get_domain(): """Return the correct translation domain that is used for this request. This will return the default domain (e.g. "messages" in /translations") if none is set for this request. """ ctx = _request_ctx_stack.top if ctx is None: return domain try: return ctx.babel_domain except AttributeError: pass babel = ctx.app.extensions.get('babel') if babel is not None: d = babel._default_domain else: d = domain ctx.babel_domain = d return d # Create shortcuts for the default Flask domain def gettext(*args, **kwargs): return get_domain().gettext(*args, **kwargs) _ = gettext def ngettext(*args, **kwargs): return get_domain().ngettext(*args, **kwargs) def pgettext(*args, **kwargs): return get_domain().pgettext(*args, **kwargs) def npgettext(*args, **kwargs): return get_domain().npgettext(*args, **kwargs) def lazy_gettext(*args, **kwargs): from speaklater import make_lazy_string return make_lazy_string(gettext, *args, **kwargs) def lazy_pgettext(*args, **kwargs): from speaklater import make_lazy_string return make_lazy_string(pgettext, *args, **kwargs) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/flask_babelex/_compat.py0000644000175000017500000000055200000000000021101 0ustar00sergeserge00000000000000# -*- coding: utf-8 -*- """ flask_babelex._compat ~~~~~~~~~~~~~~~~~~~~~ :copyright: (c) 2013 by Armin Ronacher, Daniel Neuhäuser. :license: BSD, see LICENSE for more details. """ import sys PY2 = sys.version_info[0] == 2 if PY2: text_type = unicode string_types = (str, unicode) else: text_type = str string_types = (str, ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1581088622.4903545 Flask-BabelEx-0.9.4/setup.cfg0000644000175000017500000000012300000000000016136 0ustar00sergeserge00000000000000[upload_docs] upload-dir = docs/_build/html [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088561.0 Flask-BabelEx-0.9.4/setup.py0000644000175000017500000000326200000000000016036 0ustar00sergeserge00000000000000""" Flask-BabelEx ------------- Adds i18n/l10n support to Flask applications with the help of the `Babel`_ library. This is fork of official Flask-Babel extension with following features: 1. It is possible to use multiple language catalogs in one Flask application; 2. Localization domains: your extension can package localization file(s) and use them if necessary; 3. Does not reload localizations for each request. Links ````` * `documentation `_ * `development version `_ * `original Flask-Babel extension `_. .. _Babel: http://babel.edgewall.org/ """ from setuptools import setup setup( name='Flask-BabelEx', version='0.9.4', url='http://github.com/mrjoes/flask-babelex', license='BSD', author='Serge S. Koval', author_email='serge.koval+github@gmail.com', description='Adds i18n/l10n support to Flask applications', long_description=__doc__, packages=['flask_babelex'], zip_safe=False, platforms='any', install_requires=[ 'Flask', 'Babel>=1.0', 'speaklater>=1.2', 'Jinja2>=2.5' ], classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Software Development :: Libraries :: Python Modules' ] ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1581088622.4903545 Flask-BabelEx-0.9.4/tests/0000755000175000017500000000000000000000000015463 5ustar00sergeserge00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/tests/babel.cfg0000644000175000017500000000014100000000000017205 0ustar00sergeserge00000000000000[python: **.py] [jinja2: **/templates/**.html] extensions=jinja2.ext.autoescape,jinja2.ext.with_ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/tests/tests.py0000644000175000017500000002061200000000000017200 0ustar00sergeserge00000000000000# -*- coding: utf-8 -*- from __future__ import with_statement import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) import unittest from decimal import Decimal import flask from datetime import datetime import flask_babelex as babel from flask_babelex import gettext, ngettext, lazy_gettext from flask_babelex._compat import text_type class DateFormattingTestCase(unittest.TestCase): def test_basics(self): app = flask.Flask(__name__) b = babel.Babel(app) d = datetime(2010, 4, 12, 13, 46) with app.test_request_context(): assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM' assert babel.format_date(d) == 'Apr 12, 2010' assert babel.format_time(d) == '1:46:00 PM' with app.test_request_context(): app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Vienna' assert babel.format_datetime(d) == 'Apr 12, 2010, 3:46:00 PM' assert babel.format_date(d) == 'Apr 12, 2010' assert babel.format_time(d) == '3:46:00 PM' with app.test_request_context(): app.config['BABEL_DEFAULT_LOCALE'] = 'de_DE' assert babel.format_datetime(d, 'long') == \ '12. April 2010 15:46:00 MESZ' def test_init_app(self): b = babel.Babel() app = flask.Flask(__name__) b.init_app(app) d = datetime(2010, 4, 12, 13, 46) with app.test_request_context(): assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM' assert babel.format_date(d) == 'Apr 12, 2010' assert babel.format_time(d) == '1:46:00 PM' with app.test_request_context(): app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Vienna' assert babel.format_datetime(d) == 'Apr 12, 2010, 3:46:00 PM' assert babel.format_date(d) == 'Apr 12, 2010' assert babel.format_time(d) == '3:46:00 PM' with app.test_request_context(): app.config['BABEL_DEFAULT_LOCALE'] = 'de_DE' assert babel.format_datetime(d, 'long') == \ '12. April 2010 15:46:00 MESZ' def test_custom_formats(self): app = flask.Flask(__name__) app.config.update( BABEL_DEFAULT_LOCALE='en_US', BABEL_DEFAULT_TIMEZONE='Pacific/Johnston' ) b = babel.Babel(app) b.date_formats['datetime'] = 'long' b.date_formats['datetime.long'] = 'MMMM d, yyyy h:mm:ss a' d = datetime(2010, 4, 12, 13, 46) with app.test_request_context(): assert babel.format_datetime(d) == 'April 12, 2010 3:46:00 AM' def test_custom_locale_selector(self): app = flask.Flask(__name__) b = babel.Babel(app) d = datetime(2010, 4, 12, 13, 46) the_timezone = 'UTC' the_locale = 'en_US' @b.localeselector def select_locale(): return the_locale @b.timezoneselector def select_timezone(): return the_timezone with app.test_request_context(): assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM' the_locale = 'de_DE' the_timezone = 'Europe/Vienna' with app.test_request_context(): assert babel.format_datetime(d) == '12.04.2010 15:46:00' def test_refreshing(self): app = flask.Flask(__name__) b = babel.Babel(app) d = datetime(2010, 4, 12, 13, 46) with app.test_request_context(): assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM' app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Vienna' babel.refresh() assert babel.format_datetime(d) == 'Apr 12, 2010, 3:46:00 PM' def test_non_initialized(self): app = flask.Flask(__name__) d = datetime(2010, 4, 12, 13, 46) with app.test_request_context(): assert babel.format_datetime(d) == 'Apr 12, 2010, 1:46:00 PM' class NumberFormattingTestCase(unittest.TestCase): def test_basics(self): app = flask.Flask(__name__) b = babel.Babel(app) n = 1099 with app.test_request_context(): assert babel.format_number(n) == u'1,099' assert babel.format_decimal(Decimal('1010.99')) == u'1,010.99' assert babel.format_currency(n, 'USD') == '$1,099.00' assert babel.format_percent(0.19) == '19%' assert babel.format_scientific(10000) == u'1E4' class GettextTestCase(unittest.TestCase): def test_basics(self): app = flask.Flask(__name__) b = babel.Babel(app, default_locale='de_DE') with app.test_request_context(): assert gettext(u'Hello %(name)s!', name='Peter') == 'Hallo Peter!' assert ngettext(u'%(num)s Apple', u'%(num)s Apples', 3) == u'3 Äpfel' assert ngettext(u'%(num)s Apple', u'%(num)s Apples', 1) == u'1 Apfel' def test_template_basics(self): app = flask.Flask(__name__) b = babel.Babel(app, default_locale='de_DE') t = lambda x: flask.render_template_string('{{ %s }}' % x) with app.test_request_context(): assert t("gettext('Hello %(name)s!', name='Peter')") == 'Hallo Peter!' assert t("ngettext('%(num)s Apple', '%(num)s Apples', 3)") == u'3 Äpfel' assert t("ngettext('%(num)s Apple', '%(num)s Apples', 1)") == u'1 Apfel' assert flask.render_template_string(''' {% trans %}Hello {{ name }}!{% endtrans %} ''', name='Peter').strip() == 'Hallo Peter!' assert flask.render_template_string(''' {% trans num=3 %}{{ num }} Apple {%- pluralize %}{{ num }} Apples{% endtrans %} ''', name='Peter').strip() == u'3 Äpfel' def test_lazy_gettext(self): app = flask.Flask(__name__) b = babel.Babel(app, default_locale='de_DE') yes = lazy_gettext(u'Yes') with app.test_request_context(): assert text_type(yes) == 'Ja' app.config['BABEL_DEFAULT_LOCALE'] = 'en_US' with app.test_request_context(): assert text_type(yes) == 'Yes' def test_lazy_gettext_defaultdomain(self): app = flask.Flask(__name__) domain = babel.Domain(domain='test') b = babel.Babel(app, default_locale='de_DE', default_domain=domain) first = lazy_gettext('first') with app.test_request_context(): assert text_type(first) == 'erste' app.config['BABEL_DEFAULT_LOCALE'] = 'en_US' with app.test_request_context(): assert text_type(first) == 'first' def test_list_translations(self): app = flask.Flask(__name__) b = babel.Babel(app, default_locale='de_DE') translations = b.list_translations() assert len(translations) == 1 assert str(translations[0]) == 'de' def test_domain(self): app = flask.Flask(__name__) b = babel.Babel(app, default_locale='de_DE') domain = babel.Domain(domain='test') with app.test_request_context(): assert domain.gettext('first') == 'erste' assert babel.gettext('first') == 'first' def test_as_default(self): app = flask.Flask(__name__) b = babel.Babel(app, default_locale='de_DE') domain = babel.Domain(domain='test') with app.test_request_context(): assert babel.gettext('first') == 'first' domain.as_default() assert babel.gettext('first') == 'erste' def test_default_domain(self): app = flask.Flask(__name__) domain = babel.Domain(domain='test') b = babel.Babel(app, default_locale='de_DE', default_domain=domain) with app.test_request_context(): assert babel.gettext('first') == 'erste' def test_non_initialized(self): app = flask.Flask(__name__) with app.test_request_context(): assert babel.gettext('first') == 'first' def test_multiple_apps(self): app1 = flask.Flask(__name__) b1 = babel.Babel(app1, default_locale='de_DE') app2 = flask.Flask(__name__) b2 = babel.Babel(app2, default_locale='de_DE') with app1.test_request_context(): assert babel.gettext('Yes') == 'Ja' assert 'de_DE' in b1._default_domain.cache with app2.test_request_context(): assert 'de_DE' not in b2._default_domain.cache if __name__ == '__main__': unittest.main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1581088622.4903545 Flask-BabelEx-0.9.4/tests/translations/0000755000175000017500000000000000000000000020204 5ustar00sergeserge00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1581088622.4870212 Flask-BabelEx-0.9.4/tests/translations/de/0000755000175000017500000000000000000000000020574 5ustar00sergeserge00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1581088622.4903545 Flask-BabelEx-0.9.4/tests/translations/de/LC_MESSAGES/0000755000175000017500000000000000000000000022361 5ustar00sergeserge00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/tests/translations/de/LC_MESSAGES/messages.mo0000644000175000017500000000112200000000000024521 0ustar00sergeserge00000000000000<\]z"?O%(num)s Apple%(num)s ApplesHello %(name)s!YesProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2010-05-29 17:00+0200 PO-Revision-Date: 2010-05-30 13:02+0200 Last-Translator: Armin Ronacher Language-Team: de Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 0.9.5 %(num)s Apfel%(num)s ÄpfelHallo %(name)s!Ja././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/tests/translations/de/LC_MESSAGES/messages.po0000644000175000017500000000163300000000000024533 0ustar00sergeserge00000000000000# German translations for PROJECT. # Copyright (C) 2010 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2010. # msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2010-05-29 17:00+0200\n" "PO-Revision-Date: 2010-05-30 12:56+0200\n" "Last-Translator: Armin Ronacher \n" "Language-Team: de \n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.5\n" #: tests.py:94 #, python-format msgid "Hello %(name)s!" msgstr "Hallo %(name)s!" #: tests.py:95 tests.py:96 #, python-format msgid "%(num)s Apple" msgid_plural "%(num)s Apples" msgstr[0] "%(num)s Apfel" msgstr[1] "%(num)s Äpfel" #: tests.py:119 msgid "Yes" msgstr "Ja" ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/tests/translations/de/LC_MESSAGES/test.mo0000644000175000017500000000071600000000000023701 0ustar00sergeserge00000000000000,<PQpWfirstProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2010-05-30 12:56+0200 PO-Revision-Date: 2012-04-11 15:18+0200 Last-Translator: Serge S. Koval Language-Team: LANGUAGE MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 0.9.5 erste././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/tests/translations/de/LC_MESSAGES/test.po0000644000175000017500000000124300000000000023700 0ustar00sergeserge00000000000000# Translations template for PROJECT. # Copyright (C) 2010 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2010. # msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2010-05-30 12:56+0200\n" "PO-Revision-Date: 2012-04-11 15:18+0200\n" "Last-Translator: Serge S. Koval \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.5\n" #: tests.py:94 #, python-format msgid "first" msgstr "erste" ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/tests/translations/messages.pot0000644000175000017500000000147700000000000022550 0ustar00sergeserge00000000000000# Translations template for PROJECT. # Copyright (C) 2010 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2010. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2010-05-30 12:56+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.5\n" #: tests.py:94 #, python-format msgid "Hello %(name)s!" msgstr "" #: tests.py:95 tests.py:96 #, python-format msgid "%(num)s Apple" msgid_plural "%(num)s Apples" msgstr[0] "" msgstr[1] "" #: tests.py:119 msgid "Yes" msgstr "" ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1581088451.0 Flask-BabelEx-0.9.4/tests/translations/test.pot0000644000175000017500000000122200000000000021704 0ustar00sergeserge00000000000000# Translations template for PROJECT. # Copyright (C) 2010 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2010. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2010-05-30 12:56+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.5\n" #: tests.py:94 #, python-format msgid "First" msgstr ""