summaryrefslogtreecommitdiffstats
path: root/library/msgcat/msgcat.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'library/msgcat/msgcat.tcl')
-rw-r--r--library/msgcat/msgcat.tcl191
1 files changed, 143 insertions, 48 deletions
diff --git a/library/msgcat/msgcat.tcl b/library/msgcat/msgcat.tcl
index ccf4054..cf3b9d7 100644
--- a/library/msgcat/msgcat.tcl
+++ b/library/msgcat/msgcat.tcl
@@ -9,17 +9,15 @@
#
# 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.26 2006/11/03 00:34:52 hobbs Exp $
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.4.2
+package provide msgcat 1.5.2
namespace eval msgcat {
namespace export mc mcload mclocale mcmax mcmset mcpreferences mcset \
- mcunknown
+ mcunknown mcflset mcflmset
# Records the current locale as passed to mclocale
variable Locale ""
@@ -27,6 +25,9 @@ namespace eval msgcat {
# Records the list of locales to search
variable Loclist {}
+ # Records the locale of the currently sourced message catalogue file
+ variable FileLocale
+
# Records the mapping between source strings and translated strings. The
# dict key is of the form "<locale> <namespace> <src>", where locale and
# namespace should be themselves dict values and the value is
@@ -34,7 +35,7 @@ namespace eval msgcat {
variable Msgs [dict create]
# Map of language codes used in Windows registry to those of ISO-639
- if { $::tcl_platform(platform) eq "windows" } {
+ 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
@@ -68,8 +69,8 @@ namespace eval msgcat {
15 pl 0415 pl_PL
16 pt 0416 pt_BR 0816 pt_PT
17 rm 0417 rm_CH
- 18 ro 0418 ro_RO
- 19 ru
+ 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
@@ -94,6 +95,7 @@ namespace eval msgcat {
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
@@ -177,7 +179,7 @@ namespace eval msgcat {
# args Args to pass to the format command
#
# Results:
-# Returns the translated string. Propagates errors thrown by the
+# Returns the translated string. Propagates errors thrown by the
# format command.
proc msgcat::mc {src args} {
@@ -189,7 +191,7 @@ proc msgcat::mc {src args} {
variable Locale
set ns [uplevel 1 [list ::namespace current]]
-
+
while {$ns != ""} {
foreach loc $Loclist {
if {[dict exists $Msgs $loc $ns $src]} {
@@ -278,17 +280,30 @@ proc msgcat::mcpreferences {} {
# Returns the number of message catalogs that were loaded.
proc msgcat::mcload {langdir} {
+ variable FileLocale
+ # Save the file locale if we are recursively called
+ if {[info exists FileLocale]} {
+ set nestedFileLocale $FileLocale
+ }
set x 0
foreach p [mcpreferences] {
- if { $p eq {} } {
+ 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 ""
+ }
uplevel 1 [list ::source -encoding utf-8 $langfile]
+ unset FileLocale
}
}
+ if {[info exists nestedFileLocale]} {
+ set FileLocale $nestedFileLocale
+ }
return $x
}
@@ -312,17 +327,39 @@ proc msgcat::mcset {locale src {dest ""}} {
}
set ns [uplevel 1 [list ::namespace current]]
-
+
set locale [string tolower $locale]
-
- # create nested dictionaries if they do not exist
- if {![dict exists $Msgs $locale]} {
- dict set Msgs $locale [dict create]
+
+ dict set Msgs $locale $ns $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"
}
- if {![dict exists $Msgs $locale $ns]} {
- dict set Msgs $locale $ns [dict create]
+ if {[llength [info level 0]] == 2} { ;# dest not specified
+ set dest $src
}
- dict set Msgs $locale $ns $src $dest
+
+ set ns [uplevel 1 [list ::namespace current]]
+ dict set Msgs $FileLocale $ns $src $dest
return $dest
}
@@ -337,7 +374,7 @@ proc msgcat::mcset {locale src {dest ""}} {
# Results:
# Returns the number of pairs processed
-proc msgcat::mcmset {locale pairs } {
+proc msgcat::mcmset {locale pairs} {
variable Msgs
set length [llength $pairs]
@@ -345,22 +382,46 @@ proc msgcat::mcmset {locale pairs } {
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]]
- # create nested dictionaries if they do not exist
- if {![dict exists $Msgs $locale]} {
- dict set Msgs $locale [dict create]
- }
- if {![dict exists $Msgs $locale $ns]} {
- dict set Msgs $locale $ns [dict create]
- }
foreach {src dest} $pairs {
- dict set Msgs $locale $ns $src $dest
+ dict set Msgs $locale $ns $src $dest
}
- return $length
+ 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"
+ }
+ set length [llength $pairs]
+ if {$length % 2} {
+ return -code error "bad translation list:\
+ should be \"[lindex [info level 0] 0] locale {src dest ...}\""
+ }
+
+ set ns [uplevel 1 [list ::namespace current]]
+ foreach {src dest} $pairs {
+ dict set Msgs $FileLocale $ns $src $dest
+ }
+ return [expr {$length / 2}]
}
# msgcat::mcunknown --
@@ -368,7 +429,7 @@ proc msgcat::mcmset {locale pairs } {
# This routine is called by msgcat::mc if a translation cannot
# be found for a string. 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.
+# 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.
#
@@ -390,7 +451,7 @@ proc msgcat::mcunknown {locale src args} {
# msgcat::mcmax --
#
-# Calculates the maximum length of the translated strings of the given
+# Calculates the maximum length of the translated strings of the given
# list.
#
# Arguments:
@@ -403,10 +464,10 @@ 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 len [string length $translated]
+ if {$len>$max} {
set max $len
- }
+ }
}
return $max
}
@@ -442,13 +503,15 @@ proc msgcat::ConvertLocale {value} {
# 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 {[info exists env($varName)] && ("" ne $env($varName))} {
if {![catch {
- mclocale [ConvertLocale $::env($varName)]
+ mclocale [ConvertLocale $env($varName)]
}]} {
return
}
@@ -457,8 +520,7 @@ proc msgcat::Init {} {
#
# On Darwin, fallback to current CFLocale identifier if available.
#
- if {$::tcl_platform(os) eq "Darwin" && $::tcl_platform(platform) eq "unix"
- && [info exists ::tcl::mac::locale] && $::tcl::mac::locale ne ""} {
+ if {[info exists ::tcl::mac::locale] && $::tcl::mac::locale ne ""} {
if {![catch {
mclocale [ConvertLocale $::tcl::mac::locale]
}]} {
@@ -466,21 +528,54 @@ proc msgcat::Init {} {
}
}
#
- # The rest of this routine is special processing for Windows;
- # all other platforms, get out now.
+ # The rest of this routine is special processing for Windows or
+ # Cygwin. All other platforms, get out now.
#
- if { $::tcl_platform(platform) ne "windows" } {
+ if {([info sharedlibextension] ne ".dll")
+ || [catch {package require registry}]} {
mclocale C
return
}
#
- # On Windows, try to set locale depending on registry settings,
- # or fall back on locale of "C".
+ # On Windows or Cygwin, try to set locale depending on registry
+ # settings, or fall back on locale of "C".
#
- set key {HKEY_CURRENT_USER\Control Panel\International}
- if {[catch {package require registry}] \
- || [catch {registry get $key "locale"} locale]} {
- mclocale 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
}
#
@@ -496,7 +591,7 @@ proc msgcat::Init {} {
set locale [string tolower $locale]
while {[string length $locale]} {
if {![catch {
- mclocale [ConvertLocale [dict get $WinRegToISO639 $locale]]
+ mclocale [ConvertLocale [dict get $WinRegToISO639 $locale]]
}]} {
return
}