diff --git a/static/js/i18n.js b/static/js/i18n.ts similarity index 76% rename from static/js/i18n.js rename to static/js/i18n.ts index 35f64d9ea4..45e3248250 100644 --- a/static/js/i18n.js +++ b/static/js/i18n.ts @@ -1,7 +1,9 @@ // For documentation on i18n in Zulip, see: // https://zulip.readthedocs.io/en/latest/translating/internationalization.html +import type {MessageDescriptor} from "@formatjs/intl"; import {DEFAULT_INTL_CONFIG, IntlErrorCode, createIntl, createIntlCache} from "@formatjs/intl"; +import type {FormatXMLElementFn, PrimitiveType} from "intl-messageformat"; import _ from "lodash"; import {page_params} from "./page_params"; @@ -28,26 +30,29 @@ export const $t = intl.formatMessage; export const default_html_elements = Object.fromEntries( ["b", "code", "em", "i", "kbd", "p", "strong"].map((tag) => [ tag, - (content_html) => `<${tag}>${content_html}`, + (content_html: string) => `<${tag}>${content_html}`, ]), ); -export function $t_html(descriptor, values) { +export function $t_html( + descriptor: MessageDescriptor, + values?: Record>, +): string { return intl.formatMessage(descriptor, { ...default_html_elements, ...Object.fromEntries( Object.entries(values ?? {}).map(([key, value]) => [ key, - typeof value === "function" ? value : _.escape(value), + typeof value === "function" ? value : _.escape(value?.toString()), ]), ), }); } -export let language_list; +export let language_list: typeof page_params["language_list"]; -export function get_language_name(language_code) { - const language_list_map = {}; +export function get_language_name(language_code: string): string { + const language_list_map: Record = {}; // One-to-one mapping from code to name for all languages for (const language of language_list) { @@ -56,7 +61,7 @@ export function get_language_name(language_code) { return language_list_map[language_code]; } -export function initialize(language_params) { +export function initialize(language_params: {language_list: typeof language_list}): void { const language_list_raw = language_params.language_list; // Limit offered languages to options with percentage translation >= 5% @@ -75,13 +80,22 @@ export function initialize(language_params) { // This formats language data for the language selection modal in a // 2-column format. -export function get_language_list_columns(default_language) { - const formatted_list = []; +type LanguageListColumn = { + [prop in "first" | "second"]?: { + code: string; + name: string; + name_with_percent: string; + selected: boolean; + }; +}; + +export function get_language_list_columns(default_language: string): LanguageListColumn[] { + const formatted_list: LanguageListColumn[] = []; 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 = []; + const longest_zip: [number, number][] = []; // Create a zip (itertool.zip_longest in python) for (const value of firsts) { @@ -89,11 +103,11 @@ export function get_language_list_columns(default_language) { } for (const row of longest_zip) { - const item = {}; + const item: LanguageListColumn = {}; const zip_row = [ ["first", row[0]], ["second", row[1]], - ]; + ] as const; for (const zip_value of zip_row) { if (zip_value[1] !== undefined) { const lang = language_list[zip_value[1]]; diff --git a/static/js/page_params.ts b/static/js/page_params.ts index 1951267535..11ef206fd8 100644 --- a/static/js/page_params.ts +++ b/static/js/page_params.ts @@ -1,7 +1,16 @@ import $ from "jquery"; const t1 = performance.now(); -export const page_params: Record = $("#page-params").remove().data("params"); +export const page_params: { + language_list: { + code: string; + locale: string; + name: string; + percent_translated: number | undefined; + }[]; + request_language: string; + translation_data: Record; +} = $("#page-params").remove().data("params"); const t2 = performance.now(); window.page_params_parse_time = t2 - t1; if (!page_params) { diff --git a/tsconfig.json b/tsconfig.json index 440ff6ec3d..e563acaaf1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,7 @@ /* Basic options */ "noEmit": true, - "target": "ES2019", + "target": "ES2020", "esModuleInterop": true, "moduleResolution": "node", "resolveJsonModule": true,