diff --git a/frontend_tests/puppeteer_tests/settings.ts b/frontend_tests/puppeteer_tests/settings.ts index 142b18327517c..5851ec55875ad 100644 --- a/frontend_tests/puppeteer_tests/settings.ts +++ b/frontend_tests/puppeteer_tests/settings.ts @@ -303,8 +303,10 @@ async function test_alert_words_section(page: Page): Promise { } async function change_language(page: Page, language_data_code: string): Promise { - await page.waitForSelector("#user-display-settings .setting_default_language", {visible: true}); - await page.click("#user-display-settings .setting_default_language"); + await page.waitForSelector("#user-display-settings .language_selection_button", { + visible: true, + }); + await page.click("#user-display-settings .language_selection_button"); await common.wait_for_micromodal_to_open(page); const language_selector = `a[data-code="${CSS.escape(language_data_code)}"]`; await page.click(language_selector); @@ -317,10 +319,12 @@ async function check_language_setting_status(page: Page): Promise { } async function assert_language_changed_to_chinese(page: Page): Promise { - await page.waitForSelector("#user-display-settings .setting_default_language", {visible: true}); + await page.waitForSelector("#user-display-settings .language_selection_button", { + visible: true, + }); const default_language = await common.get_text_from_selector( page, - "#user-display-settings .setting_default_language", + "#user-display-settings .language_selection_button", ); assert.strictEqual( default_language, @@ -346,7 +350,9 @@ async function test_default_language_setting(page: Page): Promise { // Check that the saved indicator appears await check_language_setting_status(page); await page.click(".reload_link"); - await page.waitForSelector("#user-display-settings .setting_default_language", {visible: true}); + await page.waitForSelector("#user-display-settings .language_selection_button", { + visible: true, + }); await assert_language_changed_to_chinese(page); await test_i18n_language_precedence(page); await page.waitForSelector(display_settings_section, {visible: true}); @@ -363,7 +369,9 @@ async function test_default_language_setting(page: Page): Promise { await page.waitForSelector("#user-display-settings .lang-time-settings-status", { visible: true, }); - await page.waitForSelector("#user-display-settings .setting_default_language", {visible: true}); + await page.waitForSelector("#user-display-settings .language_selection_button", { + visible: true, + }); } async function test_notifications_section(page: Page): Promise { diff --git a/package.json b/package.json index 3f2b809199915..c535778b2ccd8 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "jquery": "^3.4.1", "jquery-caret-plugin": "^1.5.2", "jquery-validation": "^1.19.0", + "js-cookie": "^3.0.1", "katex": "^0.15.3", "lodash": "^4.17.19", "micromodal": "^0.4.6", diff --git a/static/js/click_handlers.js b/static/js/click_handlers.js index 1466762ea031e..f95f1a6d7f16f 100644 --- a/static/js/click_handlers.js +++ b/static/js/click_handlers.js @@ -37,6 +37,7 @@ import * as reactions from "./reactions"; import * as recent_topics_ui from "./recent_topics_ui"; import * as rows from "./rows"; import * as server_events from "./server_events"; +import * as settings_display from "./settings_display"; import * as settings_panel_menu from "./settings_panel_menu"; import * as settings_toggle from "./settings_toggle"; import * as spectators from "./spectators"; @@ -671,6 +672,10 @@ export function initialize() { popovers.hide_all(); }); + $("body").on("click", ".reload_link", () => { + window.location.reload(); + }); + // COMPOSE $("body").on("click", "#compose-send-status .compose-send-status-close", () => { @@ -863,6 +868,12 @@ export function initialize() { // GEAR MENU + $("body").on("click", ".change-language-spectator, .language_selection_widget button", (e) => { + e.preventDefault(); + e.stopPropagation(); + settings_display.launch_default_language_setting_modal(); + }); + $("body").on("click", "#gear-menu .dark-theme", (e) => { // Allow propagation to close gear menu. e.preventDefault(); diff --git a/static/js/settings_config.ts b/static/js/settings_config.ts index 37438c8e25844..21c2d2e8b3609 100644 --- a/static/js/settings_config.ts +++ b/static/js/settings_config.ts @@ -573,6 +573,7 @@ export const display_settings_labels = { }), ), escape_navigates_to_default_view: $t({defaultMessage: "Escape key navigates to default view"}), + default_language_settings_label: $t({defaultMessage: "Language"}), }; export const notification_settings_labels = { diff --git a/static/js/settings_display.js b/static/js/settings_display.js index 0a435b35eac49..5316b4eb078a3 100644 --- a/static/js/settings_display.js +++ b/static/js/settings_display.js @@ -1,4 +1,5 @@ import $ from "jquery"; +import Cookies from "js-cookie"; // eslint-disable-line import/no-unresolved import render_dialog_default_language from "../templates/default_language_modal.hbs"; @@ -8,6 +9,7 @@ import * as emojisets from "./emojisets"; import {$t_html, get_language_list_columns, get_language_name} from "./i18n"; import * as loading from "./loading"; import * as overlays from "./overlays"; +import {page_params} from "./page_params"; import * as settings_org from "./settings_org"; import * as settings_ui from "./settings_ui"; import * as ui_report from "./ui_report"; @@ -42,8 +44,22 @@ function change_display_setting(data, $status_el, success_msg_html, sticky) { settings_ui.do_settings_change(channel.patch, "/json/settings", data, $status_el, opts); } -function default_language_modal_post_render($container) { - $("#user_default_language_modal") +function spectator_default_language_modal_post_render() { + $("#language_selection_modal") + .find(".language") + .on("click", (e) => { + e.preventDefault(); + e.stopPropagation(); + dialog_widget.close_modal(); + + const $link = $(e.target).closest("a[data-code]"); + Cookies.set(page_params.language_cookie_name, $link.attr("data-code")); + window.location.reload(); + }); +} + +function user_default_language_modal_post_render() { + $("#language_selection_modal") .find(".language") .on("click", (e) => { e.preventDefault(); @@ -55,11 +71,13 @@ function default_language_modal_post_render($container) { const data = {default_language: setting_value}; const new_language = $link.attr("data-name"); - $container.find(".default_language_name").text(new_language); + $( + "#user-display-settings .language_selection_widget .language_selection_button span", + ).text(new_language); change_display_setting( data, - $container.find(".lang-time-settings-status"), + $("#settings_content").find(".lang-time-settings-status"), $t_html( { defaultMessage: @@ -72,7 +90,15 @@ function default_language_modal_post_render($container) { }); } -export function launch_default_language_setting_modal($container) { +function default_language_modal_post_render() { + if (page_params.is_spectator) { + spectator_default_language_modal_post_render(); + } else { + user_default_language_modal_post_render(); + } +} + +export function launch_default_language_setting_modal() { const html_body = render_dialog_default_language({ language_list: get_language_list_columns(user_settings.default_language), }); @@ -81,11 +107,11 @@ export function launch_default_language_setting_modal($container) { html_heading: $t_html({defaultMessage: "Select default language"}), html_body, html_submit_button: $t_html({defaultMessage: "Close"}), - id: "user_default_language_modal", + id: "language_selection_modal", close_on_submit: true, focus_submit_on_open: true, single_footer_button: true, - post_render: () => default_language_modal_post_render($container), + post_render: default_language_modal_post_render, on_click: () => {}, }); } @@ -147,16 +173,6 @@ export function set_up(settings_panel) { } }); - $container.find(".setting_default_language").on("click", (e) => { - e.preventDefault(); - e.stopPropagation(); - launch_default_language_setting_modal($container); - }); - - $("body").on("click", ".reload_link", () => { - window.location.reload(); - }); - $container.find(".setting_emojiset_choice").on("click", function () { const data = {emojiset: $(this).val()}; const current_emojiset = settings_object.emojiset; diff --git a/static/shared/icons/language.svg b/static/shared/icons/language.svg new file mode 100644 index 0000000000000..5ac407b90cd15 --- /dev/null +++ b/static/shared/icons/language.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/styles/settings.css b/static/styles/settings.css index 438bd9593f41c..c94bc82a48ce4 100644 --- a/static/styles/settings.css +++ b/static/styles/settings.css @@ -395,11 +395,7 @@ td .button { display: inline-block; } - #user-display-settings .setting_default_language { - text-decoration: none; - } - - #user_default_language_modal { + #language_selection_modal { table { width: 90%; margin-top: 20px; @@ -573,7 +569,8 @@ input[type="checkbox"] { margin-top: 10px; } -#user-display-settings .setting_default_language { +.language_selection_widget .language_selection_button { + text-decoration: none; margin-left: 20px; } diff --git a/static/styles/zulip.css b/static/styles/zulip.css index e8b9b00bbf6ea..38750ae4d5eac 100644 --- a/static/styles/zulip.css +++ b/static/styles/zulip.css @@ -2167,6 +2167,12 @@ div.focused_table { } } +#gear-menu .zulip-icon-language { + position: relative; + top: 2.5px; + left: -0.5px; +} + .nav .dropdown-menu a, .typeahead.dropdown-menu a { color: inherit; diff --git a/static/templates/gear_menu.hbs b/static/templates/gear_menu.hbs index 075c8b0fde135..2fcbe028c7e08 100644 --- a/static/templates/gear_menu.hbs +++ b/static/templates/gear_menu.hbs @@ -32,6 +32,11 @@ {{/unless}} +