PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /usr/share/tcl8/8.5
Viewing File: /usr/share/tcl8/8.5/msgcat-1.6.1.tm
# msgcat.tcl -- # # This file defines various procedures which implement a # message catalog facility for Tcl programs. It should be # loaded with the command "package require msgcat". # # Copyright (c) 2010-2015 by Harald Oehlmann. # Copyright (c) 1998-2000 by Ajuba Solutions. # Copyright (c) 1998 by Mark Harrison. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. package require Tcl 8.5- # When the version number changes, be sure to update the pkgIndex.tcl file, # and the installation directory in the Makefiles. package provide msgcat 1.6.1 namespace eval msgcat { namespace export mc mcexists mcload mclocale mcmax mcmset mcpreferences mcset\ mcunknown mcflset mcflmset mcloadedlocales mcforgetpackage\ mcpackageconfig mcpackagelocale # Records the list of locales to search variable Loclist {} # List of currently loaded locales variable LoadedLocales {} # Records the locale of the currently sourced message catalogue file variable FileLocale # Configuration values per Package (e.g. client namespace). # The dict key is of the form "<option> <namespace>" and the value is the # configuration option. A nonexisting key is an unset option. variable PackageConfig [dict create mcfolder {} loadcmd {} changecmd {}\ unknowncmd {} loadedlocales {} loclist {}] # Records the mapping between source strings and translated strings. The # dict key is of the form "<namespace> <locale> <src>", where locale and # namespace should be themselves dict values and the value is # the translated string. variable Msgs [dict create] # Map of language codes used in Windows registry to those of ISO-639 if {[info sharedlibextension] eq ".dll"} { variable WinRegToISO639 [dict create {*}{ 01 ar 0401 ar_SA 0801 ar_IQ 0c01 ar_EG 1001 ar_LY 1401 ar_DZ 1801 ar_MA 1c01 ar_TN 2001 ar_OM 2401 ar_YE 2801 ar_SY 2c01 ar_JO 3001 ar_LB 3401 ar_KW 3801 ar_AE 3c01 ar_BH 4001 ar_QA 02 bg 0402 bg_BG 03 ca 0403 ca_ES 04 zh 0404 zh_TW 0804 zh_CN 0c04 zh_HK 1004 zh_SG 1404 zh_MO 05 cs 0405 cs_CZ 06 da 0406 da_DK 07 de 0407 de_DE 0807 de_CH 0c07 de_AT 1007 de_LU 1407 de_LI 08 el 0408 el_GR 09 en 0409 en_US 0809 en_GB 0c09 en_AU 1009 en_CA 1409 en_NZ 1809 en_IE 1c09 en_ZA 2009 en_JM 2409 en_GD 2809 en_BZ 2c09 en_TT 3009 en_ZW 3409 en_PH 0a es 040a es_ES 080a es_MX 0c0a es_ES@modern 100a es_GT 140a es_CR 180a es_PA 1c0a es_DO 200a es_VE 240a es_CO 280a es_PE 2c0a es_AR 300a es_EC 340a es_CL 380a es_UY 3c0a es_PY 400a es_BO 440a es_SV 480a es_HN 4c0a es_NI 500a es_PR 0b fi 040b fi_FI 0c fr 040c fr_FR 080c fr_BE 0c0c fr_CA 100c fr_CH 140c fr_LU 180c fr_MC 0d he 040d he_IL 0e hu 040e hu_HU 0f is 040f is_IS 10 it 0410 it_IT 0810 it_CH 11 ja 0411 ja_JP 12 ko 0412 ko_KR 13 nl 0413 nl_NL 0813 nl_BE 14 no 0414 no_NO 0814 nn_NO 15 pl 0415 pl_PL 16 pt 0416 pt_BR 0816 pt_PT 17 rm 0417 rm_CH 18 ro 0418 ro_RO 0818 ro_MO 19 ru 0819 ru_MO 1a hr 041a hr_HR 081a sr_YU 0c1a sr_YU@cyrillic 1b sk 041b sk_SK 1c sq 041c sq_AL 1d sv 041d sv_SE 081d sv_FI 1e th 041e th_TH 1f tr 041f tr_TR 20 ur 0420 ur_PK 0820 ur_IN 21 id 0421 id_ID 22 uk 0422 uk_UA 23 be 0423 be_BY 24 sl 0424 sl_SI 25 et 0425 et_EE 26 lv 0426 lv_LV 27 lt 0427 lt_LT 28 tg 0428 tg_TJ 29 fa 0429 fa_IR 2a vi 042a vi_VN 2b hy 042b hy_AM 2c az 042c az_AZ@latin 082c az_AZ@cyrillic 2d eu 2e wen 042e wen_DE 2f mk 042f mk_MK 30 bnt 0430 bnt_TZ 31 ts 0431 ts_ZA 32 tn 33 ven 0433 ven_ZA 34 xh 0434 xh_ZA 35 zu 0435 zu_ZA 36 af 0436 af_ZA 37 ka 0437 ka_GE 38 fo 0438 fo_FO 39 hi 0439 hi_IN 3a mt 043a mt_MT 3b se 043b se_NO 043c gd_UK 083c ga_IE 3d yi 043d yi_IL 3e ms 043e ms_MY 083e ms_BN 3f kk 043f kk_KZ 40 ky 0440 ky_KG 41 sw 0441 sw_KE 42 tk 0442 tk_TM 43 uz 0443 uz_UZ@latin 0843 uz_UZ@cyrillic 44 tt 0444 tt_RU 45 bn 0445 bn_IN 46 pa 0446 pa_IN 47 gu 0447 gu_IN 48 or 0448 or_IN 49 ta 4a te 044a te_IN 4b kn 044b kn_IN 4c ml 044c ml_IN 4d as 044d as_IN 4e mr 044e mr_IN 4f sa 044f sa_IN 50 mn 51 bo 0451 bo_CN 52 cy 0452 cy_GB 53 km 0453 km_KH 54 lo 0454 lo_LA 55 my 0455 my_MM 56 gl 0456 gl_ES 57 kok 0457 kok_IN 58 mni 0458 mni_IN 59 sd 5a syr 045a syr_TR 5b si 045b si_LK 5c chr 045c chr_US 5d iu 045d iu_CA 5e am 045e am_ET 5f ber 045f ber_MA 60 ks 0460 ks_PK 0860 ks_IN 61 ne 0461 ne_NP 0861 ne_IN 62 fy 0462 fy_NL 63 ps 64 tl 0464 tl_PH 65 div 0465 div_MV 66 bin 0466 bin_NG 67 ful 0467 ful_NG 68 ha 0468 ha_NG 69 nic 0469 nic_NG 6a yo 046a yo_NG 70 ibo 0470 ibo_NG 71 kau 0471 kau_NG 72 om 0472 om_ET 73 ti 0473 ti_ET 74 gn 0474 gn_PY 75 cpe 0475 cpe_US 76 la 0476 la_VA 77 so 0477 so_SO 78 sit 0478 sit_CN 79 pap 0479 pap_AN }] } } # msgcat::mc -- # # Find the translation for the given string based on the current # locale setting. Check the local namespace first, then look in each # parent namespace until the source is found. If additional args are # specified, use the format command to work them into the traslated # string. # If no catalog item is found, mcunknown is called in the caller frame # and its result is returned. # # Arguments: # src The string to translate. # args Args to pass to the format command # # Results: # Returns the translated string. Propagates errors thrown by the # format command. proc msgcat::mc {src args} { # this may be replaced by: # return [mcget -namespace [uplevel 1 [list ::namespace current]] --\ # $src {*}$args] # Check for the src in each namespace starting from the local and # ending in the global. variable Msgs variable Loclist set ns [uplevel 1 [list ::namespace current]] set loclist [PackagePreferences $ns] set nscur $ns while {$nscur != ""} { foreach loc $loclist { if {[dict exists $Msgs $nscur $loc $src]} { return [DefaultUnknown "" [dict get $Msgs $nscur $loc $src]\ {*}$args] } } set nscur [namespace parent $nscur] } # call package local or default unknown command set args [linsert $args 0 [lindex $loclist 0] $src] switch -exact -- [Invoke unknowncmd $args $ns result 1] { 0 { return [uplevel 1 [linsert $args 0 [namespace origin mcunknown]]] } 1 { return [DefaultUnknown {*}$args] } default { return $result } } } # msgcat::mcexists -- # # Check if a catalog item is set or if mc would invoke mcunknown. # # Arguments: # -exactnamespace Only check the exact namespace and no # parent namespaces # -exactlocale Only check the exact locale and not all members # of the preferences list # src Message catalog key # # Results: # true if an adequate catalog key was found proc msgcat::mcexists {args} { variable Msgs variable Loclist variable PackageConfig set ns [uplevel 1 [list ::namespace current]] set loclist [PackagePreferences $ns] while {[llength $args] != 1} { set args [lassign $args option] switch -glob -- $option { -exactnamespace { set exactnamespace 1 } -exactlocale { set loclist [lrange $loclist 0 0] } -* { return -code error "unknown option \"$option\"" } default { return -code error "wrong # args: should be\ \"[lindex [info level 0] 0] ?-exactnamespace?\ ?-exactlocale? src\"" } } } set src [lindex $args 0] while {$ns ne ""} { foreach loc $loclist { if {[dict exists $Msgs $ns $loc $src]} { return 1 } } if {[info exists exactnamespace]} {return 0} set ns [namespace parent $ns] } return 0 } # msgcat::mclocale -- # # Query or set the current locale. # # Arguments: # newLocale (Optional) The new locale string. Locale strings # should be composed of one or more sublocale parts # separated by underscores (e.g. en_US). # # Results: # Returns the normalized set locale. proc msgcat::mclocale {args} { variable Loclist variable LoadedLocales set len [llength $args] if {$len > 1} { return -code error "wrong # args: should be\ \"[lindex [info level 0] 0] ?newLocale?\"" } if {$len == 1} { set newLocale [string tolower [lindex $args 0]] if {$newLocale ne [file tail $newLocale]} { return -code error "invalid newLocale value \"$newLocale\":\ could be path to unsafe code." } if {[lindex $Loclist 0] ne $newLocale} { set Loclist [GetPreferences $newLocale] # locale not loaded jet LoadAll $Loclist # Invoke callback Invoke changecmd $Loclist } } return [lindex $Loclist 0] } # msgcat::GetPreferences -- # # Get list of locales from a locale. # The first element is always the lowercase locale. # Other elements have one component separated by "_" less. # Multiple "_" are seen as one separator: de__ch_spec de__ch de {} # # Arguments: # Locale. # # Results: # Locale list proc msgcat::GetPreferences {locale} { set locale [string tolower $locale] set loclist [list $locale] while {-1 !=[set pos [string last "_" $locale]]} { set locale [string range $locale 0 $pos-1] if { "_" ne [string index $locale end] } { lappend loclist $locale } } if {"" ne [lindex $loclist end]} { lappend loclist {} } return $loclist } # msgcat::mcpreferences -- # # Fetch the list of locales used to look up strings, ordered from # most preferred to least preferred. # # Arguments: # None. # # Results: # Returns an ordered list of the locales preferred by the user. proc msgcat::mcpreferences {} { variable Loclist return $Loclist } # msgcat::mcloadedlocales -- # # Get or change the list of currently loaded default locales # # The following subcommands are available: # loaded # Get the current list of loaded locales # clear # Remove all loaded locales not present in mcpreferences. # # Arguments: # subcommand One of loaded or clear # # Results: # Empty string, if not stated differently for the subcommand proc msgcat::mcloadedlocales {subcommand} { variable Loclist variable LoadedLocales variable Msgs variable PackageConfig switch -exact -- $subcommand { clear { # Remove all locales not contained in Loclist # skip any packages with package locale set LoadedLocales $Loclist foreach ns [dict keys $Msgs] { if {![dict exists $PackageConfig loclist $ns]} { foreach locale [dict keys [dict get $Msgs $ns]] { if {$locale ni $Loclist} { dict unset Msgs $ns $locale } } } } } loaded { return $LoadedLocales } default { return -code error "unknown subcommand \"$subcommand\": must be\ clear, or loaded" } } return } # msgcat::mcpackagelocale -- # # Get or change the package locale of the calling package. # # The following subcommands are available: # set # Set a package locale. # This may load message catalog files and may clear message catalog # items, if the former locale was the default locale. # Returns the normalized set locale. # The default locale is taken, if locale is not given. # get # Get the locale valid for this package. # isset # Returns true, if a package locale is set # unset # Unset the package locale and activate the default locale. # This loads message catalog file which where missing in the package # locale. # preferences # Return locale preference list valid for the package. # loaded # Return loaded locale list valid for the current package. # clear # If the current package has a package locale, remove all package # locales not containes in package mcpreferences. # It is an error to call this without a package locale set. # # The subcommands get, preferences and loaded return the corresponding # default data, if no package locale is set. # # Arguments: # subcommand see list above # locale package locale (only set subcommand) # # Results: # Empty string, if not stated differently for the subcommand proc msgcat::mcpackagelocale {subcommand {locale ""}} { # todo: implement using an ensemble variable Loclist variable LoadedLocales variable Msgs variable PackageConfig # Check option # check if required item is exactly provided if {[llength [info level 0]] == 2} { # locale not given unset locale } else { # locale given if {$subcommand in {"get" "isset" "unset" "preferences" "loaded" "clear"} } { return -code error "wrong # args: should be\ \"[lrange [info level 0] 0 1]\"" } set locale [string tolower $locale] } set ns [uplevel 1 {::namespace current}] switch -exact -- $subcommand { get { return [lindex [PackagePreferences $ns] 0] } preferences { return [PackagePreferences $ns] } loaded { return [PackageLocales $ns] } present { return [expr {$locale in [PackageLocales $ns]} ]} isset { return [dict exists $PackageConfig loclist $ns] } set { # set a package locale or add a package locale # Copy the default locale if no package locale set so far if {![dict exists $PackageConfig loclist $ns]} { dict set PackageConfig loclist $ns $Loclist dict set PackageConfig loadedlocales $ns $LoadedLocales } # Check if changed set loclist [dict get $PackageConfig loclist $ns] if {! [info exists locale] || $locale eq [lindex $loclist 0] } { return [lindex $loclist 0] } # Change loclist set loclist [GetPreferences $locale] set locale [lindex $loclist 0] dict set PackageConfig loclist $ns $loclist # load eventual missing locales set loadedLocales [dict get $PackageConfig loadedlocales $ns] if {$locale in $loadedLocales} { return $locale } set loadLocales [ListComplement $loadedLocales $loclist] dict set PackageConfig loadedlocales $ns\ [concat $loadedLocales $loadLocales] Load $ns $loadLocales return $locale } clear { # Remove all locales not contained in Loclist if {![dict exists $PackageConfig loclist $ns]} { return -code error "clear only when package locale set" } set loclist [dict get $PackageConfig loclist $ns] dict set PackageConfig loadedlocales $ns $loclist if {[dict exists $Msgs $ns]} { foreach locale [dict keys [dict get $Msgs $ns]] { if {$locale ni $loclist} { dict unset Msgs $ns $locale } } } } unset { # unset package locale and restore default locales if { ![dict exists $PackageConfig loclist $ns] } { return } # unset package locale set loadLocales [ListComplement\ [dict get $PackageConfig loadedlocales $ns] $LoadedLocales] dict unset PackageConfig loadedlocales $ns dict unset PackageConfig loclist $ns # unset keys not in global loaded locales if {[dict exists $Msgs $ns]} { foreach locale [dict keys [dict get $Msgs $ns]] { if {$locale ni $LoadedLocales} { dict unset Msgs $ns $locale } } } # Add missing locales Load $ns $loadLocales } default { return -code error "unknown subcommand \"$subcommand\": must be\ clear, get, isset, loaded, present, set, or unset" } } return } # msgcat::mcforgetpackage -- # # Remove any data of the calling package from msgcat # proc msgcat::mcforgetpackage {} { # todo: this may be implemented using an ensemble variable PackageConfig variable Msgs set ns [uplevel 1 {::namespace current}] # Remove MC items dict unset Msgs $ns # Remove config items foreach key [dict keys $PackageConfig] { dict unset PackageConfig $key $ns } return } # msgcat::mcpackageconfig -- # # Get or modify the per caller namespace (e.g. packages) config options. # # Available subcommands are: # # get get the current value or an error if not set. # isset return true, if the option is set # set set the value (see also distinct option). # Returns the number of loaded message files. # unset Clear option. return "". # # Available options are: # # mcfolder # The message catalog folder of the package. # This is automatically set by mcload. # If the value is changed using the set subcommand, an evntual # loadcmd is invoked and all message files of the package locale are # loaded. # # loadcmd # The command gets executed before a message file would be # sourced for this module. # The command is invoked with the expanded locale list to load. # The command is not invoked if the registering package namespace # is not present. # This callback might also be used as an alternative to message # files. # If the value is changed using the set subcommand, the callback is # directly invoked with the current file locale list. No file load is # executed. # # changecmd # The command is invoked, after an executed locale change. # Appended argument is expanded mcpreferences. # # unknowncmd # Use a package locale mcunknown procedure instead the global one. # The appended arguments are identical to mcunknown. # A default unknown handler is used if set to the empty string. # This consists in returning the key if no arguments are given. # With given arguments, format is used to process the arguments. # # Arguments: # subcommand Operation on the package # option The package option to get or set. # ?value? Eventual value for the subcommand # # Results: # Depends on the subcommand and option and is described there proc msgcat::mcpackageconfig {subcommand option {value ""}} { variable PackageConfig # get namespace set ns [uplevel 1 {::namespace current}] if {$option ni {"mcfolder" "loadcmd" "changecmd" "unknowncmd"}} { return -code error "bad option \"$option\": must be mcfolder, loadcmd,\ changecmd, or unknowncmd" } # check if value argument is exactly provided if {[llength [info level 0]] == 4 } { # value provided if {$subcommand in {"get" "isset" "unset"}} { return -code error "wrong # args: should be\ \"[lrange [info level 0] 0 2] value\"" } } elseif {$subcommand eq "set"} { return -code error\ "wrong # args: should be \"[lrange [info level 0] 0 2]\"" } # Execute subcommands switch -exact -- $subcommand { get { # Operation get return current value if {![dict exists $PackageConfig $option $ns]} { return -code error "package option \"$option\" not set" } return [dict get $PackageConfig $option $ns] } isset { return [dict exists $PackageConfig $option $ns] } unset { dict unset PackageConfig $option $ns } set { # Set option if {$option eq "mcfolder"} { set value [file normalize $value] } # Check if changed if { [dict exists $PackageConfig $option $ns] && $value eq [dict get $PackageConfig $option $ns] } { return 0 } # set new value dict set PackageConfig $option $ns $value # Reload pending message catalogs switch -exact -- $option { mcfolder { return [Load $ns [PackageLocales $ns]] } loadcmd { return [Load $ns [PackageLocales $ns] 1] } } return 0 } default { return -code error "unknown subcommand \"$subcommand\":\ must be get, isset, set, or unset" } } return } # msgcat::PackagePreferences -- # # Return eventual present package preferences or the default list if not # present. # # Arguments: # ns Package namespace # # Results: # locale list proc msgcat::PackagePreferences {ns} { variable PackageConfig if {[dict exists $PackageConfig loclist $ns]} { return [dict get $PackageConfig loclist $ns] } variable Loclist return $Loclist } # msgcat::PackageLocales -- # # Return eventual present package locales or the default list if not # present. # # Arguments: # ns Package namespace # # Results: # locale list proc msgcat::PackageLocales {ns} { variable PackageConfig if {[dict exists $PackageConfig loadedlocales $ns]} { return [dict get $PackageConfig loadedlocales $ns] } variable LoadedLocales return $LoadedLocales } # msgcat::ListComplement -- # # Build the complement of two lists. # Return a list with all elements in list2 but not in list1. # Optionally return the intersection. # # Arguments: # list1 excluded list # list2 included list # inlistname If not "", write in this variable the intersection list # # Results: # list with all elements in list2 but not in list1 proc msgcat::ListComplement {list1 list2 {inlistname ""}} { if {"" ne $inlistname} { upvar 1 $inlistname inlist } set inlist {} set outlist {} foreach item $list2 { if {$item in $list1} { lappend inlist $item } else { lappend outlist $item } } return $outlist } # msgcat::mcload -- # # Attempt to load message catalogs for each locale in the # preference list from the specified directory. # # Arguments: # langdir The directory to search. # # Results: # Returns the number of message catalogs that were loaded. proc msgcat::mcload {langdir} { return [uplevel 1 [list\ [namespace origin mcpackageconfig] set mcfolder $langdir]] } # msgcat::LoadAll -- # # Load a list of locales for all packages not having a package locale # list. # # Arguments: # langdir The directory to search. # # Results: # Returns the number of message catalogs that were loaded. proc msgcat::LoadAll {locales} { variable PackageConfig variable LoadedLocales if {0 == [llength $locales]} { return {} } # filter jet unloaded locales set locales [ListComplement $LoadedLocales $locales] if {0 == [llength $locales]} { return {} } lappend LoadedLocales {*}$locales set packages [lsort -unique [concat\ [dict keys [dict get $PackageConfig loadcmd]]\ [dict keys [dict get $PackageConfig mcfolder]]]] foreach ns $packages { if {! [dict exists $PackageConfig loclist $ns] } { Load $ns $locales } } return $locales } # msgcat::Load -- # # Invoke message load callback and load message catalog files. # # Arguments: # ns Namespace (equal package) to load the message catalog. # locales List of locales to load. # callbackonly true if only callback should be invoked # # Results: # Returns the number of message catalogs that were loaded. proc msgcat::Load {ns locales {callbackonly 0}} { variable FileLocale variable PackageConfig variable LoadedLocals if {0 == [llength $locales]} { return 0 } # Invoke callback Invoke loadcmd $locales $ns if {$callbackonly || ![dict exists $PackageConfig mcfolder $ns]} { return 0 } # Invoke file load set langdir [dict get $PackageConfig mcfolder $ns] # Save the file locale if we are recursively called if {[info exists FileLocale]} { set nestedFileLocale $FileLocale } set x 0 foreach p $locales { if {$p eq {}} { set p ROOT } set langfile [file join $langdir $p.msg] if {[file exists $langfile]} { incr x set FileLocale [string tolower\ [file tail [file rootname $langfile]]] if {"root" eq $FileLocale} { set FileLocale "" } namespace inscope $ns [list ::source -encoding utf-8 $langfile] unset FileLocale } } if {[info exists nestedFileLocale]} { set FileLocale $nestedFileLocale } return $x } # msgcat::Invoke -- # # Invoke a set of registered callbacks. # The callback is only invoked, if its registered namespace exists. # # Arguments: # index Index into PackageConfig to get callback command # arglist parameters to the callback invocation # ns (Optional) package to call. # If not given or empty, check all registered packages. # resultname Variable to save the callback result of the last called # callback to. May be set to "" to discard the result. # failerror (0) Fail on error if true. Otherwise call bgerror. # # Results: # Possible values: # - 0: no valid command registered # - 1: registered command was the empty string # - 2: registered command called, resultname is set # - 3: registered command failed # If multiple commands are called, the maximum of all results is returned. proc msgcat::Invoke {index arglist {ns ""} {resultname ""} {failerror 0}} { variable PackageConfig variable Config if {"" ne $resultname} { upvar 1 $resultname result } if {"" eq $ns} { set packageList [dict keys [dict get $PackageConfig $index]] } else { set packageList [list $ns] } set ret 0 foreach ns $packageList { if {[dict exists $PackageConfig $index $ns] && [namespace exists $ns]} { set cmd [dict get $PackageConfig $index $ns] if {"" eq $cmd} { if {$ret == 0} {set ret 1} } else { if {$failerror} { set result [namespace inscope $ns $cmd {*}$arglist] set ret 2 } elseif {1 == [catch { set result [namespace inscope $ns $cmd {*}$arglist] if {$ret < 2} {set ret 2} } err derr]} { after idle [concat [::interp bgerror ""]\ [list $err $derr]] set ret 3 } } } } return $ret } # msgcat::mcset -- # # Set the translation for a given string in a specified locale. # # Arguments: # locale The locale to use. # src The source string. # dest (Optional) The translated string. If omitted, # the source string is used. # # Results: # Returns the new locale. proc msgcat::mcset {locale src {dest ""}} { variable Msgs if {[llength [info level 0]] == 3} { ;# dest not specified set dest $src } set ns [uplevel 1 [list ::namespace current]] set locale [string tolower $locale] dict set Msgs $ns $locale $src $dest return $dest } # msgcat::mcflset -- # # Set the translation for a given string in the current file locale. # # Arguments: # src The source string. # dest (Optional) The translated string. If omitted, # the source string is used. # # Results: # Returns the new locale. proc msgcat::mcflset {src {dest ""}} { variable FileLocale variable Msgs if {![info exists FileLocale]} { return -code error "must only be used inside a message catalog loaded\ with ::msgcat::mcload" } return [uplevel 1 [list [namespace origin mcset] $FileLocale $src $dest]] } # msgcat::mcmset -- # # Set the translation for multiple strings in a specified locale. # # Arguments: # locale The locale to use. # pairs One or more src/dest pairs (must be even length) # # Results: # Returns the number of pairs processed proc msgcat::mcmset {locale pairs} { variable Msgs set length [llength $pairs] if {$length % 2} { return -code error "bad translation list:\ should be \"[lindex [info level 0] 0] locale {src dest ...}\"" } set locale [string tolower $locale] set ns [uplevel 1 [list ::namespace current]] foreach {src dest} $pairs { dict set Msgs $ns $locale $src $dest } return [expr {$length / 2}] } # msgcat::mcflmset -- # # Set the translation for multiple strings in the mc file locale. # # Arguments: # pairs One or more src/dest pairs (must be even length) # # Results: # Returns the number of pairs processed proc msgcat::mcflmset {pairs} { variable FileLocale variable Msgs if {![info exists FileLocale]} { return -code error "must only be used inside a message catalog loaded\ with ::msgcat::mcload" } return [uplevel 1 [list [namespace origin mcmset] $FileLocale $pairs]] } # msgcat::mcunknown -- # # This routine is called by msgcat::mc if a translation cannot # be found for a string and no unknowncmd is set for the current # package. This routine is intended to be replaced # by an application specific routine for error reporting # purposes. The default behavior is to return the source string. # If additional args are specified, the format command will be used # to work them into the traslated string. # # Arguments: # locale The current locale. # src The string to be translated. # args Args to pass to the format command # # Results: # Returns the translated value. proc msgcat::mcunknown {args} { return [uplevel 1 [list [namespace origin DefaultUnknown] {*}$args]] } # msgcat::DefaultUnknown -- # # This routine is called by msgcat::mc if a translation cannot # be found for a string in the following circumstances: # - Default global handler, if mcunknown is not redefined. # - Per package handler, if the package sets unknowncmd to the empty # string. # It returna the source string if the argument list is empty. # If additional args are specified, the format command will be used # to work them into the traslated string. # # Arguments: # locale (unused) The current locale. # src The string to be translated. # args Args to pass to the format command # # Results: # Returns the translated value. proc msgcat::DefaultUnknown {locale src args} { if {[llength $args]} { return [format $src {*}$args] } else { return $src } } # msgcat::mcmax -- # # Calculates the maximum length of the translated strings of the given # list. # # Arguments: # args strings to translate. # # Results: # Returns the length of the longest translated string. proc msgcat::mcmax {args} { set max 0 foreach string $args { set translated [uplevel 1 [list [namespace origin mc] $string]] set len [string length $translated] if {$len>$max} { set max $len } } return $max } # Convert the locale values stored in environment variables to a form # suitable for passing to [mclocale] proc msgcat::ConvertLocale {value} { # Assume $value is of form: $language[_$territory][.$codeset][@modifier] # Convert to form: $language[_$territory][_$modifier] # # Comment out expanded RE version -- bugs alleged # regexp -expanded { # ^ # Match all the way to the beginning # ([^_.@]*) # Match "lanugage"; ends with _, ., or @ # (_([^.@]*))? # Match (optional) "territory"; starts with _ # ([.]([^@]*))? # Match (optional) "codeset"; starts with . # (@(.*))? # Match (optional) "modifier"; starts with @ # $ # Match all the way to the end # } $value -> language _ territory _ codeset _ modifier if {![regexp {^([^_.@]+)(_([^.@]*))?([.]([^@]*))?(@(.*))?$} $value \ -> language _ territory _ codeset _ modifier]} { return -code error "invalid locale '$value': empty language part" } set ret $language if {[string length $territory]} { append ret _$territory } if {[string length $modifier]} { append ret _$modifier } return $ret } # Initialize the default locale proc msgcat::Init {} { global env # # set default locale, try to get from environment # foreach varName {LC_ALL LC_MESSAGES LANG} { if {[info exists env($varName)] && ("" ne $env($varName))} { if {![catch { mclocale [ConvertLocale $env($varName)] }]} { return } } } # # On Darwin, fallback to current CFLocale identifier if available. # if {[info exists ::tcl::mac::locale] && $::tcl::mac::locale ne ""} { if {![catch { mclocale [ConvertLocale $::tcl::mac::locale] }]} { return } } # # The rest of this routine is special processing for Windows or # Cygwin. All other platforms, get out now. # if {([info sharedlibextension] ne ".dll") || [catch {package require registry}]} { mclocale C return } # # On Windows or Cygwin, try to set locale depending on registry # settings, or fall back on locale of "C". # # On Vista and later: # HCU/Control Panel/Desktop : PreferredUILanguages is for language packs, # HCU/Control Pannel/International : localName is the default locale. # # They contain the local string as RFC5646, composed of: # [a-z]{2,3} : language # -[a-z]{4} : script (optional, translated by table Latn->latin) # -[a-z]{2}|[0-9]{3} : territory (optional, numerical region codes not used) # (-.*)* : variant, extension, private use (optional, not used) # Those are translated to local strings. # Examples: de-CH -> de_ch, sr-Latn-CS -> sr_cs@latin, es-419 -> es # foreach key {{HKEY_CURRENT_USER\Control Panel\Desktop} {HKEY_CURRENT_USER\Control Panel\International}}\ value {PreferredUILanguages localeName} { if {![catch {registry get $key $value} localeName] && [regexp {^([a-z]{2,3})(?:-([a-z]{4}))?(?:-([a-z]{2}))?(?:-.+)?$}\ [string tolower $localeName] match locale script territory]} { if {"" ne $territory} { append locale _ $territory } set modifierDict [dict create latn latin cyrl cyrillic] if {[dict exists $modifierDict $script]} { append locale @ [dict get $modifierDict $script] } if {![catch {mclocale [ConvertLocale $locale]}]} { return } } } # then check value locale which contains a numerical language ID if {[catch { set locale [registry get $key "locale"] }]} { mclocale C return } # # Keep trying to match against smaller and smaller suffixes # of the registry value, since the latter hexadigits appear # to determine general language and earlier hexadigits determine # more precise information, such as territory. For example, # 0409 - English - United States # 0809 - English - United Kingdom # Add more translations to the WinRegToISO639 array above. # variable WinRegToISO639 set locale [string tolower $locale] while {[string length $locale]} { if {![catch { mclocale [ConvertLocale [dict get $WinRegToISO639 $locale]] }]} { return } set locale [string range $locale 1 end] } # # No translation known. Fall back on "C" locale # mclocale C } msgcat::Init