Bug 12138 - Use placeholders in translatable Javascript strings
authorPasi Kallinen <pasi.kallinen@pttk.fi>
Thu, 24 Apr 2014 11:51:28 +0000 (14:51 +0300)
committerGalen Charlton <gmc@esilibrary.com>
Sun, 27 Apr 2014 21:24:04 +0000 (21:24 +0000)
Currently translating Javascript strings with variables in them is hard,
because the strings are created from separate parts. For example:

 _("Are you sure you want to delete the") + " " + count + " " +
_("attached items?")

This is translated in two different parts, and the translator cannot
affect the place where the count-variable is.

Now, if the javascript strings allowed placeholders, similar to how the
template strings do, the above could be written as:

_("Are you sure you want to delete the %s attached
items?").format(count)

This would make translation much easier.

Attached patch adds a Javascript string formatter, and changes all the
concatenated translatable JS strings used in intranet to use that.

To test:
1) cd misc/translator
2) perl translate update xx-YY
3) grep ^msgid po/xx-YY-i-staff-t-prog-v-3006000.po | sort | uniq >
xx-YY-pre
4) apply patch
5) perl translate update xx-YY
6) grep ^msgid po/xx-YY-i-staff-t-prog-v-3006000.po | sort | uniq >
xx-YY-post
7) compare the files: diff -Nurd xx-YY-pre xx-yy-post | less
   should show the javascript strings that changed.
8) Test the UIs where the formatted js strings are used.

Signed-off-by: Owen Leonard <oleonard@myacpl.org>

I tested *most* of the changed files. There were some instances where it
wasn't clear to me how to trigger the warnings which were modified,
especially tags/review.tt, admin/manage-marc-import.tt, and holidays.tt.
Everything I was able to test worked correctly.

Signed-off-by: Katrin Fischer <Katrin.Fischer.83@web.de>

Works nicely, no regressions found. Thx!

Signed-off-by: Galen Charlton <gmc@esilibrary.com>

34 files changed:
koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc
koha-tmpl/intranet-tmpl/prog/en/js/staff-global.js
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/addorderiso2709.tt
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/aqbasketuser_search.tt
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/invoices.tt
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/z3950_search.tt
koha-tmpl/intranet-tmpl/prog/en/modules/admin/biblio_framework.tt
koha-tmpl/intranet-tmpl/prog/en/modules/admin/item_circulation_alerts.tt
koha-tmpl/intranet-tmpl/prog/en/modules/authorities/authorities.tt
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/marc21_field_006.tt
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/value_builder/marc21_field_008.tt
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_auth_search.tt
koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_search.tt
koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline.tt
koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-manage.tt
koha-tmpl/intranet-tmpl/prog/en/modules/members/pay.tt
koha-tmpl/intranet-tmpl/prog/en/modules/patron_lists/lists.tt
koha-tmpl/intranet-tmpl/prog/en/modules/patroncards/edit-batch.tt
koha-tmpl/intranet-tmpl/prog/en/modules/patroncards/image-manage.tt
koha-tmpl/intranet-tmpl/prog/en/modules/patroncards/manage.tt
koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt
koha-tmpl/intranet-tmpl/prog/en/modules/serials/serials-edit.tt
koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt
koha-tmpl/intranet-tmpl/prog/en/modules/tags/review.tt
koha-tmpl/intranet-tmpl/prog/en/modules/tools/holidays.tt
koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tt
koha-tmpl/intranet-tmpl/prog/en/modules/tools/modborrowers.tt
koha-tmpl/intranet-tmpl/prog/en/modules/tools/quotes-upload.tt
koha-tmpl/intranet-tmpl/prog/en/modules/tools/quotes.tt

