diff --git a/static/js/admin.js b/static/js/admin.js
index 2fcb5cf1e5..ac31546286 100644
--- a/static/js/admin.js
+++ b/static/js/admin.js
@@ -213,7 +213,7 @@ function make_stream_default(stream_name) {
                 $(".active_stream_row button").closest("td").html(
                     $("
").addClass("text-error").text(JSON.parse(xhr.responseText).msg));
             } else {
-                $(".active_stream_row button").text("Failed!");
+                $(".active_stream_row button").text(i18n.t("Failed!"));
             }
         },
     });
@@ -457,7 +457,7 @@ function _setup_page() {
                $("#home-error"), 'alert-error');
         }
         $("#deactivation_user_modal").modal("hide");
-        meta.current_deactivate_user_modal_row.find("button").eq(0).prop("disabled", true).text("Working…");
+        meta.current_deactivate_user_modal_row.find("button").eq(0).prop("disabled", true).text(i18n.t("Working…"));
         channel.del({
             url: '/json/users/' + encodeURIComponent(email),
             error: function (xhr) {
@@ -466,7 +466,7 @@ function _setup_page() {
                         $("
").addClass("text-error").text(JSON.parse(xhr.responseText).msg)
                     );
                 } else {
-                     meta.current_deactivate_user_modal_row.find("button").text("Failed!");
+                    meta.current_deactivate_user_modal_row.find("button").text(i18n.t("Failed!"));
                 }
             },
             success: function () {
@@ -496,7 +496,7 @@ function _setup_page() {
                         $("
").addClass("text-error").text(JSON.parse(xhr.responseText).msg)
                     );
                 } else {
-                    row.find("button").text("Failed!");
+                    row.find("button").text(i18n.t("Failed!"));
                 }
             },
             success: function () {
@@ -862,7 +862,7 @@ function _setup_page() {
                $("#home-error"), 'alert-error');
         }
         $("#deactivation_stream_modal").modal("hide");
-        $(".active_stream_row button").prop("disabled", true).text("Working…");
+        $(".active_stream_row button").prop("disabled", true).text(i18n.t("Working…"));
         var stream_name = $(".active_stream_row").find('.stream_name').text();
         var stream_id = stream_data.get_sub(stream_name).stream_id;
         channel.del({
@@ -873,7 +873,7 @@ function _setup_page() {
                         $("
").addClass("text-error").text(JSON.parse(xhr.responseText).msg)
                     );
                 } else {
-                     $(".active_stream_row button").text("Failed!");
+                    $(".active_stream_row button").text(i18n.t("Failed!"));
                 }
             },
             success: function () {
@@ -896,7 +896,7 @@ function _setup_page() {
                         $("
").addClass("text-error").text(JSON.parse(xhr.responseText).msg)
                     );
                 } else {
-                     btn.text("Failed!");
+                    btn.text(i18n.t("Failed!"));
                 }
             },
             success: function () {
@@ -945,7 +945,7 @@ function _setup_page() {
                         $("
").addClass("text-error").text($.parseJSON(xhr.responseText).msg)
                     );
                 } else {
-                     btn.text("Failed!");
+                    btn.text(i18n.t("Failed!"));
                 }
             },
             success: function () {
@@ -1004,7 +1004,7 @@ function _setup_page() {
             success: function () {
                 aliases_info.removeClass("text-error");
                 aliases_info.addClass("text-success");
-                aliases_info.text("Deleted successfully!");
+                aliases_info.text(i18n.t("Deleted successfully!"));
             },
             error: function (xhr) {
                 aliases_info.removeClass("text-success");
@@ -1030,7 +1030,7 @@ function _setup_page() {
                 $("#id_realm_restricted_to_domain").prop("disabled", false);
                 aliases_info.removeClass("text-error");
                 aliases_info.addClass("text-success");
-                aliases_info.text("Added successfully!");
+                aliases_info.text(i18n.t("Added successfully!"));
             },
             error: function (xhr) {
                 aliases_info.removeClass("text-success");
diff --git a/static/js/click_handlers.js b/static/js/click_handlers.js
index eda20d5cba..b4ea790752 100644
--- a/static/js/click_handlers.js
+++ b/static/js/click_handlers.js
@@ -534,7 +534,7 @@ $(function () {
         $("#yes-bankrupt").hide();
         $("#no-bankrupt").hide();
         $(this).after($("
").addClass("alert alert-info settings_committed")
-               .text("Bringing you to your latest messages…"));
+                      .text(i18n.t("Bringing you to your latest messages…")));
     });
 
     (function () {
diff --git a/static/js/compose.js b/static/js/compose.js
index 27e0a816ad..e5e8a733d9 100644
--- a/static/js/compose.js
+++ b/static/js/compose.js
@@ -1080,7 +1080,7 @@ $(function () {
                          .show();
         $(".send-status-close").one('click', abort_xhr);
         $("#error-msg").html(
-            $("
").text("Uploading…")
+            $("
").text(i18n.t("Uploading…"))
                     .after('
'));
@@ -1096,22 +1096,22 @@ $(function () {
                         .removeClass("alert-info");
         $("#compose-send-button").removeAttr("disabled");
         switch (err) {
-            case 'BrowserNotSupported':
-                msg = "File upload is not yet available for your browser.";
-                break;
-            case 'TooManyFiles':
-                msg = "Unable to upload that many files at once.";
-                break;
-            case 'FileTooLarge':
-                // sanitizatio not needed as the file name is not potentially parsed as HTML, etc.
-                msg = "\"" + file.name + "\" was too large; the maximum file size is 25MiB.";
-                break;
-            case 'REQUEST ENTITY TOO LARGE':
-                msg = "Sorry, the file was too large.";
-                break;
-            default:
-                msg = "An unknown error occured.";
-                break;
+        case 'BrowserNotSupported':
+            msg = i18n.t("File upload is not yet available for your browser.");
+            break;
+        case 'TooManyFiles':
+            msg = i18n.t("Unable to upload that many files at once.");
+            break;
+        case 'FileTooLarge':
+            // sanitization not needed as the file name is not potentially parsed as HTML, etc.
+            msg = "\"" + file.name + "\"" + i18n.t(" was too large; the maximum file size is 25MiB.");
+            break;
+        case 'REQUEST ENTITY TOO LARGE':
+            msg = i18n.t("Sorry, the file was too large.");
+            break;
+        default:
+            msg = i18n.t("An unknown error occured.");
+            break;
         }
         $("#error-msg").text(msg);
     }
diff --git a/static/js/invite.js b/static/js/invite.js
index ca6edccce8..d1679fbb0b 100644
--- a/static/js/invite.js
+++ b/static/js/invite.js
@@ -71,9 +71,11 @@ exports.initialize = function () {
             invitee_emails.val('');
 
             if (page_params.development_environment) {
-                $('#dev_env_msg').text('In the Zulip development environment, outgoing emails are printed to the run-dev.py console.')
-                            .addClass('alert-info')
-                            .show();
+                // line-wrapped to avoid the i18n linter, since we don't want to translate this.
+                $('#dev_env_msg').text(
+                    'In the Zulip development environment, outgoing emails are printed to the run-dev.py console.')
+                    .addClass('alert-info')
+                    .show();
             }
 
         },
diff --git a/static/js/message_edit.js b/static/js/message_edit.js
index ca589641cd..c14496a29f 100644
--- a/static/js/message_edit.js
+++ b/static/js/message_edit.js
@@ -112,12 +112,12 @@ exports.save = function (row, from_topic_edited_only) {
         data: request,
         success: function () {
             if (msg_list === current_msg_list) {
-                row.find(".edit_error").text("Message successfully edited!").removeClass("alert-error").addClass("alert-success").show();
+                row.find(".edit_error").text(i18n.t("Message successfully edited!")).removeClass("alert-error").addClass("alert-success").show();
             }
         },
         error: function (xhr) {
             if (msg_list === current_msg_list) {
-                var message = channel.xhr_error_message("Error saving edit", xhr);
+                var message = channel.xhr_error_message(i18n.t("Error saving edit"), xhr);
                 row.find(".edit_error").text(message).show();
             }
         },
diff --git a/static/js/subs.js b/static/js/subs.js
index 8110a5c3ae..2072764b68 100644
--- a/static/js/subs.js
+++ b/static/js/subs.js
@@ -358,7 +358,7 @@ function show_subscription_settings(sub_row) {
         },
         error: function () {
             loading.destroy_indicator(indicator_elem);
-            error_elem.removeClass("hide").text("Could not fetch subscriber list");
+            error_elem.removeClass("hide").text(i18n.t("Could not fetch subscriber list"));
         },
     });
 
@@ -658,7 +658,7 @@ function change_stream_privacy(e) {
             $("#stream_privacy_modal").remove();
         },
         error: function () {
-            $("#change-stream-privacy-button").text("Try Again");
+            $("#change-stream-privacy-button").text(i18n.t("Try again"));
         },
     });
 }
@@ -1374,13 +1374,13 @@ $(function () {
                 }
             } else {
                 error_elem.addClass("hide");
-                warning_elem.removeClass("hide").text("User already subscribed");
+                warning_elem.removeClass("hide").text(i18n.t("User already subscribed"));
             }
         }
 
         function invite_failure() {
             warning_elem.addClass("hide");
-            error_elem.removeClass("hide").text("Could not add user to this stream");
+            error_elem.removeClass("hide").text(i18n.t("Could not add user to this stream"));
         }
 
         exports.invite_user_to_stream(principal, stream, invite_success, invite_failure);
@@ -1446,13 +1446,13 @@ $(function () {
                 }
             } else {
                 error_elem.addClass("hide");
-                warning_elem.removeClass("hide").text("User already not subscribed");
+                warning_elem.removeClass("hide").text(i18n.t("User is already not subscribed"));
             }
         }
 
         function removal_failure() {
             warning_elem.addClass("hide");
-            error_elem.removeClass("hide").text("Could not remove user from this stream");
+            error_elem.removeClass("hide").text(i18n.t("Error removing user from this stream"));
         }
 
         exports.remove_user_from_stream(principal, stream_name, removal_success,
diff --git a/static/js/upload_widget.js b/static/js/upload_widget.js
index 16428054c4..bdd99e77cd 100644
--- a/static/js/upload_widget.js
+++ b/static/js/upload_widget.js
@@ -62,18 +62,18 @@ var upload_widget = (function () {
             } else if (e.target.files.length === 1) {
                 var file = e.target.files[0];
                 if (file.size > 5 * 1024 * 1024) {
-                    input_error.text('File size must be < 5Mb.');
+                    input_error.text(i18n.t('File size must be < 5Mb.'));
                     input_error.show();
                     clear();
                 } else if (!is_image_format(file)) {
-                    input_error.text('File type is not supported.');
+                    input_error.text(i18n.t('File type is not supported.'));
                     input_error.show();
                     clear();
                 } else {
                     accept(file);
                 }
             } else {
-                input_error.text('Please just upload one file.');
+                input_error.text(i18n.t('Please just upload one file.'));
             }
         });
 
@@ -132,18 +132,18 @@ var upload_widget = (function () {
             } else if (e.target.files.length === 1) {
                 var file = e.target.files[0];
                 if (file.size > 5 * 1024 * 1024) {
-                    input_error.text('File size must be < 5Mb.');
+                    input_error.text(i18n.t('File size must be < 5Mb.'));
                     input_error.show();
                     clear();
                 } else if (!is_image_format(file)) {
-                    input_error.text('File type is not supported.');
+                    input_error.text(i18n.t('File type is not supported.'));
                     input_error.show();
                     clear();
                 } else {
                     accept(file);
                 }
             } else {
-                input_error.text('Please just upload one file.');
+                input_error.text(i18n.t('Please just upload one file.'));
             }
         });
 
diff --git a/tools/lint-all b/tools/lint-all
index 8d60f10b27..35887a0b9c 100755
--- a/tools/lint-all
+++ b/tools/lint-all
@@ -282,10 +282,8 @@ def build_custom_checkers(by_lang):
                          'frontend_tests/node_tests',
                          'static/js/debug.js']),
          'description': 'console.log and similar should not be used in webapp'},
-        {'pattern': 'button\.text\(["\']',
-         'exclude': set(['tools/lint-all',
-                         'frontend_tests/node_tests/templates.js']),
-         'description': 'Argument to button.text should be a literal string enclosed by i18n.t()'},
+        {'pattern': '[.]text\(["\'][a-zA-Z]',
+         'description': 'Strings passed to $().text should be wrapped in i18n.t() for internationalization'},
         {'pattern': 'compose_error\(["\']',
          'exclude': set(['tools/lint-all']),
          'description': 'Argument to compose_error should be a literal string enclosed '