Guard translation methods with typescript to protect against invalid usage (#26021)
This commit is contained in:
parent
86c563cd29
commit
469d11ffcb
10 changed files with 84 additions and 20 deletions
|
@ -14,13 +14,14 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from "react";
|
import React, { ReactNode } from "react";
|
||||||
import { _t } from "matrix-react-sdk/src/languageHandler";
|
|
||||||
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
|
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
|
||||||
|
|
||||||
|
import { _t } from "../../languageHandler";
|
||||||
|
|
||||||
// directly import the style here as this layer does not support rethemedex at this time so no matrix-react-sdk
|
// directly import the style here as this layer does not support rethemedex at this time so no matrix-react-sdk
|
||||||
// PostCSS variables will be accessible.
|
// PostCSS variables will be accessible.
|
||||||
import "../../../res/css/structures/ErrorView.pcss";
|
import "../../../res/css/structures/ErrorView.pcss";
|
||||||
import { ReactNode } from "react";
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
onAccept(): void;
|
onAccept(): void;
|
||||||
|
@ -112,15 +113,13 @@ const CompatibilityView: React.FC<IProps> = ({ onAccept }) => {
|
||||||
<h2 id="step1_heading">{_t("Your browser can't run %(brand)s", { brand })}</h2>
|
<h2 id="step1_heading">{_t("Your browser can't run %(brand)s", { brand })}</h2>
|
||||||
<p>
|
<p>
|
||||||
{_t(
|
{_t(
|
||||||
"%(brand)s uses advanced browser features which aren't " +
|
"%(brand)s uses advanced browser features which aren't supported by your current browser.",
|
||||||
"supported by your current browser.",
|
|
||||||
{ brand },
|
{ brand },
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{_t(
|
{_t(
|
||||||
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, " +
|
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.",
|
||||||
"or <safariLink>Safari</safariLink> for the best experience.",
|
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
chromeLink: (sub) => <a href="https://www.google.com/chrome">{sub}</a>,
|
chromeLink: (sub) => <a href="https://www.google.com/chrome">{sub}</a>,
|
||||||
|
@ -131,8 +130,7 @@ const CompatibilityView: React.FC<IProps> = ({ onAccept }) => {
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{_t(
|
{_t(
|
||||||
"You can continue using your current browser, but some or all features may not work " +
|
"You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.",
|
||||||
"and the look and feel of the application may be incorrect.",
|
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<button onClick={onAccept}>{_t("I understand the risks and wish to continue")}</button>
|
<button onClick={onAccept}>{_t("I understand the risks and wish to continue")}</button>
|
||||||
|
|
|
@ -15,7 +15,8 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { _t } from "matrix-react-sdk/src/languageHandler";
|
|
||||||
|
import { _t } from "../../languageHandler";
|
||||||
|
|
||||||
// directly import the style here as this layer does not support rethemedex at this time so no matrix-react-sdk
|
// directly import the style here as this layer does not support rethemedex at this time so no matrix-react-sdk
|
||||||
// PostCSS variables will be accessible.
|
// PostCSS variables will be accessible.
|
||||||
|
|
|
@ -17,7 +17,8 @@ limitations under the License.
|
||||||
|
|
||||||
import React, { ReactElement } from "react";
|
import React, { ReactElement } from "react";
|
||||||
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
|
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
|
||||||
import { _t } from "matrix-react-sdk/src/languageHandler";
|
|
||||||
|
import { _t } from "../../../languageHandler";
|
||||||
|
|
||||||
const VectorAuthFooter = (): ReactElement => {
|
const VectorAuthFooter = (): ReactElement => {
|
||||||
const brandingConfig = SdkConfig.getObject("branding");
|
const brandingConfig = SdkConfig.getObject("branding");
|
||||||
|
|
66
src/languageHandler.tsx
Normal file
66
src/languageHandler.tsx
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
IVariables,
|
||||||
|
TranslatedString,
|
||||||
|
TranslationKey as ReactTranslationKey,
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
_t as react_t,
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
_td as react_td,
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
_tDom as react_tDom,
|
||||||
|
Tags,
|
||||||
|
UserFriendlyError as ReactUserFriendlyError,
|
||||||
|
ErrorOptions,
|
||||||
|
} from "matrix-react-sdk/src/languageHandler";
|
||||||
|
import { Leaves } from "matrix-react-sdk/src/@types/common";
|
||||||
|
|
||||||
|
import type ReactEN from "matrix-react-sdk/src/i18n/strings/en_EN.json";
|
||||||
|
import type EN from "./i18n/strings/en_EN.json";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This module wraps languageHandler in the matrix-react-sdk and adds type casts to include translations
|
||||||
|
* which we know will be injected by webpack.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type TranslationKey = Leaves<typeof EN & typeof ReactEN, "|", string | { other: string }>;
|
||||||
|
|
||||||
|
export class UserFriendlyError extends ReactUserFriendlyError {
|
||||||
|
public constructor(message: TranslationKey, substitutionVariablesAndCause?: IVariables & ErrorOptions) {
|
||||||
|
super(message as ReactTranslationKey, substitutionVariablesAndCause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _td(s: TranslationKey): TranslationKey {
|
||||||
|
return react_td(s as ReactTranslationKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-next-line @typescript-eslint/naming-convention
|
||||||
|
export function _t(text: TranslationKey, variables?: IVariables): string;
|
||||||
|
export function _t(text: TranslationKey, variables: IVariables | undefined, tags: Tags): React.ReactNode;
|
||||||
|
export function _t(text: TranslationKey, variables?: IVariables, tags?: Tags): TranslatedString {
|
||||||
|
return react_t(text as ReactTranslationKey, variables, tags!);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-next-line @typescript-eslint/naming-convention
|
||||||
|
export function _tDom(text: TranslationKey, variables?: IVariables): TranslatedString;
|
||||||
|
export function _tDom(text: TranslationKey, variables: IVariables, tags: Tags): React.ReactNode;
|
||||||
|
export function _tDom(text: TranslationKey, variables?: IVariables, tags?: Tags): TranslatedString {
|
||||||
|
return react_tDom(text as ReactTranslationKey, variables!, tags!);
|
||||||
|
}
|
|
@ -23,7 +23,6 @@ import "matrix-js-sdk/src/browser-index";
|
||||||
|
|
||||||
import React, { ReactElement } from "react";
|
import React, { ReactElement } from "react";
|
||||||
import PlatformPeg from "matrix-react-sdk/src/PlatformPeg";
|
import PlatformPeg from "matrix-react-sdk/src/PlatformPeg";
|
||||||
import { UserFriendlyError } from "matrix-react-sdk/src/languageHandler";
|
|
||||||
import AutoDiscoveryUtils from "matrix-react-sdk/src/utils/AutoDiscoveryUtils";
|
import AutoDiscoveryUtils from "matrix-react-sdk/src/utils/AutoDiscoveryUtils";
|
||||||
import { AutoDiscovery, ClientConfig } from "matrix-js-sdk/src/autodiscovery";
|
import { AutoDiscovery, ClientConfig } from "matrix-js-sdk/src/autodiscovery";
|
||||||
import * as Lifecycle from "matrix-react-sdk/src/Lifecycle";
|
import * as Lifecycle from "matrix-react-sdk/src/Lifecycle";
|
||||||
|
@ -38,6 +37,7 @@ import { ValidatedServerConfig } from "matrix-react-sdk/src/utils/ValidatedServe
|
||||||
import { parseQs } from "./url_utils";
|
import { parseQs } from "./url_utils";
|
||||||
import VectorBasePlatform from "./platform/VectorBasePlatform";
|
import VectorBasePlatform from "./platform/VectorBasePlatform";
|
||||||
import { getInitialScreenAfterLogin, getScreenFromLocation, init as initRouting, onNewScreen } from "./routing";
|
import { getInitialScreenAfterLogin, getScreenFromLocation, init as initRouting, onNewScreen } from "./routing";
|
||||||
|
import { UserFriendlyError } from "../languageHandler";
|
||||||
|
|
||||||
// add React and ReactPerf to the global namespace, to make them easier to access via the console
|
// add React and ReactPerf to the global namespace, to make them easier to access via the console
|
||||||
// this incidentally means we can forget our React imports in JSX files without penalty.
|
// this incidentally means we can forget our React imports in JSX files without penalty.
|
||||||
|
@ -147,8 +147,7 @@ async function verifyServerConfig(): Promise<IConfigOptions> {
|
||||||
if (hsUrl && (wkConfig || serverName)) {
|
if (hsUrl && (wkConfig || serverName)) {
|
||||||
// noinspection ExceptionCaughtLocallyJS
|
// noinspection ExceptionCaughtLocallyJS
|
||||||
throw new UserFriendlyError(
|
throw new UserFriendlyError(
|
||||||
"Invalid configuration: a default_hs_url can't be specified along with default_server_name " +
|
"Invalid configuration: a default_hs_url can't be specified along with default_server_name or default_server_config",
|
||||||
"or default_server_config",
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (incompatibleOptions.length < 1) {
|
if (incompatibleOptions.length < 1) {
|
||||||
|
|
|
@ -199,8 +199,7 @@ async function start(): Promise<void> {
|
||||||
// This uses the default brand since the app config is unavailable.
|
// This uses the default brand since the app config is unavailable.
|
||||||
return showError(_t("Your Element is misconfigured"), [
|
return showError(_t("Your Element is misconfigured"), [
|
||||||
_t(
|
_t(
|
||||||
"Your Element configuration contains invalid JSON. " +
|
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.",
|
||||||
"Please correct the problem and reload the page.",
|
|
||||||
),
|
),
|
||||||
_t("The message from the parser is: %(message)s", {
|
_t("The message from the parser is: %(message)s", {
|
||||||
message: error.message || _t("Invalid JSON"),
|
message: error.message || _t("Invalid JSON"),
|
||||||
|
|
|
@ -184,4 +184,4 @@ export async function loadModules(): Promise<void> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const _t = languageHandler._t;
|
export { _t } from "../languageHandler";
|
||||||
|
|
|
@ -21,7 +21,6 @@ limitations under the License.
|
||||||
import { UpdateCheckStatus, UpdateStatus } from "matrix-react-sdk/src/BasePlatform";
|
import { UpdateCheckStatus, UpdateStatus } from "matrix-react-sdk/src/BasePlatform";
|
||||||
import BaseEventIndexManager from "matrix-react-sdk/src/indexing/BaseEventIndexManager";
|
import BaseEventIndexManager from "matrix-react-sdk/src/indexing/BaseEventIndexManager";
|
||||||
import dis from "matrix-react-sdk/src/dispatcher/dispatcher";
|
import dis from "matrix-react-sdk/src/dispatcher/dispatcher";
|
||||||
import { _t } from "matrix-react-sdk/src/languageHandler";
|
|
||||||
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
|
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
|
||||||
import { IConfigOptions } from "matrix-react-sdk/src/IConfigOptions";
|
import { IConfigOptions } from "matrix-react-sdk/src/IConfigOptions";
|
||||||
import * as rageshake from "matrix-react-sdk/src/rageshake/rageshake";
|
import * as rageshake from "matrix-react-sdk/src/rageshake/rageshake";
|
||||||
|
@ -48,6 +47,7 @@ import DesktopCapturerSourcePicker from "matrix-react-sdk/src/components/views/e
|
||||||
import VectorBasePlatform from "./VectorBasePlatform";
|
import VectorBasePlatform from "./VectorBasePlatform";
|
||||||
import { SeshatIndexManager } from "./SeshatIndexManager";
|
import { SeshatIndexManager } from "./SeshatIndexManager";
|
||||||
import { IPCManager } from "./IPCManager";
|
import { IPCManager } from "./IPCManager";
|
||||||
|
import { _t } from "../../languageHandler";
|
||||||
|
|
||||||
interface SquirrelUpdate {
|
interface SquirrelUpdate {
|
||||||
releaseNotes: string;
|
releaseNotes: string;
|
||||||
|
|
|
@ -18,11 +18,11 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import BasePlatform from "matrix-react-sdk/src/BasePlatform";
|
import BasePlatform from "matrix-react-sdk/src/BasePlatform";
|
||||||
import { _t } from "matrix-react-sdk/src/languageHandler";
|
|
||||||
|
|
||||||
import type { IConfigOptions } from "matrix-react-sdk/src/IConfigOptions";
|
import type { IConfigOptions } from "matrix-react-sdk/src/IConfigOptions";
|
||||||
import { getVectorConfig } from "../getconfig";
|
import { getVectorConfig } from "../getconfig";
|
||||||
import Favicon from "../../favicon";
|
import Favicon from "../../favicon";
|
||||||
|
import { _t } from "../../languageHandler";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vector-specific extensions to the BasePlatform template
|
* Vector-specific extensions to the BasePlatform template
|
||||||
|
|
|
@ -18,7 +18,6 @@ limitations under the License.
|
||||||
|
|
||||||
import { UpdateCheckStatus, UpdateStatus } from "matrix-react-sdk/src/BasePlatform";
|
import { UpdateCheckStatus, UpdateStatus } from "matrix-react-sdk/src/BasePlatform";
|
||||||
import dis from "matrix-react-sdk/src/dispatcher/dispatcher";
|
import dis from "matrix-react-sdk/src/dispatcher/dispatcher";
|
||||||
import { _t } from "matrix-react-sdk/src/languageHandler";
|
|
||||||
import { hideToast as hideUpdateToast, showToast as showUpdateToast } from "matrix-react-sdk/src/toasts/UpdateToast";
|
import { hideToast as hideUpdateToast, showToast as showUpdateToast } from "matrix-react-sdk/src/toasts/UpdateToast";
|
||||||
import { Action } from "matrix-react-sdk/src/dispatcher/actions";
|
import { Action } from "matrix-react-sdk/src/dispatcher/actions";
|
||||||
import { CheckUpdatesPayload } from "matrix-react-sdk/src/dispatcher/payloads/CheckUpdatesPayload";
|
import { CheckUpdatesPayload } from "matrix-react-sdk/src/dispatcher/payloads/CheckUpdatesPayload";
|
||||||
|
@ -27,6 +26,7 @@ import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
import VectorBasePlatform from "./VectorBasePlatform";
|
import VectorBasePlatform from "./VectorBasePlatform";
|
||||||
import { parseQs } from "../url_utils";
|
import { parseQs } from "../url_utils";
|
||||||
|
import { _t } from "../../languageHandler";
|
||||||
|
|
||||||
const POKE_RATE_MS = 10 * 60 * 1000; // 10 min
|
const POKE_RATE_MS = 10 * 60 * 1000; // 10 min
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue