1msgcat(n) Tcl Bundled Packages msgcat(n)
2
3
4
5______________________________________________________________________________
6
8 msgcat - Tcl message catalog
9
11 package require Tcl 8.5
12
13 package require msgcat 1.6
14
15 ::msgcat::mc src-string ?arg arg ...?
16
17 ::msgcat::mcmax ?src-string src-string ...?
18
19 ::msgcat::mcexists ?-exactnamespace? ?-exactlocale? src-string │
20
21 ::msgcat::mclocale ?newLocale?
22
23 ::msgcat::mcpreferences
24
25 ::msgcat::mcloadedlocales subcommand ?locale? │
26
27 ::msgcat::mcload dirname
28
29 ::msgcat::mcset locale src-string ?translate-string?
30
31 ::msgcat::mcmset locale src-trans-list
32
33 ::msgcat::mcflset src-string ?translate-string?
34
35 ::msgcat::mcflmset src-trans-list
36
37 ::msgcat::mcunknown locale src-string ?arg arg ...?
38
39 ::msgcat::mcpackagelocale subcommand ?locale? │
40
41 ::msgcat::mcpackageconfig subcommand option ?value? │
42
43 ::msgcat::mcforgetpackage
44______________________________________________________________________________
45
47 The msgcat package provides a set of functions that can be used to man‐
48 age multi-lingual user interfaces. Text strings are defined in a “mes‐
49 sage catalog” which is independent from the application, and which can
50 be edited or localized without modifying the application source code.
51 New languages or locales may be provided by adding a new file to the
52 message catalog.
53
54 msgcat distinguises packages by its namespace. Each package has its
55 own message catalog and configuration settings in msgcat.
56
57 A locale is a specification string describing a user language like
58 de_ch for Swiss German. In msgcat, there is a global locale initial‐
59 ized by the system locale of the current system. Each package may de‐
60 cide to use the global locale or to use a package specific locale.
61
62 The global locale may be changed on demand, for example by a user ini‐
63 tiated language change or within a multi user application like a web
64 server.
65
67 ::msgcat::mc src-string ?arg arg ...?
68 Returns a translation of src-string according to the current lo‐
69 cale. If additional arguments past src-string are given, the
70 format command is used to substitute the additional arguments in
71 the translation of src-string.
72
73 ::msgcat::mc will search the messages defined in the current
74 namespace for a translation of src-string; if none is found, it
75 will search in the parent of the current namespace, and so on
76 until it reaches the global namespace. If no translation string
77 exists, ::msgcat::mcunknown is called and the string returned
78 from ::msgcat::mcunknown is returned.
79
80 ::msgcat::mc is the main function used to localize an applica‐
81 tion. Instead of using an English string directly, an applica‐
82 tion can pass the English string through ::msgcat::mc and use
83 the result. If an application is written for a single language
84 in this fashion, then it is easy to add support for additional
85 languages later simply by defining new message catalog entries.
86
87 ::msgcat::mcmax ?src-string src-string ...?
88 Given several source strings, ::msgcat::mcmax returns the length
89 of the longest translated string. This is useful when designing
90 localized GUIs, which may require that all buttons, for example,
91 be a fixed width (which will be the width of the widest button).
92
93 ::msgcat::mcexists ?-exactnamespace? ?-exactlocale? src-string
94 Return true, if there is a translation for the given src-string. │
95
96 The search may be limited by the option -exactnamespace to only │
97 check the current namespace and not any parent namespaces. │
98
99 It may also be limited by the option -exactlocale to only check │
100 the first prefered locale (e.g. first element returned by ::msg‐ │
101 cat::mcpreferences if global locale is used). │
102
103 ::msgcat::mclocale ?newLocale?
104 This function sets the locale to newLocale. If newLocale is
105 omitted, the current locale is returned, otherwise the current
106 locale is set to newLocale. msgcat stores and compares the lo‐
107 cale in a case-insensitive manner, and returns locales in lower‐
108 case. The initial locale is determined by the locale specified
109 in the user's environment. See LOCALE SPECIFICATION below for a
110 description of the locale string format.
111
112 If the locale is set, the preference list of locales is evalu‐ │
113 ated. Locales in this list are loaded now, if not jet loaded.
114
115 ::msgcat::mcpreferences
116 Returns an ordered list of the locales preferred by the user,
117 based on the user's language specification. The list is ordered
118 from most specific to least preference. The list is derived
119 from the current locale set in msgcat by ::msgcat::mclocale, and
120 cannot be set independently. For example, if the current locale
121 is en_US_funky, then ::msgcat::mcpreferences returns
122 {en_us_funky en_us en {}}.
123
124 ::msgcat::mcloadedlocales subcommand ?locale?
125 This group of commands manage the list of loaded locales for
126 packages not setting a package locale.
127
128 The subcommand get returns the list of currently loaded locales.
129
130 The subcommand present requires the argument locale and returns
131 true, if this locale is loaded.
132
133 The subcommand clear removes all locales and their data, which
134 are not in the current preference list.
135
136 ::msgcat::mcload dirname
137 Searches the specified directory for files that match the lan‐ │
138 guage specifications returned by ::msgcat::mcloadedlocales get │
139 (or msgcat::mcpackagelocale preferences if a package locale is │
140 set) (note that these are all lowercase), extended by the file │
141 extension “.msg”. Each matching file is read in order, assuming │
142 a UTF-8 encoding. The file contents are then evaluated as a Tcl │
143 script. This means that Unicode characters may be present in │
144 the message file either directly in their UTF-8 encoded form, or │
145 by use of the backslash-u quoting recognized by Tcl evaluation. │
146 The number of message files which matched the specification and │
147 were loaded is returned. │
148
149 In addition, the given folder is stored in the msgcat package │
150 configuration option mcfolder to eventually load message catalog │
151 files required by a locale change.
152
153 ::msgcat::mcset locale src-string ?translate-string?
154 Sets the translation for src-string to translate-string in the
155 specified locale and the current namespace. If translate-string
156 is not specified, src-string is used for both. The function re‐
157 turns translate-string.
158
159 ::msgcat::mcmset locale src-trans-list
160 Sets the translation for multiple source strings in src-trans-
161 list in the specified locale and the current namespace. src-
162 trans-list must have an even number of elements and is in the
163 form {src-string translate-string ?src-string translate-string
164 ...?} ::msgcat::mcmset can be significantly faster than multiple
165 invocations of ::msgcat::mcset. The function returns the number
166 of translations set.
167
168 ::msgcat::mcflset src-string ?translate-string?
169 Sets the translation for src-string to translate-string in the
170 current namespace for the locale implied by the name of the mes‐
171 sage catalog being loaded via ::msgcat::mcload. If translate-
172 string is not specified, src-string is used for both. The func‐
173 tion returns translate-string.
174
175 ::msgcat::mcflmset src-trans-list
176 Sets the translation for multiple source strings in src-trans-
177 list in the current namespace for the locale implied by the name
178 of the message catalog being loaded via ::msgcat::mcload. src-
179 trans-list must have an even number of elements and is in the
180 form {src-string translate-string ?src-string translate-string
181 ...?} ::msgcat::mcflmset can be significantly faster than multi‐
182 ple invocations of ::msgcat::mcflset. The function returns the
183 number of translations set.
184
185 ::msgcat::mcunknown locale src-string ?arg arg ...?
186 This routine is called by ::msgcat::mc in the case when a trans‐
187 lation for src-string is not defined in the current locale. The
188 default action is to return src-string passed by format if there
189 are any arguments. This procedure can be redefined by the ap‐
190 plication, for example to log error messages for each unknown
191 string. The ::msgcat::mcunknown procedure is invoked at the
192 same stack context as the call to ::msgcat::mc. The return
193 value of ::msgcat::mcunknown is used as the return value for the
194 call to ::msgcat::mc. │
195
196 Note that this routine is only called if the concerned package │
197 did not set a package locale unknown command name. │
198
199 ::msgcat::mcforgetpackage │
200 The calling package clears all its state within the msgcat pack‐ │
201 age including all settings and translations.
202
204 The locale is specified to msgcat by a locale string passed to ::msg‐
205 cat::mclocale. The locale string consists of a language code, an op‐
206 tional country code, and an optional system-specific code, each sepa‐
207 rated by “_”. The country and language codes are specified in stan‐
208 dards ISO-639 and ISO-3166. For example, the locale “en” specifies
209 English and “en_US” specifies U.S. English.
210
211 When the msgcat package is first loaded, the locale is initialized ac‐
212 cording to the user's environment. The variables env(LC_ALL),
213 env(LC_MESSAGES), and env(LANG) are examined in order. The first of
214 them to have a non-empty value is used to determine the initial locale.
215 The value is parsed according to the XPG4 pattern
216
217 language[_country][.codeset][@modifier]
218
219 to extract its parts. The initial locale is then set by calling ::msg‐
220 cat::mclocale with the argument
221
222 language[_country][_modifier]
223
224 On Windows and Cygwin, if none of those environment variables is set,
225 msgcat will attempt to extract locale information from the registry.
226 From Windows Vista on, the RFC4747 locale name "lang-script-country-op‐
227 tions" is transformed to the locale as "lang_country_script" (Example:
228 sr-Latn-CS -> sr_cs_latin). For Windows XP, the language id is trans‐
229 formed analoguously (Example: 0c1a -> sr_yu_cyrillic). If all these
230 attempts to discover an initial locale from the user's environment
231 fail, msgcat defaults to an initial locale of “C”.
232
233 When a locale is specified by the user, a “best match” search is per‐
234 formed during string translation. For example, if a user specifies
235 en_GB_Funky, the locales “en_gb_funky”, “en_gb”, “en” and “” (the empty
236 string) are searched in order until a matching translation string is
237 found. If no translation string is available, then the unknown handler
238 is called.
239
241 Strings stored in the message catalog are stored relative to the name‐
242 space from which they were added. This allows multiple packages to use
243 the same strings without fear of collisions with other packages. It
244 also allows the source string to be shorter and less prone to typo‐
245 graphical error.
246
247 For example, executing the code
248
249 ::msgcat::mcset en hello "hello from ::"
250 namespace eval foo {
251 ::msgcat::mcset en hello "hello from ::foo"
252 }
253 puts [::msgcat::mc hello]
254 namespace eval foo {puts [::msgcat::mc hello]}
255
256 will print
257
258 hello from ::
259 hello from ::foo
260
261 When searching for a translation of a message, the message catalog will
262 search first the current namespace, then the parent of the current
263 namespace, and so on until the global namespace is reached. This al‐
264 lows child namespaces to “inherit” messages from their parent name‐
265 space.
266
267 For example, executing (in the “en” locale) the code
268
269 ::msgcat::mcset en m1 ":: message1"
270 ::msgcat::mcset en m2 ":: message2"
271 ::msgcat::mcset en m3 ":: message3"
272 namespace eval ::foo {
273 ::msgcat::mcset en m2 "::foo message2"
274 ::msgcat::mcset en m3 "::foo message3"
275 }
276 namespace eval ::foo::bar {
277 ::msgcat::mcset en m3 "::foo::bar message3"
278 }
279 namespace import ::msgcat::mc
280 puts "[mc m1]; [mc m2]; [mc m3]"
281 namespace eval ::foo {puts "[mc m1]; [mc m2]; [mc m3]"}
282 namespace eval ::foo::bar {puts "[mc m1]; [mc m2]; [mc m3]"}
283
284 will print
285
286 :: message1; :: message2; :: message3
287 :: message1; ::foo message2; ::foo message3
288 :: message1; ::foo message2; ::foo::bar message3
289
291 Message files can be located in any directory, subject to the following
292 conditions:
293
294 [1] All message files for a package are in the same directory.
295
296 [2] The message file name is a msgcat locale specifier (all lower‐
297 case) followed by “.msg”. For example:
298
299 es.msg — spanish
300 en_gb.msg — United Kingdom English
301
302 Exception: The message file for the root locale “” is called
303 “ROOT.msg”. This exception is made so as not to cause peculiar behav‐
304 ior, such as marking the message file as “hidden” on Unix file systems.
305
306 [3] The file contains a series of calls to mcflset and mcflmset,
307 setting the necessary translation strings for the language,
308 likely enclosed in a namespace eval so that all source strings
309 are tied to the namespace of the package. For example, a short
310 es.msg might contain:
311
312 namespace eval ::mypackage {
313 ::msgcat::mcflset "Free Beer" "Cerveza Gratis"
314 }
315
317 If a package is installed into a subdirectory of the tcl_pkgPath and
318 loaded via package require, the following procedure is recommended.
319
320 [1] During package installation, create a subdirectory msgs under
321 your package directory.
322
323 [2] Copy your *.msg files into that directory.
324
325 [3] Add the following command to your package initialization script:
326
327 # load language files, stored in msgs subdirectory
328 ::msgcat::mcload [file join [file dirname [info script]] msgs]
329
331 It is possible that a message string used as an argument to format
332 might have positionally dependent parameters that might need to be
333 repositioned. For example, it might be syntactically desirable to re‐
334 arrange the sentence structure while translating.
335
336 format "We produced %d units in location %s" $num $city
337 format "In location %s we produced %d units" $city $num
338
339 This can be handled by using the positional parameters:
340
341 format "We produced %1\$d units in location %2\$s" $num $city
342 format "In location %2\$s we produced %1\$d units" $num $city
343
344 Similarly, positional parameters can be used with scan to extract val‐
345 ues from internationalized strings. Note that it is not necessary to
346 pass the output of ::msgcat::mc to format directly; by passing the val‐
347 ues to substitute in as arguments, the formatting substitution is done
348 directly.
349
350 msgcat::mc {Produced %1$d at %2$s} $num $city
351 # ... where that key is mapped to one of the
352 # human-oriented versions by msgcat::mcset
353
355 A package using msgcat may choose to use its own package private locale │
356 and its own set of loaded locales, independent to the global locale set │
357 by ::msgcat::mclocale. │
358
359 This allows a package to change its locale without causing any locales │
360 load or removal in other packages and not to invoke the global locale │
361 change callback (see below). │
362
363 This action is controled by the following ensemble: │
364
365 ::msgcat::mcpackagelocale set ?locale? │
366 Set or change a package private locale. The package private lo‐ │
367 cale is set to the given locale if the locale is given. If the │
368 option locale is not given, the package is set to package pri‐ │
369 vate locale mode, but no locale is changed (e.g. if the global │
370 locale was valid for the package before, it is copied to the │
371 package private locale). │
372
373 This command may cause the load of locales. │
374
375 ::msgcat::mcpackagelocale get │
376 Return the package private locale or the global locale, if no │
377 package private locale is set. │
378
379 ::msgcat::mcpackagelocale preferences │
380 Return the package private preferences or the global prefer‐ │
381 ences, if no package private locale is set. │
382
383 ::msgcat::mcpackagelocale loaded │
384 Return the list of locales loaded for this package. │
385
386 ::msgcat::mcpackagelocale isset │
387 Returns true, if a package private locale is set. │
388
389 ::msgcat::mcpackagelocale unset │
390 Unset the package private locale and use the globale locale. │
391 Load and remove locales to adjust the list of loaded locales for │
392 the package to the global loaded locales list. │
393
394 ::msgcat::mcpackagelocale present locale │
395 Returns true, if the given locale is loaded for the package. │
396
397 ::msgcat::mcpackagelocale clear │
398 Clear any loaded locales of the package not present in the pack‐ │
399 age preferences. │
400
402 Each package using msgcat has a set of options within msgcat. The │
403 package options are described in the next sectionPackage options. Each │
404 package option may be set or unset individually using the following en‐ │
405 semble: │
406
407 ::msgcat::mcpackageconfig get option │
408 Return the current value of the given option. This call returns │
409 an error if the option is not set for the package. │
410
411 ::msgcat::mcpackageconfig isset option │
412 Returns 1, if the given option is set for the package, 0 other‐ │
413 wise. │
414
415 ::msgcat::mcpackageconfig set option value │
416 Set the given option to the given value. This may invoke addi‐ │
417 tional actions in dependency of the option. The return value is │
418 0 or the number of loaded packages for the option mcfolder. │
419
420 ::msgcat::mcpackageconfig unset option │
421 Unsets the given option for the package. No action is taken if │
422 the option is not set for the package. The empty string is re‐ │
423 turned. │
424
425 Package options │
426 The following package options are available for each package: │
427
428 mcfolder │
429 This is the message folder of the package. This option is set by │
430 mcload and by the subcommand set. Both are identical and both │
431 return the number of loaded message catalog files. │
432
433 Setting or changing this value will load all locales contained │
434 in the preferences valid for the package. This implies also to │
435 invoke any set loadcmd (see below). │
436
437 Unsetting this value will disable message file load for the │
438 package. │
439
440 loadcmd │
441 This callback is invoked before a set of message catalog files │
442 are loaded for the package which has this property set. │
443
444 This callback may be used to do any preparation work for message │
445 file load or to get the message data from another source like a │
446 data base. In this case, no message files are used (mcfolder is │
447 unset). │
448
449 See section callback invocation below. The parameter list ap‐ │
450 pended to this callback is the list of locales to load. │
451
452 If this callback is changed, it is called with the preferences │
453 valid for the package. │
454
455 changecmd │
456 This callback is invoked when a default local change was per‐ │
457 formed. Its purpose is to allow a package to update any depen‐ │
458 dency on the default locale like showing the GUI in another lan‐ │
459 guage. │
460
461 See the callback invocation section below. The parameter list │
462 appended to this callback is mcpreferences. The registered │
463 callbacks are invoked in no particular order. │
464
465 unknowncmd │
466 Use a package locale mcunknown procedure instead of the standard │
467 version supplied by the msgcat package (msgcat::mcunknown). │
468
469 The called procedure must return the formatted message which │
470 will finally be returned by msgcat::mc. │
471
472 A generic unknown handler is used if set to the empty string. │
473 This consists in returning the key if no arguments are given. │
474 With given arguments, format is used to process the arguments. │
475
476 See section callback invocation below. The appended arguments │
477 are identical to ::msgcat::mcunknown. │
478
479 Callback invocation │
480 A package may decide to register one or multiple callbacks, as de‐ │
481 scribed above. │
482
483 Callbacks are invoked, if: │
484
485 1. the callback command is set, │
486
487 2. the command is not the empty string, │
488
489 3. the registering namespace exists. │
490
491 If a called routine fails with an error, the bgerror routine for the │
492 interpreter is invoked after command completion. Only exception is the │
493 callback unknowncmd, where an error causes the invoking mc-command to │
494 fail with that error. │
495
496 Examples │
497 Packages which display a GUI may update their widgets when the global │
498 locale changes. To register to a callback, use: │
499 namespace eval gui { │
500 msgcat::mcpackageconfig changecmd updateGUI │
501
502 proc updateGUI args { │
503 puts "New locale is '[lindex $args 0]'." │
504 } │
505 } │
506 % msgcat::mclocale fr │
507 fr │
508 % New locale is 'fr'. │
509
510 If locales (or additional locales) are contained in another source like │
511 a data base, a package may use the load callback and not mcload: │
512 namespace eval db { │
513 msgcat::mcpackageconfig loadcmd loadMessages │
514
515 proc loadMessages args { │
516 foreach locale $args { │
517 if {[LocaleInDB $locale]} { │
518 msgcat::mcmset $locale [GetLocaleList $locale] │
519 } │
520 } │
521 } │
522 } │
523
524 The clock command implementation uses msgcat with a package locale to │
525 implement the command line parameter -locale. Here are some sketches │
526 of the implementation: │
527
528 First, a package locale is initialized and the generic unknown function │
529 is desactivated: │
530 msgcat::mcpackagelocale set │
531 msgcat::mcpackageconfig unknowncmd "" │
532 As an example, the user requires the week day in a certain locale as │
533 follows: │
534 clock format [clock seconds] -format %A -locale fr │
535 clock sets the package locale to fr and looks for the day name as fol‐ │
536 lows: │
537 msgcat::mcpackagelocale set $locale │
538 return [lindex [msgcat::mc DAYS_OF_WEEK_FULL] $day] │
539 ### Returns "mercredi" │
540 Within clock, some message-catalog items are heavy in computation and │
541 thus are dynamically cached using: │
542 proc ::tcl::clock::LocalizeFormat { locale format } { │
543 set key FORMAT_$format │
544 if { [::msgcat::mcexists -exactlocale -exactnamespace $key] } {│
545 return [mc $key] │
546 } │
547 #...expensive computation of format clipped... │
548 mcset $locale $key $format │
549 return $format │
550 } │
551
553 The message catalog code was developed by Mark Harrison.
554
556 format(n), scan(n), namespace(n), package(n)
557
559 internationalization, i18n, localization, l10n, message, text, transla‐
560 tion
561
562
563
564msgcat 1.5 msgcat(n)