Version 42 of msgcat

Updated 2007-03-06 19:38:23 by LES

Purpose: information relating to the message catalog interface.


Documentation can be found at http://www.purl.org/tcl/home/man/tcl8.4/TclCmd/msgcat.htm


The msgcat package (standard with Tcl since 8.1) addresses the problem of hard coded application text.

Instead of

 label .x -text Files

if you write

 label .x -text [mc Files]

then you can create catalog entries for various languages for the term "Files". Also, mc will apply formatting to the string, so

 puts [mc "Directory contains %d files" $nfiles]

will allow a translator to work with the string "Directory contains %d files".

The above example assumes you have once invoked

 package require msgcat ;# and done 
 namespace import msgcat::* ;# (or msgcat::mc).

Provided you have .msg files containing

 ::msgcat::mcset de Files Dateien
 ::msgcat::mcset fr Files Fichiers

(notice that the rootname part has the naming convention that it shall be the contained language - for e.g. locale "en_us_funky", msgcat searches the contents of first en_us_funky.msg, then en_us.msg, then en.msg) then either automagically (when env(LANG) is accordingly set) or by

 ::msgcat::mclocale fr

.x will have the text "Fichiers".

If you want to package your messages into the application file, you can as well do this with mcset. See Multilingual menu and A little stopwatch for examples.


Note that msgcat 1.3 (comes with Tcl 8.4) also initializes the locale from ::env(LC_ALL) or ::env(LC_MESSAGES).

LES: I don't have ::env(LC_ALL) and ::env(LC_MESSAGES) on Slackware 11.


Arjen Markus This came up in the newsgroup:

The utility frink is able to adjust the source code so that the new code uses the msgcat package.


The 8.3.4 release of the PPC binary is broken in that it lacks msgcat and bgerror implementations. Melissa Schrumpf explains the situation with her customary clarity

    ... bgerror and msgcat are contained in tcl/library/msgcat/msgcat.tcl.

    Do this:

    Copy "Simply Tk (PPC)" to "Simply Tk (PPC).edit"

    Run ResEdit (or Resourcer, or whathaveyou).  Open a "Simply Tk
    (PPC).edit" in ResEdit.  Open the "TEXT" resources.  Open resource ID
       "package require msgcat"

    This will be right at the top.

    Next, open tcl/library/msgcat/msgcat.tcl in a text editor.  Copy from
    the beginning of the line:

       package provide msgcat 1.1.1  




    through to the end of the file.

    Return to ResEdit.  Delete the line "package require msgcat" and,
    in its place, paste the code you copied from msgcat.tcl.
    Close all resources and save.

    You now have a fixed stand-alone Tk shell.      

Anton Kovalenko has written, "Also, there is a small but useful script, which converts non-ascii characters from current system encoding to \uXXXX sequences. I think it would be useful to anyone who works often with tcl message catalogs. http://kovalenko.webzone.ru/unicodize.tcl (A/AK: chat.ru is down, so my page migrated) "

LES: "Forbidden. You don't have permission to access /unicodize.tcl on this server."


A/AK: there are some things about msgcat and shortcut keys, that are important for GUI application writers. EKB And this seems to have been continued into ampersand magic.


KHM Any Idea where to download this tool?

LV KHM - msgcat is a part of Tcl itself. Or are you talking about some other tool?


GNU gettext has support (since V 0.13 [L1 ]) for Tcl msgcat and conversion tools from and to PO format. http://ftp.gnu.org/gnu/gettext/


Simple Tk example of switching languages, complements of dgp:

 package require Tk

 bgerror 123

 msgcat::mclocale "fr"
 msgcat::mcload [file join $::tk_library msgs]
 bgerror 123

 msgcat::mclocale "en_gb"
 msgcat::mcload [file join $::tk_library msgs]
 bgerror 123

Now, how can I determine what languages are available for mclocale?


escargo 8 Dec 2003 - What if you want to do some form of parameter substitution in the strings that you might use with msgcat? In some systems I have developed, messages were somewhat macro-like; you might pass a number or a name (of a file, for example) that should be part of the message. Is there anything in the msgcat that does the substitution internally, or do I have to add my own layer on top of it?

RS: Easy, for instance with format:

 msgcat::mcset fr "Directory contains %d files" "Il y a %d fichiers"
 ...
 puts [format [mc "Directory contains %d files"] $nfiles]

AM Also very useful: the %$1s type format codes - with this you can interchange variables if needed.

-- I should insert an example --

DGP Even easier. There's a format already built-in to mc:

 puts [mc "Directory contains %d files" $nfiles]

EKB I moved this example up to the top of the page and combined it with the intro text so it's easier to find.


Examples of using msgcat:


RS 2007-01-08: Here's a simple self-contained example for testing:

 #!/usr/bin/env tclsh
 package require msgcat

 msgcat::mcset de yes Ja
 msgcat::mcset de no  Nein
 msgcat::mcset fr yes Oui
 msgcat::mcset fr no  Non

 proc localbool value {
    if {$value} {msgcat::mc yes} else {msgcat::mc no}
 }
 puts [localbool 0]/[localbool 1]

That's all. Save that to a file, and run it with different LANG settings:

 $ /Tcl/msgcat.tcl
 Nein/Ja
 $ LANG=fr /Tcl/msgcat.tcl
 Non/Oui
 $ LANG=en /Tcl/msgcat.tcl
 no/yes

Back to Tcl core extension syntax.


See also:


Tcl syntax help - Arts and crafts of Tcl-Tk programming

Category Command - Category Local - Category String Processing