index f69a7cd..a296dd1 100644 (file)
         var countdeletedorders = [% countdeletedorders %];
         var is_confirmed;
        if (count > 0){
-            is_confirmed = alert( count + " " +_("item(s) are attached to this record. You must delete all items before deleting this record.") );
+            is_confirmed = alert( _("%s item(s) are attached to this record. You must delete all items before deleting this record.").format(count) );
          }
         else if (countorders > 0){
             [% IF ( CAN_user_acquisition_order_manage ) %]
-                is_confirmed = confirm( _("Warning: This record is used in")+" "+ countorders + " " +_("order(s). Deleting it could cause serious issues on acquisition module. Are you sure you want to delete this record?") );
+                is_confirmed = confirm( _("Warning: This record is used in %s order(s). Deleting it could cause serious issues on acquisition module. Are you sure you want to delete this record?").format(countorders) );
             [% ELSE %]
-                is_confirmed = alert( countorders + " " +_("order(s) are using this record. You need order managing permissions to delete this record.") );
+                is_confirmed = alert( _("%s order(s) are using this record. You need order managing permissions to delete this record.").format(countorders) );
             [% END %]
         }
         else if (countdeletedorders > 0){
              [% IF ( CAN_user_acquisition_order_manage ) %]
-                 is_confirmed = confirm( countdeletedorders + " " +_("deleted order(s) are using this record. Are you sure you want to delete this record?") );
+                 is_confirmed = confirm( _("%s deleted order(s) are using this record. Are you sure you want to delete this record?").format(countdeletedorders) );
              [% ELSE %]
-                 is_confirmed = alert( countdeletedorders + " " +_("deleted order(s) are using this record. You need order managing permissions to delete this record.") );
+                 is_confirmed = alert( _("%s deleted order(s) are using this record. You need order managing permissions to delete this record.").format(countdeletedorders) );
              [% END %]
         }
         else if ( holdcount > 0 ) {
-            is_confirmed = confirm( holdcount + " " + _("holds(s) for this record. Are you sure you want to delete this record?"));
+            is_confirmed = confirm( _("%s holds(s) for this record. Are you sure you want to delete this record?").format(holdcount) );
         } else {
             is_confirmed = confirm(_("Are you sure you want to delete this record?"));
         }
