diff --git a/frontend_tests/node_tests/settings_org.js b/frontend_tests/node_tests/settings_org.js index c46e2a6858..6e33be50e8 100644 --- a/frontend_tests/node_tests/settings_org.js +++ b/frontend_tests/node_tests/settings_org.js @@ -126,10 +126,10 @@ function test_realms_domain_modal(override, add_realm_domain) { assert(posted); success_callback(); - assert.equal(info.val(), "translated: Added successfully!"); + assert.equal(info.val(), "translated HTML: Added successfully!"); error_callback({}); - assert.equal(info.val(), "translated: Failed"); + assert.equal(info.val(), "translated HTML: Failed"); } function createSaveButtons(subsection) { @@ -395,10 +395,13 @@ function test_change_allow_subdomains(change_allow_subdomains) { change_allow_subdomains.call(elem_obj, ev); success_callback(); - assert.equal(info.val(), "translated: Update successful: Subdomains allowed for example.com"); + assert.equal( + info.val(), + "translated HTML: Update successful: Subdomains allowed for example.com", + ); error_callback({}); - assert.equal(info.val(), "translated: Failed"); + assert.equal(info.val(), "translated HTML: Failed"); allow = false; elem_obj.prop("checked", allow); @@ -406,7 +409,7 @@ function test_change_allow_subdomains(change_allow_subdomains) { success_callback(); assert.equal( info.val(), - "translated: Update successful: Subdomains no longer allowed for example.com", + "translated HTML: Update successful: Subdomains no longer allowed for example.com", ); } diff --git a/frontend_tests/node_tests/settings_user_groups.js b/frontend_tests/node_tests/settings_user_groups.js index 296aadd883..22593cc65f 100644 --- a/frontend_tests/node_tests/settings_user_groups.js +++ b/frontend_tests/node_tests/settings_user_groups.js @@ -530,7 +530,7 @@ test_ui("on_events", (override) => { $("#admin-user-group-status").show(); $("form.admin-user-group-form input[type='text']").val("fake-content"); ui_report.success = (text, ele) => { - assert.equal(text, "translated: User group added!"); + assert.equal(text, "translated HTML: User group added!"); assert.equal(ele, $("#admin-user-group-status")); }; @@ -546,7 +546,7 @@ test_ui("on_events", (override) => { const xhr = { responseText: '{"msg":"fake-msg"}', }; - assert.equal(error_msg, "translated: Failed"); + assert.equal(error_msg, "translated HTML: Failed"); assert.deepEqual(error_obj, xhr); assert.equal(ele, $("#admin-user-group-status")); }; @@ -765,7 +765,7 @@ test_ui("on_events", (override) => { const xhr = { responseText: '{"msg":"fake-msg"}', }; - assert.equal(error_msg, "translated: Failed"); + assert.equal(error_msg, "translated HTML: Failed"); assert.deepEqual(error_obj, xhr); assert.equal(ele, user_group_error); }; diff --git a/static/js/attachments_ui.js b/static/js/attachments_ui.js index c59712ec9d..48eba9c502 100644 --- a/static/js/attachments_ui.js +++ b/static/js/attachments_ui.js @@ -4,7 +4,7 @@ import render_settings_upload_space_stats from "../templates/settings/upload_spa import render_uploaded_files_list from "../templates/uploaded_files_list.hbs"; import * as channel from "./channel"; -import {i18n} from "./i18n"; +import {$t_html} from "./i18n"; import * as ListWidget from "./list_widget"; import * as loading from "./loading"; import {page_params} from "./page_params"; @@ -55,10 +55,10 @@ function delete_attachments(attachment) { url: "/json/attachments/" + attachment, idempotent: true, error(xhr) { - ui_report.error(i18n.t("Failed"), xhr, status); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, status); }, success() { - ui_report.success(i18n.t("Attachment deleted"), status); + ui_report.success($t_html({defaultMessage: "Attachment deleted"}), status); }, }); } @@ -162,7 +162,7 @@ export function set_up_attachments() { }, error(xhr) { loading.destroy_indicator($("#attachments_loading_indicator")); - ui_report.error(i18n.t("Failed"), xhr, status); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, status); }, }); } diff --git a/static/js/compose.js b/static/js/compose.js index 18fd222003..fb3a560b45 100644 --- a/static/js/compose.js +++ b/static/js/compose.js @@ -1271,7 +1271,7 @@ export function initialize() { } if (status !== "abort") { ui_report.generic_embed_error( - i18n.t("Failed to create video call."), + $t_html({defaultMessage: "Failed to create video call."}), ); } }, diff --git a/static/js/hash_util.js b/static/js/hash_util.js index de2ca2938e..66b38719ec 100644 --- a/static/js/hash_util.js +++ b/static/js/hash_util.js @@ -1,6 +1,6 @@ import $ from "jquery"; -import {i18n} from "./i18n"; +import {$t_html} from "./i18n"; import * as narrow_state from "./narrow_state"; import * as people from "./people"; import * as stream_data from "./stream_data"; @@ -78,7 +78,12 @@ export function decodeHashComponent(str) { // TODO: Show possible valid URLs to the user. return decodeURIComponent(str.replace(/\./g, "%")); } catch { - ui_report.error(i18n.t("Invalid URL"), undefined, $("#home-error"), 2000); + ui_report.error( + $t_html({defaultMessage: "Invalid URL"}), + undefined, + $("#home-error"), + 2000, + ); return ""; } } diff --git a/static/js/invite.js b/static/js/invite.js index 11c2bda267..3c8d74b2d7 100644 --- a/static/js/invite.js +++ b/static/js/invite.js @@ -10,7 +10,7 @@ import render_settings_dev_env_email_access from "../templates/settings/dev_env_ import * as browser_history from "./browser_history"; import * as channel from "./channel"; import * as common from "./common"; -import {i18n} from "./i18n"; +import {$t_html, i18n} from "./i18n"; import * as overlays from "./overlays"; import {page_params} from "./page_params"; import * as stream_data from "./stream_data"; @@ -68,7 +68,10 @@ function submit_invitation_form() { data, beforeSend, success() { - ui_report.success(i18n.t("User(s) invited successfully."), invite_status); + ui_report.success( + $t_html({defaultMessage: "User(s) invited successfully."}), + invite_status, + ); invitee_emails_group.removeClass("warning"); invitee_emails.val(""); diff --git a/static/js/message_edit.js b/static/js/message_edit.js index e1eff4f8f7..a90d7e8cb7 100644 --- a/static/js/message_edit.js +++ b/static/js/message_edit.js @@ -11,7 +11,7 @@ import * as compose_actions from "./compose_actions"; import * as composebox_typeahead from "./composebox_typeahead"; import * as condense from "./condense"; import * as echo from "./echo"; -import {i18n} from "./i18n"; +import {$t_html, i18n} from "./i18n"; import * as loading from "./loading"; import * as markdown from "./markdown"; import * as message_lists from "./message_lists"; @@ -910,7 +910,7 @@ export function delete_message(msg_id) { ); hide_delete_btn_show_spinner(false); ui_report.error( - i18n.t("Error deleting message"), + $t_html({defaultMessage: "Error deleting message"}), xhr, $("#delete-message-error"), ); @@ -983,7 +983,12 @@ export function move_topic_containing_message_to_stream( }, error(xhr) { reset_modal_ui(); - ui_report.error(i18n.t("Error moving the topic"), xhr, $("#home-error"), 4000); + ui_report.error( + $t_html({defaultMessage: "Error moving the topic"}), + xhr, + $("#home-error"), + 4000, + ); }, }); } diff --git a/static/js/message_edit_history.js b/static/js/message_edit_history.js index a7c581192b..d07ef60572 100644 --- a/static/js/message_edit_history.js +++ b/static/js/message_edit_history.js @@ -4,7 +4,7 @@ import $ from "jquery"; import render_message_edit_history from "../templates/message_edit_history.hbs"; import * as channel from "./channel"; -import {i18n} from "./i18n"; +import {$t_html} from "./i18n"; import * as people from "./people"; import * as timerender from "./timerender"; import * as ui_report from "./ui_report"; @@ -64,7 +64,7 @@ export function fetch_and_render_message_history(message) { }, error(xhr) { ui_report.error( - i18n.t("Error fetching message edit history"), + $t_html({defaultMessage: "Error fetching message edit history"}), xhr, $("#message-history-error"), ); diff --git a/static/js/reload.js b/static/js/reload.js index bd8f0890be..6f0ee00aa5 100644 --- a/static/js/reload.js +++ b/static/js/reload.js @@ -184,7 +184,7 @@ export function initialize() { hashchange.changehash(vars.oldhash); } -function do_reload_app(send_after_reload, save_pointer, save_narrow, save_compose, message) { +function do_reload_app(send_after_reload, save_pointer, save_narrow, save_compose, message_html) { if (reload_state.is_in_progress()) { blueslip.log("do_reload_app: Doing nothing since reload_in_progress"); return; @@ -200,7 +200,7 @@ function do_reload_app(send_after_reload, save_pointer, save_narrow, save_compos } // TODO: We need a better API for showing messages. - ui_report.message(message, $("#reloading-application")); + ui_report.message(message_html, $("#reloading-application")); blueslip.log("Starting server requested page reload"); reload_state.set_state_to_in_progress(); @@ -234,10 +234,10 @@ export function initiate({ save_narrow = true, save_compose = true, send_after_reload = false, - message = "Reloading ...", + message_html = "Reloading ...", }) { if (immediate) { - do_reload_app(send_after_reload, save_pointer, save_narrow, save_compose, message); + do_reload_app(send_after_reload, save_pointer, save_narrow, save_compose, message_html); } if (reload_state.is_pending()) { @@ -274,7 +274,7 @@ export function initiate({ let compose_started_handler; function reload_from_idle() { - do_reload_app(false, save_pointer, save_narrow, save_compose, message); + do_reload_app(false, save_pointer, save_narrow, save_compose, message_html); } // Make sure we always do a reload eventually after diff --git a/static/js/server_events_dispatch.js b/static/js/server_events_dispatch.js index 32668e8566..517f41b590 100644 --- a/static/js/server_events_dispatch.js +++ b/static/js/server_events_dispatch.js @@ -146,7 +146,7 @@ export function dispatch_normal_event(event) { save_pointer: true, save_narrow: true, save_compose: true, - message: "The application has been updated; reloading!", + message_html: "The application has been updated; reloading!", }; if (event.immediate) { reload_options.immediate = true; diff --git a/static/js/settings_account.js b/static/js/settings_account.js index ffc43c8f2b..ab2b712c27 100644 --- a/static/js/settings_account.js +++ b/static/js/settings_account.js @@ -10,7 +10,7 @@ import * as blueslip from "./blueslip"; import * as channel from "./channel"; import * as common from "./common"; import {csrf_token} from "./csrf"; -import {$t_html, i18n} from "./i18n"; +import {$t_html} from "./i18n"; import * as overlays from "./overlays"; import {page_params} from "./page_params"; import * as people from "./people"; @@ -89,8 +89,8 @@ function display_avatar_upload_started() { $("#user-avatar-upload-widget .image-delete-button").hide(); } -function settings_change_error(message, xhr) { - ui_report.error(message, xhr, $("#account-settings-status").expectOne()); +function settings_change_error(message_html, xhr) { + ui_report.error(message_html, xhr, $("#account-settings-status").expectOne()); } function update_custom_profile_field(field, method) { @@ -308,7 +308,11 @@ export function set_up() { $("#show_api_key").show(); }, error(xhr) { - ui_report.error(i18n.t("Error"), xhr, $("#api_key_status").expectOne()); + ui_report.error( + $t_html({defaultMessage: "Error"}), + xhr, + $("#api_key_status").expectOne(), + ); $("#show_api_key").hide(); $("#api_key_modal").show(); }, @@ -428,7 +432,7 @@ export function set_up() { ); return; } else if (!password_ok) { - settings_change_error(i18n.t("New password is too weak")); + settings_change_error($t_html({defaultMessage: "New password is too weak"})); return; } } @@ -504,9 +508,10 @@ export function set_up() { overlays.close_modal("#change_email_modal"); }, error_msg_element: change_email_error, - success_msg: i18n - .t("Check your email (%s) to confirm the new address.") - .replace("%s", data.email), + success_msg_html: $t_html( + {defaultMessage: "Check your email ({email}) to confirm the new address."}, + {email: data.email}, + ), }; settings_ui.do_settings_change( channel.patch, diff --git a/static/js/settings_display.js b/static/js/settings_display.js index 75830f5307..72f62ad005 100644 --- a/static/js/settings_display.js +++ b/static/js/settings_display.js @@ -2,7 +2,7 @@ import $ from "jquery"; import * as channel from "./channel"; import * as emojisets from "./emojisets"; -import {i18n} from "./i18n"; +import {$t_html} from "./i18n"; import * as loading from "./loading"; import * as overlays from "./overlays"; import {page_params} from "./page_params"; @@ -14,18 +14,20 @@ const meta = { loaded: false, }; -function change_display_setting(data, status_element, success_msg, sticky) { +function change_display_setting(data, status_element, success_msg_html, sticky) { const $status_el = $(status_element); const status_is_sticky = $status_el.data("is_sticky"); - const display_message = status_is_sticky ? $status_el.data("sticky_msg") : success_msg; + const display_message_html = status_is_sticky + ? $status_el.data("sticky_msg_html") + : success_msg_html; const opts = { - success_msg: display_message, + success_msg_html: display_message_html, sticky: status_is_sticky || sticky, }; if (sticky) { $status_el.data("is_sticky", true); - $status_el.data("sticky_msg", success_msg); + $status_el.data("sticky_msg_html", success_msg_html); } settings_ui.do_settings_change( channel.patch, @@ -66,8 +68,12 @@ export function set_up() { change_display_setting( data, "#display-settings-status", - i18n.t( - "Saved. Please reload for the change to take effect.", + $t_html( + { + defaultMessage: + "Saved. Please reload for the change to take effect.", + }, + {"z-link": (content_html) => `${content_html}`}, ), true, ); @@ -92,8 +98,12 @@ export function set_up() { change_display_setting( data, "#language-settings-status", - i18n.t( - "Saved. Please reload for the change to take effect.", + $t_html( + { + defaultMessage: + "Saved. Please reload for the change to take effect.", + }, + {"z-link": (content_html) => `${content_html}`}, ), true, ); @@ -148,7 +158,7 @@ export function set_up() { success() {}, error(xhr) { ui_report.error( - settings_ui.strings.failure, + settings_ui.strings.failure_html, xhr, $("#emoji-settings-status").expectOne(), ); @@ -176,7 +186,7 @@ export async function report_emojiset_change() { loading.destroy_indicator($("#emojiset_spinner")); $("#emojiset_select").val(page_params.emojiset); ui_report.success( - i18n.t("Emojiset changed successfully!"), + $t_html({defaultMessage: "Emojiset changed successfully!"}), $("#emoji-settings-status").expectOne(), ); const spinner = $("#emoji-settings-status").expectOne(); diff --git a/static/js/settings_emoji.js b/static/js/settings_emoji.js index 8f9166e461..0b11a60471 100644 --- a/static/js/settings_emoji.js +++ b/static/js/settings_emoji.js @@ -5,7 +5,7 @@ import render_admin_emoji_list from "../templates/admin_emoji_list.hbs"; import render_settings_emoji_settings_tip from "../templates/settings/emoji_settings_tip.hbs"; import * as channel from "./channel"; -import {i18n} from "./i18n"; +import {$t_html} from "./i18n"; import * as ListWidget from "./list_widget"; import * as loading from "./loading"; import {page_params} from "./page_params"; @@ -191,7 +191,10 @@ export function set_up() { } if (emoji.name.trim() === "") { - ui_report.client_error(i18n.t("Failed: Emoji name is required."), emoji_status); + ui_report.client_error( + $t_html({defaultMessage: "Failed: Emoji name is required."}), + emoji_status, + ); return; } $("#admin_emoji_submit").prop("disabled", true); @@ -207,7 +210,10 @@ export function set_up() { contentType: false, success() { $("#admin-emoji-status").hide(); - ui_report.success(i18n.t("Custom emoji added!"), emoji_status); + ui_report.success( + $t_html({defaultMessage: "Custom emoji added!"}), + emoji_status, + ); $("form.admin-emoji-form input[type='text']").val(""); $("#admin_emoji_submit").prop("disabled", false); emoji_widget.clear(); @@ -216,7 +222,7 @@ export function set_up() { $("#admin-emoji-status").hide(); const errors = JSON.parse(xhr.responseText).msg; xhr.responseText = JSON.stringify({msg: errors}); - ui_report.error(i18n.t("Failed"), xhr, emoji_status); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, emoji_status); $("#admin_emoji_submit").prop("disabled", false); }, }); diff --git a/static/js/settings_exports.js b/static/js/settings_exports.js index b6c20d5f52..5ac2f70ecf 100644 --- a/static/js/settings_exports.js +++ b/static/js/settings_exports.js @@ -3,7 +3,7 @@ import $ from "jquery"; import render_admin_export_list from "../templates/admin_export_list.hbs"; import * as channel from "./channel"; -import {i18n} from "./i18n"; +import {$t_html} from "./i18n"; import * as ListWidget from "./list_widget"; import * as loading from "./loading"; import * as people from "./people"; @@ -106,13 +106,13 @@ export function set_up() { url: "/json/export/realm", success() { ui_report.success( - i18n.t("Export started. Check back in a few minutes."), + $t_html({defaultMessage: "Export started. Check back in a few minutes."}), export_status, 4000, ); }, error(xhr) { - ui_report.error(i18n.t("Export failed"), xhr, export_status); + ui_report.error($t_html({defaultMessage: "Export failed"}), xhr, export_status); }, }); }); diff --git a/static/js/settings_invites.js b/static/js/settings_invites.js index dab54d4c28..328c43c713 100644 --- a/static/js/settings_invites.js +++ b/static/js/settings_invites.js @@ -5,7 +5,7 @@ import render_settings_revoke_invite_modal from "../templates/settings/revoke_in import * as blueslip from "./blueslip"; import * as channel from "./channel"; -import {i18n} from "./i18n"; +import {$t_html, i18n} from "./i18n"; import * as ListWidget from "./list_widget"; import * as loading from "./loading"; import {page_params} from "./page_params"; @@ -25,7 +25,11 @@ export function reset() { function failed_listing_invites(xhr) { loading.destroy_indicator($("#admin_page_invites_loading_indicator")); - ui_report.error(i18n.t("Error listing invites"), xhr, $("#invites-field-status")); + ui_report.error( + $t_html({defaultMessage: "Error listing invites"}), + xhr, + $("#invites-field-status"), + ); } function add_invited_as_text(invites) { @@ -102,7 +106,9 @@ function do_revoke_invite() { if (modal_invite_id !== meta.invite_id || modal_is_multiuse !== meta.is_multiuse) { blueslip.error("Invite revoking canceled due to non-matching fields."); ui_report.client_error( - i18n.t("Resending encountered an error. Please reload and try again."), + $t_html({ + defaultMessage: "Resending encountered an error. Please reload and try again.", + }), $("#home-error"), ); } @@ -201,7 +207,9 @@ export function on_load_success(invites_data, initialize_event_handlers) { if (modal_invite_id !== meta.invite_id) { blueslip.error("Invite resending canceled due to non-matching fields."); ui_report.client_error( - i18n.t("Resending encountered an error. Please reload and try again."), + $t_html({ + defaultMessage: "Resending encountered an error. Please reload and try again.", + }), $("#home-error"), ); } diff --git a/static/js/settings_linkifiers.js b/static/js/settings_linkifiers.js index efbb47e212..ee3b4d1c76 100644 --- a/static/js/settings_linkifiers.js +++ b/static/js/settings_linkifiers.js @@ -3,7 +3,7 @@ import $ from "jquery"; import render_admin_linkifier_list from "../templates/admin_linkifier_list.hbs"; import * as channel from "./channel"; -import {i18n} from "./i18n"; +import {$t_html} from "./i18n"; import * as ListWidget from "./list_widget"; import {page_params} from "./page_params"; import * as ui from "./ui"; @@ -135,22 +135,25 @@ export function build_page() { $("#linkifier_format_string").val(""); add_linkifier_button.prop("disabled", false); linkifier.id = data.id; - ui_report.success(i18n.t("Custom linkifier added!"), linkifier_status); + ui_report.success( + $t_html({defaultMessage: "Custom linkifier added!"}), + linkifier_status, + ); }, error(xhr) { const errors = JSON.parse(xhr.responseText).errors; add_linkifier_button.prop("disabled", false); if (errors.pattern !== undefined) { xhr.responseText = JSON.stringify({msg: errors.pattern}); - ui_report.error(i18n.t("Failed"), xhr, pattern_status); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, pattern_status); } if (errors.url_format_string !== undefined) { xhr.responseText = JSON.stringify({msg: errors.url_format_string}); - ui_report.error(i18n.t("Failed"), xhr, format_status); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, format_status); } if (errors.__all__ !== undefined) { xhr.responseText = JSON.stringify({msg: errors.__all__}); - ui_report.error(i18n.t("Failed"), xhr, linkifier_status); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, linkifier_status); } }, }); diff --git a/static/js/settings_org.js b/static/js/settings_org.js index 6e28a4b2f6..0adb38b04c 100644 --- a/static/js/settings_org.js +++ b/static/js/settings_org.js @@ -8,7 +8,7 @@ import * as blueslip from "./blueslip"; import * as channel from "./channel"; import {csrf_token} from "./csrf"; import {DropdownListWidget as dropdown_list_widget} from "./dropdown_list_widget"; -import {i18n} from "./i18n"; +import {$t_html, i18n} from "./i18n"; import * as loading from "./loading"; import * as overlays from "./overlays"; import {page_params} from "./page_params"; @@ -734,7 +734,7 @@ export function build_page() { error(xhr) { change_save_button_state(save_btn_container, "failed"); save_button.hide(); - ui_report.error(i18n.t("Save failed"), xhr, failed_alert_elem); + ui_report.error($t_html({defaultMessage: "Save failed"}), xhr, failed_alert_elem); }, }); }; @@ -966,11 +966,14 @@ export function build_page() { channel.del({ url, success() { - ui_report.success(i18n.t("Deleted successfully!"), realm_domains_info); + ui_report.success( + $t_html({defaultMessage: "Deleted successfully!"}), + realm_domains_info, + ); fade_status_element(realm_domains_info); }, error(xhr) { - ui_report.error(i18n.t("Failed"), xhr, realm_domains_info); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, realm_domains_info); fade_status_element(realm_domains_info); }, }); @@ -995,11 +998,14 @@ export function build_page() { "checked", false, ); - ui_report.success(i18n.t("Added successfully!"), realm_domains_info); + ui_report.success( + $t_html({defaultMessage: "Added successfully!"}), + realm_domains_info, + ); fade_status_element(realm_domains_info); }, error(xhr) { - ui_report.error(i18n.t("Failed"), xhr, realm_domains_info); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, realm_domains_info); fade_status_element(realm_domains_info); }, }); @@ -1021,23 +1027,28 @@ export function build_page() { success() { if (allow_subdomains) { ui_report.success( - i18n.t("Update successful: Subdomains allowed for __domain__", { - domain, - }), + $t_html( + {defaultMessage: "Update successful: Subdomains allowed for {domain}"}, + {domain}, + ), realm_domains_info, ); } else { ui_report.success( - i18n.t("Update successful: Subdomains no longer allowed for __domain__", { - domain, - }), + $t_html( + { + defaultMessage: + "Update successful: Subdomains no longer allowed for {domain}", + }, + {domain}, + ), realm_domains_info, ); } fade_status_element(realm_domains_info); }, error(xhr) { - ui_report.error(i18n.t("Failed"), xhr, realm_domains_info); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, realm_domains_info); fade_status_element(realm_domains_info); }, }); @@ -1120,7 +1131,7 @@ export function build_page() { url: "/json/realm/deactivate", error(xhr) { ui_report.error( - i18n.t("Failed"), + $t_html({defaultMessage: "Failed"}), xhr, $("#admin-realm-deactivation-status").expectOne(), ); diff --git a/static/js/settings_streams.js b/static/js/settings_streams.js index 4b0a82d024..cac53343c8 100644 --- a/static/js/settings_streams.js +++ b/static/js/settings_streams.js @@ -3,7 +3,7 @@ import $ from "jquery"; import render_admin_default_streams_list from "../templates/admin_default_streams_list.hbs"; import * as channel from "./channel"; -import {i18n} from "./i18n"; +import {$t_html} from "./i18n"; import * as ListWidget from "./list_widget"; import * as loading from "./loading"; import {page_params} from "./page_params"; @@ -80,9 +80,9 @@ function make_stream_default(stream_id) { data, error(xhr) { if (xhr.status.toString().charAt(0) === "4") { - ui_report.error(i18n.t("Failed"), xhr, default_stream_status); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, default_stream_status); } else { - ui_report.error(i18n.t("Failed"), default_stream_status); + ui_report.error($t_html({defaultMessage: "Failed"}), default_stream_status); } default_stream_status.show(); }, diff --git a/static/js/settings_ui.js b/static/js/settings_ui.js index aa5286231b..a56886da2a 100644 --- a/static/js/settings_ui.js +++ b/static/js/settings_ui.js @@ -1,6 +1,6 @@ import $ from "jquery"; -import {i18n} from "./i18n"; +import {$t_html, i18n} from "./i18n"; import * as loading from "./loading"; import * as ui_report from "./ui_report"; @@ -12,8 +12,8 @@ export function display_checkmark($elem) { } export const strings = { - success: i18n.t("Saved"), - failure: i18n.t("Save failed"), + success_html: $t_html({defaultMessage: "Saved"}), + failure_html: $t_html({defaultMessage: "Save failed"}), saving: i18n.t("Saving"), }; @@ -26,7 +26,7 @@ export function do_settings_change( data, status_element, { - success_msg = strings.success, + success_msg_html = strings.success_html, success_continuation, error_continuation, sticky = false, @@ -44,7 +44,7 @@ export function do_settings_change( data, success(reponse_data) { setTimeout(() => { - ui_report.success(success_msg, spinner, remove_after); + ui_report.success(success_msg_html, spinner, remove_after); display_checkmark(spinner); }, appear_after); if (success_continuation !== undefined) { @@ -54,9 +54,9 @@ export function do_settings_change( error(xhr) { if (error_msg_element) { loading.destroy_indicator(spinner); - ui_report.error(strings.failure, xhr, error_msg_element); + ui_report.error(strings.failure_html, xhr, error_msg_element); } else { - ui_report.error(strings.failure, xhr, spinner); + ui_report.error(strings.failure_html, xhr, spinner); } if (error_continuation !== undefined) { error_continuation(xhr); diff --git a/static/js/settings_user_groups.js b/static/js/settings_user_groups.js index 9438792539..fd84e5dc9c 100644 --- a/static/js/settings_user_groups.js +++ b/static/js/settings_user_groups.js @@ -6,7 +6,7 @@ import render_confirm_delete_user from "../templates/confirm_delete_user.hbs"; import * as channel from "./channel"; import * as confirm_dialog from "./confirm_dialog"; -import {i18n} from "./i18n"; +import {$t_html, i18n} from "./i18n"; import {page_params} from "./page_params"; import * as people from "./people"; import * as pill_typeahead from "./pill_typeahead"; @@ -208,7 +208,7 @@ export function populate_user_groups() { error(xhr) { const errors = JSON.parse(xhr.responseText).msg; xhr.responseText = JSON.stringify({msg: errors}); - ui_report.error(i18n.t("Failed"), xhr, user_group_status); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, user_group_status); update_cancel_button(); $(`#user-groups #${CSS.escape(data.id)} .name`).text(group_data.name); $(`#user-groups #${CSS.escape(data.id)} .description`).text( @@ -323,14 +323,17 @@ export function set_up() { data: group, success() { user_group_status.hide(); - ui_report.success(i18n.t("User group added!"), user_group_status); + ui_report.success( + $t_html({defaultMessage: "User group added!"}), + user_group_status, + ); $("form.admin-user-group-form input[type='text']").val(""); }, error(xhr) { user_group_status.hide(); const errors = JSON.parse(xhr.responseText).msg; xhr.responseText = JSON.stringify({msg: errors}); - ui_report.error(i18n.t("Failed"), xhr, user_group_status); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, user_group_status); }, }); }); diff --git a/static/js/stream_create.js b/static/js/stream_create.js index c89d4830a1..770038fe0c 100644 --- a/static/js/stream_create.js +++ b/static/js/stream_create.js @@ -6,7 +6,7 @@ import render_subscription_invites_warning_modal from "../templates/subscription import * as blueslip from "./blueslip"; import * as channel from "./channel"; -import {i18n} from "./i18n"; +import {$t_html, i18n} from "./i18n"; import * as loading from "./loading"; import {page_params} from "./page_params"; import * as peer_data from "./peer_data"; @@ -156,7 +156,7 @@ function create_stream() { // and paste over a description with newline characters in it. Prevent that. if (description.includes("\n")) { ui_report.client_error( - i18n.t("The stream description cannot contain newline characters."), + $t_html({defaultMessage: "The stream description cannot contain newline characters."}), $(".stream_create_info"), ); return undefined; @@ -218,7 +218,10 @@ function create_stream() { success() { $("#create_stream_name").val(""); $("#create_stream_description").val(""); - ui_report.success(i18n.t("Stream successfully created!"), $(".stream_create_info")); + ui_report.success( + $t_html({defaultMessage: "Stream successfully created!"}), + $(".stream_create_info"), + ); loading.destroy_indicator($("#stream_creating_indicator")); // The rest of the work is done via the subscribe event we will get }, @@ -237,7 +240,11 @@ function create_stream() { stream_name_error.trigger("select"); } - ui_report.error(i18n.t("Error creating stream"), xhr, $(".stream_create_info")); + ui_report.error( + $t_html({defaultMessage: "Error creating stream"}), + xhr, + $(".stream_create_info"), + ); loading.destroy_indicator($("#stream_creating_indicator")); }, }); diff --git a/static/js/stream_edit.js b/static/js/stream_edit.js index dc224ed5ee..1e664082dd 100644 --- a/static/js/stream_edit.js +++ b/static/js/stream_edit.js @@ -12,7 +12,7 @@ import * as browser_history from "./browser_history"; import * as channel from "./channel"; import * as confirm_dialog from "./confirm_dialog"; import * as hash_util from "./hash_util"; -import {i18n} from "./i18n"; +import {$t_html, i18n} from "./i18n"; import * as input_pill from "./input_pill"; import * as ListWidget from "./list_widget"; import * as narrow_state from "./narrow_state"; @@ -606,7 +606,7 @@ function change_stream_privacy(e) { // The rest will be done by update stream event we will get. }, error(xhr) { - ui_report.error(i18n.t("Failed"), xhr, stream_privacy_status); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, stream_privacy_status); $("#change-stream-privacy-button").text(i18n.t("Try again")); }, }); @@ -633,13 +633,17 @@ export function change_stream_name(e) { success() { new_name_box.val(""); ui_report.success( - i18n.t("The stream has been renamed!"), + $t_html({defaultMessage: "The stream has been renamed!"}), $(".stream_change_property_info"), ); }, error(xhr) { new_name_box.text(old_name); - ui_report.error(i18n.t("Error"), xhr, $(".stream_change_property_info")); + ui_report.error( + $t_html({defaultMessage: "Error"}), + xhr, + $(".stream_change_property_info"), + ); }, }); } @@ -683,7 +687,7 @@ export function change_stream_description(e) { success() { // The event from the server will update the rest of the UI ui_report.success( - i18n.t("The stream description has been updated!"), + $t_html({defaultMessage: "The stream description has been updated!"}), $(".stream_change_property_info"), ); }, @@ -691,7 +695,11 @@ export function change_stream_description(e) { sub_settings .find(".stream-description-editable") .html(util.clean_user_content_links(sub.rendered_description)); - ui_report.error(i18n.t("Error"), xhr, $(".stream_change_property_info")); + ui_report.error( + $t_html({defaultMessage: "Error"}), + xhr, + $(".stream_change_property_info"), + ); }, }); } @@ -700,7 +708,7 @@ export function archive_stream(stream_id, alert_element, stream_row) { channel.del({ url: "/json/streams/" + stream_id, error(xhr) { - ui_report.error(i18n.t("Failed"), xhr, alert_element); + ui_report.error($t_html({defaultMessage: "Failed"}), xhr, alert_element); }, success() { stream_row.remove(); @@ -861,7 +869,10 @@ export function initialize() { const stream_id = get_stream_id(e.target); if (!stream_id) { - ui_report.client_error(i18n.t("Invalid stream id"), $(".stream_change_property_info")); + ui_report.client_error( + $t_html({defaultMessage: "Invalid stream id"}), + $(".stream_change_property_info"), + ); return; } const stream_name = stream_data.maybe_get_stream_name(stream_id); @@ -878,7 +889,10 @@ export function initialize() { const stream_id = $(e.target).data("stream-id"); overlays.close_modal("#deactivation_stream_modal"); if (!stream_id) { - ui_report.client_error(i18n.t("Invalid stream id"), $(".stream_change_property_info")); + ui_report.client_error( + $t_html({defaultMessage: "Invalid stream id"}), + $(".stream_change_property_info"), + ); return; } const row = $(".stream-row.active"); diff --git a/static/js/subs.js b/static/js/subs.js index bfc732c3af..bc3d28178e 100644 --- a/static/js/subs.js +++ b/static/js/subs.js @@ -15,7 +15,7 @@ import * as components from "./components"; import * as compose_state from "./compose_state"; import * as confirm_dialog from "./confirm_dialog"; import * as hash_util from "./hash_util"; -import {i18n} from "./i18n"; +import {$t_html, i18n} from "./i18n"; import * as loading from "./loading"; import * as message_live_update from "./message_live_update"; import * as message_view_header from "./message_view_header"; @@ -857,7 +857,10 @@ function ajaxSubscribe(stream, color, stream_row) { // Display the canonical stream capitalization. true_stream_name = res.already_subscribed[people.my_current_email()][0]; ui_report.success( - i18n.t("Already subscribed to __stream__", {stream: true_stream_name}), + $t_html( + {defaultMessage: "Already subscribed to {stream}"}, + {stream: true_stream_name}, + ), $(".stream_change_property_info"), ); } @@ -872,7 +875,7 @@ function ajaxSubscribe(stream, color, stream_row) { hide_subscribe_toggle_spinner(stream_row); } ui_report.error( - i18n.t("Error adding subscription"), + $t_html({defaultMessage: "Error adding subscription"}), xhr, $(".stream_change_property_info"), ); @@ -901,7 +904,7 @@ function ajaxUnsubscribe(sub, stream_row) { hide_subscribe_toggle_spinner(stream_row); } ui_report.error( - i18n.t("Error removing subscription"), + $t_html({defaultMessage: "Error removing subscription"}), xhr, $(".stream_change_property_info"), ); diff --git a/static/js/ui_report.js b/static/js/ui_report.js index 5d767f6585..2901f010ef 100644 --- a/static/js/ui_report.js +++ b/static/js/ui_report.js @@ -10,13 +10,13 @@ import {i18n} from "./i18n"; cls- class that we want to add/remove to/from the status_box */ -export function message(response, status_box, cls = "alert", remove_after = false) { +export function message(response_html, status_box, cls = "alert", remove_after = false) { // Note we use html() below, since we can rely on our callers escaping HTML - // via i18n.t when interpolating data. + // via $t_html when interpolating data. status_box .removeClass(common.status_classes) .addClass(cls) - .html(response) + .html(response_html) .stop(true) .fadeTo(0, 1); if (remove_after) { @@ -27,35 +27,35 @@ export function message(response, status_box, cls = "alert", remove_after = fals status_box.addClass("show"); } -export function error(response, xhr, status_box, remove_after) { +export function error(response_html, xhr, status_box, remove_after) { if (xhr && xhr.status.toString().charAt(0) === "4") { // Only display the error response for 4XX, where we've crafted // a nice response. - const server_response = _.escape(JSON.parse(xhr.responseText).msg); - if (response) { - response += ": " + server_response; + const server_response_html = _.escape(JSON.parse(xhr.responseText).msg); + if (response_html) { + response_html += ": " + server_response_html; } else { - response = server_response; + response_html = server_response_html; } } - message(response, status_box, "alert-error", remove_after); + message(response_html, status_box, "alert-error", remove_after); } -export function client_error(response, status_box, remove_after) { - message(response, status_box, "alert-error", remove_after); +export function client_error(response_html, status_box, remove_after) { + message(response_html, status_box, "alert-error", remove_after); } -export function success(response, status_box, remove_after) { - message(response, status_box, "alert-success", remove_after); +export function success(response_html, status_box, remove_after) { + message(response_html, status_box, "alert-success", remove_after); } -export function generic_embed_error(error) { +export function generic_embed_error(error_html) { const $alert = $("
"); const $exit = "
"; $(".alert-box").append( - $alert.html($exit + "
" + error + "
").addClass("show"), + $alert.html($exit + "
" + error_html + "
").addClass("show"), ); }