tcltk: updated release script to use 8.5.13 release
[msysgit/kirr.git] / mingw / lib / tcl8 / 8.5 / msgcat-1.4.4.tm
blob369ed520c744e2e3756714721be0d4d21cf7d42d
1 # msgcat.tcl --
3 #       This file defines various procedures which implement a
4 #       message catalog facility for Tcl programs.  It should be
5 #       loaded with the command "package require msgcat".
7 # Copyright (c) 1998-2000 by Ajuba Solutions.
8 # Copyright (c) 1998 by Mark Harrison.
10 # See the file "license.terms" for information on usage and redistribution
11 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 package require Tcl 8.5
14 # When the version number changes, be sure to update the pkgIndex.tcl file,
15 # and the installation directory in the Makefiles.
16 package provide msgcat 1.4.4
18 namespace eval msgcat {
19     namespace export mc mcload mclocale mcmax mcmset mcpreferences mcset \
20             mcunknown
22     # Records the current locale as passed to mclocale
23     variable Locale ""
25     # Records the list of locales to search
26     variable Loclist {}
28     # Records the mapping between source strings and translated strings.  The
29     # dict key is of the form "<locale> <namespace> <src>", where locale and
30     # namespace should be themselves dict values and the value is
31     # the translated string.
32     variable Msgs [dict create]
34     # Map of language codes used in Windows registry to those of ISO-639
35     if { $::tcl_platform(platform) eq "windows" } {
36         variable WinRegToISO639 [dict create  {*}{
37             01 ar 0401 ar_SA 0801 ar_IQ 0c01 ar_EG 1001 ar_LY 1401 ar_DZ
38                   1801 ar_MA 1c01 ar_TN 2001 ar_OM 2401 ar_YE 2801 ar_SY
39                   2c01 ar_JO 3001 ar_LB 3401 ar_KW 3801 ar_AE 3c01 ar_BH
40                   4001 ar_QA
41             02 bg 0402 bg_BG
42             03 ca 0403 ca_ES
43             04 zh 0404 zh_TW 0804 zh_CN 0c04 zh_HK 1004 zh_SG 1404 zh_MO
44             05 cs 0405 cs_CZ
45             06 da 0406 da_DK
46             07 de 0407 de_DE 0807 de_CH 0c07 de_AT 1007 de_LU 1407 de_LI
47             08 el 0408 el_GR
48             09 en 0409 en_US 0809 en_GB 0c09 en_AU 1009 en_CA 1409 en_NZ
49                   1809 en_IE 1c09 en_ZA 2009 en_JM 2409 en_GD 2809 en_BZ
50                   2c09 en_TT 3009 en_ZW 3409 en_PH
51             0a es 040a es_ES 080a es_MX 0c0a es_ES@modern 100a es_GT 140a es_CR
52                   180a es_PA 1c0a es_DO 200a es_VE 240a es_CO 280a es_PE
53                   2c0a es_AR 300a es_EC 340a es_CL 380a es_UY 3c0a es_PY
54                   400a es_BO 440a es_SV 480a es_HN 4c0a es_NI 500a es_PR
55             0b fi 040b fi_FI
56             0c fr 040c fr_FR 080c fr_BE 0c0c fr_CA 100c fr_CH 140c fr_LU
57                   180c fr_MC
58             0d he 040d he_IL
59             0e hu 040e hu_HU
60             0f is 040f is_IS
61             10 it 0410 it_IT 0810 it_CH
62             11 ja 0411 ja_JP
63             12 ko 0412 ko_KR
64             13 nl 0413 nl_NL 0813 nl_BE
65             14 no 0414 no_NO 0814 nn_NO
66             15 pl 0415 pl_PL
67             16 pt 0416 pt_BR 0816 pt_PT
68             17 rm 0417 rm_CH
69             18 ro 0418 ro_RO
70             19 ru
71             1a hr 041a hr_HR 081a sr_YU 0c1a sr_YU@cyrillic
72             1b sk 041b sk_SK
73             1c sq 041c sq_AL
74             1d sv 041d sv_SE 081d sv_FI
75             1e th 041e th_TH
76             1f tr 041f tr_TR
77             20 ur 0420 ur_PK 0820 ur_IN
78             21 id 0421 id_ID
79             22 uk 0422 uk_UA
80             23 be 0423 be_BY
81             24 sl 0424 sl_SI
82             25 et 0425 et_EE
83             26 lv 0426 lv_LV
84             27 lt 0427 lt_LT
85             28 tg 0428 tg_TJ
86             29 fa 0429 fa_IR
87             2a vi 042a vi_VN
88             2b hy 042b hy_AM
89             2c az 042c az_AZ@latin 082c az_AZ@cyrillic
90             2d eu
91             2e wen 042e wen_DE
92             2f mk 042f mk_MK
93             30 bnt 0430 bnt_TZ
94             31 ts 0431 ts_ZA
95             33 ven 0433 ven_ZA
96             34 xh 0434 xh_ZA
97             35 zu 0435 zu_ZA
98             36 af 0436 af_ZA
99             37 ka 0437 ka_GE
100             38 fo 0438 fo_FO
101             39 hi 0439 hi_IN
102             3a mt 043a mt_MT
103             3b se 043b se_NO
104             043c gd_UK 083c ga_IE
105             3d yi 043d yi_IL
106             3e ms 043e ms_MY 083e ms_BN
107             3f kk 043f kk_KZ
108             40 ky 0440 ky_KG
109             41 sw 0441 sw_KE
110             42 tk 0442 tk_TM
111             43 uz 0443 uz_UZ@latin 0843 uz_UZ@cyrillic
112             44 tt 0444 tt_RU
113             45 bn 0445 bn_IN
114             46 pa 0446 pa_IN
115             47 gu 0447 gu_IN
116             48 or 0448 or_IN
117             49 ta
118             4a te 044a te_IN
119             4b kn 044b kn_IN
120             4c ml 044c ml_IN
121             4d as 044d as_IN
122             4e mr 044e mr_IN
123             4f sa 044f sa_IN
124             50 mn
125             51 bo 0451 bo_CN
126             52 cy 0452 cy_GB
127             53 km 0453 km_KH
128             54 lo 0454 lo_LA
129             55 my 0455 my_MM
130             56 gl 0456 gl_ES
131             57 kok 0457 kok_IN
132             58 mni 0458 mni_IN
133             59 sd
134             5a syr 045a syr_TR
135             5b si 045b si_LK
136             5c chr 045c chr_US
137             5d iu 045d iu_CA
138             5e am 045e am_ET
139             5f ber 045f ber_MA
140             60 ks 0460 ks_PK 0860 ks_IN
141             61 ne 0461 ne_NP 0861 ne_IN
142             62 fy 0462 fy_NL
143             63 ps
144             64 tl 0464 tl_PH
145             65 div 0465 div_MV
146             66 bin 0466 bin_NG
147             67 ful 0467 ful_NG
148             68 ha 0468 ha_NG
149             69 nic 0469 nic_NG
150             6a yo 046a yo_NG
151             70 ibo 0470 ibo_NG
152             71 kau 0471 kau_NG
153             72 om 0472 om_ET
154             73 ti 0473 ti_ET
155             74 gn 0474 gn_PY
156             75 cpe 0475 cpe_US
157             76 la 0476 la_VA
158             77 so 0477 so_SO
159             78 sit 0478 sit_CN
160             79 pap 0479 pap_AN
161         }]
162     }
165 # msgcat::mc --
167 #       Find the translation for the given string based on the current
168 #       locale setting. Check the local namespace first, then look in each
169 #       parent namespace until the source is found.  If additional args are
170 #       specified, use the format command to work them into the traslated
171 #       string.
173 # Arguments:
174 #       src     The string to translate.
175 #       args    Args to pass to the format command
177 # Results:
178 #       Returns the translated string.  Propagates errors thrown by the
179 #       format command.
181 proc msgcat::mc {src args} {
182     # Check for the src in each namespace starting from the local and
183     # ending in the global.
185     variable Msgs
186     variable Loclist
187     variable Locale
189     set ns [uplevel 1 [list ::namespace current]]
191     while {$ns != ""} {
192         foreach loc $Loclist {
193             if {[dict exists $Msgs $loc $ns $src]} {
194                 if {[llength $args] == 0} {
195                     return [dict get $Msgs $loc $ns $src]
196                 } else {
197                     return [format [dict get $Msgs $loc $ns $src] {*}$args]
198                 }
199             }
200         }
201         set ns [namespace parent $ns]
202     }
203     # we have not found the translation
204     return [uplevel 1 [list [namespace origin mcunknown] \
205             $Locale $src {*}$args]]
208 # msgcat::mclocale --
210 #       Query or set the current locale.
212 # Arguments:
213 #       newLocale       (Optional) The new locale string. Locale strings
214 #                       should be composed of one or more sublocale parts
215 #                       separated by underscores (e.g. en_US).
217 # Results:
218 #       Returns the current locale.
220 proc msgcat::mclocale {args} {
221     variable Loclist
222     variable Locale
223     set len [llength $args]
225     if {$len > 1} {
226         return -code error "wrong # args: should be\
227                 \"[lindex [info level 0] 0] ?newLocale?\""
228     }
230     if {$len == 1} {
231         set newLocale [lindex $args 0]
232         if {$newLocale ne [file tail $newLocale]} {
233             return -code error "invalid newLocale value \"$newLocale\":\
234                     could be path to unsafe code."
235         }
236         set Locale [string tolower $newLocale]
237         set Loclist {}
238         set word ""
239         foreach part [split $Locale _] {
240             set word [string trim "${word}_${part}" _]
241             if {$word ne [lindex $Loclist 0]} {
242                 set Loclist [linsert $Loclist 0 $word]
243             }
244         }
245         lappend Loclist {}
246         set Locale [lindex $Loclist 0]
247     }
248     return $Locale
251 # msgcat::mcpreferences --
253 #       Fetch the list of locales used to look up strings, ordered from
254 #       most preferred to least preferred.
256 # Arguments:
257 #       None.
259 # Results:
260 #       Returns an ordered list of the locales preferred by the user.
262 proc msgcat::mcpreferences {} {
263     variable Loclist
264     return $Loclist
267 # msgcat::mcload --
269 #       Attempt to load message catalogs for each locale in the
270 #       preference list from the specified directory.
272 # Arguments:
273 #       langdir         The directory to search.
275 # Results:
276 #       Returns the number of message catalogs that were loaded.
278 proc msgcat::mcload {langdir} {
279     set x 0
280     foreach p [mcpreferences] {
281         if { $p eq {} } {
282             set p ROOT
283         }
284         set langfile [file join $langdir $p.msg]
285         if {[file exists $langfile]} {
286             incr x
287             uplevel 1 [list ::source -encoding utf-8 $langfile]
288         }
289     }
290     return $x
293 # msgcat::mcset --
295 #       Set the translation for a given string in a specified locale.
297 # Arguments:
298 #       locale          The locale to use.
299 #       src             The source string.
300 #       dest            (Optional) The translated string.  If omitted,
301 #                       the source string is used.
303 # Results:
304 #       Returns the new locale.
306 proc msgcat::mcset {locale src {dest ""}} {
307     variable Msgs
308     if {[llength [info level 0]] == 3} { ;# dest not specified
309         set dest $src
310     }
312     set ns [uplevel 1 [list ::namespace current]]
314     set locale [string tolower $locale]
316     dict set Msgs $locale $ns $src $dest
317     return $dest
320 # msgcat::mcmset --
322 #       Set the translation for multiple strings in a specified locale.
324 # Arguments:
325 #       locale          The locale to use.
326 #       pairs           One or more src/dest pairs (must be even length)
328 # Results:
329 #       Returns the number of pairs processed
331 proc msgcat::mcmset {locale pairs } {
332     variable Msgs
334     set length [llength $pairs]
335     if {$length % 2} {
336         return -code error "bad translation list:\
337                  should be \"[lindex [info level 0] 0] locale {src dest ...}\""
338     }
340     set locale [string tolower $locale]
341     set ns [uplevel 1 [list ::namespace current]]
343     foreach {src dest} $pairs {
344         dict set Msgs $locale $ns $src $dest
345     }
347     return $length
350 # msgcat::mcunknown --
352 #       This routine is called by msgcat::mc if a translation cannot
353 #       be found for a string.  This routine is intended to be replaced
354 #       by an application specific routine for error reporting
355 #       purposes.  The default behavior is to return the source string.
356 #       If additional args are specified, the format command will be used
357 #       to work them into the traslated string.
359 # Arguments:
360 #       locale          The current locale.
361 #       src             The string to be translated.
362 #       args            Args to pass to the format command
364 # Results:
365 #       Returns the translated value.
367 proc msgcat::mcunknown {locale src args} {
368     if {[llength $args]} {
369         return [format $src {*}$args]
370     } else {
371         return $src
372     }
375 # msgcat::mcmax --
377 #       Calculates the maximum length of the translated strings of the given
378 #       list.
380 # Arguments:
381 #       args    strings to translate.
383 # Results:
384 #       Returns the length of the longest translated string.
386 proc msgcat::mcmax {args} {
387     set max 0
388     foreach string $args {
389         set translated [uplevel 1 [list [namespace origin mc] $string]]
390         set len [string length $translated]
391         if {$len>$max} {
392             set max $len
393         }
394     }
395     return $max
398 # Convert the locale values stored in environment variables to a form
399 # suitable for passing to [mclocale]
400 proc msgcat::ConvertLocale {value} {
401     # Assume $value is of form: $language[_$territory][.$codeset][@modifier]
402     # Convert to form: $language[_$territory][_$modifier]
403     #
404     # Comment out expanded RE version -- bugs alleged
405     # regexp -expanded {
406     #   ^               # Match all the way to the beginning
407     #   ([^_.@]*)       # Match "lanugage"; ends with _, ., or @
408     #   (_([^.@]*))?    # Match (optional) "territory"; starts with _
409     #   ([.]([^@]*))?   # Match (optional) "codeset"; starts with .
410     #   (@(.*))?        # Match (optional) "modifier"; starts with @
411     #   $               # Match all the way to the end
412     # } $value -> language _ territory _ codeset _ modifier
413     if {![regexp {^([^_.@]+)(_([^.@]*))?([.]([^@]*))?(@(.*))?$} $value \
414             -> language _ territory _ codeset _ modifier]} {
415         return -code error "invalid locale '$value': empty language part"
416     }
417     set ret $language
418     if {[string length $territory]} {
419         append ret _$territory
420     }
421     if {[string length $modifier]} {
422         append ret _$modifier
423     }
424     return $ret
427 # Initialize the default locale
428 proc msgcat::Init {} {
429     global env tcl_platform
431     #
432     # set default locale, try to get from environment
433     #
434     foreach varName {LC_ALL LC_MESSAGES LANG} {
435         if {[info exists env($varName)] && ("" ne $env($varName))} {
436             if {![catch {
437                 mclocale [ConvertLocale $env($varName)]
438             }]} {
439                 return
440             }
441         }
442     }
443     #
444     # On Darwin, fallback to current CFLocale identifier if available.
445     #
446     if {[info exists ::tcl::mac::locale] && $::tcl::mac::locale ne ""} {
447         if {![catch {
448             mclocale [ConvertLocale $::tcl::mac::locale]
449         }]} {
450             return
451         }
452     }
453     #
454     # The rest of this routine is special processing for Windows;
455     # all other platforms, get out now.
456     #
457     if {$tcl_platform(platform) ne "windows"} {
458         mclocale C
459         return
460     }
461     #
462     # On Windows, try to set locale depending on registry settings,
463     # or fall back on locale of "C".
464     #
465     if {[catch {
466         package require registry
467         set key {HKEY_CURRENT_USER\Control Panel\International}
468         set locale [registry get $key "locale"]
469     }]} {
470         mclocale C
471         return
472     }
473     #
474     # Keep trying to match against smaller and smaller suffixes
475     # of the registry value, since the latter hexadigits appear
476     # to determine general language and earlier hexadigits determine
477     # more precise information, such as territory.  For example,
478     #     0409 - English - United States
479     #     0809 - English - United Kingdom
480     # Add more translations to the WinRegToISO639 array above.
481     #
482     variable WinRegToISO639
483     set locale [string tolower $locale]
484     while {[string length $locale]} {
485         if {![catch {
486             mclocale [ConvertLocale [dict get $WinRegToISO639 $locale]]
487         }]} {
488             return
489         }
490         set locale [string range $locale 1 end]
491     }
492     #
493     # No translation known.  Fall back on "C" locale
494     #
495     mclocale C
497 msgcat::Init