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}}
|
{{#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}}
|
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",