mirror of https://github.com/zulip/zulip.git
ts: Convert i18n module to TypeScript.
We update our tsconfig target to ES2020 so that we don't get type errors related to some properties not being in Intl that is used by @formatjs/intl.
This commit is contained in:
parent
f1a0a790fe
commit
9418ae51fa
|
@ -1,7 +1,9 @@
|
||||||
// For documentation on i18n in Zulip, see:
|
// For documentation on i18n in Zulip, see:
|
||||||
// https://zulip.readthedocs.io/en/latest/translating/internationalization.html
|
// 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 {DEFAULT_INTL_CONFIG, IntlErrorCode, createIntl, createIntlCache} from "@formatjs/intl";
|
||||||
|
import type {FormatXMLElementFn, PrimitiveType} from "intl-messageformat";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
|
||||||
import {page_params} from "./page_params";
|
import {page_params} from "./page_params";
|
||||||
|
@ -28,26 +30,29 @@ export const $t = intl.formatMessage;
|
||||||
export const default_html_elements = Object.fromEntries(
|
export const default_html_elements = Object.fromEntries(
|
||||||
["b", "code", "em", "i", "kbd", "p", "strong"].map((tag) => [
|
["b", "code", "em", "i", "kbd", "p", "strong"].map((tag) => [
|
||||||
tag,
|
tag,
|
||||||
(content_html) => `<${tag}>${content_html}</${tag}>`,
|
(content_html: string) => `<${tag}>${content_html}</${tag}>`,
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
export function $t_html(descriptor, values) {
|
export function $t_html(
|
||||||
|
descriptor: MessageDescriptor,
|
||||||
|
values?: Record<string, PrimitiveType | FormatXMLElementFn<string, string>>,
|
||||||
|
): string {
|
||||||
return intl.formatMessage(descriptor, {
|
return intl.formatMessage(descriptor, {
|
||||||
...default_html_elements,
|
...default_html_elements,
|
||||||
...Object.fromEntries(
|
...Object.fromEntries(
|
||||||
Object.entries(values ?? {}).map(([key, value]) => [
|
Object.entries(values ?? {}).map(([key, value]) => [
|
||||||
key,
|
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) {
|
export function get_language_name(language_code: string): string {
|
||||||
const language_list_map = {};
|
const language_list_map: Record<string, string> = {};
|
||||||
|
|
||||||
// One-to-one mapping from code to name for all languages
|
// One-to-one mapping from code to name for all languages
|
||||||
for (const language of language_list) {
|
for (const language of language_list) {
|
||||||
|
@ -56,7 +61,7 @@ export function get_language_name(language_code) {
|
||||||
return language_list_map[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;
|
const language_list_raw = language_params.language_list;
|
||||||
|
|
||||||
// Limit offered languages to options with percentage translation >= 5%
|
// 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
|
// This formats language data for the language selection modal in a
|
||||||
// 2-column format.
|
// 2-column format.
|
||||||
export function get_language_list_columns(default_language) {
|
type LanguageListColumn = {
|
||||||
const formatted_list = [];
|
[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 language_len = language_list.length;
|
||||||
const firsts_end = Math.floor(language_len / 2) + (language_len % 2);
|
const firsts_end = Math.floor(language_len / 2) + (language_len % 2);
|
||||||
const firsts = _.range(0, firsts_end);
|
const firsts = _.range(0, firsts_end);
|
||||||
const seconds = _.range(firsts_end, language_len);
|
const seconds = _.range(firsts_end, language_len);
|
||||||
const longest_zip = [];
|
const longest_zip: [number, number][] = [];
|
||||||
|
|
||||||
// Create a zip (itertool.zip_longest in python)
|
// Create a zip (itertool.zip_longest in python)
|
||||||
for (const value of firsts) {
|
for (const value of firsts) {
|
||||||
|
@ -89,11 +103,11 @@ export function get_language_list_columns(default_language) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const row of longest_zip) {
|
for (const row of longest_zip) {
|
||||||
const item = {};
|
const item: LanguageListColumn = {};
|
||||||
const zip_row = [
|
const zip_row = [
|
||||||
["first", row[0]],
|
["first", row[0]],
|
||||||
["second", row[1]],
|
["second", row[1]],
|
||||||
];
|
] as const;
|
||||||
for (const zip_value of zip_row) {
|
for (const zip_value of zip_row) {
|
||||||
if (zip_value[1] !== undefined) {
|
if (zip_value[1] !== undefined) {
|
||||||
const lang = language_list[zip_value[1]];
|
const lang = language_list[zip_value[1]];
|
|
@ -1,7 +1,16 @@
|
||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
|
|
||||||
const t1 = performance.now();
|
const t1 = performance.now();
|
||||||
export const page_params: Record<string, unknown> = $("#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<string, string>;
|
||||||
|
} = $("#page-params").remove().data("params");
|
||||||
const t2 = performance.now();
|
const t2 = performance.now();
|
||||||
window.page_params_parse_time = t2 - t1;
|
window.page_params_parse_time = t2 - t1;
|
||||||
if (!page_params) {
|
if (!page_params) {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
/* Basic options */
|
/* Basic options */
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"target": "ES2019",
|
"target": "ES2020",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
|
|
Loading…
Reference in New Issue