Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/frontend/account/i18n-selector.tsx
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45/*6Basically a drop-down to change the langauge (i18n localization)7*/89import { DownOutlined } from "@ant-design/icons";10import { Button, Dropdown, MenuProps, Modal, Space, Tooltip } from "antd";11import { SizeType } from "antd/es/config-provider/SizeContext";12import { useState } from "react";13import { defineMessage, useIntl } from "react-intl";1415import { redux, useTypedRedux } from "@cocalc/frontend/app-framework";16import { I18N_HINT_ACCOUNT_SETTINGS } from "@cocalc/frontend/app/i18n-banner";17import { useLocalizationCtx } from "@cocalc/frontend/app/localize";18import { Icon, Paragraph } from "@cocalc/frontend/components";19import {20getLocale,21labels,22Locale,23LOCALIZATIONS,24OTHER_SETTINGS_LOCALE_KEY,25} from "@cocalc/frontend/i18n";26import { KEEP_EN_LOCALE } from "@cocalc/util/consts/locale";2728interface Props {29isWide?: boolean;30size?: SizeType;31confirm?: boolean;32}3334export const I18N_TITLE = defineMessage({35id: "account.account_page.translation.info.title",36defaultMessage: "Translation Information",37description: "Title of translation information modal",38});3940export const I18N_MESSAGE = defineMessage({41id: "account.account_page.translation.info.content",42defaultMessage: `43We're excited to start offering our application in multiple languages! Here's what you need to know:4445<ul>46<li><b>Work in Progress</b>: Our translation effort is just beginning. Many parts of the application are not yet translated.</li>47<li><b>Gradual Improvement</b>: We're continuously working to expand our language coverage. You'll see more content translated over time.</li>48<li><b>Your Help is Welcome</b>: We value our community's input. If you're fluent in multiple languages and would like to contribute to our translation efforts, we'd love to hear from you!</li>49<li><b>Contact Us</b>: To learn more about contributing to translations or to report any issues, please reach out to our support team.</li>50</ul>5152Thank you for your patience and understanding as we work to make our application accessible to a global audience!`,53description: "Content of translation information modal",54});5556export function I18NSelector(props: Readonly<Props>) {57const { isWide = true, size, confirm = false } = props;5859const intl = useIntl();60const { setLocale, locale } = useLocalizationCtx();6162const other_settings = useTypedRedux("account", "other_settings");6364const i18n_enabled = useTypedRedux("customize", "i18n");65const [langOpen, setLangOpen] = useState<boolean>(false);6667if (68i18n_enabled == null ||69i18n_enabled.isEmpty() ||70(i18n_enabled.size === 1 && i18n_enabled.includes("en"))71) {72return null;73}7475const i18n: Locale = getLocale(other_settings);7677const items: MenuProps["items"] =78Object.entries(LOCALIZATIONS)79.filter(([key, _]) => i18n_enabled.includes(key as any))80.map(([key, { name, trans, native, flag }]) => {81const other = key === locale ? name : intl.formatMessage(trans);82return { key, label: `${flag} ${native} (${other})` };83}) ?? [];8485items.push({ type: "divider" });86items.push({87key: "help",88label: (89<Space>90<Icon name="translation-outlined" />91{intl.formatMessage({92id: "account.account_page.translation.info.label",93defaultMessage: "Translation Info...",94description: "Label of translation information modal in dropdown",95})}96</Space>97),98onClick: () =>99Modal.info({100width: "min(90vw, 600px)",101title: intl.formatMessage(I18N_TITLE),102content: <Paragraph>{intl.formatMessage(I18N_MESSAGE)}</Paragraph>,103}),104});105106function changeLocale(key) {107const loc = key === "en" ? KEEP_EN_LOCALE : key;108redux109.getActions("account")110.set_other_settings(OTHER_SETTINGS_LOCALE_KEY, loc);111setLocale(loc);112}113114const menu: MenuProps = {115items,116style: { maxHeight: "75vh", overflow: "auto" },117onClick: ({ key }) => {118if (key in LOCALIZATIONS) {119if (confirm) {120Modal.confirm({121onOk: () => changeLocale(key),122title: intl.formatMessage(123{124id: "account.account_page.translation.change.title",125defaultMessage: "Change language to {lang}?",126},127{128lang: `${LOCALIZATIONS[key].native} (${LOCALIZATIONS[key].name})`,129},130),131content: I18N_HINT_ACCOUNT_SETTINGS,132});133} else {134changeLocale(key);135}136}137},138};139140const lang_icon = LOCALIZATIONS[i18n]?.flag;141142const title =143i18n in LOCALIZATIONS144? intl.formatMessage(LOCALIZATIONS[i18n].trans)145: i18n;146147const cur = `${title} (${LOCALIZATIONS[i18n]?.name ?? i18n})`;148const msg = intl.formatMessage(labels.account_language_tooltip);149const tooltip = (150<>151{cur}152<br />153{msg}154{labels.account_language_tooltip.defaultMessage != msg ? (155<>156<br />({labels.account_language_tooltip.defaultMessage})157</>158) : undefined}159</>160);161162return (163<Tooltip title={langOpen ? undefined : tooltip} trigger={["hover"]}>164<Dropdown165menu={menu}166trigger={["click"]}167onOpenChange={(open) => setLangOpen(open)}168>169<Button size={size}>170<Space>171{lang_icon}172{isWide ? title : undefined}173<DownOutlined />174</Space>175</Button>176</Dropdown>177</Tooltip>178);179}180181182