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