Index: openacs-4/packages/acs-lang/tcl/lang-message-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-lang/tcl/lang-message-procs.tcl,v diff -u -r1.51.8.1 -r1.51.8.2 --- openacs-4/packages/acs-lang/tcl/lang-message-procs.tcl 27 Aug 2013 12:20:35 -0000 1.51.8.1 +++ openacs-4/packages/acs-lang/tcl/lang-message-procs.tcl 12 Sep 2013 16:25:48 -0000 1.51.8.2 @@ -17,6 +17,65 @@ namespace eval lang::message {} +ad_proc -public lang::message::check { + locale + package_key + message_key + message +} { +
+ Check a message for semantic and sanity correctness (usually called just before a message is registered). + Throws an error when one of the checks fails. +
+} { + # Qualify the locale variable value with a country code if it is + # just a language + if { [string length $locale] == 2 } { + # It seems to be a language (iso codes are 2 characters) + # We don't do a more throughout check since this is not + # invoked by users. + # let's get the default locale for that language + set locale [lang::util::default_locale_from_lang $locale] + } + + # Create a globally (across packages) unique key for the cache + set key "${package_key}.${message_key}" + + # Check that non-en_US messages don't have invalid embedded variables + # Exclude the special case of datetime configuration messages in acs-lang. An alternative + # to treating those messages as a special case here would be to have those messages use + # quoted percentage signs (double percentage signs). + if { $locale ne "en_US" && ![regexp {^acs-lang\.localization-} $key] } { + set embedded_vars [get_embedded_vars $message] + set embedded_vars_en_us [get_embedded_vars [lang::message::lookup en_US $key {} {} 0]] + set missing_vars [util_get_subset_missing $embedded_vars $embedded_vars_en_us] + + if { [llength $missing_vars] > 0 } { + error "Message key '$key' in locale '$locale' has these embedded variables not present in the en_US locale: [join $missing_vars ","]." + } + } + + # If a localization key from acs-lang... + if {[regexp {^acs-lang\.localization-(.*)} $key match lc_key]} { + # ...number separators for decimal and thousands must be checked to ensure they are not equal, + # otherwise the localized number parsing will fail. + if {$lc_key in {decimal_point thousands_sep mon_decimal_point mon_thousands_sep}} { + if {[regexp {^mon_(.*)} $lc_key match lc_key]} { + set decimal_point [lc_get -locale $locale "mon_decimal_point"] + set thousands_sep [lc_get -locale $locale "mon_thousands_sep"] + } else { + set decimal_point [lc_get -locale $locale "decimal_point"] + set thousands_sep [lc_get -locale $locale "thousands_sep"] + } + set $lc_key $message + if {$decimal_point eq $thousands_sep} { + error "Message keys for thousands and decimal separators must be different." + } + } + } +} + + ad_proc -public lang::message::register { {-update_sync:boolean} {-upgrade_status "no_upgrade"} @@ -98,21 +157,10 @@ error $error_message } } - - # Check that non-en_US messages don't have invalid embedded variables - # Exclude the special case of datetime configuration messages in acs-lang. An alternative - # to treating those messages as a special case here would be to have those messages use - # quoted percentage signs (double percentage signs). - if { $locale ne "en_US" && ![regexp {^acs-lang\.localization-} $key] } { - set embedded_vars [get_embedded_vars $message] - set embedded_vars_en_us [get_embedded_vars [lang::message::lookup en_US $key {} {} 0]] - set missing_vars [util_get_subset_missing $embedded_vars $embedded_vars_en_us] - - if { [llength $missing_vars] > 0 } { - error "Message key '$key' in locale '$locale' has these embedded variables not present in the en_US locale: [join $missing_vars ","]. Message has not been imported." - } - } + # Call semantic and sanity checks on the key before registering. + lang::message::check $locale $package_key $message_key $message + # Build up an array of columns to set array set cols [list] if { $update_sync_p } { Index: openacs-4/packages/acs-lang/tcl/test/acs-lang-test-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-lang/tcl/test/acs-lang-test-procs.tcl,v diff -u -r1.17 -r1.17.10.1 --- openacs-4/packages/acs-lang/tcl/test/acs-lang-test-procs.tcl 10 Jan 2007 21:22:04 -0000 1.17 +++ openacs-4/packages/acs-lang/tcl/test/acs-lang-test-procs.tcl 12 Sep 2013 16:25:48 -0000 1.17.10.1 @@ -1063,3 +1063,15 @@ lang::message::unregister $package_key $message_key } } + +aa_register_case lang_messages_correct { + This test calls the checks to ensure a message is correct on every message in the system +} { + aa_run_with_teardown -rollback -test_code { + db_foreach query " + select message_key, package_key, locale, message from lang_messages" { + aa_false "Message $message_key in package $package_key for locale $locale correct" \ + [catch {lang::message::check $locale $package_key $message_key $message}] + } + } +} Index: openacs-4/packages/acs-lang/www/admin/edit-localized-message.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-lang/www/admin/edit-localized-message.tcl,v diff -u -r1.17.8.1 -r1.17.8.2 --- openacs-4/packages/acs-lang/www/admin/edit-localized-message.tcl 27 Aug 2013 12:20:36 -0000 1.17.8.1 +++ openacs-4/packages/acs-lang/www/admin/edit-localized-message.tcl 12 Sep 2013 16:25:48 -0000 1.17.8.2 @@ -168,6 +168,16 @@ } } -on_submit { + set first_translated_message "" + + with_catch errmsg { + # Call semantic and sanity checks on the key before registering. + lang::message::check $locale $package_key $message_key $message + } { + template::form::set_error message message $errmsg + break + } + # Register message via acs-lang lang::message::register -comment $comment $locale $package_key $message_key $message