From 8fc3715ea86ea3083eda5ccc0d6f52dc3fa9f5b8 Mon Sep 17 00:00:00 2001 From: Gaurav Pandey Date: Wed, 16 Jun 2021 02:07:07 +0530 Subject: [PATCH] settings: Remove language_list_dbl_col from page_params. The language_list_dbl_col parameter in the page_params is used by only the web client frontend. The value is calculated in the backend and then passed as a page_param which is unnecessary considering that the whole process is beneficial for the front_end only. Hence move the entire calculation code to the frontend. Fixes part of #18673. --- frontend_tests/node_tests/i18n.js | 79 ++++++++++++++++++- static/js/i18n.js | 65 +++++++++++++++ static/js/settings.js | 3 +- static/templates/default_language_modal.hbs | 10 +-- .../templates/settings/display_settings.hbs | 2 +- zerver/lib/home.py | 2 - zerver/lib/i18n.py | 42 ---------- zerver/tests/test_home.py | 1 - 8 files changed, 151 insertions(+), 53 deletions(-) diff --git a/frontend_tests/node_tests/i18n.js b/frontend_tests/node_tests/i18n.js index d1c4f3855d..bb08b5e972 100644 --- a/frontend_tests/node_tests/i18n.js +++ b/frontend_tests/node_tests/i18n.js @@ -2,6 +2,8 @@ const {strict: assert} = require("assert"); +const _ = require("lodash"); + const {unmock_module, zrequire} = require("../zjsunit/namespace"); const {run_test} = require("../zjsunit/test"); const {page_params} = require("../zjsunit/zpage_params"); @@ -23,7 +25,7 @@ page_params.translation_data = { // `i18n.js` initializes FormatJS and is imported by // `templates.js`. unmock_module("../../static/js/i18n"); -const {$t, $t_html} = zrequire("i18n"); +const {$t, $t_html, get_language_list_columns} = zrequire("i18n"); run_test("$t", () => { // Normally the id would be provided by babel-plugin-formatjs, but @@ -104,3 +106,78 @@ run_test("tr_tag", () => { const html = require("../../static/templates/settings_tab.hbs")(args); assert.ok(html.indexOf("Déclencheurs de notification") > 0); }); + +run_test("language_list", () => { + page_params.language_list = [ + { + code: "en", + locale: "en", + name: "English", + }, + { + code: "en-gb", + locale: "en_GB", + name: "British English", + percent_translated: 99, + }, + { + code: "id", + locale: "id", + name: "Bahasa Indonesia", + percent_translated: 32, + }, + ]; + + const successful_formatted_list = [ + { + first: { + name: "English", + code: "en", + name_with_percent: "English", + selected: true, + }, + second: { + name: "Bahasa Indonesia", + code: "id", + name_with_percent: "Bahasa Indonesia (32%)", + selected: false, + }, + }, + { + first: { + name: "British English", + code: "en-gb", + name_with_percent: "British English (99%)", + selected: false, + }, + }, + ]; + + const formatted_list = get_language_list_columns("en"); + + function check_value_match(element, position) { + assert.equal( + formatted_list[element][position].name, + successful_formatted_list[element][position].name, + ); + assert.equal( + formatted_list[element][position].code, + successful_formatted_list[element][position].code, + ); + assert.equal( + formatted_list[element][position].name_with_percent, + successful_formatted_list[element][position].name_with_percent, + ); + assert.equal( + formatted_list[element][position].selected, + successful_formatted_list[element][position].selected, + ); + } + + for (const element of _.range(0, formatted_list.length)) { + check_value_match(element, "first"); + if (formatted_list[element].second) { + check_value_match(element, "second"); + } + } +}); diff --git a/static/js/i18n.js b/static/js/i18n.js index f3d8d91439..4168a2f675 100644 --- a/static/js/i18n.js +++ b/static/js/i18n.js @@ -43,3 +43,68 @@ export function $t_html(descriptor, values) { ), }); } + +// This formats language data for the language selection modal in a +// 2-column format. +export function get_language_list_columns(default_language) { + const language_list = []; + + // Only render languages with percentage translation >= 5% + for (const language of page_params.language_list) { + if (language.percent_translated === undefined || language.percent_translated >= 5) { + language_list.push({ + code: language.code, + locale: language.locale, + name: language.name, + percent_translated: language.percent_translated, + }); + } + } + + const formatted_list = []; + const language_len = language_list.length; + const firsts_end = Math.floor(language_len / 2) + (language_len % 2); + const firsts = _.range(0, firsts_end); + const seconds = _.range(firsts_end, language_len); + + const longest_zip = []; + + // Create a zip (itertool.zip_longest in python) + for (const value of firsts) { + longest_zip.push([value, seconds[value]]); + } + + for (const row of longest_zip) { + const item = {}; + const zip_row = [ + ["first", row[0]], + ["second", row[1]], + ]; + for (const zip_value of zip_row) { + if (zip_value[1] !== undefined) { + const lang = language_list[zip_value[1]]; + const name = lang.name; + let name_with_percent = name; + if (lang.percent_translated !== undefined) { + name_with_percent = name + " (" + lang.percent_translated + "%)"; + } + + let selected = false; + + if (default_language === lang.code || default_language === lang.locale) { + selected = true; + } + + item[zip_value[0]] = { + name, + code: lang.code, + name_with_percent, + selected, + }; + } + } + + formatted_list.push(item); + } + return formatted_list; +} diff --git a/static/js/settings.js b/static/js/settings.js index 3b97f2b5ef..8d75fa0a11 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -7,7 +7,7 @@ import render_settings_tab from "../templates/settings_tab.hbs"; import * as admin from "./admin"; import * as blueslip from "./blueslip"; import * as common from "./common"; -import {$t, $t_html} from "./i18n"; +import {$t, $t_html, get_language_list_columns} from "./i18n"; import * as overlays from "./overlays"; import {page_params} from "./page_params"; import * as people from "./people"; @@ -113,6 +113,7 @@ export function build_page() { user_can_change_avatar: settings_data.user_can_change_avatar(), user_role_text: people.get_user_type(page_params.user_id), default_language_name: settings_display.default_language_name, + language_list_dbl_col: get_language_list_columns(page_params.default_language), }); $(".settings-box").html(rendered_settings_tab); diff --git a/static/templates/default_language_modal.hbs b/static/templates/default_language_modal.hbs index 2ad62983ad..918a77210d 100644 --- a/static/templates/default_language_modal.hbs +++ b/static/templates/default_language_modal.hbs @@ -21,23 +21,23 @@

