From 7a43bd40e805191b59ac6cd750192c6a105e36a7 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 17 Jun 2002 05:37:39 +0000 Subject: * Revised locale initialization to interpret environment variable locale values according to XPG4, and to recognize the LC_ALL and LC_MESSAGES values over that of LANG. Also added many Windows Registry locale values to those recognized by msgcat. Revised tests and docs. Bumped to version 1.3. Thanks to Bruno Haible for the report and assistance crafting the solution. [Bug 525522, 525525] --- ChangeLog | 13 + doc/msgcat.n | 83 +++-- library/msgcat/msgcat.tcl | 191 ++++++---- library/msgcat/pkgIndex.tcl | 2 +- tests/msgcat.test | 883 +++++++++++++++++++++++++------------------- 5 files changed, 692 insertions(+), 480 deletions(-) diff --git a/ChangeLog b/ChangeLog index 87b89dd..546fab6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2002-06-17 Don Porter + + * doc/msgcat.n: + * library/msgcat/msgcat.tcl: + * library/msgcat/pkgIndex.tcl: + * tests/msgcat.test: Revised locale initialization to interpret + environment variable locale values according to XPG4, and to + recognize the LC_ALL and LC_MESSAGES values over that of LANG. + Also added many Windows Registry locale values to those + recognized by msgcat. Revised tests and docs. Bumped to + version 1.3. Thanks to Bruno Haible for the report and + assistance crafting the solution. [Bug 525522, 525525] + 2002-06-16 Miguel Sofer * generic/tclCompile.c (TclCompileTokens): a better algorithm for diff --git a/doc/msgcat.n b/doc/msgcat.n index dddf499..2fb5591 100644 --- a/doc/msgcat.n +++ b/doc/msgcat.n @@ -15,7 +15,7 @@ msgcat \- Tcl message catalog .SH SYNOPSIS \fBpackage require Tcl 8.2\fR .sp -\fBpackage require msgcat 1.2\fR +\fBpackage require msgcat 1.3\fR .sp \fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR? .sp @@ -80,37 +80,46 @@ fixed width (which will be the width of the widest button). \fB::msgcat::mclocale \fR?\fInewLocale\fR? This function sets the locale to \fInewLocale\fR. If \fInewLocale\fR is omitted, the current locale is returned, otherwise the current locale -is set to \fInewLocale\fR. -The initial locale defaults to the locale specified in -the user's environment. See \fBLOCALE AND SUBLOCALE SPECIFICATION\fR +is set to \fInewLocale\fR. msgcat stores and compares the locale in a +case-insensitive manner, and returns locales in lowercase. +The initial locale is determined by the locale specified in +the user's environment. See \fBLOCALE SPECIFICATION\fR below for a description of the locale string format. .TP \fB::msgcat::mcpreferences\fR Returns an ordered list of the locales preferred by the user, based on the user's language specification. The list is ordered from most specific to least -preference. If the user has specified LANG=en_US_funky, -this procedure would return {en_US_funky en_US en}. +preference. The list is derived from the current +locale set in msgcat by \fBmsgcat::mclocale\fR, and +cannot be set independently. For example, if the +current locale is en_US_funky, then \fBmsgcat::mcpreferences\fR +returns {en_US_funky en_US en}. .TP \fB::msgcat::mcload \fIdirname\fR Searches the specified directory for files that match -the language specifications returned by \fB::msgcat::mcpreferences\fR. -Each file located is sourced. The file extension is ``.msg''. -The number of message files which matched the specification +the language specifications returned by \fB::msgcat::mcpreferences\fR, +extended by the file extension ``.msg''. Each matching file is +read in order, assuming a UTF-8 encoding. The file contents are +then evaluated as a Tcl script. This means that non-Latin characters +may be present in the message file either directly in their UTF-8 +encoded form, or by use of the backslash-u quoting recognized by Tcl +evaluation. The number of message files which matched the specification and were loaded is returned. .TP \fB::msgcat::mcset \fIlocale src-string \fR?\fItranslate-string\fR? Sets the translation for \fIsrc-string\fR to \fItranslate-string\fR -in the specified \fIlocale\fR. If \fItranslate-string\fR is not -specified, \fIsrc-string\fR is used for both. The function -returns \fItranslate-string\fR. +in the specified \fIlocale\fR and the current namespace. If +\fItranslate-string\fR is not specified, \fIsrc-string\fR is used +for both. The function returns \fItranslate-string\fR. .TP \fB::msgcat::mcmset \fIlocale src-trans-list\fR Sets the translation for multiple source strings in -\fIsrc-trans-list\fR in the specified \fIlocale\fR. +\fIsrc-trans-list\fR in the specified \fIlocale\fR and the current +namespace. \fIsrc-trans-list\fR must have an even number of elements and is in the form {\fIsrc-string translate-string\fR ?\fIsrc-string -translate-string ...\fR?} \fBmcsetcat::mcmset\fR can be significantly +translate-string ...\fR?} \fBmsgcat::mcmset\fR can be significantly faster than multiple invocations of \fBmsgcat::mcset\fR. The function returns the number of translations set. .TP @@ -125,22 +134,35 @@ same stack context as the call to \fB::msgcat::mc\fR. The return vaue of \fB::msgcat::mcunknown\fR is used as the return vaue for the call to \fB::msgcat::mc\fR. -.SH "LOCALE AND SUBLOCALE SPECIFICATION" +.SH "LOCALE SPECIFICATION" .PP -The locale is specified by a locale string. +The locale is specified to \fBmsgcat\fR by a locale string +passed to \fB::msgcat::mclocale\fR. The locale string consists of a language code, an optional country code, and an optional system-specific code, each separated by ``_''. The country and language codes are specified in standards ISO-639 and ISO-3166. -For example, the locale ``en'' specifies English and - ``en_US'' specifes U.S. English. +For example, the locale ``en'' specifies English and ``en_US'' specifies +U.S. English. .PP -The locale defaults to the value in \fBenv(LANG)\fR at the time the -\fBmsgcat\fR package is loaded. On Windows, if \fBenv(LANG)\fR is not -set, the package will attempt to extract locale information from the -registry. If it cannot find this information in the registry, or on -non-Windows platforms when \fBenv(LANG)\fR is not defined, the -locale defaults to ``C''. +When the msgcat package is first loaded, the locale is initialized +according to the user's environment. The variables \fBenv(LC_ALL)\fR, +\fBenv(LC_MESSAGES)\fR, and \fBenv(LANG)\fR are examined in order. +The first of them to have a non-empty value is used to determine the +initial locale. The value is parsed according to the XPG4 pattern +.CS +language[_country][.codeset][@modifier] +.CE +to extract its parts. The initial locale is then set by calling +\fBmsgcat::mclocale\fR with the argument +.CS +language[_country][_modifier] +.CE +On Windows, if none of those environment variables is set, msgcat will +attempt to extract locale information from the +registry. If all these attempts to discover an initial locale +from the user's environment fail, msgcat defaults to an initial +locale of ``C''. .PP When a locale is specified by the user, a ``best match'' search is performed during string translation. For example, if a user specifies @@ -177,7 +199,7 @@ then the parent of the current namespace, and so on until the global namespace is reached. This allows child namespaces to "inherit" messages from their parent namespace. .PP -For example, executing the code +For example, executing (in the ``en'' locale) the code .CS mcset en m1 ":: message1" mcset en m2 ":: message2" @@ -214,10 +236,15 @@ es.msg -- spanish en_UK.msg -- UK English .CE .IP [3] -The file contains a series of calls to mcset, setting the -necessary translation strings for the language. For example: +The file contains a series of calls to \fBmcset\fR and +\fBmcmset\fR, setting the necessary translation strings +for the language, likely enclosed in a \fBnamespace eval\fR +so that all source strings are tied to the namespace of +the package. For example, a short \fBes.msg\fR might contain: .CS -::msgcat::mcset es "Free Beer!" "Cerveza Gracias!" +namespace eval ::mypackage { + ::msgcat::mcset es "Free Beer!" "Cerveza Gracias!" +} .CE .SH "RECOMMENDED MESSAGE SETUP FOR PACKAGES" diff --git a/library/msgcat/msgcat.tcl b/library/msgcat/msgcat.tcl index 7299004..01b4477 100644 --- a/library/msgcat/msgcat.tcl +++ b/library/msgcat/msgcat.tcl @@ -10,25 +10,41 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: msgcat.tcl,v 1.13 2002/04/20 00:35:19 dgp Exp $ +# RCS: @(#) $Id: msgcat.tcl,v 1.14 2002/06/17 05:37:39 dgp Exp $ package require Tcl 8.2 -package provide msgcat 1.2.3 +package provide msgcat 1.3 namespace eval msgcat { namespace export mc mcload mclocale mcmax mcmset mcpreferences mcset \ mcunknown # Records the current locale as passed to mclocale - variable locale "" + variable Locale "" # Records the list of locales to search - variable loclist {} + variable Loclist {} # Records the mapping between source strings and translated strings. The # array key is of the form ",," and the value is # the translated string. - array set msgs {} + array set Msgs {} + + # Map of language codes used in Windows registry to those of ISO-639 + array set WinRegToISO639 { + 0409 en_US 0809 en_UK 43c gd 83c ga 01 ar 02 bg 03 ca 04 zh 05 + cs 06 da 07 de 08 el 0a es 0b fi 0c fr 0d he 0e hu 0f is 10 it + 11 ja 12 ko 13 da 14 no 15 pl 16 pt 17 rm 18 ro 19 ru 1a hr + 1b sk 1c sq 1d sv 1e th 1f tr 20 ur 21 id 22 uk 23 be 24 sl + 25 et 26 lv 27 lt 28 tg 29 fa 2a vi 2b hy 2c az 2d eu 2e wen + 2f mk 30 bnt 31 ts 33 ven 34 xh 35 zu 36 af 37 ka 38 fo 39 hi + 3a mt 3b se 3d yi 3e ms 3f kk 40 ky 41 sw 42 tk 43 uz 44 tt + 45 bn 46 pa 47 gu 48 or 49 ta 4a te 4b kn 4c ml 4d as 4e mr + 4f sa 50 mn 51 bo 52 cy 53 km 54 lo 55 my 56 gl 57 kok 58 mni + 59 sd 5a syr 5b si 5c chr 5d iu 5e am 5f ber 60 ks 61 ne 62 fy + 63 ps 64 tl 65 div 66 bin 67 ful 68 ha 69 nic 6a yo 70 ibo + 71 kau 72 om 73 ti 74 gn 75 cpe 76 la 77 so 78 sit 79 pap + } } # msgcat::mc -- @@ -51,20 +67,20 @@ proc msgcat::mc {src args} { # Check for the src in each namespace starting from the local and # ending in the global. - variable msgs - variable loclist - variable locale + variable Msgs + variable Loclist + variable Locale set ns [uplevel 1 [list ::namespace current]] while {$ns != ""} { - foreach loc $loclist { - if {[info exists msgs($loc,$ns,$src)]} { + foreach loc $Loclist { + if {[info exists Msgs($loc,$ns,$src)]} { if {[llength $args] == 0} { - return $msgs($loc,$ns,$src) + return $Msgs($loc,$ns,$src) } else { return [uplevel 1 \ - [linsert $args 0 ::format $msgs($loc,$ns,$src)]] + [linsert $args 0 ::format $Msgs($loc,$ns,$src)]] } } } @@ -72,7 +88,7 @@ proc msgcat::mc {src args} { } # we have not found the translation return [uplevel 1 \ - [linsert $args 0 [::namespace origin mcunknown] $locale $src]] + [linsert $args 0 [::namespace origin mcunknown] $Locale $src]] } # msgcat::mclocale -- @@ -88,8 +104,8 @@ proc msgcat::mc {src args} { # Returns the current locale. proc msgcat::mclocale {args} { - variable loclist - variable locale + variable Loclist + variable Locale set len [llength $args] if {$len > 1} { @@ -97,15 +113,15 @@ proc msgcat::mclocale {args} { } if {$len == 1} { - set locale [string tolower [lindex $args 0]] - set loclist {} + set Locale [string tolower [lindex $args 0]] + set Loclist {} set word "" - foreach part [split $locale _] { + foreach part [split $Locale _] { set word [string trimleft "${word}_${part}" _] - set loclist [linsert $loclist 0 $word] + set Loclist [linsert $Loclist 0 $word] } } - return $locale + return $Locale } # msgcat::mcpreferences -- @@ -120,8 +136,8 @@ proc msgcat::mclocale {args} { # Returns an ordered list of the locales preferred by the user. proc msgcat::mcpreferences {} { - variable loclist - return $loclist + variable Loclist + return $Loclist } # msgcat::mcload -- @@ -164,14 +180,14 @@ proc msgcat::mcload {langdir} { # Returns the new locale. proc msgcat::mcset {locale src {dest ""}} { - variable msgs + variable Msgs if {[string equal $dest ""]} { set dest $src } set ns [uplevel 1 [list ::namespace current]] - set msgs([string tolower $locale],$ns,$src) $dest + set Msgs([string tolower $locale],$ns,$src) $dest return $dest } @@ -187,7 +203,7 @@ proc msgcat::mcset {locale src {dest ""}} { # Returns the number of pairs processed proc msgcat::mcmset {locale pairs } { - variable msgs + variable Msgs set length [llength $pairs] if {$length % 2} { @@ -198,7 +214,7 @@ proc msgcat::mcmset {locale pairs } { set ns [uplevel 1 [list ::namespace current]] foreach {src dest} $pairs { - set msgs($locale,$ns,$src) $dest + set Msgs($locale,$ns,$src) $dest } return $length @@ -252,61 +268,76 @@ proc msgcat::mcmax {args} { return $max } -# Initialize the default locale +# 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 + regexp {^([^_.@]*)(_([^.@]*))?([.]([^@]*))?(@(.*))?$} $value \ + -> language _ territory _ codeset _ modifier + set ret $language + if {[string length $territory]} { + append ret _$territory + } + if {[string length $modifier]} { + append ret _$modifier + } + return $ret +} -namespace eval msgcat { +# Initialize the default locale +proc msgcat::Init {} { + # # set default locale, try to get from environment - if {[info exists ::env(LANG)]} { - mclocale $::env(LANG) - } else { - if { $tcl_platform(platform) == "windows" } { - # try to set locale depending on registry settings - # - set key {HKEY_CURRENT_USER\Control Panel\International} - if {[catch {package require registry}] || \ - [catch {registry get $key "locale"} locale]} { - mclocale "C" - } else { - - # - # Clean up registry value for translating LCID value - # by using only the last 2 digits, since first - # 2 digits appear to be the country... For example - # 0409 - English - United States - # 0809 - English - United Kingdom - # - set locale [string trimleft $locale "0"] - set locale [string range $locale end-1 end] - set locale [string tolower $locale] - switch -- $locale { - 01 { mclocale "ar" } - 02 { mclocale "bg" } - 03 { mclocale "ca" } - 04 { mclocale "zh" } - 05 { mclocale "cs" } - 06 { mclocale "da" } - 07 { mclocale "de" } - 08 { mclocale "el" } - 09 { mclocale "en" } - 0a { mclocale "es" } - 0b { mclocale "fi" } - 0c { mclocale "fr" } - 0d { mclocale "he" } - 0e { mclocale "hu" } - 0f { mclocale "is" } - 10 { mclocale "it" } - 11 { mclocale "ja" } - 12 { mclocale "ko" } - 13 { mclocale "da" } - 14 { mclocale "no" } - 15 { mclocale "pl" } - 16 { mclocale "pt" } - - default { mclocale "C" } - } - } - } else { - mclocale "C" - } + # + foreach varName {LC_ALL LC_MESSAGES LANG} { + if {[info exists ::env($varName)] + && ![string equal "" $::env($varName)]} { + mclocale [ConvertLocale $::env($varName)] + return + } + } + # + # On Windows, try to set locale depending on registry settings, + # or fall back on locale of "C". Other platforms will return + # when they fail to load the registry package. + # + set key {HKEY_CURRENT_USER\Control Panel\International} + if {[catch {package require registry}] \ + || [catch {registry get $key "locale"} 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 $WinRegToISO639($locale)}]} { + return + } + set locale [string range $locale 1 end] } + # + # No translation known. Fall back on "C" locale + # + mclocale C } +msgcat::Init diff --git a/library/msgcat/pkgIndex.tcl b/library/msgcat/pkgIndex.tcl index cc1af0c..9d16a19 100644 --- a/library/msgcat/pkgIndex.tcl +++ b/library/msgcat/pkgIndex.tcl @@ -1,2 +1,2 @@ if {![package vsatisfies [package provide Tcl] 8.2]} {return} -package ifneeded msgcat 1.2.3 [list source [file join $dir msgcat.tcl]] +package ifneeded msgcat 1.3 [list source [file join $dir msgcat.tcl]] diff --git a/tests/msgcat.test b/tests/msgcat.test index 633c869..2ea01cd 100644 --- a/tests/msgcat.test +++ b/tests/msgcat.test @@ -1,330 +1,457 @@ -# Commands covered: ::msgcat::mc ::msgcat::mclocale -# ::msgcat::mcpreferences ::msgcat::mcload -# ::msgcat::mcset ::msgcat::mcmset ::msgcat::mcunknown -# -# This file contains a collection of tests for the msgcat script library. +# This file contains a collection of tests for the msgcat package. # Sourcing this file into Tcl runs the tests and # generates output for errors. No output means no errors were found. # # Copyright (c) 1998 Mark Harrison. # Copyright (c) 1998-1999 by Scriptics Corporation. +# Contributions from Don Porter, NIST, 2002. (not subject to US copyright) # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: msgcat.test,v 1.10 2000/07/17 22:25:26 ericm Exp $ +# Note that after running these tests, entries will be left behind in the +# message catalogs for locales foo, foo_BAR, and foo_BAR_baz. +# +# RCS: @(#) $Id: msgcat.test,v 1.11 2002/06/17 05:37:39 dgp Exp $ -if {[lsearch [namespace children] ::tcltest] == -1} { - package require tcltest - namespace import -force ::tcltest::* +package require Tcl 8.2 +if {[catch {package require tcltest 2}]} { + puts stderr "Skipping tests in [info script]. tcltest 2 required." + return } +if {[catch {package require msgcat 1.3}]} { + puts stderr "Skipping tests in [info script]. No msgcat 1.3 found to test." + return +} + +namespace eval ::msgcat::test { + namespace import ::msgcat::* + namespace import ::tcltest::test + namespace import ::tcltest::cleanupTests + namespace import ::tcltest::temporaryDirectory + namespace import ::tcltest::make* + namespace import ::tcltest::remove* -if {[catch {package require msgcat 1.0}]} { - if {[info exist msgcat1]} { - catch {puts "Cannot load msgcat 1.0 package"} - return - } else { - catch {puts "Running msgcat 1.0 tests in slave interp"} - set interp [interp create msgcat1] - $interp eval [list set msgcat1 "running"] - $interp eval [list source [info script]] - interp delete $interp - return + # Tests msgcat-0.*: locale initialization + + proc PowerSet {l} { + if {[llength $l] == 0} {return [list [list]]} + set element [lindex $l 0] + set rest [lrange $l 1 end] + set result [list] + foreach x [PowerSet $rest] { + lappend result [linsert $x 0 $element] + lappend result $x + } + return $result } -} -set oldlocale [::msgcat::mclocale] + variable envVars {LC_ALL LC_MESSAGES LANG} + variable count 0 + variable body + variable result + variable setVars + foreach setVars [PowerSet $envVars] { + set result [string tolower [lindex $setVars 0]] + if {[string length $result] == 0} { + set result c + } + test msgcat-0.$count { + locale initialization from environment variables + } -setup { + variable var + foreach var $envVars { + catch {variable $var $::env($var)} + catch {unset ::env($var)} + } + foreach var $setVars { + set ::env($var) $var + } + interp create [namespace current]::i + i eval [list package ifneeded msgcat [package provide msgcat] \ + [package ifneeded msgcat [package provide msgcat]]] + i eval package require msgcat + } -cleanup { + interp delete [namespace current]::i + foreach var $envVars { + catch {unset ::env($var)} + catch {set ::env($var) [set [namespace current]::$var]} + } + } -body {i eval msgcat::mclocale} -result $result + incr count + } + catch {unset result} + + # Could add tests of initialization from Windows registry here. + # Use a fake registry package. -# some tests fail in tne environment variable LANG exists and is not C + # Tests msgcat-1.*: [mclocale], [mcpreferences] -if {[info exists env(LANG)] && ($env(LANG) != "C")} { - set ::tcltest::testConstraints(LANGisC) 0 -} else { - set ::tcltest::testConstraints(LANGisC) 1 -} + test msgcat-1.3 {mclocale set, single element} -setup { + variable locale [mclocale] + } -cleanup { + mclocale $locale + } -body { + mclocale en + } -result en -# -# Test the various permutations of mclocale -# and mcpreferences. -# + test msgcat-1.4 {mclocale get, single element} -setup { + variable locale [mclocale] + mclocale en + } -cleanup { + mclocale $locale + } -body { + mclocale + } -result en -test msgcat-1.1 {::msgcat::mclocale default} {LANGisC} { - ::msgcat::mclocale -} {c} -test msgcat-1.2 {::msgcat::mcpreferences, single element} {LANGisC} { - ::msgcat::mcpreferences -} {c} -test msgcat-1.3 {::msgcat::mclocale, single element} { - ::msgcat::mclocale en -} {en} -test msgcat-1.4 {::msgcat::mclocale, single element} { - ::msgcat::mclocale -} {en} -test msgcat-1.5 {::msgcat::mcpreferences, single element} { - ::msgcat::mcpreferences -} {en} -test msgcat-1.6 {::msgcat::mclocale, two elements} { - ::msgcat::mclocale en_US -} {en_us} -test msgcat-1.7 {::msgcat::mclocale, two elements} { - ::msgcat::mclocale en_US - ::msgcat::mclocale -} {en_us} -test msgcat-1.8 {::msgcat::mcpreferences, two elements} { - ::msgcat::mcpreferences -} {en_us en} -test msgcat-1.9 {::msgcat::mclocale, three elements} { - ::msgcat::mclocale en_US_funky -} {en_us_funky} -test msgcat-1.10 {::msgcat::mclocale, three elements} { - ::msgcat::mclocale -} {en_us_funky} -test msgcat-1.11 {::msgcat::mcpreferences, three elements} { - ::msgcat::mcpreferences -} {en_us_funky en_us en} + test msgcat-1.5 {mcpreferences, single element} -setup { + variable locale [mclocale] + mclocale en + } -cleanup { + mclocale $locale + } -body { + mcpreferences + } -result en -# -# Test mcset and mc, ensuring that namespace partitioning -# is working. -# + test msgcat-1.6 {mclocale set, two elements} -setup { + variable locale [mclocale] + } -cleanup { + mclocale $locale + } -body { + mclocale en_US + } -result en_us -test msgcat-2.1 {::msgcat::mcset, global scope} { - ::msgcat::mcset foo_BAR text1 text2 -} {text2} -test msgcat-2.2 {::msgcat::mcset, global scope, default} { - ::msgcat::mcset foo_BAR text3 -} {text3} -test msgcat-2.2 {::msgcat::mcset, namespace overlap} { - namespace eval bar {::msgcat::mcset foo_BAR con1 con1bar} - namespace eval baz {::msgcat::mcset foo_BAR con1 con1baz} -} {con1baz} -test msgcat-2.3 {::msgcat::mcset, namespace overlap} { - ::msgcat::mclocale foo_BAR - namespace eval bar {::msgcat::mc con1} -} {con1bar} -test msgcat-2.4 {::msgcat::mcset, namespace overlap} { - ::msgcat::mclocale foo_BAR - namespace eval baz {::msgcat::mc con1} -} {con1baz} -test msgcat-2.5 {::msgcat::mcmset, global scope} { - ::msgcat::mcmset foo_BAR { - src1 trans1 - src2 trans2 - } - ::msgcat::mc src1 -} {trans1} -test msgcat-2.6 {::msgcat::mcmset, namespace overlap} { - namespace eval bar {::msgcat::mcmset foo_BAR {con2 con2bar}} - namespace eval baz {::msgcat::mcmset foo_BAR {con2 con2baz}} -} {2} -test msgcat-2.7 {::msgcat::mcmset, namespace overlap} { - ::msgcat::mclocale foo_BAR - namespace eval baz {::msgcat::mc con2} -} {con2baz} + test msgcat-1.7 {mclocale get, two elements} -setup { + variable locale [mclocale] + mclocale en_US + } -cleanup { + mclocale $locale + } -body { + mclocale + } -result en_us + test msgcat-1.8 {mcpreferences, two elements} -setup { + variable locale [mclocale] + mclocale en_US + } -cleanup { + mclocale $locale + } -body { + mcpreferences + } -result {en_us en} -# -# Test mcset and mc, ensuring that more specific locales -# (e.g. "en_UK") will search less specific locales -# (e.g. "en") for translation strings. -# -# Do this for the 12 permutations of -# locales: {foo foo_BAR foo_BAR_baz} -# strings: {ov1 ov2 ov3 ov4} -# locale foo defines ov1, ov2, ov3 -# locale foo_BAR defines ov2, ov3 -# locale foo_BAR_BAZ defines ov3 -# (ov4 is defined in none) -# So, -# ov3 should be resolved in foo, foo_BAR, foo_BAR_baz -# ov2 should be resolved in foo, foo_BAR -# ov2 should resolve to foo_BAR in foo_BAR_baz -# ov1 should be resolved in foo -# ov1 should resolve to foo in foo_BAR, foo_BAR_baz -# ov4 should be resolved in none, and call mcunknown -# + test msgcat-1.9 {mclocale set, three elements} -setup { + variable locale [mclocale] + } -cleanup { + mclocale $locale + } -body { + mclocale en_US_funky + } -result en_us_funky -test msgcat-3.1 {::msgcat::mcset, overlap} { - ::msgcat::mcset foo ov1 ov1_foo - ::msgcat::mcset foo ov2 ov2_foo - ::msgcat::mcset foo ov3 ov3_foo - ::msgcat::mcset foo_BAR ov2 ov2_foo_BAR - ::msgcat::mcset foo_BAR ov3 ov3_foo_BAR - ::msgcat::mcset foo_BAR_baz ov3 ov3_foo_BAR_baz -} {ov3_foo_BAR_baz} -# top level, locale foo -test msgcat-3.2 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo - ::msgcat::mc ov1 -} {ov1_foo} -test msgcat-3.3 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo - ::msgcat::mc ov2 -} {ov2_foo} -test msgcat-3.4 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo - ::msgcat::mc ov3 -} {ov3_foo} -test msgcat-3.5 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo - ::msgcat::mc ov4 -} {ov4} -# second level, locale foo_BAR -test msgcat-3.6 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo_BAR - ::msgcat::mc ov1 -} {ov1_foo} -test msgcat-3.7 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo_BAR - ::msgcat::mc ov2 -} {ov2_foo_BAR} -test msgcat-3.8 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo_BAR - ::msgcat::mc ov3 -} {ov3_foo_BAR} -test msgcat-3.9 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo_BAR - ::msgcat::mc ov4 -} {ov4} -# third level, locale foo_BAR_baz -test msgcat-3.10 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo_BAR_baz - ::msgcat::mc ov1 -} {ov1_foo} -test msgcat-3.11 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo_BAR_baz - ::msgcat::mc ov2 -} {ov2_foo_BAR} -test msgcat-3.12 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo_BAR_baz - ::msgcat::mc ov3 -} {ov3_foo_BAR_baz} -test msgcat-3.13 {::msgcat::mcset, overlap} { - ::msgcat::mclocale foo_BAR_baz - ::msgcat::mc ov4 -} {ov4} + test msgcat-1.10 {mclocale get, three elements} -setup { + variable locale [mclocale] + mclocale en_US_funky + } -cleanup { + mclocale $locale + } -body { + mclocale + } -result en_us_funky -# -# Test mcunknown, first the default operation -# and then with an overridden definition. -# + test msgcat-1.11 {mcpreferences, three elements} -setup { + variable locale [mclocale] + mclocale en_US_funky + } -cleanup { + mclocale $locale + } -body { + mcpreferences + } -result {en_us_funky en_us en} + + # Tests msgcat-2.*: [mcset], [mcmset], namespace partitioning + + test msgcat-2.1 {mcset, global scope} { + namespace eval :: ::msgcat::mcset foo_BAR text1 text2 + } {text2} + + test msgcat-2.2 {mcset, global scope, default} { + namespace eval :: ::msgcat::mcset foo_BAR text3 + } {text3} + + test msgcat-2.2 {mcset, namespace overlap} { + namespace eval baz {::msgcat::mcset foo_BAR con1 con1baz} + } {con1baz} + + test msgcat-2.3 {mcset, namespace overlap} -setup { + namespace eval bar {::msgcat::mcset foo_BAR con1 con1bar} + namespace eval baz {::msgcat::mcset foo_BAR con1 con1baz} + variable locale [mclocale] + mclocale foo_BAR + } -cleanup { + mclocale $locale + } -body { + namespace eval bar {::msgcat::mc con1} + } -result con1bar + + test msgcat-2.4 {mcset, namespace overlap} -setup { + namespace eval bar {::msgcat::mcset foo_BAR con1 con1bar} + namespace eval baz {::msgcat::mcset foo_BAR con1 con1baz} + variable locale [mclocale] + mclocale foo_BAR + } -cleanup { + mclocale $locale + } -body { + namespace eval baz {::msgcat::mc con1} + } -result con1baz + + test msgcat-2.5 {mcmset, global scope} -setup { + namespace eval :: { + ::msgcat::mcmset foo_BAR { + src1 trans1 + src2 trans2 + } + } + variable locale [mclocale] + mclocale foo_BAR + } -cleanup { + mclocale $locale + } -body { + namespace eval :: { + ::msgcat::mc src1 + } + } -result trans1 -test msgcat-4.1 {::msgcat::mcunknown, default} { - ::msgcat::mcset foo unk1 "unknown 1" -} {unknown 1} -test msgcat-4.2 {::msgcat::mcunknown, default} { - ::msgcat::mclocale foo - ::msgcat::mc unk1 -} {unknown 1} -test msgcat-4.3 {::msgcat::mcunknown, default} { - ::msgcat::mclocale foo - ::msgcat::mc unk2 -} {unk2} -test msgcat-4.4 {::msgcat::mcunknown, overridden} { - rename ::msgcat::mcunknown oldproc - proc ::msgcat::mcunknown {dom s} { - return "unknown:$dom:$s" + test msgcat-2.6 {mcmset, namespace overlap} -setup { + namespace eval bar {::msgcat::mcmset foo_BAR {con2 con2bar}} + namespace eval baz {::msgcat::mcmset foo_BAR {con2 con2baz}} + variable locale [mclocale] + mclocale foo_BAR + } -cleanup { + mclocale $locale + } -body { + namespace eval bar {::msgcat::mc con2} + } -result con2bar + + test msgcat-2.7 {mcmset, namespace overlap} -setup { + namespace eval bar {::msgcat::mcmset foo_BAR {con2 con2bar}} + namespace eval baz {::msgcat::mcmset foo_BAR {con2 con2baz}} + variable locale [mclocale] + mclocale foo_BAR + } -cleanup { + mclocale $locale + } -body { + namespace eval baz {::msgcat::mc con2} + } -result con2baz + + # Tests msgcat-3.*: [mcset], [mc], catalog "inheritance" + # + # Test mcset and mc, ensuring that more specific locales + # (e.g. en_UK) will search less specific locales + # (e.g. en) for translation strings. + # + # Do this for the 12 permutations of + # locales: {foo foo_BAR foo_BAR_baz} + # strings: {ov1 ov2 ov3 ov4} + # locale foo defines ov1, ov2, ov3 + # locale foo_BAR defines ov2, ov3 + # locale foo_BAR_BAZ defines ov3 + # (ov4 is defined in none) + # So, + # ov3 should be resolved in foo, foo_BAR, foo_BAR_baz + # ov2 should be resolved in foo, foo_BAR + # ov2 should resolve to foo_BAR in foo_BAR_baz + # ov1 should be resolved in foo + # ov1 should resolve to foo in foo_BAR, foo_BAR_baz + # ov4 should be resolved in none, and call mcunknown + # + variable count 2 + variable result + array set result { + foo,ov1 ov1_foo foo,ov2 ov2_foo foo,ov3 ov3_foo foo,ov4 ov4 + foo_BAR,ov1 ov1_foo foo_BAR,ov2 ov2_foo_BAR foo_BAR,ov3 ov3_foo_BAR + foo_BAR,ov4 ov4 foo_BAR_baz,ov1 ov1_foo foo_BAR_baz,ov2 ov2_foo_BAR + foo_BAR_baz,ov3 ov3_foo_BAR_baz foo_BAR_baz,ov4 ov4 } - ::msgcat::mclocale foo - set result [::msgcat::mc unk1] - rename ::msgcat::mcunknown {} - rename oldproc ::msgcat::mcunknown - set result -} {unknown 1} -test msgcat-4.5 {::msgcat::mcunknown, overridden} { - rename ::msgcat::mcunknown oldproc - proc ::msgcat::mcunknown {dom s} { - return "unknown:$dom:$s" + variable loc + variable string + foreach loc {foo foo_BAR foo_BAR_baz} { + foreach string {ov1 ov2 ov3 ov4} { + test msgcat-3.$count {mcset, overlap} -setup { + mcset foo ov1 ov1_foo + mcset foo ov2 ov2_foo + mcset foo ov3 ov3_foo + mcset foo_BAR ov2 ov2_foo_BAR + mcset foo_BAR ov3 ov3_foo_BAR + mcset foo_BAR_baz ov3 ov3_foo_BAR_baz + variable locale [mclocale] + mclocale $loc + } -cleanup { + mclocale $locale + } -body { + mc $string + } -result $result($loc,$string) + incr count + } } - ::msgcat::mclocale foo - set result [::msgcat::mc unk2] - rename ::msgcat::mcunknown {} - rename oldproc ::msgcat::mcunknown - set result -} {unknown:foo:unk2} -test msgcat-4.6 {::msgcat::mcunknown, uplevel context} { - rename ::msgcat::mcunknown oldproc - proc ::msgcat::mcunknown {dom s} { - return "unknown:$dom:$s:[info level]" + catch {unset result} + + # Tests msgcat-4.*: [mcunknown] + + test msgcat-4.2 {mcunknown, default} -setup { + mcset foo unk1 "unknown 1" + variable locale [mclocale] + mclocale foo + } -cleanup { + mclocale $locale + } -body { + mc unk1 + } -result {unknown 1} + + test msgcat-4.3 {mcunknown, default} -setup { + mcset foo unk1 "unknown 1" + variable locale [mclocale] + mclocale foo + } -cleanup { + mclocale $locale + } -body { + mc unk2 + } -result unk2 + + test msgcat-4.4 {mcunknown, overridden} -setup { + rename ::msgcat::mcunknown SavedMcunknown + proc ::msgcat::mcunknown {dom s} { + return unknown:$dom:$s + } + mcset foo unk1 "unknown 1" + variable locale [mclocale] + mclocale foo + } -cleanup { + mclocale $locale + rename ::msgcat::mcunknown {} + rename SavedMcunknown ::msgcat::mcunknown + } -body { + mc unk1 + } -result {unknown 1} + + test msgcat-4.5 {mcunknown, overridden} -setup { + rename ::msgcat::mcunknown SavedMcunknown + proc ::msgcat::mcunknown {dom s} { + return unknown:$dom:$s + } + mcset foo unk1 "unknown 1" + variable locale [mclocale] + mclocale foo + } -cleanup { + mclocale $locale + rename ::msgcat::mcunknown {} + rename SavedMcunknown ::msgcat::mcunknown + } -body { + mc unk2 + } -result {unknown:foo:unk2} + + test msgcat-4.6 {mcunknown, uplevel context} -setup { + rename ::msgcat::mcunknown SavedMcunknown + proc ::msgcat::mcunknown {dom s} { + return "unknown:$dom:$s:[expr {[info level] - 1}]" + } + mcset foo unk1 "unknown 1" + variable locale [mclocale] + mclocale foo + } -cleanup { + mclocale $locale + rename ::msgcat::mcunknown {} + rename SavedMcunknown ::msgcat::mcunknown + } -body { + mc unk2 + } -result unknown:foo:unk2:[info level] + + # Tests msgcat-5.*: [mcload] + + variable locales {foo foo_BAR foo_BAR_baz} + makeDirectory msgdir + foreach loc $locales { + makeFile "::msgcat::mcset $loc abc abc-$loc" \ + [string tolower [file join msgdir $loc.msg]] + } + variable count 1 + foreach loc {foo foo_BAR foo_BAR_baz} { + test msgcat-5.$count {mcload} -setup { + variable locale [mclocale] + mclocale $loc + } -cleanup { + mclocale $locale + } -body { + mcload [file join [temporaryDirectory] msgdir] + } -result $count + incr count } - ::msgcat::mclocale foo - set result [::msgcat::mc unk2] - rename ::msgcat::mcunknown {} - rename oldproc ::msgcat::mcunknown - set result -} {unknown:foo:unk2:1} - -# -# Test mcload. Need to set up an environment for -# these tests by creating a temporary directory and -# message files. -# + # Even though foo_BAR_notexist does not exist, + # foo_BAR and foo should be loaded. + test msgcat-5.4 {mcload} -setup { + variable locale [mclocale] + mclocale foo_BAR_notexist + } -cleanup { + mclocale $locale + } -body { + mcload [file join [temporaryDirectory] msgdir] + } -result 2 -set locales {en en_US en_US_funky} + test msgcat-5.5 {mcload} -setup { + variable locale [mclocale] + mclocale no_FI_notexist + } -cleanup { + mclocale $locale + } -body { + mcload [file join [temporaryDirectory] msgdir] + } -result 0 -catch {file mkdir msgdir} -foreach l $locales { - set fd [open [string tolower [file join msgdir $l.msg]] w] - puts $fd "::msgcat::mcset $l abc abc-$l" - close $fd -} + test msgcat-5.6 {mcload} -setup { + variable locale [mclocale] + mclocale foo + } -cleanup { + mclocale $locale + } -body { + mc abc + } -result abc-foo -test msgcat-5.1 {::msgcat::mcload} { - ::msgcat::mclocale en - ::msgcat::mcload msgdir -} {1} -test msgcat-5.2 {::msgcat::mcload} { - ::msgcat::mclocale en_US - ::msgcat::mcload msgdir -} {2} -test msgcat-5.3 {::msgcat::mcload} { - ::msgcat::mclocale en_US_funky - ::msgcat::mcload msgdir -} {3} - -# Even though en_US_notexist does not exist, -# en_US and en should be loaded. - -test msgcat-5.4 {::msgcat::mcload} { - ::msgcat::mclocale en_US_notexist - ::msgcat::mcload msgdir -} {2} -test msgcat-5.5 {::msgcat::mcload} { - ::msgcat::mclocale no_FI_notexist - ::msgcat::mcload msgdir -} {0} -test msgcat-5.6 {::msgcat::mcload} { - ::msgcat::mclocale en - ::msgcat::mc abc -} {abc-en} -test msgcat-5.7 {::msgcat::mcload} { - ::msgcat::mclocale en_US - ::msgcat::mc abc -} {abc-en_US} -test msgcat-5.8 {::msgcat::mcload} { - ::msgcat::mclocale en_US_funky - ::msgcat::mc abc -} {abc-en_US_funky} -test msgcat-5.9 {::msgcat::mcload} { - rename ::msgcat::mcunknown oldproc - proc ::msgcat::mcunknown {dom s} { - return "unknown:$dom:$s" + test msgcat-5.7 {mcload} -setup { + variable locale [mclocale] + mclocale foo_BAR + } -cleanup { + mclocale $locale + } -body { + mc abc + } -result abc-foo_BAR + + test msgcat-5.8 {mcload} -setup { + variable locale [mclocale] + mclocale foo_BAR_baz + } -cleanup { + mclocale $locale + } -body { + mc abc + } -result abc-foo_BAR_baz + + test msgcat-5.9 {mcload} -setup { + rename ::msgcat::mcunknown SavedMcunknown + proc ::msgcat::mcunknown {dom s} { + return unknown:$dom:$s + } + variable locale [mclocale] + mclocale no_FI_notexist + } -cleanup { + mclocale $locale + rename ::msgcat::mcunknown {} + rename SavedMcunknown ::msgcat::mcunknown + } -body { + mc abc + } -result unknown:no_fi_notexist:abc + + + foreach loc $locales { + removeFile [string tolower [file join msgdir $loc.msg]] } - ::msgcat::mclocale no_FI_notexist - set result [::msgcat::mc abc] - rename ::msgcat::mcunknown {} - rename oldproc ::msgcat::mcunknown - set result -} {unknown:no_fi_notexist:abc} - -# cleanup temp files -foreach l $locales { - file delete [string tolower [file join msgdir $l.msg]] -} -# Clean out the msg catalogs -file delete msgdir + removeDirectory msgdir + # Tests msgcat-6.*: [mcset], [mc] namespace inheritance # # Test mcset and mc, ensuring that resolution for messages # proceeds from the current ns to its parent and so on to the @@ -332,7 +459,7 @@ file delete msgdir # # Do this for the 12 permutations of # locales: foo -# namespaces: ::foo ::foo::bar ::foo::bar::baz +# namespaces: foo foo::bar foo::bar::baz # strings: {ov1 ov2 ov3 ov4} # namespace ::foo defines ov1, ov2, ov3 # namespace ::foo::bar defines ov2, ov3 @@ -347,82 +474,96 @@ file delete msgdir # ov4 should be resolved in none, and call mcunknown # -namespace eval ::foo { - ::msgcat::mcset foo ov1 "ov1_foo" - ::msgcat::mcset foo ov2 "ov2_foo" - ::msgcat::mcset foo ov3 "ov3_foo" + variable result + array set result { + foo,ov1 ov1_foo foo,ov2 ov2_foo foo,ov3 ov3_foo foo,ov4 ov4 + foo::bar,ov1 ov1_foo foo::bar,ov2 ov2_foo_bar + foo::bar,ov3 ov3_foo_bar foo::bar,ov4 ov4 foo::bar::baz,ov1 ov1_foo + foo::bar::baz,ov2 ov2_foo_bar foo::bar::baz,ov3 ov3_foo_bar_baz + foo::bar::baz,ov4 ov4 + } + variable count 1 + variable ns + foreach ns {foo foo::bar foo::bar::baz} { + foreach string {ov1 ov2 ov3 ov4} { + test msgcat-6.$count {mcset, overlap} -setup { + namespace eval foo { + ::msgcat::mcset foo ov1 ov1_foo + ::msgcat::mcset foo ov2 ov2_foo + ::msgcat::mcset foo ov3 ov3_foo + namespace eval bar { + ::msgcat::mcset foo ov2 ov2_foo_bar + ::msgcat::mcset foo ov3 ov3_foo_bar + namespace eval baz { + ::msgcat::mcset foo ov3 "ov3_foo_bar_baz" + } + } + + } + variable locale [mclocale] + mclocale foo + } -cleanup { + mclocale $locale + namespace delete foo + } -body { + namespace eval $ns [list ::msgcat::mc $string] + } -result $result($ns,$string) + incr count + } + } + + # Tests msgcat-7.*: [mc] extra args processed by [format] + + test msgcat-7.1 {mc extra args go through to format} -setup { + mcset foo format1 "this is a test" + mcset foo format2 "this is a %s" + mcset foo format3 "this is a %s %s" + variable locale [mclocale] + mclocale foo + } -cleanup { + mclocale $locale + } -body { + mc format1 "good test" + } -result "this is a test" + + test msgcat-7.2 {mc extra args go through to format} -setup { + mcset foo format1 "this is a test" + mcset foo format2 "this is a %s" + mcset foo format3 "this is a %s %s" + variable locale [mclocale] + mclocale foo + } -cleanup { + mclocale $locale + } -body { + mc format2 "good test" + } -result "this is a good test" + + test msgcat-7.3 {mc errors from format are propagated} -setup { + mcset foo format1 "this is a test" + mcset foo format2 "this is a %s" + mcset foo format3 "this is a %s %s" + variable locale [mclocale] + mclocale foo + } -cleanup { + mclocale $locale + } -body { + catch {mc format3 "good test"} + } -result 1 + + test msgcat-7.4 {mc, extra args are given to unknown} -setup { + mcset foo format1 "this is a test" + mcset foo format2 "this is a %s" + mcset foo format3 "this is a %s %s" + variable locale [mclocale] + mclocale foo + } -cleanup { + mclocale $locale + } -body { + mc "this is a %s" "good test" + } -result "this is a good test" + + cleanupTests } -namespace eval ::foo::bar { - ::msgcat::mcset foo ov2 "ov2_foo_bar" - ::msgcat::mcset foo ov3 "ov3_foo_bar" -} -namespace eval ::foo::bar::baz { - ::msgcat::mcset foo ov3 "ov3_foo_bar_baz" -} -::msgcat::mclocale foo - -# namespace ::foo -test msgcat-6.1 {::msgcat::mc, namespace resolution} { - namespace eval ::foo {::msgcat::mc ov1} -} {ov1_foo} -test msgcat-6.2 {::msgcat::mc, namespace resolution} { - namespace eval ::foo {::msgcat::mc ov2} -} {ov2_foo} -test msgcat-6.3 {::msgcat::mc, namespace resolution} { - namespace eval ::foo {::msgcat::mc ov3} -} {ov3_foo} -test msgcat-6.4 {::msgcat::mc, namespace resolution} { - namespace eval ::foo {::msgcat::mc ov4} -} {ov4} -# namespace ::foo::bar -test msgcat-6.5 {::msgcat::mc, namespace resolution} { - namespace eval ::foo::bar {::msgcat::mc ov1} -} {ov1_foo} -test msgcat-6.6 {::msgcat::mc, namespace resolution} { - namespace eval ::foo::bar {::msgcat::mc ov2} -} {ov2_foo_bar} -test msgcat-6.7 {::msgcat::mc, namespace resolution} { - namespace eval ::foo::bar {::msgcat::mc ov3} -} {ov3_foo_bar} -test msgcat-6.8 {::msgcat::mc, namespace resolution} { - namespace eval ::foo::bar {::msgcat::mc ov4} -} {ov4} -# namespace ::foo -test msgcat-6.9 {::msgcat::mc, namespace resolution} { - namespace eval ::foo::bar::baz {::msgcat::mc ov1} -} {ov1_foo} -test msgcat-6.10 {::msgcat::mc, namespace resolution} { - namespace eval ::foo::bar::baz {::msgcat::mc ov2} -} {ov2_foo_bar} -test msgcat-6.11 {::msgcat::mc, namespace resolution} { - namespace eval ::foo::bar::baz {::msgcat::mc ov3} -} {ov3_foo_bar_baz} -test msgcat-6.12 {::msgcat::mc, namespace resolution} { - namespace eval ::foo::bar::baz {::msgcat::mc ov4} -} {ov4} - -namespace delete ::foo::bar::baz ::foo::bar ::foo - -::msgcat::mclocale foo -::msgcat::mcset foo format1 "this is a test" -::msgcat::mcset foo format2 "this is a %s" -::msgcat::mcset foo format3 "this is a %s %s" - -test msgcat-7.1 {::msgcat::mc, extra args go through to format} { - ::msgcat::mc format1 "good test" -} "this is a test" -test msgcat-7.2 {::msgcat::mc, extra args go through to format} { - ::msgcat::mc format2 "good test" -} "this is a good test" -test msgcat-7.3 {::msgcat::mc, errors from format are propagated} { - catch {::msgcat::mc format3 "good test"} -} 1 -test msgcat-7.4 {::msgcat::mc, extra args are given to unknown} { - ::msgcat::mc "this is a %s" "good test" -} "this is a good test" - -# Reset the locale -::msgcat::mclocale $oldlocale - -::tcltest::cleanupTests +namespace delete ::msgcat::test return + -- cgit v0.12