Files
blap/src/modules/Api.ts
T
David Baker 5370f25870 Introduce i18nContext (#31347)
* Introduce i18nContext

 * Adds a context that holds the module i1n API
 * Switches shared components to use that instead of importing it directly
 * Adds the context to MatrixChat and BaseDalog so it should be available most places in EW

This is a relatively small PR but does change the way the shared components do i18n so
just doing this one by itself (it stands by itself anyway).

This will allow shared components to use i18n when used in modules.

* Add the file

* Fix import lint

* Name the translate function _t

Then it should continue to get picked up by the script

This seems a bit flaky and ew but I'm not sure I want to get into
changing this in this PR.

* Put humanize back to calling something called _t too

* Missed one

* Add i18n context wrapper to stories

* Unused import

* Fix imports

* wrap richitem

* Wrap other richitem & richlist

* One day I will get my head around this syntax

* Fix import spacing

* Add wrapper to test

* unused import

* Hack around dependency cycle

* Make a moduleapi instance for tests

* Add i18n wrapper to jest-matrix-react

* Simple test for i18napi

* Import type

* Move i18n context wrapper to storybook template

* Unused imports & fix pill story

* Move i18n to its own provider

* Add i18ncontext wrapper to jest tests

* imports

* Bump module api to 1.7.0

* tsdoc
2025-12-02 13:47:14 +00:00

98 lines
4.7 KiB
TypeScript

/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { createRoot, type Root } from "react-dom/client";
import { type Api, type RuntimeModuleConstructor } from "@element-hq/element-web-module-api";
import { I18nApi } from "@element-hq/web-shared-components";
import { ModuleRunner } from "./ModuleRunner.ts";
import AliasCustomisations from "../customisations/Alias.ts";
import { RoomListCustomisations } from "../customisations/RoomList.ts";
import ChatExportCustomisations from "../customisations/ChatExport.ts";
import { ComponentVisibilityCustomisations } from "../customisations/ComponentVisibility.ts";
import DirectoryCustomisations from "../customisations/Directory.ts";
import LifecycleCustomisations from "../customisations/Lifecycle.ts";
import * as MediaCustomisations from "../customisations/Media.ts";
import UserIdentifierCustomisations from "../customisations/UserIdentifier.ts";
import { WidgetPermissionCustomisations } from "../customisations/WidgetPermissions.ts";
import { WidgetVariableCustomisations } from "../customisations/WidgetVariables.ts";
import { ConfigApi } from "./ConfigApi.ts";
import { CustomComponentsApi } from "./customComponentApi";
import { WatchableProfile } from "./Profile.ts";
import { NavigationApi } from "./Navigation.ts";
import { openDialog } from "./Dialog.tsx";
import { overwriteAccountAuth } from "./Auth.ts";
import { ElementWebExtrasApi } from "./ExtrasApi.ts";
import { ElementWebBuiltinsApi } from "./BuiltinsApi.tsx";
import { ClientApi } from "./ClientApi.ts";
import { StoresApi } from "./StoresApi.ts";
const legacyCustomisationsFactory = <T extends object>(baseCustomisations: T) => {
let used = false;
return (customisations: T) => {
if (used) throw new Error("Legacy customisations can only be registered by one module");
Object.assign(baseCustomisations, customisations);
used = true;
};
};
/**
* Implementation of the @element-hq/element-web-module-api runtime module API.
*/
export class ModuleApi implements Api {
private static _instance: ModuleApi;
public static get instance(): ModuleApi {
if (!ModuleApi._instance) {
ModuleApi._instance = new ModuleApi();
window.mxModuleApi = ModuleApi._instance;
}
return ModuleApi._instance;
}
/* eslint-disable @typescript-eslint/naming-convention */
public async _registerLegacyModule(LegacyModule: RuntimeModuleConstructor): Promise<void> {
ModuleRunner.instance.registerModule((api) => new LegacyModule(api));
}
public readonly _registerLegacyAliasCustomisations = legacyCustomisationsFactory(AliasCustomisations);
public readonly _registerLegacyChatExportCustomisations = legacyCustomisationsFactory(ChatExportCustomisations);
public readonly _registerLegacyComponentVisibilityCustomisations = legacyCustomisationsFactory(
ComponentVisibilityCustomisations,
);
public readonly _registerLegacyDirectoryCustomisations = legacyCustomisationsFactory(DirectoryCustomisations);
public readonly _registerLegacyLifecycleCustomisations = legacyCustomisationsFactory(LifecycleCustomisations);
public readonly _registerLegacyMediaCustomisations = legacyCustomisationsFactory(MediaCustomisations);
public readonly _registerLegacyRoomListCustomisations = legacyCustomisationsFactory(RoomListCustomisations);
public readonly _registerLegacyUserIdentifierCustomisations =
legacyCustomisationsFactory(UserIdentifierCustomisations);
public readonly _registerLegacyWidgetPermissionsCustomisations =
legacyCustomisationsFactory(WidgetPermissionCustomisations);
public readonly _registerLegacyWidgetVariablesCustomisations =
legacyCustomisationsFactory(WidgetVariableCustomisations);
/* eslint-enable @typescript-eslint/naming-convention */
public readonly navigation = new NavigationApi();
public readonly openDialog = openDialog;
public readonly overwriteAccountAuth = overwriteAccountAuth;
public readonly profile = new WatchableProfile();
public readonly config = new ConfigApi();
public readonly i18n = new I18nApi();
public readonly customComponents = new CustomComponentsApi();
public readonly extras = new ElementWebExtrasApi();
public readonly builtins = new ElementWebBuiltinsApi();
public readonly rootNode = document.getElementById("matrixchat")!;
public readonly client = new ClientApi();
public readonly stores = new StoresApi();
public createRoot(element: Element): Root {
return createRoot(element);
}
}
export type ModuleApiType = ModuleApi;