- {{#each page_params.language_list_dbl_col}} + {{#each language_list}} diff --git a/static/templates/settings/display_settings.hbs b/static/templates/settings/display_settings.hbs index b0354eec9c..1da4b44196 100644 --- a/static/templates/settings/display_settings.hbs +++ b/static/templates/settings/display_settings.hbs @@ -14,7 +14,7 @@ - {{> ../default_language_modal guidelines_link="https://zulip.readthedocs.io/en/latest/translating/translating.html"}} + {{> ../default_language_modal language_list=language_list_dbl_col guidelines_link="https://zulip.readthedocs.io/en/latest/translating/translating.html"}}
diff --git a/zerver/lib/home.py b/zerver/lib/home.py index 2f27b3edac..122bd8701c 100644 --- a/zerver/lib/home.py +++ b/zerver/lib/home.py @@ -14,7 +14,6 @@ from zerver.lib.events import do_events_register from zerver.lib.i18n import ( get_and_set_request_language, get_language_list, - get_language_list_for_templates, get_language_translation_data, ) from zerver.lib.users import compute_show_invites_and_add_streams @@ -196,7 +195,6 @@ def build_page_params_for_home_page_load( # Only show marketing email settings if on Zulip Cloud corporate_enabled=settings.CORPORATE_ENABLED, ## Misc. extra data. - language_list_dbl_col=get_language_list_for_templates(register_ret["default_language"]), language_list=get_language_list(), needs_tutorial=needs_tutorial, first_in_realm=first_in_realm, diff --git a/zerver/lib/i18n.py b/zerver/lib/i18n.py index c7b374763f..a897555487 100644 --- a/zerver/lib/i18n.py +++ b/zerver/lib/i18n.py @@ -1,10 +1,8 @@ # See https://zulip.readthedocs.io/en/latest/translating/internationalization.html import logging -import operator import os from functools import lru_cache -from itertools import zip_longest from typing import Any, Dict, List, Optional import orjson @@ -21,46 +19,6 @@ def get_language_list() -> List[Dict[str, Any]]: return languages["name_map"] -def get_language_list_for_templates(default_language: str) -> List[Dict[str, Dict[str, str]]]: - language_list = [ - lang - for lang in get_language_list() - if "percent_translated" not in lang or lang["percent_translated"] >= 5.0 - ] - - formatted_list = [] - lang_len = len(language_list) - firsts_end = (lang_len // 2) + operator.mod(lang_len, 2) - firsts = list(range(0, firsts_end)) - seconds = list(range(firsts_end, lang_len)) - assert len(firsts) + len(seconds) == lang_len - for row in zip_longest(firsts, seconds): - item = {} - for position, ind in zip(["first", "second"], row): - if ind is None: - continue - - lang = language_list[ind] - percent = name = lang["name"] - if "percent_translated" in lang: - percent = "{} ({}%)".format(name, lang["percent_translated"]) - - selected = False - if default_language in (lang["code"], lang["locale"]): - selected = True - - item[position] = { - "name": name, - "code": lang["code"], - "percent": percent, - "selected": selected, - } - - formatted_list.append(item) - - return formatted_list - - def get_language_name(code: str) -> str: for lang in get_language_list(): if code in (lang["code"], lang["locale"]): diff --git a/zerver/tests/test_home.py b/zerver/tests/test_home.py index 6e54fb3d9b..23c214803f 100644 --- a/zerver/tests/test_home.py +++ b/zerver/tests/test_home.py @@ -106,7 +106,6 @@ class HomeTest(ZulipTestCase): "is_spectator", "jitsi_server_url", "language_list", - "language_list_dbl_col", "last_event_id", "left_side_userlist", "login_page",
{{#if this.first.selected}} - {{this.first.percent}} + {{this.first.name_with_percent}} {{else}} - {{this.first.percent}} + {{this.first.name_with_percent}} {{/if}} {{#if this.second.selected}} - {{this.second.percent}} + {{this.second.name_with_percent}} {{else}} - {{this.second.percent}} + {{this.second.name_with_percent}} {{/if}}