@@ -74,9 +74,9 @@
         var holdcount = [% holdcount %];
 
         if ( holdcount > 0 ) {
-            alert( holdcount + " " + _("hold(s) on this record. You must delete all holds before deleting all items.") );
+            alert( _("%s hold(s) on this record. You must delete all holds before deleting all items.").format(holdcount) );
         } else if ( count > 0 ) {
-            if( confirm( _("Are you sure you want to delete the") + " " + count + " " + _("attached items?") ) ) {
+            if( confirm( _("Are you sure you want to delete the %s attached items?").format(count) ) ) {
                 window.location="/cgi-bin/koha/cataloguing/additem.pl?op=delallitems&amp;biblionumber=[% biblionumber %]";
             } else {
                 return false;
index 909d74c..c553a6d 100644 (file)
@@ -3,6 +3,19 @@ if ( KOHA === undefined ) var KOHA = {};
 
 function _(s) { return s; } // dummy function for gettext
 
+// http://stackoverflow.com/questions/1038746/equivalent-of-string-format-in-jquery/5341855#5341855
+String.prototype.format = function() { return formatstr(this, arguments) }
+function formatstr(str, col) {
+    col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1);
+    var idx = 0;
+    return str.replace(/%%|%s|%(\d+)\$s/g, function (m, n) {
+        if (m == "%%") { return "%"; }
+        if (m == "%s") { return col[idx++]; }
+        return col[n];
+    });
+};
+
+
 // http://stackoverflow.com/questions/14859281/select-tab-by-name-in-jquery-ui-1-10-0/16550804#16550804
 $.fn.tabIndex = function () {
     return $(this).parent().find(this).index() - 1;
index 577d555..149d532 100644 (file)
@@ -34,7 +34,7 @@
             if (total_errors > 0) {
                 var alertString  = _("Form not submitted because of the following problem(s)");
                 alertString += "\n------------------------------------------------------------------------------------\n";
-                alertString += "\n- "+ total_errors + _(" mandatory fields empty (highlighted)");
+                alertString += "\n- " + _("%s mandatory fields empty (highlighted)").format(total_errors);
                 alert(alertString);
                 return false;
             }
index 9b7f52b..91ca764 100644 (file)
@@ -18,7 +18,7 @@
     function add_user(borrowernumber, borrowername) {
         var p = window.opener;
         if(p.add_basket_user(borrowernumber, borrowername) < 0) {
-            alert(_("Borrower '" + borrowername + "' is already in the list."));
+            alert(_("Borrower '%s' is already in the list.").format(borrowername));
         }
     }
 //]]>
index e6527a5..546f597 100644 (file)
@@ -31,7 +31,7 @@ $(document).ready(function() {
     });
     $(".modal").on("show", function(){
         var basket = $(this).data("basketno");
-        var legend = _("Add order to basket") + " " + basket;
+        var legend = _("Add order to basket %s").format(basket);
         $(this).find("legend").html(legend);
     });
 });
index 8f0c21d..7bfef8c 100644 (file)
@@ -70,7 +70,7 @@ $(document).ready(function() {
                         $('#merge_' + prop).val(invoice[prop]);
                     });
                     if (invoice.closedate) {
-                        $('#merge_status').text(_("Closed on " + invoice.closedate + ""));
+                        $('#merge_status').text(_("Closed on %s").format(invoice.closedate));
                     } else {
                         $('#merge_status').text(_("Open"));
                     }
index e1d9ad5..6b825b9 100644 (file)
@@ -60,8 +60,7 @@ function Check(ff) {
 
     if (totalExceedsBudget(ff.budget_id.value, ff.total.value  )  ) {
         ok=1;
-        _alertString += "\n- " + _("Order total (") + ff.total.value +
-            _(") exceeds budget available (") + actTotal+")";
+        _alertString += "\n- " + _("Order total (%s) exceeds budget available (%s)").format(ff.total.value, actTotal);
     }
 
     if ( ff.field_value ) {
@@ -69,7 +68,7 @@ function Check(ff) {
         if (empty_item_mandatory > 0) {
             ok = 1;
             _alertString +=
-                "\n- " + empty_item_mandatory + _(" item mandatory fields empty");
+                "\n- " + _("%s item mandatory fields empty").format(empty_item_mandatory);
         }
 
     }
index 6d2b3fa..dc0beec 100644 (file)
@@ -13,7 +13,7 @@
             if (total_errors != 0) {
                 var alertString = _("Form not submitted because of the following problem(s)");
                 alertString += "\n------------------------------------------------------------------------------------\n";
-                alertString += "\n- "+ total_errors+_(" mandatory fields empty (highlighted)");
+                alertString += "\n- " + _("%s mandatory fields empty (highlighted)").format(total_errors);
                 alert(alertString);
                 return false;
             }
index 32d449c..99096e5 100644 (file)
@@ -59,7 +59,7 @@ function validate_goto_page(){
         return false;
     }
     else if(page < 1 || page > [% total_pages %] ) {
-        alert(_("The page should be a number between 1 and ") + [% total_pages %] + ".");
+        alert(_("The page should be a number between 1 and %s.").format([% total_pages %]));
         return false;
     }
     else {
index ec458b3..382c366 100644 (file)
@@ -67,7 +67,7 @@ function Check(f) {
 
         var matches = new RegExp("\\?error_import_export=(.+)$").exec(window.location.search);
         if (matches && matches.length > 1) {
-            alert(_("Error importing the framework ") + decodeURIComponent(matches[1]));
+            alert(_("Error importing the framework %s").format(decodeURIComponent(matches[1])));
         }
 
         $('input.input_import').change( function() {
@@ -89,7 +89,7 @@ function Check(f) {
             if (/(?:\.csv|\.ods|\.xml)$/.test(obj.val())) {
                 if (confirm(_("Do you really want to import the framework fields and subfields? This will overwrite the current configuration. For safety reasons please use the export option to make a backup"))) {
                     var frameworkcode = $('#' + id + ' input:hidden[name=frameworkcode]').val();
-                    $('#importing_' + frameworkcode).find("span").html(_("Importing to framework:")+"<strong>" + frameworkcode + "</strong>. " +_("Importing from file:")+"<i>" + obj.val().replace(new RegExp("^.+[/\\\\]"),"") + "</i>");
+                    $('#importing_' + frameworkcode).find("span").html(_("Importing to framework: %s. Importing from file: %s").format("<strong>" + frameworkcode + "</strong>", "<i>" + obj.val().replace(new RegExp("^.+[/\\\\]"),"") + "</i>"));
                     if (navigator.userAgent.toLowerCase().indexOf('msie') != -1) {
                         var timestamp = new Date().getTime();
                         $('#importing_' + frameworkcode).find("img").attr('src', '[% interface %]/[% theme %]/img/loading-small.gif' + '?' +timestamp);
index d4efbef..ad451e1 100644 (file)
@@ -45,7 +45,7 @@ $(function(){
     var blocked            = _("Blocked!");
     var saving             = _("Saving...");
     var disabledForAll     = _("Disabled for all");
-    var disabledForCurrent = _("Disabled for") + ' ' + $branch;
+    var disabledForCurrent = _("Disabled for %s").format($branch);
 
     $('#branch_selector input:submit').hide();
     $('#branch').change(function(){
index e8afb18..b7dcbf7 100644 (file)
@@ -46,7 +46,7 @@ function AreMandatoriesNotOk(){
         // alert (id_string);
         if( ! $("#" + id_string).val() ){
             $("#" + id_string).attr('class','subfield_not_filled').focus();
-            StrAlert += "\t* "+label[i]+_(" in tab ")+tab[i]+"\n";
+            StrAlert += "\t* " + _("%s in tab %s").format(label[i], tab[i]) + "\n";
         }
     }
     
@@ -79,7 +79,7 @@ function AreMandatoriesNotOk(){
        
        if(isempty){
                flag = 1;
-                       StrAlert += "\t* Field " + arr[0] + _(" is mandatory, at least one of its subfields must be filled") + "\n";
+                StrAlert += "\t* " + _("Field %s is mandatory, at least one of its subfields must be filled.").format(arr[0]) + "\n";
        }
        
     }
index 01218b2..f446d6e 100644 (file)
@@ -258,7 +258,7 @@ function AreMandatoriesNotOk(){
       if (tabflag[tagsubfieldid][0]==0){
         var tag=tagsubfieldid.substr(0,3);
         var subfield=tagsubfieldid.substr(3,1);    
-        StrAlert += "\t* "+_("tag ")+tag+_(" subfield ")+subfield+" "+tabflag[tagsubfieldid][1]+_(" in tab ")+tabflag[tagsubfieldid][2]+"\n";
+        StrAlert += "\t* "+_("tag %s subfield %s %s in tab %s").format(tag, subfield, tabflag[tagsubfieldid][1], tabflag[tagsubfieldid][2]) + "\n";
         //StrAlert += "\t* "+label[i]+_(" in tab ")+tab[i]+"\n"; 
         flag=1;    
       }   
@@ -308,7 +308,7 @@ function AreMandatoriesNotOk(){
        
        if(isempty){
                flag = 1;
-               StrAlert += _("\t* Field ") + arr[0] + _(" is mandatory, at least one of its subfields must be filled.") + "\n";
+                StrAlert += "\t* " + _("Field %s is mandatory, at least one of its subfields must be filled.").format(arr[0]) + "\n";
        }
        
     }
index 2d7f4b5..85a4486 100644 (file)
@@ -64,7 +64,7 @@ function Check(f) {
     if (total_errors > 0) {
         var alertString2 = _("Form not submitted because of the following problem(s)");
         alertString2 += "\n------------------------------------------------------------------------------------\n";
-        alertString2 += "\n- "+ total_errors + _(" mandatory fields empty (highlighted)");
+        alertString2 += "\n- " + _("%s mandatory fields empty (highlighted)").format(total_errors);
         alert(alertString2);
         return false;
     }
index 37524ff..4f2fe48 100644 (file)
@@ -24,7 +24,7 @@
 
     function changeTypeofMaterial(form)
     {
-        if (form.material_type.options[form.material_type.selectedIndex].value != "" && confirm(_("Show values for") +' \'' + form.material_type.options[form.material_type.selectedIndex].text + '\' ' +_("material type?"))) {
+        if (form.material_type.options[form.material_type.selectedIndex].value != "" && confirm(_("Show values for '%s' material type?").format(form.material_type.options[form.material_type.selectedIndex].text))) {
             objXmlControlField.setIdMaterial(form.material_type.options[form.material_type.selectedIndex].value);
             objXmlControlField.renderTemplate();
             renderResult(tr_result, form.result.value, true);
index 4a5b8f8..5bb381b 100644 (file)
@@ -24,7 +24,7 @@
 
     function changeTypeofMaterial(form)
     {
-        if (form.material_type.options[form.material_type.selectedIndex].value != "" && confirm(_("Show values for") + ' \'' + form.material_type.options[form.material_type.selectedIndex].text + '\' ' + _("material type?"))) {
+        if (form.material_type.options[form.material_type.selectedIndex].value != "" && confirm(_("Show values for '%s' material type?").format(form.material_type.options[form.material_type.selectedIndex].text))) {
             objXmlControlField.setIdMaterial(form.material_type.options[form.material_type.selectedIndex].value);
             objXmlControlField.renderTemplate();
             renderResult(tr_result, form.result.value, true);
index f60dba9..08ba74e 100644 (file)
@@ -68,7 +68,7 @@ function validate_goto_page(){
         return false;
     }
     else if(page < 1 || page > [% total_pages %] ) {
-        alert(_("The page should be a number between 1 and ") + [% total_pages %] + ".");
+        alert(_("The page should be a number between 1 and %s.").format([% total_pages %]));
         return false;
     }
     else {
index b3123e3..37b03dc 100644 (file)
@@ -69,7 +69,7 @@ function validate_goto_page(){
         return false;
     }
     else if(page < 1 || page > [% total_pages %] ) {
-        alert(_("The page should be a number between 1 and ") + [% total_pages %] + ".");
+        alert(_("The page should be a number between 1 and %s.").format([% total_pages %]));
         return false;
     }
     else {
index 49f443e..fe617c1 100644 (file)
@@ -119,7 +119,7 @@ function synchronize() {
         }).done(function (data) {
             if (data) {
                 $('.loading-overlay').hide();
-                alert(_("Please log in to Koha and try again. (Error: '" + data + "')"));
+                alert(_("Please log in to Koha and try again. (Error: '%s')").format(data));
             } else {
                 var uploadIter = $.indexedDB("koha").objectStore("transactions").each(uploadTransaction);
                 uploadIter.done(function() {
@@ -193,7 +193,7 @@ function finishedLoading() {
 
 function loadRecords(page) {
 [% IF (AllowOfflineCirculation) %]
-    $(".loading-overlay div").text(_("Loading page " + page + ", please wait..."));
+    $(".loading-overlay div").text(_("Loading page %s, please wait...").format(page));
     $(".loading-overlay").show();
     $.ajax({
         type: "GET",
@@ -378,7 +378,7 @@ function showPatron(barcode, patron, error) {
     if (patron.name.length > 0) {
         $('.patron-title').text(patron.name);
     } else {
-        $('.patron-title').text(_("Unrecognized patron") + " (" + barcode + ")");
+        $('.patron-title').text(_("Unrecognized patron (%s)").format(barcode));
     }
     if (patron.address.length > 0 || patron.address2.length > 0) {
         $('#patron-address-1').text(patron.address);
@@ -403,12 +403,12 @@ function showPatron(barcode, patron, error) {
         $('#patron-email').html('<span class="empty" id="noemailstored">' + _("No email stored.") + '</span></li>');
     }
     if (patron.categorycode.length > 0) {
-        $('#patron-category').text(_("Category: ") + patron.categorycode);
+        $('#patron-category').text(_("Category: %s").format(patron.categorycode));
     } else {
         $('#patron-category').html('<span class="empty" id="unknowncategory">' + _("Category code unknown.") + '</span></li>');
     }
     if (patron.branchcode.length > 0) {
-        $('#patron-library').text(_("Home library: ") + patron.branchcode);
+        $('#patron-library').text(_("Home library: %s").format(patron.branchcode));
     } else {
         $('#patron-library').html('<span class="empty" id="unknowncategory">' + _("Home library unknown.") + '</span></li>');
     }
index 791bac0..a5b1845 100644 (file)
@@ -7,7 +7,7 @@
             function DeleteConfirm() {
                 var element_id = selected_layout("delete");
                 if (element_id>-1) {
-                    var msg = "Are you sure you want to delete [% label_element %] " + element_id + "?"
+                    var msg = _("Are you sure you want to delete %s %s?").format("[% label_element %]", element_id);
                     var answer = confirm(msg);
                     if (answer) {
                         window.location = "/cgi-bin/koha/labels/label-manage.pl?op=delete&amp;label_element=[% label_element %]&amp;element_id=" + element_id;
@@ -64,7 +64,7 @@
                         return(document.layouts.action[selected[0]].value);
                     }
                     else {
-                        alert(_("Please select only one ")+"[% label_element %]"+_(" to")+op+".");
+                        alert(_("Please select only one %s to %s.").format("[% label_element %]", op));
                         return (-1);
                     }
                 }
@@ -73,7 +73,7 @@
                         return(document.layouts.action.value);
                     }
                 };
-                alert(_("Please select a ")+"[% label_element %].");
+                alert(_("Please select a %s.").format("[% label_element %]"));
                 return (-1);
             };
         //]]>
index 80d7785..58a80fe 100644 (file)
@@ -16,8 +16,7 @@ function enableCheckboxActions(){
     $(document).ready(function(){
  $('#pay-fines-form').preventDoubleFormSubmit();
         $("#woall").click(function(event){
-            var msg = _("Are you sure you want to write off %s in outstanding fines? This cannot be undone!");
-            msg = msg.replace( "%s", "[% total | format('%.2f') %]" );
+            var msg = _("Are you sure you want to write off %s in outstanding fines? This cannot be undone!").format( "[% total | format('%.2f') %]" );
             var answer = confirm(msg);
                 if (!answer){
                     event.preventDefault();
index ec8c2b4..8be8035 100644 (file)
@@ -16,7 +16,7 @@
     });
 
     function ConfirmDelete( list ) {
-        return confirm( _("Are you sure you want to delete the list ") + list + "?" );
+        return confirm( _("Are you sure you want to delete the list %s?").format(list) );
     }
 //]]>
 </script>
index 60806f1..0851936 100644 (file)
@@ -7,7 +7,7 @@
     <script type="text/javascript">
         //<![CDATA[
            function DeleteConfirm() {
-                var msg = _("Are you sure you want to delete batch") + " [% batch_id %]?";
+                var msg = _("Are you sure you want to delete batch %s?").format("[% batch_id %]");
                 var answer = confirm(msg);
                 if (answer) {
                     window.location = "/cgi-bin/koha/patroncards/manage.pl?op=delete&amp;card_element=batch&amp;element_id=[% batch_id %]";
@@ -32,7 +32,7 @@
                     }
                     getstr = items.join("&");
                     item_msg = item_num.join(", ");
-                    var msg = "Are you sure you want to remove card number(s): " + item_msg + " from this batch?"
+                    var msg = _("Are you sure you want to remove card number(s): %s from this batch?").format(item_msg);
                 }
                 else {
                     alert(_("Please select at least label to delete."));
index 9c8f944..2f53b93 100644 (file)
@@ -6,7 +6,7 @@
             function DeleteConfirm() {
                 var results = selected_images("delete");
                 if (results.images != -1) {
-                    var msg = "Are you sure you want to delete image(s): " + results.image_ids + "?";
+                    var msg = _("Are you sure you want to delete image(s): %s?").format(results.image_ids);
                     var answer = confirm(msg);
                     if (answer) {
                         window.location = "/cgi-bin/koha/patroncards/image-manage.pl?op=delete&" + results.images;
@@ -32,7 +32,7 @@
                 else if (document.delete_images.action.checked){
                         return {images:"batch_id="+document.delete_images.action.value, image_ids:document.delete_images.action.value};
                 };
-                alert(_("Please select image(s) to ") + op + ".");
+                alert(_("Please select image(s) to %s.").format(op));
                 return (-1);
             };
         $(document).ready(function() {
index a0ac1f0..5acaf68 100644 (file)
@@ -7,7 +7,7 @@
             function DeleteConfirm() {
                 var element_id = selected_layout("delete");
                 if (element_id>-1) {
-                    var msg = _("Are you sure you want to delete") + " [% card_element %] " + element_id + "?"
+                    var msg = _("Are you sure you want to delete %s %s?").format("[% card_element %]", element_id);
                     var answer = confirm(msg);
                     if (answer) {
                         window.location = "/cgi-bin/koha/patroncards/manage.pl?op=delete&card_element=[% card_element %]&element_id=" + element_id;
@@ -64,7 +64,7 @@
                         return(document.layouts.action[selected[0]].value);
                     }
                     else {
-                        alert(_("Please select only one ")+"[% card_element %]"+_(" to ") + op + ".");
+                        alert(_("Please select only one %s to %s.").format("[% card_element %]", op));
                         return (-1);
                     }
                 }
@@ -73,7 +73,7 @@
                         return(document.layouts.action.value);
                     }
                 };
-                alert(_("Please select a ")+"[% card_element %].");
+                alert(_("Please select a %s.").format("[% card_element %]"));
                 return (-1);
             };
 
index 3494655..cafc072 100644 (file)
@@ -105,7 +105,7 @@ function checkMultiHold() {
 
         switch (override_items[itemnumber].holdallowed) {
             case 0: msg = _("This item normally cannot be put on hold."); break;
-            case 1: msg = _("This item normally cannot be put on hold except for patrons from ") + override_items[itemnumber].homebranch + "."; break;
+            case 1: msg = _("This item normally cannot be put on hold except for patrons from %s.").format(override_items[itemnumber].homebranch); break;
         }
 
         msg += "\n\n" + _("Place hold on this item?");
index bddffca..5d47d73 100644 (file)
@@ -86,7 +86,7 @@ $(document).ready(function() {
         if ( total_errors > 0 ) {
             var mes  = _("Form not submitted because of the following problem(s)");
             mes += "\n------------------------------------------------------------------------------------\n";
-            mes += "\n- " + total_errors + _(" mandatory fields empty (highlighted)");
+            mes += "\n- " _("%s mandatory fields empty (highlighted)").format(total_errors);
             alert(mes);
             return false;
         }
index 1402135..2923c97 100644 (file)
@@ -261,8 +261,7 @@ function testPredictionPattern() {
     [% END %]
 
     if(error){
-        alert(_("Cannot test prediction pattern for the following reason(s):") + "\n\n"
-            + error_msg);
+        alert(_("Cannot test prediction pattern for the following reason(s): %s").format(error_msg));
         return false;
     }
 
@@ -323,8 +322,7 @@ function saveAdvancedPattern() {
     var cnfrm = 1;
     if(found){
         var msg = _("This pattern name already exists. Do you want to modify it?")
-            + "\n" + _("Warning: it will modify the pattern for all subscriptions")
-            + _("that are using it.");
+            + "\n" + _("Warning: it will modify the pattern for all subscriptions that are using it.");
         cnfrm = confirm(msg);
     }
 
index dab830e..b4dcebe 100644 (file)
@@ -54,22 +54,22 @@ tr > td input,td input[type="submit"] { font-size: 85%; padding: 1px; }
                // window.alert(_("AJAX approved tag: ") + tag);
        };
        var failure_approve = function(tag){
-               window.alert(_("AJAX failed to approve tag: ") + tag);
+                window.alert(_("AJAX failed to approve tag: %s").format(tag));
        };
        var success_reject  = function(tag){
                // window.alert(_("AJAX rejected tag: ") + tag);
        };
        var failure_reject  = function(tag){
-               window.alert(_("AJAX failed to reject tag: ") + tag);
+                window.alert(_("AJAX failed to reject tag: %s").format(tag));
        };
        var success_test    = function(tag){
-               $('#verdict').html(tag + _(" is permitted!"));
+                $('#verdict').html(_("%s is permitted!").format(tag));
        };
        var failure_test    = function(tag){
-               $('#verdict').html(tag + _(" is prohibited!"));
+                $('#verdict').html(_("%s is prohibited!").format(tag));
        };
        var indeterminate_test = function(tag){
-               $('#verdict').html(tag + _(" is neither permitted nor prohibited!"));
+                $('#verdict').html(_("%s is neither permitted nor prohibited!").format(tag));
        };
 
        var success_test_call = function() {
@@ -122,7 +122,7 @@ tr > td input,td input[type="submit"] { font-size: 85%; padding: 1px; }
                        }
                });
                $("*").ajaxError(function(evt, request, settings){
-                       if ((alerted +=1) <= 1){ window.alert(_("AJAX error")+" (" + alerted + " alert)"); }
+                        if ((alerted +=1) <= 1){ window.alert(_("AJAX error (%s alert)").format(alerted)); }
                });
         $("#tagst").dataTable($.extend(true, {}, dataTablesDefaults, {
             "aoColumnDefs": [
index ea001e4..bfc4d7e 100644 (file)
         var dayMonth = month + '/' + day;
         var dateString = year + '/' + month + '/' + day;
         if (exception_holidays[dateString] != null) {
-            return [true, "exception", _("Exception") + ": "+exception_holidays[dateString].title];
+            return [true, "exception", _("Exception: %s").format(exception_holidays[dateString].title)];
         } else if ( week_days[weekDay] != null ){
-            return [true, "repeatableweekly", _("Weekly holiday") + ": "+week_days[weekDay].title];
+            return [true, "repeatableweekly", _("Weekly holiday: %s").format(week_days[weekDay].title)];
         } else if ( day_month_holidays[dayMonth] != null ) {
-            return [true, "repeatableyearly", _("Yearly holiday") + ": "+day_month_holidays[dayMonth].title];
+            return [true, "repeatableyearly", _("Yearly holiday: %s").format(day_month_holidays[dayMonth].title)];
         } else if (holidays[dateString] != null) {
-            return [true, "holiday", _("Single holiday") + ": "+holidays[dateString].title];
+            return [true, "holiday", _("Single holiday: %s").format(holidays[dateString].title)];
         } else {
             return [true, "normalday", _("Normal day")];
         }
index 98b2c08..3d5f01d 100644 (file)
@@ -84,17 +84,15 @@ $(document).ready(function(){
             );
 
             if ( aData['match_id'] ) {
+                [% IF ( record_type == 'auth' ) -%]
+                var matching_msg = _("Matches authority %s (score=%s):%s");
+                [%- ELSE -%]
+                var matching_msg = _("Matches biblio %s (score=%s):%s");
+                [%- END %]
                 $('td:eq(4)', nRow).html(
-                    [% IF ( record_type == 'auth' ) -%]
-                    _("Matches authority ")
-                    [%- ELSE -%]
-                    _("Matches biblio ")
-                    [%- END %]
-                    + aData['match_id']
-                    + " (" + _("score") + "="
-                    + aData['score']
-                    + '):' + '<a target="_blank" href="' + record_details_url
-                    + aData['match_id'] + '">' + aData['match_citation'] + '</a>'
+                    matching_msg.format(aData['match_id'], aData['score'],
+                    '<a target="_blank" href="' + record_details_url
+                    + aData['match_id'] + '">' + aData['match_citation'] + '</a>')
                 );
             }
 
index 1271224..dfb2107 100644 (file)
@@ -70,7 +70,7 @@
             var information_category_node = $(select_attr).parent().parent().find('span.information_category');
             information_category_node.html("");
             if ( category.length > 0 ) {
-                information_category_node.html(_("This attribute will be only applied to the patron's category") +' "' + category + '"');
+                information_category_node.html(_("This attribute will be only applied to the patron's category %s").format(category));
             }
             if ( type == 'select' ) {
                 var options = '<option value = ""></option>';
index 8a9de12..21fa005 100644 (file)
         var fileSizeInK = Math.round(evt.target.files[0].size/1024);
 
         if (!fileType.match(/comma-separated-values|csv|excel/i)) {
-            alert(_("Uploads limited to csv. Incorrect filetype: ")+fileType);
+            alert(_("Uploads limited to csv. Incorrect filetype: %s").format(fileType));
             parent.location='quotes-upload.pl';
             return;
         }
         if (fileSizeInK > 512) {
-            if (!confirm(evt.target.files[0].name+' '+fileSizeInK+_(" KB Do you really want to upload this file?"))) {
+            if (!confirm(_("%s %s KB Do you really want to upload this file?").format(evt.target.files[0].name, fileSizeInK))) {
                 parent.location='quotes-upload.pl';
                 return;
             }
             success     : function(){
                             var response = JSON.parse(jqXHR.responseText);
                             if (response.success) {
-                                alert(response.records+_(" quotes saved."));
+                                alert(_("%s quotes saved.").format(response.records));
                                 window.location.reload(true);   // is this the best route?
                             }
                             else {
-                                alert(response.records+_(" quotes saved, but an error has occurred. Please ask your administrator to check the server log for more details."));
+                                alert(_("%s quotes saved, but an error has occurred. Please ask your administrator to check the server log for more details.").format(response.records));
                                 window.location.reload(true);   // is this the best route?
                             }
                           },
         if (!idsToDelete) {
             alert(_("Please select a quote(s) by clicking the quote id(s) you desire to delete."));
         }
-        else if (confirm(_("Are you sure you wish to delete quote(s) ")+idsToDelete+"?")) {
+        else if (confirm(_("Are you sure you wish to delete quote(s) %s?").format(idsToDelete))) {
             oTable.$('.selected').each(function(){
                 oTable.fnDeleteRow(this);
             });
index f5e5268..007b2cb 100644 (file)
             if (!idsToDelete) {
                 alert(_("Please select a quote(s) by clicking the quote id(s) you desire to delete."));
             }
-            else if (confirm(_("Are you sure you wish to delete quote(s) ")+idsToDelete+"?")) {
+            else if (confirm(_("Are you sure you wish to delete quote(s) %s?").format(idsToDelete))) {
                 oTable.$('.selected').each(function(){
                         var quoteID = $(this).attr('id');
                             $.ajax({