Flask-Babel-0.11.2/0000755000076500000240000000000013075413505014123 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/docs/0000755000076500000240000000000013075413505015053 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/docs/_static/0000755000076500000240000000000013075413505016501 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/docs/_static/flask-babel.png0000644000076500000240000005005513075412770021362 0ustar tylerstaff00000000000000PNG  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} Flask-Babel-0.11.2/docs/index.rst0000644000076500000240000002351713075412770016727 0ustar tylerstaff00000000000000Flask-Babel =========== .. module:: flask.ext.babel Flask-Babel 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-Babel or alternatively if you have pip installed:: $ pip install Flask-Babel Please note that Flask-Babel 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.ext.babel 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 the following 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. `BABEL_TRANSLATION_DIRECTORIES` A semi-colon (``;``) separated string of absolute and relative (to the app root) paths to translation folders. Defaults to ``translations``. `BABEL_DOMAIN` The message domain used by the application. Defaults to ``messages``. =============================== ============================================= 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.ext.babel 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.ext.babel 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 up, 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.ext.babel 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.ext.babel import lazy_gettext class MyForm(formlibrary.FormBase): success_message = lazy_gettext(u'The form was successfully saved.') So how does Flask-Babel 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-Babel 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. 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-Babel. Configuration ````````````` .. autoclass:: Babel :members: Context Functions ````````````````` .. autofunction:: get_translations .. autofunction:: get_locale .. autofunction:: get_timezone 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 .. autofunction:: force_locale .. _Flask: http://flask.pocoo.org/ .. _babel: http://babel.edgewall.org/ .. _pytz: http://pytz.sourceforge.net/ .. _speaklater: http://pypi.python.org/pypi/speaklater Flask-Babel-0.11.2/docs/make.bat0000644000076500000240000001002213075412770016456 0ustar tylerstaff00000000000000@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 Flask-Babel-0.11.2/docs/Makefile0000644000076500000240000001100413075412770016512 0ustar tylerstaff00000000000000# 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." Flask-Babel-0.11.2/flask_babel/0000755000076500000240000000000013075413505016350 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/flask_babel/__init__.py0000644000076500000240000005301013075412770020463 0ustar tylerstaff00000000000000# -*- coding: utf-8 -*- """ flaskext.babel ~~~~~~~~~~~~~~ Implements i18n/l10n support for Flask applications based on Babel. :copyright: (c) 2013 by Armin Ronacher, Daniel Neuhäuser. :license: BSD, see LICENSE for more details. """ from __future__ import absolute_import import os from datetime import datetime from contextlib import contextmanager from flask import current_app, request from flask.ctx import has_request_context from babel import dates, numbers, support, Locale from werkzeug import ImmutableDict try: from pytz.gae import pytz except ImportError: from pytz import timezone, UTC else: timezone = pytz.timezone UTC = pytz.UTC from flask_babel._compat import string_types from flask_babel.speaklater import LazyString 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', default_domain='messages', date_formats=None, configure_jinja=True): self._default_locale = default_locale self._default_timezone = default_timezone self._default_domain = default_domain self._date_formats = date_formats self._configure_jinja = configure_jinja self.app = app 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) app.config.setdefault('BABEL_DOMAIN', self._default_domain) 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_translations().ugettext(x), lambda s, p, n: 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 """ result = [] for dirname in self.translation_directories: if not os.path.isdir(dirname): continue 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 other translations are found, add the default locale. 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 Locale.parse(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']) @property def domain(self): """The message domain for the translations as a string. """ return self.app.config['BABEL_DOMAIN'] @property def translation_directories(self): directories = self.app.config.get( 'BABEL_TRANSLATION_DIRECTORIES', 'translations' ).split(';') for path in directories: if os.path.isabs(path): yield path else: yield os.path.join(self.app.root_path, path) def get_translations(): """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 = _get_current_context() if ctx is None: return support.NullTranslations() translations = getattr(ctx, 'babel_translations', None) if translations is None: translations = support.Translations() babel = current_app.extensions['babel'] for dirname in babel.translation_directories: catalog = support.Translations.load( dirname, [get_locale()], babel.domain ) translations.merge(catalog) # FIXME: Workaround for merge() being really, really stupid. It # does not copy _info, plural(), or any other instance variables # populated by GNUTranslations. We probably want to stop using # `support.Translations.merge` entirely. if hasattr(catalog, 'plural'): translations.plural = catalog.plural ctx.babel_translations = translations return translations 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. """ ctx = _get_current_context() if ctx is None: return None locale = getattr(ctx, 'babel_locale', None) if locale is None: babel = current_app.extensions['babel'] if babel.locale_selector_func is None: locale = babel.default_locale else: rv = babel.locale_selector_func() if rv is None: locale = babel.default_locale else: locale = Locale.parse(rv) 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. """ ctx = _get_current_context() tzinfo = getattr(ctx, 'babel_tzinfo', None) if tzinfo is None: babel = current_app.extensions['babel'] 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 = _get_current_context() for key in 'babel_locale', 'babel_tzinfo', 'babel_translations': if hasattr(ctx, key): delattr(ctx, key) @contextmanager def force_locale(locale): """Temporarily overrides the currently selected locale. Sometimes it is useful to switch the current locale to different one, do some tasks and then revert back to the original one. For example, if the user uses German on the web site, but you want to send them an email in English, you can use this function as a context manager:: with force_locale('en_US'): send_email(gettext('Hello!'), ...) :param locale: The locale to temporary switch to (ex: 'en_US'). """ ctx = _get_current_context() if ctx is None: yield return babel = current_app.extensions['babel'] orig_locale_selector_func = babel.locale_selector_func orig_attrs = {} for key in ('babel_translations', 'babel_locale'): orig_attrs[key] = getattr(ctx, key, None) try: babel.locale_selector_func = lambda: locale for key in orig_attrs: setattr(ctx, key, None) yield finally: babel.locale_selector_func = orig_locale_selector_func for key, value in orig_attrs.items(): setattr(ctx, key, value) def _get_format(key, format): """A small helper for the datetime formatting functions. Looks up format defaults for different kinds. """ babel = current_app.extensions['babel'] if format is None: format = babel.date_formats[key] if format in ('short', 'medium', 'full', 'long'): rv = babel.date_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', add_direction=False, threshold=0.85): """Format the elapsed time from the given date to now or the given timedelta. 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, threshold=threshold, add_direction=add_direction, 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, currency_digits=True, format_type='standard'): """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 :param currency_digits: use the currency’s number of decimal digits [default: True] :param format_type: the currency format type to use [default: standard] :return: the formatted number :rtype: unicode """ locale = get_locale() return numbers.format_currency( number, currency, format=format, locale=locale, currency_digits=currency_digits, format_type=format_type ) 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) def gettext(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 = get_translations() if t is None: return string if not variables else string % variables s = t.ugettext(string) return s if not variables else s % variables _ = gettext def ngettext(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 = get_translations() if t is None: s = singular if num == 1 else plural return s if not variables else s % variables s = t.ungettext(singular, plural, num) return s if not variables else s % variables def pgettext(context, string, **variables): """Like :func:`gettext` but with a context. .. versionadded:: 0.7 """ t = get_translations() if t is None: return string if not variables else string % variables s = t.upgettext(context, string) return s if not variables else s % variables def npgettext(context, singular, plural, num, **variables): """Like :func:`ngettext` but with a context. .. versionadded:: 0.7 """ variables.setdefault('num', num) t = get_translations() if t is None: s = singular if num == 1 else plural return s if not variables else s % variables s = t.unpgettext(context, singular, plural, num) return s if not variables else s % variables def lazy_gettext(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) """ return LazyString(gettext, string, **variables) def lazy_pgettext(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 """ return LazyString(pgettext, context, string, **variables) def _get_current_context(): if has_request_context(): return request if current_app: return current_app Flask-Babel-0.11.2/flask_babel/_compat.py0000644000076500000240000000055613075412770020355 0ustar tylerstaff00000000000000# -*- coding: utf-8 -*- """ flask.ext.babel._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, ) Flask-Babel-0.11.2/flask_babel/speaklater.py0000644000076500000240000000350413075412770021062 0ustar tylerstaff00000000000000# -*- coding: utf-8 -*- from flask_babel._compat import text_type class LazyString(object): def __init__(self, func, *args, **kwargs): self._func = func self._args = args self._kwargs = kwargs def __getattr__(self, attr): if attr == "__setstate__": raise AttributeError(attr) string = text_type(self) if hasattr(string, attr): return getattr(string, attr) raise AttributeError(attr) def __repr__(self): return "l'{0}'".format(text_type(self)) def __str__(self): return text_type(self._func(*self._args, **self._kwargs)) def __len__(self): return len(text_type(self)) def __getitem__(self, key): return text_type(self)[key] def __iter__(self): return iter(text_type(self)) def __contains__(self, item): return item in text_type(self) def __add__(self, other): return text_type(self) + other def __radd__(self, other): return other + text_type(self) def __mul__(self, other): return text_type(self) * other def __rmul__(self, other): return other * text_type(self) def __lt__(self, other): return text_type(self) < other def __le__(self, other): return text_type(self) <= other def __eq__(self, other): return text_type(self) == other def __ne__(self, other): return text_type(self) != other def __gt__(self, other): return text_type(self) > other def __ge__(self, other): return text_type(self) >= other def __html__(self): return text_type(self) def __hash__(self): return hash(text_type(self)) def __mod__(self, other): return text_type(self) % other def __rmod__(self, other): return other + text_type(self)Flask-Babel-0.11.2/Flask_Babel.egg-info/0000755000076500000240000000000013075413505017742 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/Flask_Babel.egg-info/dependency_links.txt0000644000076500000240000000000113075413505024010 0ustar tylerstaff00000000000000 Flask-Babel-0.11.2/Flask_Babel.egg-info/not-zip-safe0000644000076500000240000000000113075413505022170 0ustar tylerstaff00000000000000 Flask-Babel-0.11.2/Flask_Babel.egg-info/PKG-INFO0000644000076500000240000000223313075413505021037 0ustar tylerstaff00000000000000Metadata-Version: 1.1 Name: Flask-Babel Version: 0.11.2 Summary: Adds i18n/l10n support to Flask applications Home-page: http://github.com/python-babel/flask-babel Author: Armin Ronacher Author-email: armin.ronacher@active-4.com License: BSD Description: Flask-Babel ----------- Adds i18n/l10n support to Flask applications with the help of the `Babel`_ library. Links ````` * `documentation `_ * `development version `_ .. _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 Flask-Babel-0.11.2/Flask_Babel.egg-info/requires.txt0000644000076500000240000000003513075413505022340 0ustar tylerstaff00000000000000Flask Babel>=2.3 Jinja2>=2.5 Flask-Babel-0.11.2/Flask_Babel.egg-info/SOURCES.txt0000644000076500000240000000156213075413505021632 0ustar tylerstaff00000000000000LICENSE MANIFEST.in Makefile setup.cfg setup.py Flask_Babel.egg-info/PKG-INFO Flask_Babel.egg-info/SOURCES.txt Flask_Babel.egg-info/dependency_links.txt Flask_Babel.egg-info/not-zip-safe Flask_Babel.egg-info/requires.txt Flask_Babel.egg-info/top_level.txt docs/Makefile docs/conf.py docs/index.rst docs/make.bat docs/_static/flask-babel.png flask_babel/__init__.py flask_babel/_compat.py flask_babel/speaklater.py tests/babel.cfg tests/tests.py tests/renamed_translations/messages.pot tests/renamed_translations/de/LC_MESSAGES/messages.mo tests/renamed_translations/de/LC_MESSAGES/messages.po tests/translations/messages.pot tests/translations/de/LC_MESSAGES/messages.mo tests/translations/de/LC_MESSAGES/messages.po tests/translations_different_domain/myapp.pot tests/translations_different_domain/de/LC_MESSAGES/myapp.mo tests/translations_different_domain/de/LC_MESSAGES/myapp.poFlask-Babel-0.11.2/Flask_Babel.egg-info/top_level.txt0000644000076500000240000000001413075413505022467 0ustar tylerstaff00000000000000flask_babel Flask-Babel-0.11.2/LICENSE0000644000076500000240000000266113075412770015140 0ustar tylerstaff00000000000000Copyright (c) 2010 by Armin Ronacher. 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. Flask-Babel-0.11.2/Makefile0000644000076500000240000000056413075412770015573 0ustar tylerstaff00000000000000.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 Flask-Babel-0.11.2/MANIFEST.in0000644000076500000240000000035413075412770015666 0ustar tylerstaff00000000000000include 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 Flask-Babel-0.11.2/PKG-INFO0000644000076500000240000000223313075413505015220 0ustar tylerstaff00000000000000Metadata-Version: 1.1 Name: Flask-Babel Version: 0.11.2 Summary: Adds i18n/l10n support to Flask applications Home-page: http://github.com/python-babel/flask-babel Author: Armin Ronacher Author-email: armin.ronacher@active-4.com License: BSD Description: Flask-Babel ----------- Adds i18n/l10n support to Flask applications with the help of the `Babel`_ library. Links ````` * `documentation `_ * `development version `_ .. _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 Flask-Babel-0.11.2/setup.cfg0000644000076500000240000000017413075413505015746 0ustar tylerstaff00000000000000[upload_docs] upload-dir = docs/_build/html [metadata] description-file = README.md [egg_info] tag_build = tag_date = 0 Flask-Babel-0.11.2/setup.py0000644000076500000240000000241613075413275015644 0ustar tylerstaff00000000000000""" Flask-Babel ----------- Adds i18n/l10n support to Flask applications with the help of the `Babel`_ library. Links ````` * `documentation `_ * `development version `_ .. _Babel: http://babel.edgewall.org/ """ from setuptools import setup setup( name='Flask-Babel', version='0.11.2', url='http://github.com/python-babel/flask-babel', license='BSD', author='Armin Ronacher', author_email='armin.ronacher@active-4.com', description='Adds i18n/l10n support to Flask applications', long_description=__doc__, packages=['flask_babel'], zip_safe=False, platforms='any', install_requires=[ 'Flask', 'Babel>=2.3', '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' ] ) Flask-Babel-0.11.2/tests/0000755000076500000240000000000013075413505015265 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/tests/babel.cfg0000644000076500000240000000014113075412770017012 0ustar tylerstaff00000000000000[python: **.py] [jinja2: **/templates/**.html] extensions=jinja2.ext.autoescape,jinja2.ext.with_ Flask-Babel-0.11.2/tests/renamed_translations/0000755000076500000240000000000013075413505021501 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/tests/renamed_translations/de/0000755000076500000240000000000013075413505022071 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/tests/renamed_translations/de/LC_MESSAGES/0000755000076500000240000000000013075413505023656 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/tests/renamed_translations/de/LC_MESSAGES/messages.mo0000644000076500000240000000112213075412770026021 0ustar tylerstaff00000000000000<\]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!JaFlask-Babel-0.11.2/tests/renamed_translations/de/LC_MESSAGES/messages.po0000644000076500000240000000163313075412770026033 0ustar tylerstaff00000000000000# 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" Flask-Babel-0.11.2/tests/renamed_translations/messages.pot0000644000076500000240000000147713075412770024050 0ustar tylerstaff00000000000000# 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 "" Flask-Babel-0.11.2/tests/tests.py0000644000076500000240000002307313075412770017011 0ustar tylerstaff00000000000000# -*- coding: utf-8 -*- from __future__ import with_statement import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) import pickle import unittest from decimal import Decimal import flask from datetime import datetime, timedelta import flask_babel as babel from flask_babel import gettext, ngettext, lazy_gettext, get_translations from babel.support import NullTranslations from flask_babel._compat import text_type class IntegrationTestCase(unittest.TestCase): def test_no_request_context(self): b = babel.Babel() app = flask.Flask(__name__) b.init_app(app) with app.app_context(): assert isinstance(get_translations(), NullTranslations) def test_multiple_directories(self): """ Ensure we can load translations from multiple directories. """ b = babel.Babel() app = flask.Flask(__name__) app.config.update({ 'BABEL_TRANSLATION_DIRECTORIES': ';'.join(( 'translations', 'renamed_translations' )), 'BABEL_DEFAULT_LOCALE': 'de_DE' }) b.init_app(app) with app.test_request_context(): translations = b.list_translations() assert(len(translations) == 2) assert(str(translations[0]) == 'de') assert(str(translations[1]) == 'de') assert gettext( u'Hello %(name)s!', name='Peter' ) == 'Hallo Peter!' def test_different_domain(self): """ Ensure we can load translations from multiple directories. """ b = babel.Babel() app = flask.Flask(__name__) app.config.update({ 'BABEL_TRANSLATION_DIRECTORIES': 'translations_different_domain', 'BABEL_DEFAULT_LOCALE': 'de_DE', 'BABEL_DOMAIN': 'myapp' }) b.init_app(app) with app.test_request_context(): translations = b.list_translations() assert(len(translations) == 1) assert(str(translations[0]) == 'de') assert gettext(u'Good bye') == 'Auf Wiedersehen' def test_lazy_old_style_formatting(self): lazy_string = lazy_gettext(u'Hello %(name)s') assert lazy_string % {u'name': u'test'} == u'Hello test' lazy_string = lazy_gettext(u'test') assert u'Hello %s' % lazy_string == u'Hello test' def test_lazy_pickling(self): lazy_string = lazy_gettext(u'Foo') pickled = pickle.dumps(lazy_string) unpickled = pickle.loads(pickled) assert unpickled == lazy_string class DateFormattingTestCase(unittest.TestCase): def test_basics(self): app = flask.Flask(__name__) babel.Babel(app) d = datetime(2010, 4, 12, 13, 46) delta = timedelta(days=6) 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' assert babel.format_timedelta(delta) == '1 week' assert babel.format_timedelta(delta, threshold=1) == '6 days' 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 um 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 um 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__) 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_force_locale(self): app = flask.Flask(__name__) b = babel.Babel(app) @b.localeselector def select_locale(): return 'de_DE' with app.test_request_context(): assert str(babel.get_locale()) == 'de_DE' with babel.force_locale('en_US'): assert str(babel.get_locale()) == 'en_US' assert str(babel.get_locale()) == 'de_DE' class NumberFormattingTestCase(unittest.TestCase): def test_basics(self): app = flask.Flask(__name__) 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__) 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__) 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')") == \ u'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__) babel.Babel(app, default_locale='de_DE') yes = lazy_gettext(u'Yes') with app.test_request_context(): assert text_type(yes) == 'Ja' assert yes.__html__() == 'Ja' app.config['BABEL_DEFAULT_LOCALE'] = 'en_US' with app.test_request_context(): assert text_type(yes) == 'Yes' assert yes.__html__() == 'Yes' 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_no_formatting(self): """ Ensure we don't format strings unless a variable is passed. """ app = flask.Flask(__name__) babel.Babel(app) with app.test_request_context(): assert gettext(u'Test %s') == u'Test %s' assert gettext(u'Test %(name)s', name=u'test') == u'Test test' assert gettext(u'Test %s') % 'test' == u'Test test' if __name__ == '__main__': unittest.main() Flask-Babel-0.11.2/tests/translations/0000755000076500000240000000000013075413505020006 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/tests/translations/de/0000755000076500000240000000000013075413505020376 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/tests/translations/de/LC_MESSAGES/0000755000076500000240000000000013075413505022163 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/tests/translations/de/LC_MESSAGES/messages.mo0000644000076500000240000000112213075412770024326 0ustar tylerstaff00000000000000<\]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!JaFlask-Babel-0.11.2/tests/translations/de/LC_MESSAGES/messages.po0000644000076500000240000000163313075412770024340 0ustar tylerstaff00000000000000# 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" Flask-Babel-0.11.2/tests/translations/messages.pot0000644000076500000240000000147713075412770022355 0ustar tylerstaff00000000000000# 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 "" Flask-Babel-0.11.2/tests/translations_different_domain/0000755000076500000240000000000013075413505023363 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/tests/translations_different_domain/de/0000755000076500000240000000000013075413505023753 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/tests/translations_different_domain/de/LC_MESSAGES/0000755000076500000240000000000013075413505025540 5ustar tylerstaff00000000000000Flask-Babel-0.11.2/tests/translations_different_domain/de/LC_MESSAGES/myapp.mo0000644000076500000240000000121013075412770027220 0ustar tylerstaff00000000000000DlmHeu%(num)s Apple%(num)s ApplesGood byeHello %(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 12:56+0200 Last-Translator: Armin Ronacher Language: de 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 2.3.4 %(num)s Apfel%(num)s ÄpfelAuf WiedersehenHallo %(name)s!JaFlask-Babel-0.11.2/tests/translations_different_domain/de/LC_MESSAGES/myapp.po0000644000076500000240000000170513075412770027234 0ustar tylerstaff00000000000000# 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" msgid "Good bye" msgstr "Auf Wiedersehen" Flask-Babel-0.11.2/tests/translations_different_domain/myapp.pot0000644000076500000240000000153213075412770025241 0ustar tylerstaff00000000000000# 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 "" msgid "Good bye" msgstr ""