Merge branch 'develop' into t3chguy/compound-icons-20260106
2
.github/workflows/build.yml
vendored
@ -66,7 +66,7 @@ jobs:
|
||||
run: VERSION=$(scripts/get-version-from-git.sh) yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: webapp-${{ matrix.image }}
|
||||
path: webapp
|
||||
|
||||
2
.github/workflows/build_debian.yaml
vendored
@ -62,7 +62,7 @@ jobs:
|
||||
dpkg-gencontrol -v"$VERSION" -ldebian/tmp/DEBIAN/changelog
|
||||
dpkg-deb -Zxz --root-owner-group --build debian/tmp element-web.deb
|
||||
|
||||
- uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: element-web.deb
|
||||
path: element-web.deb
|
||||
|
||||
2
.github/workflows/build_develop.yml
vendored
@ -53,7 +53,7 @@ jobs:
|
||||
|
||||
- run: mv dist/element-*.tar.gz dist/develop.tar.gz
|
||||
|
||||
- uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: webapp
|
||||
path: dist/develop.tar.gz
|
||||
|
||||
@ -25,7 +25,7 @@ jobs:
|
||||
actions: read
|
||||
steps:
|
||||
- name: Download HTML report
|
||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
|
||||
10
.github/workflows/end-to-end-tests.yaml
vendored
@ -74,7 +74,7 @@ jobs:
|
||||
run: VERSION=$(scripts/get-version-from-git.sh) yarn build
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: webapp
|
||||
path: webapp
|
||||
@ -128,7 +128,7 @@ jobs:
|
||||
repository: element-hq/element-web
|
||||
|
||||
- name: 📥 Download artifact
|
||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
|
||||
with:
|
||||
name: webapp
|
||||
path: webapp
|
||||
@ -172,7 +172,7 @@ jobs:
|
||||
|
||||
- name: Upload blob report to GitHub Actions Artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: all-blob-reports-${{ matrix.project }}-${{ matrix.runner }}
|
||||
path: blob-report
|
||||
@ -212,7 +212,7 @@ jobs:
|
||||
|
||||
- name: Download blob reports from GitHub Actions Artifacts
|
||||
if: inputs.skip != true
|
||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
|
||||
with:
|
||||
pattern: all-blob-reports-*
|
||||
path: all-blob-reports
|
||||
@ -228,7 +228,7 @@ jobs:
|
||||
# Upload the HTML report even if one of our reporters fails, this can happen when stale screenshots are detected
|
||||
- name: Upload HTML report
|
||||
if: always() && inputs.skip != true
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: html-report
|
||||
path: playwright-report
|
||||
|
||||
2
.github/workflows/netlify.yaml
vendored
@ -28,7 +28,7 @@ jobs:
|
||||
Exercise caution. Use test accounts.
|
||||
|
||||
- name: 📥 Download artifact
|
||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
|
||||
@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
id: cpr
|
||||
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8
|
||||
with:
|
||||
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
branch: actions/playwright-image-updates
|
||||
|
||||
@ -27,7 +27,7 @@ jobs:
|
||||
run: "sudo apt-get install -y tree"
|
||||
|
||||
- name: Download Diffs
|
||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
|
||||
@ -60,7 +60,7 @@ jobs:
|
||||
|
||||
- name: Upload received images & diffs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: received-images
|
||||
path: packages/shared-components/playwright/shared-component-received
|
||||
|
||||
13
.github/workflows/static_analysis.yaml
vendored
@ -41,8 +41,8 @@ jobs:
|
||||
- name: Typecheck Shared Components
|
||||
run: "yarn --cwd packages/shared-components run lint:types"
|
||||
|
||||
i18n_lint:
|
||||
name: "i18n Check"
|
||||
i18n_lint_ew:
|
||||
name: "i18n Check (Element Web)"
|
||||
uses: matrix-org/matrix-web-i18n/.github/workflows/i18n_check.yml@main
|
||||
permissions:
|
||||
pull-requests: read
|
||||
@ -59,6 +59,15 @@ jobs:
|
||||
devtools|settings|elementCallUrl
|
||||
labs|sliding_sync_description
|
||||
|
||||
i18n_lint_shared_components:
|
||||
name: "i18n Check (Shared Components)"
|
||||
uses: matrix-org/matrix-web-i18n/.github/workflows/i18n_check.yml@main
|
||||
permissions:
|
||||
pull-requests: read
|
||||
with:
|
||||
path: "packages/shared-components"
|
||||
hardcoded-words: "Element"
|
||||
|
||||
rethemendex_lint:
|
||||
name: "Rethemendex Check"
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
4
.github/workflows/tests.yml
vendored
@ -84,7 +84,7 @@ jobs:
|
||||
|
||||
- name: Upload Artifact
|
||||
if: env.ENABLE_COVERAGE == 'true'
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: coverage-${{ matrix.runner }}
|
||||
path: |
|
||||
@ -159,7 +159,7 @@ jobs:
|
||||
|
||||
- name: Upload Artifact
|
||||
if: env.ENABLE_COVERAGE == 'true'
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: coverage-sharedcomponents
|
||||
path: |
|
||||
|
||||
@ -9,7 +9,7 @@ jobs:
|
||||
name: Move PRs asking for design review to the design board
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: octokit/graphql-action@abaeca7ba4f0325d63b8de7ef943c2418d161b93 # v3.0.0
|
||||
- uses: octokit/graphql-action@ddde8ebb2493e79f390e6449c725c21663a67505 # v3.0.2
|
||||
id: find_team_members
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
@ -52,7 +52,7 @@ jobs:
|
||||
fi
|
||||
env:
|
||||
TEAM: "design"
|
||||
- uses: octokit/graphql-action@abaeca7ba4f0325d63b8de7ef943c2418d161b93 # v3.0.0
|
||||
- uses: octokit/graphql-action@ddde8ebb2493e79f390e6449c725c21663a67505 # v3.0.2
|
||||
id: add_to_project
|
||||
if: steps.any_matching_reviewers.outputs.match == 'true'
|
||||
with:
|
||||
@ -76,7 +76,7 @@ jobs:
|
||||
name: Move PRs asking for design review to the design board
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: octokit/graphql-action@abaeca7ba4f0325d63b8de7ef943c2418d161b93 # v3.0.0
|
||||
- uses: octokit/graphql-action@ddde8ebb2493e79f390e6449c725c21663a67505 # v3.0.2
|
||||
id: find_team_members
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
@ -119,7 +119,7 @@ jobs:
|
||||
fi
|
||||
env:
|
||||
TEAM: "product"
|
||||
- uses: octokit/graphql-action@abaeca7ba4f0325d63b8de7ef943c2418d161b93 # v3.0.0
|
||||
- uses: octokit/graphql-action@ddde8ebb2493e79f390e6449c725c21663a67505 # v3.0.2
|
||||
id: add_to_project
|
||||
if: steps.any_matching_reviewers.outputs.match == 'true'
|
||||
with:
|
||||
|
||||
2
.github/workflows/update-jitsi.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
||||
run: "yarn update:jitsi"
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8
|
||||
with:
|
||||
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
branch: actions/jitsi-update
|
||||
|
||||
@ -18,6 +18,18 @@
|
||||
"file": "element-web.json",
|
||||
"excludes": ["src/i18n/strings/en_EN.json"],
|
||||
"lang": "${autodetectLang}"
|
||||
},
|
||||
{
|
||||
"pattern": "packages/shared-components/src/i18n/strings/en_EN.json",
|
||||
"file": "shared-components.json",
|
||||
"lang": "inherited"
|
||||
},
|
||||
{
|
||||
"group": "existing",
|
||||
"pattern": "packages/shared-components/src/i18n/strings/*.json",
|
||||
"file": "shared-components.json",
|
||||
"excludes": ["packages/shared-components/src/i18n/strings/en_EN.json"],
|
||||
"lang": "${autodetectLang}"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -27,6 +39,10 @@
|
||||
{
|
||||
"conditions": "equals: ${file}, element-web.json",
|
||||
"output": "src/i18n/strings/${langLsrUnderscore}.json"
|
||||
},
|
||||
{
|
||||
"conditions": "equals: ${file}, shared-components.json",
|
||||
"output": "packages/shared-components/src/i18n/strings/${langLsrUnderscore}.json"
|
||||
}
|
||||
],
|
||||
"includeSourceLang": "${includeSourceLang|false}",
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
"UserFriendlyError"
|
||||
],
|
||||
"scripts": {
|
||||
"i18n": "matrix-gen-i18n src res packages/shared-components/src && yarn i18n:sort && yarn i18n:lint",
|
||||
"i18n": "matrix-gen-i18n src res && yarn i18n:sort && yarn i18n:lint",
|
||||
"i18n:sort": "jq --sort-keys '.' src/i18n/strings/en_EN.json > src/i18n/strings/en_EN.json.tmp && mv src/i18n/strings/en_EN.json.tmp src/i18n/strings/en_EN.json",
|
||||
"i18n:lint": "matrix-i18n-lint && prettier --log-level=silent --write src/i18n/strings/ --ignore-path /dev/null",
|
||||
"i18n:diff": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && yarn i18n && matrix-compare-i18n-files src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
|
||||
@ -69,7 +69,7 @@
|
||||
"postinstall": "patch-package"
|
||||
},
|
||||
"resolutions": {
|
||||
"**/pretty-format/react-is": "19.2.1",
|
||||
"**/pretty-format/react-is": "19.2.3",
|
||||
"@types/react": "19.2.7",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"oidc-client-ts": "3.4.1",
|
||||
@ -85,7 +85,7 @@
|
||||
"@element-hq/web-shared-components": "link:packages/shared-components",
|
||||
"@fontsource/fira-code": "^5",
|
||||
"@fontsource/inter": "^5",
|
||||
"@formatjs/intl-segmenter": "^11.5.7",
|
||||
"@formatjs/intl-segmenter": "^12.0.0",
|
||||
"@matrix-org/analytics-events": "^0.30.0",
|
||||
"@matrix-org/emojibase-bindings": "^1.5.0",
|
||||
"@matrix-org/react-sdk-module-api": "^2.4.0",
|
||||
@ -137,7 +137,7 @@
|
||||
"opus-recorder": "^8.0.3",
|
||||
"pako": "^2.0.3",
|
||||
"png-chunks-extract": "^1.0.0",
|
||||
"posthog-js": "1.302.2",
|
||||
"posthog-js": "1.313.0",
|
||||
"qrcode": "1.5.4",
|
||||
"re-resizable": "6.11.2",
|
||||
"react": "^19.0.0",
|
||||
|
||||
5
packages/shared-components/.prettierrc.js
Normal file
@ -0,0 +1,5 @@
|
||||
// Even though this (at time of writing) is identical Element Web's
|
||||
// .prettierrc.js, shared components needs its own because otherwise
|
||||
// this refers to element web's copy of eslint-plugin-matrix-org which
|
||||
// would require element-web's modules to be installed.
|
||||
module.exports = require("eslint-plugin-matrix-org/.prettierrc.js");
|
||||
@ -10,16 +10,14 @@ import { WithTooltip, IconButton, TooltipLinkList } from "storybook/internal/com
|
||||
import React from "react";
|
||||
import { GlobeIcon } from "@storybook/icons";
|
||||
|
||||
// We can't import `shared/i18n.tsx` directly here.
|
||||
// The storybook addon doesn't seem to benefit the vite config of storybook and we can't resolve the alias in i18n.tsx.
|
||||
import json from "../../../webapp/i18n/languages.json";
|
||||
const languages = Object.keys(json).filter((lang) => lang !== "default");
|
||||
const languages = JSON.parse(process.env.STORYBOOK_LANGUAGES);
|
||||
|
||||
/**
|
||||
* Returns the title of a language in the user's locale.
|
||||
*/
|
||||
function languageTitle(language: string): string {
|
||||
return new Intl.DisplayNames([language], { type: "language", style: "short" }).of(language) || language;
|
||||
const normalisedLang = language.toLowerCase().replace("_", "-");
|
||||
return new Intl.DisplayNames([normalisedLang], { type: "language", style: "short" }).of(normalisedLang) || language;
|
||||
}
|
||||
|
||||
export const languageAddon: Addon = {
|
||||
|
||||
@ -7,12 +7,15 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import type { StorybookConfig } from "@storybook/react-vite";
|
||||
import path from "node:path";
|
||||
import fs from "node:fs";
|
||||
import { nodePolyfills } from "vite-plugin-node-polyfills";
|
||||
import { mergeConfig } from "vite";
|
||||
|
||||
// Get a list of available languages so the language selector can display them at runtime
|
||||
const languages = fs.readdirSync("src/i18n/strings").map((f) => f.slice(0, -5));
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ["../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
|
||||
staticDirs: ["../../../webapp"],
|
||||
addons: ["@storybook/addon-docs", "@storybook/addon-designs", "@storybook/addon-a11y"],
|
||||
framework: "@storybook/react-vite",
|
||||
core: {
|
||||
@ -29,8 +32,42 @@ const config: StorybookConfig = {
|
||||
$webapp: path.resolve("../../webapp"),
|
||||
},
|
||||
},
|
||||
// Needed for counterpart to work
|
||||
plugins: [nodePolyfills({ include: ["process", "util"] })],
|
||||
plugins: [
|
||||
// Needed for counterpart to work
|
||||
nodePolyfills({ include: ["process", "util"] }),
|
||||
{
|
||||
name: "language-middleware",
|
||||
configureServer(server) {
|
||||
server.middlewares.use((req, res, next) => {
|
||||
if (req.url === "/i18n/languages.json") {
|
||||
// Dynamically generate a languages.json file based on what files are available
|
||||
const langJson: Record<string, string> = {};
|
||||
for (const lang of languages) {
|
||||
const normalizedLanguage = lang.toLowerCase().replace("_", "-");
|
||||
const languageParts = normalizedLanguage.split("-");
|
||||
if (languageParts.length === 2 && languageParts[0] === languageParts[1]) {
|
||||
langJson[languageParts[0]] = `${lang}.json`;
|
||||
} else {
|
||||
langJson[normalizedLanguage] = `${lang}.json`;
|
||||
}
|
||||
}
|
||||
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.end(JSON.stringify(langJson));
|
||||
} else if (req.url?.startsWith("/i18n/")) {
|
||||
// Serve the individual language files, which annoyingly can't be a simple
|
||||
// static dir because the directory structure in src doesn't match what
|
||||
// the app requests.
|
||||
const langFile = req.url.split("/").pop();
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
fs.createReadStream(`src/i18n/strings/${langFile}`).pipe(res);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
server: {
|
||||
allowedHosts: ["localhost", ".docker.internal"],
|
||||
},
|
||||
@ -42,5 +79,9 @@ const config: StorybookConfig = {
|
||||
url: "https://element-hq.github.io/compound-web/",
|
||||
},
|
||||
},
|
||||
env: (config) => ({
|
||||
...config,
|
||||
STORYBOOK_LANGUAGES: JSON.stringify(languages),
|
||||
}),
|
||||
};
|
||||
export default config;
|
||||
|
||||
@ -34,8 +34,11 @@
|
||||
"package.json"
|
||||
],
|
||||
"scripts": {
|
||||
"i18n": "matrix-gen-i18n src && yarn i18n:sort && yarn i18n:lint",
|
||||
"i18n:sort": "jq --sort-keys '.' src/i18n/strings/en_EN.json > src/i18n/strings/en_EN.json.tmp && mv src/i18n/strings/en_EN.json.tmp src/i18n/strings/en_EN.json",
|
||||
"i18n:lint": "matrix-i18n-lint && prettier --log-level=silent --write src/i18n/strings/ --ignore-path /dev/null",
|
||||
"test": "jest",
|
||||
"prepare": "patch-package && yarn --cwd ../.. build:res && node scripts/gatherTranslationKeys.ts && vite build",
|
||||
"prepare": "patch-package && vite build",
|
||||
"storybook": "storybook dev -p 6007",
|
||||
"build-storybook": "storybook build",
|
||||
"lint": "yarn lint:types && yarn lint:js",
|
||||
|
||||
@ -1,67 +0,0 @@
|
||||
/*
|
||||
Copyright 2025 Element Creations 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.
|
||||
*/
|
||||
|
||||
// Gathers all the translation keys from element-web's en_EN.json into a TypeScript type definition file
|
||||
// that exports a type `TranslationKey` which is a union of all supported translation keys.
|
||||
// This prevents having to import the json file and make typescript do the work as this results in vite-dts
|
||||
// generating an import to the json file in the .d.ts which doesn't work at runtime: this way, the type
|
||||
// gets put into the bundle.
|
||||
// XXX: It should *not* be in the 'src' directory, being a generated file, but if it isn't then the type
|
||||
// bundler won't bundle the types and will leave the file as a relative import, which will break.
|
||||
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import { dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const i18nStringsPath = path.resolve(__dirname, "../../../src/i18n/strings/en_EN.json");
|
||||
const outPath = path.resolve(__dirname, "../src/i18nKeys.d.ts");
|
||||
|
||||
function gatherKeys(obj: any, prefix: string[] = []): string[] {
|
||||
if (typeof obj !== "object" || obj === null) return [];
|
||||
let keys: string[] = [];
|
||||
for (const key of Object.keys(obj)) {
|
||||
const value = obj[key];
|
||||
|
||||
// add the path (for both leaves and intermediates as then we include plurals)
|
||||
keys.push([...prefix, key].join("|"));
|
||||
if (typeof value === "object" && value !== null) {
|
||||
// If the value is an object, recurse
|
||||
keys = keys.concat(gatherKeys(value, [...prefix, key]));
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const json = JSON.parse(fs.readFileSync(i18nStringsPath, "utf8"));
|
||||
const keys = gatherKeys(json);
|
||||
const typeDef =
|
||||
"/*\n" +
|
||||
" * Copyright 2025 Element Creations Ltd.\n" +
|
||||
" *\n" +
|
||||
" * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial\n" +
|
||||
" * Please see LICENSE files in the repository root for full details.\n" +
|
||||
" */\n" +
|
||||
"\n" +
|
||||
"// This file is auto-generated by gatherTranslationKeys.ts\n" +
|
||||
"// Do not edit manually.\n\n" +
|
||||
"export type TranslationKey =\n" +
|
||||
keys.map((k) => ` | \"${k}\"`).join("\n") +
|
||||
";\n";
|
||||
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
||||
fs.writeFileSync(outPath, typeDef, "utf8");
|
||||
console.log(`Wrote ${keys.length} keys to ${outPath}`);
|
||||
}
|
||||
|
||||
if (import.meta.url.startsWith("file:")) {
|
||||
const modulePath = fileURLToPath(import.meta.url);
|
||||
if (process.argv[1] === modulePath) {
|
||||
main();
|
||||
}
|
||||
}
|
||||
14
packages/shared-components/src/@types/i18n.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
Copyright 2025 Element Creations 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 { type TranslationKey as _TranslationKey } from "matrix-web-i18n";
|
||||
|
||||
import type Translations from "../i18n/strings/en_EN.json";
|
||||
|
||||
declare global {
|
||||
type TranslationKey = _TranslationKey<typeof Translations>;
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/cs.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Panel posunu zvuku"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Smazat",
|
||||
"dismiss": "Zavřít",
|
||||
"explore_rooms": "Procházet místnosti",
|
||||
"pause": "Pozastavit",
|
||||
"play": "Přehrát",
|
||||
"search": "Hledání"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "Identita %(displayName)s (<b>%(userId)s</b>) se změnila. <a>Další informace</a>",
|
||||
"withdraw_verification_action": "Zrušit ověření"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Otevřít číselník"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "před jedním dnem",
|
||||
"about_hour_ago": "asi před hodinou",
|
||||
"about_minute_ago": "před minutou",
|
||||
"few_seconds_ago": "před pár vteřinami",
|
||||
"in_about_day": "asi za den",
|
||||
"in_about_hour": "asi za hodinu",
|
||||
"in_about_minute": "asi za minutu",
|
||||
"in_few_seconds": "za pár vteřin",
|
||||
"in_n_days": "za %(num)s dní",
|
||||
"in_n_hours": "za %(num)s hodin",
|
||||
"in_n_minutes": "za %(num)s minut",
|
||||
"n_days_ago": "před %(num)s dny",
|
||||
"n_hours_ago": "před %(num)s hodinami",
|
||||
"n_minutes_ago": "před %(num)s minutami"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Audio přehrávač",
|
||||
"error_downloading_audio": "Chyba při stahování audia",
|
||||
"unnamed_audio": "Nepojmenovaný audio soubor"
|
||||
}
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/cy.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Bar chwilio sain"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Dileu",
|
||||
"dismiss": "Gwrthod",
|
||||
"explore_rooms": "Archwilio Ystafelloedd",
|
||||
"pause": "Oedi",
|
||||
"play": "Chwarae",
|
||||
"search": "Chwilio"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "Cafodd hunaniaeth (<b>%(userId)s</b>) %(displayName)s ei ailosod. <a>Dysgu rhagor</a>",
|
||||
"withdraw_verification_action": "Tynnu'r dilysiad yn ôl"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Agor y pad deialu"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "tua diwrnod yn ôl",
|
||||
"about_hour_ago": "tua awr yn ol",
|
||||
"about_minute_ago": "tua munud yn ôl",
|
||||
"few_seconds_ago": "ychydig eiliadau yn ôl",
|
||||
"in_about_day": "tua diwrnod o nawr",
|
||||
"in_about_hour": "tuag awr o hyn",
|
||||
"in_about_minute": "tua munud o nawr",
|
||||
"in_few_seconds": "ychydig eiliadau o nawr",
|
||||
"in_n_days": "%(num)s diwrnod o nawr",
|
||||
"in_n_hours": "%(num)s awr o nawr",
|
||||
"in_n_minutes": "%(num)s munud o nawr",
|
||||
"n_days_ago": "%(num)s diwrnod yn ôl",
|
||||
"n_hours_ago": "%(num)s awr yn ôl",
|
||||
"n_minutes_ago": "%(num)s munud yn ôl"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Chwaraewr sain",
|
||||
"error_downloading_audio": "Gwall wrth llwytho i lawrsain",
|
||||
"unnamed_audio": "Sain dienw"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/da.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Progressionsmarkør for lydafspiller"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Slet",
|
||||
"dismiss": "Afvis",
|
||||
"explore_rooms": "Udforsk rum",
|
||||
"pause": "Pausér",
|
||||
"play": "Afspil",
|
||||
"search": "Søg"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "omkring en dag siden",
|
||||
"about_hour_ago": "for omkring en time siden",
|
||||
"about_minute_ago": "for omkring et minut siden",
|
||||
"few_seconds_ago": "for et par sekunder siden",
|
||||
"in_about_day": "om cirka en dag fra nu",
|
||||
"in_about_hour": "omkring en time fra nu",
|
||||
"in_about_minute": "omkring et minut fra nu",
|
||||
"in_few_seconds": "et par sekunder fra nu",
|
||||
"in_n_days": "%(num)s dage fra nu",
|
||||
"in_n_hours": "%(num)s timer fra nu",
|
||||
"in_n_minutes": "%(num)s minutter fra nu",
|
||||
"n_days_ago": "%(num)s dage siden",
|
||||
"n_hours_ago": "%(num)s timer siden",
|
||||
"n_minutes_ago": "%(num)s minutter siden"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Fejl ved download af lyd",
|
||||
"unnamed_audio": "Unavngiven lyd"
|
||||
}
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/de_DE.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Audio-Suchleiste"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Löschen",
|
||||
"dismiss": "Ausblenden",
|
||||
"explore_rooms": "Chats erkunden",
|
||||
"pause": "Pausieren",
|
||||
"play": "Abspielen",
|
||||
"search": "Suchen"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "%(displayName)s's (<b>%(userId)s</b>) Identität wurde zurückgesetzt. <a>Mehr erfahren </a>",
|
||||
"withdraw_verification_action": "Verifizierung zurückziehen"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Wähltastatur öffnen"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "vor etwa einem Tag",
|
||||
"about_hour_ago": "vor etwa einer Stunde",
|
||||
"about_minute_ago": "vor etwa einer Minute",
|
||||
"few_seconds_ago": "vor ein paar Sekunden",
|
||||
"in_about_day": "in etwa einem Tag",
|
||||
"in_about_hour": "in etwa einer Stunde",
|
||||
"in_about_minute": "in etwa einer Minute",
|
||||
"in_few_seconds": "in ein paar Sekunden",
|
||||
"in_n_days": "in %(num)s Tagen",
|
||||
"in_n_hours": "in %(num)s Stunden",
|
||||
"in_n_minutes": "In etwa %(num)s Minuten",
|
||||
"n_days_ago": "vor %(num)s Tagen",
|
||||
"n_hours_ago": "vor %(num)s Stunden",
|
||||
"n_minutes_ago": "vor %(num)s Minuten"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Audio-Player",
|
||||
"error_downloading_audio": "Fehler beim Herunterladen der Audiodatei",
|
||||
"unnamed_audio": "Unbenannte Audiodatei"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/el.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "Διαγραφή",
|
||||
"dismiss": "Απόρριψη",
|
||||
"explore_rooms": "Εξερευνήστε αίθουσες",
|
||||
"pause": "Παύση",
|
||||
"play": "Αναπαραγωγή",
|
||||
"search": "Αναζήτηση"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Άνοιγμα πληκτρολογίου κλήσης"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "σχεδόν μία μέρα πριν",
|
||||
"about_hour_ago": "σχεδόν μία ώρα πριν",
|
||||
"about_minute_ago": "σχεδόν ένα λεπτό πριν",
|
||||
"few_seconds_ago": "λίγα δευτερόλεπτα πριν",
|
||||
"in_about_day": "περίπου μια μέρα από τώρα",
|
||||
"in_about_hour": "περίπου μία ώρα από τώρα",
|
||||
"in_about_minute": "περίπου ένα λεπτό από τώρα",
|
||||
"in_few_seconds": "λίγα δευτερόλεπτα από τώρα",
|
||||
"in_n_days": "%(num)s μέρες από τώρα",
|
||||
"in_n_hours": "%(num)s ώρες από τώρα",
|
||||
"in_n_minutes": "%(num)s λεπτά από τώρα",
|
||||
"n_days_ago": "%(num)s μέρες πριν",
|
||||
"n_hours_ago": "%(num)s ώρες πριν",
|
||||
"n_minutes_ago": "%(num)s λεπτά πριν"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Σφάλμα λήψης ήχου",
|
||||
"unnamed_audio": "Ήχος χωρίς όνομα"
|
||||
}
|
||||
}
|
||||
}
|
||||
44
packages/shared-components/src/i18n/strings/en_EN.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Audio seek bar"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Delete",
|
||||
"dismiss": "Dismiss",
|
||||
"explore_rooms": "Explore rooms",
|
||||
"pause": "Pause",
|
||||
"play": "Play",
|
||||
"search": "Search"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Open dial pad"
|
||||
},
|
||||
"room": {
|
||||
"status_bar": {
|
||||
"history_visible": "This room has been configured so that new members can read history. <a>Learn More</a>"
|
||||
}
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "about a day ago",
|
||||
"about_hour_ago": "about an hour ago",
|
||||
"about_minute_ago": "about a minute ago",
|
||||
"few_seconds_ago": "a few seconds ago",
|
||||
"in_about_day": "about a day from now",
|
||||
"in_about_hour": "about an hour from now",
|
||||
"in_about_minute": "about a minute from now",
|
||||
"in_few_seconds": "a few seconds from now",
|
||||
"in_n_days": "%(num)s days from now",
|
||||
"in_n_hours": "%(num)s hours from now",
|
||||
"in_n_minutes": "%(num)s minutes from now",
|
||||
"n_days_ago": "%(num)s days ago",
|
||||
"n_hours_ago": "%(num)s hours ago",
|
||||
"n_minutes_ago": "%(num)s minutes ago"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Audio player",
|
||||
"error_downloading_audio": "Error downloading audio",
|
||||
"unnamed_audio": "Unnamed audio"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/eo.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "Forigi",
|
||||
"dismiss": "Rezigni",
|
||||
"explore_rooms": "Esplori ĉambrojn",
|
||||
"pause": "Paŭzigi",
|
||||
"play": "Ludi",
|
||||
"search": "Serĉi"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Malfermi ciferplaton"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "antaŭ ĉirkaŭ tago",
|
||||
"about_hour_ago": "antaŭ ĉirkaŭ horo",
|
||||
"about_minute_ago": "antaŭ ĉirkaŭ minuto",
|
||||
"few_seconds_ago": "antaŭ kelkaj sekundoj",
|
||||
"in_about_day": "ĉirkaŭ tagon de nun",
|
||||
"in_about_hour": "ĉirkaŭ horon de nun",
|
||||
"in_about_minute": "ĉirkaŭ minuton de nun",
|
||||
"in_few_seconds": "kelkajn sekundojn de nun",
|
||||
"in_n_days": "%(num)s tagojn de nun",
|
||||
"in_n_hours": "%(num)s horojn de nun",
|
||||
"in_n_minutes": "%(num)s minutojn de nun",
|
||||
"n_days_ago": "antaŭ %(num)s tagoj",
|
||||
"n_hours_ago": "antaŭ %(num)s horoj",
|
||||
"n_minutes_ago": "antaŭ %(num)s minutoj"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Eraris elŝuto de sondosiero",
|
||||
"unnamed_audio": "Sennoma sondosiero"
|
||||
}
|
||||
}
|
||||
}
|
||||
39
packages/shared-components/src/i18n/strings/es.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Barra de búsqueda de audio"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Borrar",
|
||||
"dismiss": "Omitir",
|
||||
"explore_rooms": "Explorar salas",
|
||||
"pause": "Pausar",
|
||||
"play": "Reproducir",
|
||||
"search": "Buscar"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Abrir teclado numérico"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "hace aprox. un día",
|
||||
"about_hour_ago": "hace aprox. una hora",
|
||||
"about_minute_ago": "hace aproximadamente un minuto",
|
||||
"few_seconds_ago": "hace unos segundos",
|
||||
"in_about_day": "dentro de un día",
|
||||
"in_about_hour": "dentro de una hora",
|
||||
"in_about_minute": "dentro de un minuto",
|
||||
"in_few_seconds": "dentro de unos segundos",
|
||||
"in_n_days": "dentro de %(num)s días",
|
||||
"in_n_hours": "dentro de %(num)s horas",
|
||||
"in_n_minutes": "dentro de %(num)s minutos",
|
||||
"n_days_ago": "hace %(num)s días",
|
||||
"n_hours_ago": "hace %(num)s horas",
|
||||
"n_minutes_ago": "hace %(num)s minutos"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Reproductor de audio",
|
||||
"error_downloading_audio": "Error al descargar el audio",
|
||||
"unnamed_audio": "Audio sin título"
|
||||
}
|
||||
}
|
||||
}
|
||||
48
packages/shared-components/src/i18n/strings/et.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Heli kerimisriba"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Kustuta",
|
||||
"dismiss": "Loobu",
|
||||
"explore_rooms": "Tutvu jututubadega",
|
||||
"pause": "Peata",
|
||||
"play": "Esita",
|
||||
"search": "Otsing"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "Kasutaja %(displayName)s (<b>%(userId)s</b>) võrguidentiteet on lähtestatud. <a>Lisateave</a>",
|
||||
"withdraw_verification_action": "Eemalda verifitseerimine"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Ava numbriklahvistik"
|
||||
},
|
||||
"room": {
|
||||
"status_bar": {
|
||||
"history_visible": "See jututuba on seadistatud sel viisil, et uued liikmed saavad lugeda varasemat ajalugu.<a> Lisateave</a>"
|
||||
}
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "umbes päev tagasi",
|
||||
"about_hour_ago": "umbes tund aega tagasi",
|
||||
"about_minute_ago": "umbes minut tagasi",
|
||||
"few_seconds_ago": "mõni sekund tagasi",
|
||||
"in_about_day": "umbes päeva pärast",
|
||||
"in_about_hour": "umbes tunni pärast",
|
||||
"in_about_minute": "umbes minuti pärast",
|
||||
"in_few_seconds": "mõne sekundi pärast",
|
||||
"in_n_days": "%(num)s päeva pärast",
|
||||
"in_n_hours": "%(num)s tunni pärast",
|
||||
"in_n_minutes": "%(num)s minuti pärast",
|
||||
"n_days_ago": "%(num)s päeva tagasi",
|
||||
"n_hours_ago": "%(num)s tundi tagasi",
|
||||
"n_minutes_ago": "%(num)s minutit tagasi"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Meediaesitaja",
|
||||
"error_downloading_audio": "Helifaili allalaadimine ei õnnestunud",
|
||||
"unnamed_audio": "Nimetu helifail"
|
||||
}
|
||||
}
|
||||
}
|
||||
29
packages/shared-components/src/i18n/strings/fa.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "پاککردن",
|
||||
"dismiss": "نادیده بگیر",
|
||||
"explore_rooms": "جستجو در اتاق ها",
|
||||
"pause": "متوقفکردن",
|
||||
"play": "اجرا کردن",
|
||||
"search": "جستجو"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "باز کردن صفحه شمارهگیری"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "حدود یک روز قبل",
|
||||
"about_hour_ago": "حدود یک ساعت قبل",
|
||||
"about_minute_ago": "حدود یک دقیقه قبل",
|
||||
"few_seconds_ago": "چند ثانیه قبل",
|
||||
"in_about_day": "حدود یک روز دیگر",
|
||||
"in_about_hour": "حدود یک ساعت دیگر",
|
||||
"in_about_minute": "حدود یک دقیقه دیگر",
|
||||
"in_few_seconds": "چند ثانیه دیگر",
|
||||
"in_n_days": "%(num)s روز دیگر",
|
||||
"in_n_hours": "%(num)s ساعت دیگر",
|
||||
"in_n_minutes": "%(num)s دقیقه دیگر",
|
||||
"n_days_ago": "%(num)s روز قبل",
|
||||
"n_hours_ago": "%(num)s ساعت قبل",
|
||||
"n_minutes_ago": "%(num)s دقیقه قبل"
|
||||
}
|
||||
}
|
||||
38
packages/shared-components/src/i18n/strings/fi.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Äänen siirtymispalkki"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Poista",
|
||||
"dismiss": "Hylkää",
|
||||
"explore_rooms": "Selaa huoneita",
|
||||
"pause": "Keskeytä",
|
||||
"play": "Toista",
|
||||
"search": "Haku"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Avaa näppäimistö"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "noin päivä sitten",
|
||||
"about_hour_ago": "noin tunti sitten",
|
||||
"about_minute_ago": "noin minuutti sitten",
|
||||
"few_seconds_ago": "muutama sekunti sitten",
|
||||
"in_about_day": "noin päivä sitten",
|
||||
"in_about_hour": "noin tunti sitten",
|
||||
"in_about_minute": "noin minuutti sitten",
|
||||
"in_few_seconds": "muutama sekunti sitten",
|
||||
"in_n_days": "%(num)s päivää sitten",
|
||||
"in_n_hours": "%(num)s tuntia sitten",
|
||||
"in_n_minutes": "%(num)s minuuttia sitten",
|
||||
"n_days_ago": "%(num)s päivää sitten",
|
||||
"n_hours_ago": "%(num)s tuntia sitten",
|
||||
"n_minutes_ago": "%(num)s minuuttia sitten"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Virhe ääntä ladattaessa",
|
||||
"unnamed_audio": "Nimetön ääni"
|
||||
}
|
||||
}
|
||||
}
|
||||
48
packages/shared-components/src/i18n/strings/fr.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Barre de recherche audio"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Supprimer",
|
||||
"dismiss": "Ignorer",
|
||||
"explore_rooms": "Parcourir les salons",
|
||||
"pause": "Pause",
|
||||
"play": "Lecture",
|
||||
"search": "Rechercher"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "L'identité de %(displayName)s (<b>%(userId)s</b>) semble avoir changé. <a>En savoir plus</a>",
|
||||
"withdraw_verification_action": "Révoquer la vérification"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Ouvrir le pavé de numérotation"
|
||||
},
|
||||
"room": {
|
||||
"status_bar": {
|
||||
"history_visible": "Ce salon a été configuré afin que les nouveaux membres puissent lire l'historique.<a> En savori plus</a>"
|
||||
}
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "il y a environ un jour",
|
||||
"about_hour_ago": "il y a environ une heure",
|
||||
"about_minute_ago": "il y a environ une minute",
|
||||
"few_seconds_ago": "il y a quelques secondes",
|
||||
"in_about_day": "dans un jour environ",
|
||||
"in_about_hour": "dans une heure environ",
|
||||
"in_about_minute": "dans une minute environ",
|
||||
"in_few_seconds": "dans quelques secondes",
|
||||
"in_n_days": "dans %(num)s jours",
|
||||
"in_n_hours": "dans %(num)s heures",
|
||||
"in_n_minutes": "dans %(num)s minutes",
|
||||
"n_days_ago": "il y a %(num)s jours",
|
||||
"n_hours_ago": "il y a %(num)s heures",
|
||||
"n_minutes_ago": "il y a %(num)s minutes"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Lecteur audio",
|
||||
"error_downloading_audio": "Erreur lors du téléchargement de l’audio",
|
||||
"unnamed_audio": "Audio sans nom"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/gl.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "Eliminar",
|
||||
"dismiss": "Rexeitar",
|
||||
"explore_rooms": "Explorar salas",
|
||||
"pause": "Deter",
|
||||
"play": "Reproducir",
|
||||
"search": "Busca"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Abrir marcador"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "onte",
|
||||
"about_hour_ago": "fai unha hora",
|
||||
"about_minute_ago": "fai un minuto",
|
||||
"few_seconds_ago": "fai uns segundos",
|
||||
"in_about_day": "foi onte",
|
||||
"in_about_hour": "fará unha hora",
|
||||
"in_about_minute": "haberá un minuto",
|
||||
"in_few_seconds": "hai só uns segundos",
|
||||
"in_n_days": "fará %(num)s días",
|
||||
"in_n_hours": "fará %(num)s horas",
|
||||
"in_n_minutes": "fará %(num)s minutos",
|
||||
"n_days_ago": "fai %(num)s días",
|
||||
"n_hours_ago": "fai %(num)s horas",
|
||||
"n_minutes_ago": "fai %(num)s minutos"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Erro ao descargar o audio",
|
||||
"unnamed_audio": "Audio sen nome"
|
||||
}
|
||||
}
|
||||
}
|
||||
27
packages/shared-components/src/i18n/strings/he.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "מחק",
|
||||
"dismiss": "התעלם",
|
||||
"explore_rooms": "גלה חדרים",
|
||||
"search": "חפש"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "פתח לוח חיוג"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "בערך לפני יום",
|
||||
"about_hour_ago": "בערך לפני כשעה",
|
||||
"about_minute_ago": "לפני בערך דקה",
|
||||
"few_seconds_ago": "לפני מספר שניות",
|
||||
"in_about_day": "בערך בעוד יום מעכשיו",
|
||||
"in_about_hour": "בערך בעוד כשעה",
|
||||
"in_about_minute": "בערך עוד דקה אחת",
|
||||
"in_few_seconds": "בעוד מספר שניות מעכשיו",
|
||||
"in_n_days": "בעוד %(num)s ימים מעכשיו",
|
||||
"in_n_hours": "בעוד %(num)s שעות",
|
||||
"in_n_minutes": "בעוד %(num)s דקות",
|
||||
"n_days_ago": "לפני %(num)s ימים",
|
||||
"n_hours_ago": "לפני %(num)s שעות",
|
||||
"n_minutes_ago": "לפני %(num)s דקות"
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/hu.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Hang keresősávja"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Törlés",
|
||||
"dismiss": "Eltüntetés",
|
||||
"explore_rooms": "Szobák felderítése",
|
||||
"pause": "Szünet",
|
||||
"play": "Lejátszás",
|
||||
"search": "Keresés"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "Úgy tűnik, hogy %(displayName)s (<b>%(userId)s</b>) személyazonossága megváltozott. <a>További információ</a>",
|
||||
"withdraw_verification_action": "Ellenőrzés visszavonása"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Számlap megnyitása"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "egy napja",
|
||||
"about_hour_ago": "egy órája",
|
||||
"about_minute_ago": "egy perce",
|
||||
"few_seconds_ago": "néhány másodperce",
|
||||
"in_about_day": "egy nap múlva",
|
||||
"in_about_hour": "egy óra múlva",
|
||||
"in_about_minute": "egy perc múlva",
|
||||
"in_few_seconds": "másodpercek múlva",
|
||||
"in_n_days": "%(num)s nap múlva",
|
||||
"in_n_hours": "%(num)s óra múlva",
|
||||
"in_n_minutes": "%(num)s perc múlva",
|
||||
"n_days_ago": "%(num)s nappal ezelőtt",
|
||||
"n_hours_ago": "%(num)s órával ezelőtt",
|
||||
"n_minutes_ago": "%(num)s perccel ezelőtt"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Hanglejátszó",
|
||||
"error_downloading_audio": "Hiba a hang letöltésekor",
|
||||
"unnamed_audio": "Névtelen hang"
|
||||
}
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/hy.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Աուդիո որոնման գոտի"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Ջնջել",
|
||||
"dismiss": "Հեռացնել",
|
||||
"explore_rooms": "Փնտրել սենյակներ",
|
||||
"pause": "Դադար",
|
||||
"play": "Միացնել",
|
||||
"search": "Որոնել"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "%(displayName)s-ի (<b>%(userId)s</b> ) ինքնությունը վերակայվել է։ <a> Իմանալ ավելին</a>",
|
||||
"withdraw_verification_action": "Հետ կանչել հաստատումը"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Բացեք թվերի հավաքման վահանակը"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "մոտ մեկ օր առաջ",
|
||||
"about_hour_ago": "մոտ մեկ ժամ առաջ",
|
||||
"about_minute_ago": "մոտ մեկ րոպե առաջ",
|
||||
"few_seconds_ago": "մի քանի վայրկյան առաջ",
|
||||
"in_about_day": "մոտ մեկ օր անց",
|
||||
"in_about_hour": "մոտ մեկ ժամ անց",
|
||||
"in_about_minute": "մոտ մեկ րոպե անց",
|
||||
"in_few_seconds": "մի քանի վայրկյան անց",
|
||||
"in_n_days": "%(num)s օր անց",
|
||||
"in_n_hours": "%(num)s ժամ անց",
|
||||
"in_n_minutes": "%(num)s րոպեներ անց",
|
||||
"n_days_ago": "%(num)s օր առաջ",
|
||||
"n_hours_ago": "%(num)s ժամ առաջ",
|
||||
"n_minutes_ago": "%(num)s րոպե առաջ"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Աուդիո նվագարկիչ",
|
||||
"error_downloading_audio": "Աուդիո ներբեռնման սխալ",
|
||||
"unnamed_audio": "Անանուն աուդիո"
|
||||
}
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/id.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Bilah pencarian audio"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Hapus",
|
||||
"dismiss": "Abaikan",
|
||||
"explore_rooms": "Jelajahi ruangan",
|
||||
"pause": "Jeda",
|
||||
"play": "Mainkan",
|
||||
"search": "Cari"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "Identitas (<b>%(userId)s</b>) %(displayName)s tampaknya telah berubah. <a>Pelajari lebih lanjut</a>",
|
||||
"withdraw_verification_action": "Tolak verifikasi"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Buka tombol penyetel"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "1 hari yang lalu",
|
||||
"about_hour_ago": "1 jam yang lalu",
|
||||
"about_minute_ago": "1 menit yang lalu",
|
||||
"few_seconds_ago": "beberapa detik yang lalu",
|
||||
"in_about_day": "1 hari dari sekarang",
|
||||
"in_about_hour": "1 jam dari sekarang",
|
||||
"in_about_minute": "1 menit dari sekarang",
|
||||
"in_few_seconds": "beberapa detik dari sekarang",
|
||||
"in_n_days": "%(num)s hari dari sekarang",
|
||||
"in_n_hours": "%(num)s jam dari sekarang",
|
||||
"in_n_minutes": "%(num)s dari sekarang",
|
||||
"n_days_ago": "%(num)s hari yang lalu",
|
||||
"n_hours_ago": "%(num)s jam yang lalu",
|
||||
"n_minutes_ago": "%(num)s menit yang lalu"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Pemutar audio",
|
||||
"error_downloading_audio": "Terjadi kesalahan mengunduh audio",
|
||||
"unnamed_audio": "Audio tidak dinamai"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/is.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "Eyða",
|
||||
"dismiss": "Hunsa",
|
||||
"explore_rooms": "Kanna spjallrásir",
|
||||
"pause": "Bið",
|
||||
"play": "Spila",
|
||||
"search": "Leita"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Opna talnaborð"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "fyrir um degi síðan",
|
||||
"about_hour_ago": "fyrir um klukkustund síðan",
|
||||
"about_minute_ago": "fyrir um það bil mínútu síðan",
|
||||
"few_seconds_ago": "fyrir örfáum sekúndum síðan",
|
||||
"in_about_day": "eftir um það bil einn dag",
|
||||
"in_about_hour": "eftir um það bil klukkustund",
|
||||
"in_about_minute": "eftir um það bil mínútu",
|
||||
"in_few_seconds": "eftir nokkrar sekúndur",
|
||||
"in_n_days": "eftir %(num)s daga",
|
||||
"in_n_hours": "eftir %(num)s klukkustundir",
|
||||
"in_n_minutes": "eftir %(num)s mínútur",
|
||||
"n_days_ago": "fyrir %(num)s dögum síðan",
|
||||
"n_hours_ago": "fyrir %(num)s klukkustundum síðan",
|
||||
"n_minutes_ago": "fyrir %(num)s mínútum síðan"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Villa við að sækja hljóð",
|
||||
"unnamed_audio": "Nafnlaust hljóð"
|
||||
}
|
||||
}
|
||||
}
|
||||
38
packages/shared-components/src/i18n/strings/it.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Barra di ricerca audio"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Elimina",
|
||||
"dismiss": "Chiudi",
|
||||
"explore_rooms": "Esplora stanze",
|
||||
"pause": "Pausa",
|
||||
"play": "Riproduci",
|
||||
"search": "Cerca"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Apri tastierino"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "circa un giorno fa",
|
||||
"about_hour_ago": "circa un'ora fa",
|
||||
"about_minute_ago": "circa un minuto fa",
|
||||
"few_seconds_ago": "pochi secondi fa",
|
||||
"in_about_day": "circa un giorno da adesso",
|
||||
"in_about_hour": "circa un'ora da adesso",
|
||||
"in_about_minute": "circa un minuto da adesso",
|
||||
"in_few_seconds": "pochi secondi da adesso",
|
||||
"in_n_days": "%(num)s giorni da adesso",
|
||||
"in_n_hours": "%(num)s ore da adesso",
|
||||
"in_n_minutes": "%(num)s minuti da adesso",
|
||||
"n_days_ago": "%(num)s giorni fa",
|
||||
"n_hours_ago": "%(num)s ore fa",
|
||||
"n_minutes_ago": "%(num)s minuti fa"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Errore di scaricamento dell'audio",
|
||||
"unnamed_audio": "Audio senza nome"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/ja.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "削除",
|
||||
"dismiss": "閉じる",
|
||||
"explore_rooms": "ルームを探す",
|
||||
"pause": "一時停止",
|
||||
"play": "再生",
|
||||
"search": "検索"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "ダイヤルパッドを開く"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "約1日前",
|
||||
"about_hour_ago": "約1時間前",
|
||||
"about_minute_ago": "約1分前",
|
||||
"few_seconds_ago": "数秒前",
|
||||
"in_about_day": "今から約1日前",
|
||||
"in_about_hour": "今から約1時間前",
|
||||
"in_about_minute": "今から約1分前",
|
||||
"in_few_seconds": "今から数秒前",
|
||||
"in_n_days": "今から%(num)s日前",
|
||||
"in_n_hours": "今から%(num)s時間前",
|
||||
"in_n_minutes": "今から%(num)s分前",
|
||||
"n_days_ago": "%(num)s日前",
|
||||
"n_hours_ago": "%(num)s時間前",
|
||||
"n_minutes_ago": "%(num)s分前"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "音声をダウンロードする際にエラーが発生しました",
|
||||
"unnamed_audio": "名前のない音声"
|
||||
}
|
||||
}
|
||||
}
|
||||
32
packages/shared-components/src/i18n/strings/ka.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "წაშლა",
|
||||
"dismiss": "დახურვა",
|
||||
"explore_rooms": "ოთახების დათავლიერება",
|
||||
"pause": "პაუზა",
|
||||
"play": "დაკვრა",
|
||||
"search": "ძიება"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "დაახლოებით ერთი დღის წინ",
|
||||
"about_hour_ago": "დაახლოებით ერთი საათის წინ",
|
||||
"about_minute_ago": "დაახლოებით ერთი წუთის წინ",
|
||||
"few_seconds_ago": "რამდენიმე წამის წინ",
|
||||
"in_about_day": "დაახლოებით ერთი დღის შემდეგ",
|
||||
"in_about_hour": "დაახლოებით ერთი საათის შემდეგ",
|
||||
"in_about_minute": "დაახლოებით ერთი წუთის შემდეგ",
|
||||
"in_few_seconds": "რამდენიმე წამის შემდეგ",
|
||||
"in_n_days": "%(num)sდღეებიდან",
|
||||
"in_n_hours": "%(num)sსაათის შემდეგ",
|
||||
"in_n_minutes": "%(num)sწუთის შემდეგ",
|
||||
"n_days_ago": "%(num)sდღის წინ",
|
||||
"n_hours_ago": "%(num)sსაათის წინ",
|
||||
"n_minutes_ago": "%(num)sწუთის წინ"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "შეცდომა აუდიოს ჩამოტვირთვისას",
|
||||
"unnamed_audio": "უსახელო აუდიო"
|
||||
}
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/ko.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "오디오 탐색 바"
|
||||
},
|
||||
"action": {
|
||||
"delete": "삭제",
|
||||
"dismiss": "버리기",
|
||||
"explore_rooms": "방 검색",
|
||||
"pause": "일시중지",
|
||||
"play": "재생",
|
||||
"search": "찾기"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "%(displayName)s (<b>%(userId)s</b>)의 신원이 재설정되었습니다. <a>자세히 알아보기</a>",
|
||||
"withdraw_verification_action": "인증 취소"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "다이얼 패드 열기"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "약 1일 전",
|
||||
"about_hour_ago": "약 1 시간 전",
|
||||
"about_minute_ago": "약 1분 전",
|
||||
"few_seconds_ago": "몇 초 전",
|
||||
"in_about_day": "하루 정도 후",
|
||||
"in_about_hour": "지금부터 한 시간 정도 후에",
|
||||
"in_about_minute": "지금부터 약 1분 후",
|
||||
"in_few_seconds": "몇 초 후",
|
||||
"in_n_days": "지금부터 %(num)s 일 후에",
|
||||
"in_n_hours": "지금부터 %(num)s 시간 후",
|
||||
"in_n_minutes": "지금부터 %(num)s분 후",
|
||||
"n_days_ago": "%(num)s일 전",
|
||||
"n_hours_ago": "%(num)s 시간 전",
|
||||
"n_minutes_ago": "%(num)s분 전"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "오디오 플레이어",
|
||||
"error_downloading_audio": "오디오 다운로드 중 오류 발생",
|
||||
"unnamed_audio": "이름 없는 오디오"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/lo.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "ລຶບ",
|
||||
"dismiss": "ຍົກເລີກ",
|
||||
"explore_rooms": "ການສຳຫຼວດຫ້ອງ",
|
||||
"pause": "ຢຸດຊົ່ວຄາວ",
|
||||
"play": "ຫຼິ້ນ",
|
||||
"search": "ຊອກຫາ"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "ເປີດແຜ່ນປັດ"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "ປະມານຫນຶ່ງມື້ກ່ອນຫນ້ານີ້",
|
||||
"about_hour_ago": "ປະມານຫນຶ່ງຊົ່ວໂມງກ່ອນຫນ້ານີ້",
|
||||
"about_minute_ago": "ປະມານໜຶ່ງວິນາທີກ່ອນຫນ້ານີ້",
|
||||
"few_seconds_ago": "ສອງສາມວິນາທີກ່ອນຫນ້ານີ້",
|
||||
"in_about_day": "ປະມານນຶ່ງມື້ຈາກນີ້",
|
||||
"in_about_hour": "ປະມານຫນຶ່ງຊົ່ວໂມງຈາກປະຈຸບັນນີ້",
|
||||
"in_about_minute": "ປະມານໜຶ່ງນາທີຕໍ່ຈາກນີ້",
|
||||
"in_few_seconds": "ສອງສາມວິນາທີຕໍ່ຈາກນີ້ໄປ",
|
||||
"in_n_days": "%(num)s ມື້ຕໍ່ຈາກນີ້",
|
||||
"in_n_hours": "%(num)s ຊົ່ວໂມງຈາກປະຈຸບັນນີ້",
|
||||
"in_n_minutes": "%(num)s ນາທີຕໍ່ຈາກນີ້",
|
||||
"n_days_ago": "%(num)sມື້ກ່ອນຫນ້ານີ້",
|
||||
"n_hours_ago": "%(num)s ຊົ່ວໂມງກ່ອນ",
|
||||
"n_minutes_ago": "%(num)s ນາທີກ່ອນ"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "ເກີດຄວາມຜິດພາດໃນການດາວໂຫຼດສຽງ",
|
||||
"unnamed_audio": "ສຽງບໍ່ມີຊື່"
|
||||
}
|
||||
}
|
||||
}
|
||||
24
packages/shared-components/src/i18n/strings/lt.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "Ištrinti",
|
||||
"dismiss": "Atmesti",
|
||||
"explore_rooms": "Žvalgyti kambarius",
|
||||
"search": "Ieškoti"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "maždaug prieš dieną",
|
||||
"about_hour_ago": "maždaug prieš valandą",
|
||||
"about_minute_ago": "maždaug prieš minutę",
|
||||
"few_seconds_ago": "prieš kelias sekundes",
|
||||
"in_about_day": "apie dieną nuo dabar",
|
||||
"in_about_hour": "apie valandą nuo dabar",
|
||||
"in_about_minute": "apie minutę nuo dabar",
|
||||
"in_few_seconds": "keletą sekundžių nuo dabar",
|
||||
"in_n_days": "%(num)s dienas(-ų) nuo dabar",
|
||||
"in_n_hours": "%(num)s valandas(-ų) nuo dabar",
|
||||
"in_n_minutes": "%(num)s minutes(-ų) nuo dabar",
|
||||
"n_days_ago": "prieš %(num)s dienas(-ų)",
|
||||
"n_hours_ago": "prieš %(num)s valandas(-ų)",
|
||||
"n_minutes_ago": "prieš %(num)s minutes(-ų)"
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/lv.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Audio meklēšanas josla"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Izdzēst",
|
||||
"dismiss": "Atmest",
|
||||
"explore_rooms": "Pārlūkot istabas",
|
||||
"pause": "Pauzēt",
|
||||
"play": "Atskaņot",
|
||||
"search": "Meklēt"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "aptuveni dienu iepriekš",
|
||||
"about_hour_ago": "aptuveni stundu iepriekš",
|
||||
"about_minute_ago": "aptuveni minūti iepriekš",
|
||||
"few_seconds_ago": "pirms dažām sekundēm",
|
||||
"in_about_day": "aptuveni dienu kopš šī brīža",
|
||||
"in_about_hour": "aptuveni stundu kopš šī brīža",
|
||||
"in_about_minute": "aptuveni minūti kopš šī brīža",
|
||||
"in_few_seconds": "dažas sekundes kopš šī brīža",
|
||||
"in_n_days": "%(num)s dienas kopš šī brīža",
|
||||
"in_n_hours": "%(num)s stundas kopš šī brīža",
|
||||
"in_n_minutes": "%(num)s minūtes kopš šī brīža",
|
||||
"n_days_ago": "%(num)s dienas iepriekš",
|
||||
"n_hours_ago": "%(num)s stundas iepriekš",
|
||||
"n_minutes_ago": "%(num)s minūtes iepriekš"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Kļūda skaņas lejupielādēšanā",
|
||||
"unnamed_audio": "Nenosaukts audio"
|
||||
}
|
||||
}
|
||||
}
|
||||
38
packages/shared-components/src/i18n/strings/mg_MG.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Audio mitady bar"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Esorina",
|
||||
"dismiss": "Hanario",
|
||||
"explore_rooms": "Tsidiho ny efitrano",
|
||||
"pause": "Mihato",
|
||||
"play": "Milalao",
|
||||
"search": "Karohina"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Sokafy ny dial pad"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "Tokony ho iray andro izay",
|
||||
"about_hour_ago": "Manakaiky adin'iray Teo ho eo",
|
||||
"about_minute_ago": "Misy iray minitra Teo izay",
|
||||
"few_seconds_ago": "Segondra vitsy lasa",
|
||||
"in_about_day": "Anatiny iray andro eo ho eo",
|
||||
"in_about_hour": "Adiny iray eo ho eo",
|
||||
"in_about_minute": "Afaka iray minitra eo ho eo",
|
||||
"in_few_seconds": "Afaka segondra vitsy",
|
||||
"in_n_days": "%(num) s andro manomboka izao",
|
||||
"in_n_hours": "% (num) sAnatiny ora vitsivitsy",
|
||||
"in_n_minutes": "% (Num) sAfaka minitra vitsy",
|
||||
"n_days_ago": "%(num)s Andro vitsivitsy izay",
|
||||
"n_hours_ago": "%(num)sOra maromaro",
|
||||
"n_minutes_ago": "%(Num)s Minitra vitsivitsy izay"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Hadisoana tamin'ny fampidinana feo",
|
||||
"unnamed_audio": "Audio tsy voatonona anarana"
|
||||
}
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/nb_NO.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Søkelinje for lyd"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Slett",
|
||||
"dismiss": "Avvis",
|
||||
"explore_rooms": "Se alle rom",
|
||||
"pause": "Pause",
|
||||
"play": "Spill av",
|
||||
"search": "Søk"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "%(displayName)ss (<b>%(userId)s</b>) identitet ser ut til å ha endret seg. <a>Finn ut mer</a>",
|
||||
"withdraw_verification_action": "Trekk tilbake verifisering"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Åpne nummerpanelet"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "cirka 1 dag siden",
|
||||
"about_hour_ago": "cirka 1 time siden",
|
||||
"about_minute_ago": "cirka 1 minutt siden",
|
||||
"few_seconds_ago": "noen sekunder siden",
|
||||
"in_about_day": "rundt en dag fra nå",
|
||||
"in_about_hour": "rundt en time fra nå",
|
||||
"in_about_minute": "rundt et minutt fra nå",
|
||||
"in_few_seconds": "om noen sekunder fra nå",
|
||||
"in_n_days": "%(num)s dager fra nå",
|
||||
"in_n_hours": "%(num)s timer fra nå",
|
||||
"in_n_minutes": "%(num)s minutter fra nå",
|
||||
"n_days_ago": "%(num)s dager siden",
|
||||
"n_hours_ago": "%(num)s timer siden",
|
||||
"n_minutes_ago": "%(num)s minutter siden"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Lydavspiller",
|
||||
"error_downloading_audio": "Feil ved nedlasting av lyd",
|
||||
"unnamed_audio": "Ikke navngitt lyd"
|
||||
}
|
||||
}
|
||||
}
|
||||
38
packages/shared-components/src/i18n/strings/nl.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Audio zoekbalk"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Verwijderen",
|
||||
"dismiss": "Sluiten",
|
||||
"explore_rooms": "Kamers ontdekken",
|
||||
"pause": "Pauze",
|
||||
"play": "Afspelen",
|
||||
"search": "Zoeken"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Kiestoetsen openen"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "ongeveer een dag geleden",
|
||||
"about_hour_ago": "ongeveer een uur geleden",
|
||||
"about_minute_ago": "ongeveer een minuut geleden",
|
||||
"few_seconds_ago": "enige tellen geleden",
|
||||
"in_about_day": "over een dag of zo",
|
||||
"in_about_hour": "over ongeveer een uur",
|
||||
"in_about_minute": "over ongeveer een minuut",
|
||||
"in_few_seconds": "over een paar tellen",
|
||||
"in_n_days": "over %(num)s dagen",
|
||||
"in_n_hours": "over %(num)s uur",
|
||||
"in_n_minutes": "over %(num)s minuten",
|
||||
"n_days_ago": "%(num)s dagen geleden",
|
||||
"n_hours_ago": "%(num)s uur geleden",
|
||||
"n_minutes_ago": "%(num)s minuten geleden"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Fout bij downloaden van audio",
|
||||
"unnamed_audio": "Naamloze audio"
|
||||
}
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/pl.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Pasek wyszukiwania audio"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Usuń",
|
||||
"dismiss": "Pomiń",
|
||||
"explore_rooms": "Przeglądaj pokoje",
|
||||
"pause": "Wstrzymaj",
|
||||
"play": "Odtwórz",
|
||||
"search": "Szukaj"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "Tożsamość %(displayName)s (<b>%(userId)s</b>) została zresetowana. <a>Dowiedz się więcej</a>",
|
||||
"withdraw_verification_action": "Wycofaj weryfikację"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Otwórz klawiaturę numeryczną"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "około dzień temu",
|
||||
"about_hour_ago": "około godziny temu",
|
||||
"about_minute_ago": "około minuty temu",
|
||||
"few_seconds_ago": "kilka sekund temu",
|
||||
"in_about_day": "około dnia od teraz",
|
||||
"in_about_hour": "około godziny od teraz",
|
||||
"in_about_minute": "około minuty od teraz",
|
||||
"in_few_seconds": "za kilka sekund",
|
||||
"in_n_days": "za %(num)s dni",
|
||||
"in_n_hours": "za %(num)s godzin",
|
||||
"in_n_minutes": "za %(num)s minut",
|
||||
"n_days_ago": "%(num)s dni temu",
|
||||
"n_hours_ago": "%(num)s godzin temu",
|
||||
"n_minutes_ago": "%(num)s minut temu"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Odtwarzacz audio",
|
||||
"error_downloading_audio": "Wystąpił błąd w trakcie pobierania audio",
|
||||
"unnamed_audio": "Audio bez nazwy"
|
||||
}
|
||||
}
|
||||
}
|
||||
42
packages/shared-components/src/i18n/strings/pt.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Barra de procura de áudio"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Apagar",
|
||||
"dismiss": "Descartar",
|
||||
"explore_rooms": "Explorar rooms",
|
||||
"pause": "Pausar",
|
||||
"play": "Reproduzir",
|
||||
"search": "Pesquisar"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "A identidade de %(displayName)s (<b>%(userId)s</b> ) foi alterada. <a> Saber mais</a>",
|
||||
"withdraw_verification_action": "Retirar verificação"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Abre o teclado de marcação"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "há cerca de um dia",
|
||||
"about_hour_ago": "há cerca de uma hora",
|
||||
"about_minute_ago": "há cerca de um minuto",
|
||||
"few_seconds_ago": "há alguns segundos atrás",
|
||||
"in_about_day": "daqui a um dia",
|
||||
"in_about_hour": "daqui a uma hora",
|
||||
"in_about_minute": "daqui a um minuto",
|
||||
"in_few_seconds": "daqui a alguns segundos",
|
||||
"in_n_days": "daqui a %(num)s dias",
|
||||
"in_n_hours": "daqui a %(num)s horas",
|
||||
"in_n_minutes": "daqui a %(num)s minutos",
|
||||
"n_days_ago": "%(num)s dias atrás",
|
||||
"n_hours_ago": "%(num)s horas atrás",
|
||||
"n_minutes_ago": "%(num)s minutos atrás"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Erro ao descarregar áudio",
|
||||
"unnamed_audio": "Áudio sem nome"
|
||||
}
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/pt_BR.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Barra de busca de áudio"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Excluir",
|
||||
"dismiss": "Dispensar",
|
||||
"explore_rooms": "Explorar salas",
|
||||
"pause": "Pausar",
|
||||
"play": "Reproduzir",
|
||||
"search": "Buscar"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "A identidade de %(displayName)s (<b>%(userId)s</b>) parece ter mudado. <a>Saiba mais</a>",
|
||||
"withdraw_verification_action": "Retirar verificação"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Abrir o teclado de discagem"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "há aproximadamente um dia",
|
||||
"about_hour_ago": "há aproximadamente uma hora",
|
||||
"about_minute_ago": "há aproximadamente um minuto",
|
||||
"few_seconds_ago": "há alguns segundos",
|
||||
"in_about_day": "dentro de aproximadamente um dia",
|
||||
"in_about_hour": "dentro de aproximadamente uma hora",
|
||||
"in_about_minute": "dentro de aproximadamente um minuto",
|
||||
"in_few_seconds": "dentro de alguns segundos",
|
||||
"in_n_days": "dentro de %(num)s dias",
|
||||
"in_n_hours": "dentro de %(num)s horas",
|
||||
"in_n_minutes": "dentro de %(num)s minutos",
|
||||
"n_days_ago": "há %(num)s dias",
|
||||
"n_hours_ago": "há %(num)s horas",
|
||||
"n_minutes_ago": "há %(num)s minutos"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Reprodutor de Áudio",
|
||||
"error_downloading_audio": "Erro ao baixar o áudio",
|
||||
"unnamed_audio": "Áudio sem nome"
|
||||
}
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/ru.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Панель поиска аудио"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Удалить",
|
||||
"dismiss": "Закрыть",
|
||||
"explore_rooms": "Обзор комнат",
|
||||
"pause": "Пауза",
|
||||
"play": "Воспроизведение",
|
||||
"search": "Поиск"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "Идентичность %(displayName)s (<b>%(userId)s</b>), похоже, изменилась. <a>Узнать больше</a>",
|
||||
"withdraw_verification_action": "Подтверждение верификации"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Открыть панель набора номера"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "около суток назад",
|
||||
"about_hour_ago": "около часа назад",
|
||||
"about_minute_ago": "около минуты назад",
|
||||
"few_seconds_ago": "несколько секунд назад",
|
||||
"in_about_day": "примерно через день",
|
||||
"in_about_hour": "примерно через час",
|
||||
"in_about_minute": "примерно через минуту",
|
||||
"in_few_seconds": "несколько секунд назад",
|
||||
"in_n_days": "%(num)s дней спустя",
|
||||
"in_n_hours": "%(num)s часов спустя",
|
||||
"in_n_minutes": "%(num)s минут спустя",
|
||||
"n_days_ago": "%(num)s дней назад",
|
||||
"n_hours_ago": "%(num)s часов назад",
|
||||
"n_minutes_ago": "%(num)s минут назад"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Аудиоплеер",
|
||||
"error_downloading_audio": "Ошибка загрузки аудио",
|
||||
"unnamed_audio": "Безымянное аудио"
|
||||
}
|
||||
}
|
||||
}
|
||||
48
packages/shared-components/src/i18n/strings/sk.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Panel vyhľadávania zvuku"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Vymazať",
|
||||
"dismiss": "Zamietnuť",
|
||||
"explore_rooms": "Preskúmať miestnosti",
|
||||
"pause": "Pozastaviť",
|
||||
"play": "Prehrať",
|
||||
"search": "Hľadať"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "Zdá sa, že identita (<b>%(userId)s</b>) používateľa %(displayName)s bola obnovená. <a>Zistiť viac </a>",
|
||||
"withdraw_verification_action": "Zrušiť overenie"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Otvoriť číselník"
|
||||
},
|
||||
"room": {
|
||||
"status_bar": {
|
||||
"history_visible": "Správy, ktoré odošlete, budú zdieľané s novými členmi pozvanými do tejto miestnosti. <a>Zistiť viac</a>"
|
||||
}
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "asi pred jedným dňom",
|
||||
"about_hour_ago": "približne pred hodinou",
|
||||
"about_minute_ago": "približne pred minútou",
|
||||
"few_seconds_ago": "pred pár sekundami",
|
||||
"in_about_day": "približne o deň",
|
||||
"in_about_hour": "približne o hodinu",
|
||||
"in_about_minute": "približne o minútu",
|
||||
"in_few_seconds": "o pár sekúnd",
|
||||
"in_n_days": "o %(num)s dní",
|
||||
"in_n_hours": "o %(num)s hodín",
|
||||
"in_n_minutes": "o %(num)s minút",
|
||||
"n_days_ago": "pred %(num)s dňami",
|
||||
"n_hours_ago": "pred %(num)s hodinami",
|
||||
"n_minutes_ago": "pred %(num)s minútami"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Prehrávač zvuku",
|
||||
"error_downloading_audio": "Chyba pri sťahovaní zvuku",
|
||||
"unnamed_audio": "Nepomenovaný zvukový záznam"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/sq.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "Fshije",
|
||||
"dismiss": "Mos e merr parasysh",
|
||||
"explore_rooms": "Eksploroni dhoma",
|
||||
"pause": "Ndalesë",
|
||||
"play": "Luaje",
|
||||
"search": "Kërkoni"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Hap butona numrash"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "rreth një ditë më parë",
|
||||
"about_hour_ago": "rreth një orë më parë",
|
||||
"about_minute_ago": "rreth një minutë më parë",
|
||||
"few_seconds_ago": "pak sekonda më parë",
|
||||
"in_about_day": "rreth një ditë nga tani",
|
||||
"in_about_hour": "rreth një orë nga tani",
|
||||
"in_about_minute": "rreth një minutë nga tani",
|
||||
"in_few_seconds": "pak sekonda nga tani",
|
||||
"in_n_days": "%(num)s ditë nga tani",
|
||||
"in_n_hours": "%(num)s orë nga tani",
|
||||
"in_n_minutes": "%(num)s minuta nga tani",
|
||||
"n_days_ago": "%(num)s ditë më parë",
|
||||
"n_hours_ago": "%(num)s orë më parë",
|
||||
"n_minutes_ago": "%(num)s minuta më parë"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Gabim në shkarkim audioje",
|
||||
"unnamed_audio": "Audio pa emër"
|
||||
}
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/sv.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Förloppsfält för ljud"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Radera",
|
||||
"dismiss": "Avvisa",
|
||||
"explore_rooms": "Utforska rum",
|
||||
"pause": "Pausa",
|
||||
"play": "Spela",
|
||||
"search": "Sök"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "%(displayName)ss (<b>%(userId)s</b> ) identitet verkar ha ändrats.<a> Läs mer</a>",
|
||||
"withdraw_verification_action": "Återkalla verifieringen"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Öppna knappsats"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "cirka en dag sedan",
|
||||
"about_hour_ago": "cirka en timme sedan",
|
||||
"about_minute_ago": "cirka en minut sedan",
|
||||
"few_seconds_ago": "några sekunder sedan",
|
||||
"in_about_day": "om cirka en dag",
|
||||
"in_about_hour": "om cirka en timme",
|
||||
"in_about_minute": "om cirka en minut",
|
||||
"in_few_seconds": "om några sekunder",
|
||||
"in_n_days": "om %(num)s dagar",
|
||||
"in_n_hours": "om %(num)s timmar",
|
||||
"in_n_minutes": "om %(num)s minuter",
|
||||
"n_days_ago": "%(num)s dagar sedan",
|
||||
"n_hours_ago": "%(num)s timmar sedan",
|
||||
"n_minutes_ago": "%(num)s minuter sedan"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Ljudspelare",
|
||||
"error_downloading_audio": "Fel vid nedladdning av ljud",
|
||||
"unnamed_audio": "Namnlöst ljud"
|
||||
}
|
||||
}
|
||||
}
|
||||
42
packages/shared-components/src/i18n/strings/tr.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Ses arama çubuğu"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Sil",
|
||||
"dismiss": "Kapat",
|
||||
"explore_rooms": "Odaları keşfet",
|
||||
"pause": "Durdur",
|
||||
"play": "Oynat",
|
||||
"search": "Ara"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "%(displayName)s'ın (<b>%(userId)s</b>) kimliği değişmiş gibi görünüyor. <a>Daha fazla bilgi </a>",
|
||||
"withdraw_verification_action": "Doğrulamayı iptal et"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Arama tuşlarını aç"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "yaklaşık bir gün önce",
|
||||
"about_hour_ago": "yaklaşık bir saat önce",
|
||||
"about_minute_ago": "yaklaşık bir dakika önce",
|
||||
"few_seconds_ago": "bir kaç saniye önce",
|
||||
"in_about_day": "şu andan itibaren yaklaşık bir gün",
|
||||
"in_about_hour": "şu andan itibaren yaklaşık bir saat",
|
||||
"in_about_minute": "şu andan itibaren yaklaşık bir dakika",
|
||||
"in_few_seconds": "şu andan itibaren bir kaç saniye",
|
||||
"in_n_days": "şu andan itibaren %(num)s gün",
|
||||
"in_n_hours": "şu andan itibaren %(num)s saat",
|
||||
"in_n_minutes": "şu andan itibaren %(num)s dakika",
|
||||
"n_days_ago": "%(num)s gün önce",
|
||||
"n_hours_ago": "%(num)s saat önce",
|
||||
"n_minutes_ago": "%(num)s dakika önce"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Ses dosyası indirilirken hata oluştu",
|
||||
"unnamed_audio": "İsimsiz ses"
|
||||
}
|
||||
}
|
||||
}
|
||||
43
packages/shared-components/src/i18n/strings/uk.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"a11y": {
|
||||
"seek_bar_label": "Панель гортання аудіо"
|
||||
},
|
||||
"action": {
|
||||
"delete": "Видалити",
|
||||
"dismiss": "Відхилити",
|
||||
"explore_rooms": "Каталог кімнат",
|
||||
"pause": "Призупинити",
|
||||
"play": "Відтворити",
|
||||
"search": "Пошук"
|
||||
},
|
||||
"encryption": {
|
||||
"pinned_identity_changed": "Ідентичність %(displayName)s (<b>%(userId)s</b>) скинуто. <a>Докладніше</a>",
|
||||
"withdraw_verification_action": "Відкликати верифікацію"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Відкрити номеронабирач"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "близько доби тому",
|
||||
"about_hour_ago": "близько години тому",
|
||||
"about_minute_ago": "близько хвилини тому",
|
||||
"few_seconds_ago": "Декілька секунд тому",
|
||||
"in_about_day": "приблизно через день",
|
||||
"in_about_hour": "приблизно через годину",
|
||||
"in_about_minute": "приблизно через хвилинку",
|
||||
"in_few_seconds": "декілька секунд тому",
|
||||
"in_n_days": "%(num)s днів по тому",
|
||||
"in_n_hours": "%(num)s годин по тому",
|
||||
"in_n_minutes": "%(num)s хвилин по тому",
|
||||
"n_days_ago": "%(num)s днів тому",
|
||||
"n_hours_ago": "%(num)s годин тому",
|
||||
"n_minutes_ago": "%(num)s хвилин тому"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"audio_player": "Звуковий програвач",
|
||||
"error_downloading_audio": "Помилка завантаження аудіо",
|
||||
"unnamed_audio": "Аудіо без назви"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/vi.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "Xoá",
|
||||
"dismiss": "Bỏ qua",
|
||||
"explore_rooms": "Khám phá các phòng",
|
||||
"pause": "Tạm dừng",
|
||||
"play": "Chạy",
|
||||
"search": "Tìm kiếm"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "Mở bàn phím quay số"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "khoảng một ngày trước",
|
||||
"about_hour_ago": "khoảng một giờ trước",
|
||||
"about_minute_ago": "khoảng một phút trước",
|
||||
"few_seconds_ago": "vài giây trước",
|
||||
"in_about_day": "khoảng một ngày kể từ bây giờ",
|
||||
"in_about_hour": "khoảng một giờ kể từ bây giờ",
|
||||
"in_about_minute": "khoảng một phút kể từ bây giờ",
|
||||
"in_few_seconds": "một vài giây kể từ bây giờ",
|
||||
"in_n_days": "%(num)s ngày kể từ bây giờ",
|
||||
"in_n_hours": "%(num)s giờ kể từ bây giờ",
|
||||
"in_n_minutes": "%(num)s phút kể từ bây giờ",
|
||||
"n_days_ago": "%(num)s ngày trước",
|
||||
"n_hours_ago": "%(num)s giờ trước",
|
||||
"n_minutes_ago": "%(num)s phút trước"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Lỗi khi tải xuống âm thanh",
|
||||
"unnamed_audio": "Âm thanh không tên"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/zh_Hans.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "删除",
|
||||
"dismiss": "忽略",
|
||||
"explore_rooms": "查找房间",
|
||||
"pause": "暂停",
|
||||
"play": "播放",
|
||||
"search": "搜索"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "打开拨号键盘"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "约一天前",
|
||||
"about_hour_ago": "约一小时前",
|
||||
"about_minute_ago": "约一分钟前",
|
||||
"few_seconds_ago": "数秒前",
|
||||
"in_about_day": "从现在开始约一天",
|
||||
"in_about_hour": "从现在开始约一小时",
|
||||
"in_about_minute": "从现在开始约一分钟",
|
||||
"in_few_seconds": "从现在开始数秒",
|
||||
"in_n_days": "从现在开始%(num)s天",
|
||||
"in_n_hours": "从现在开始%(num)s小时",
|
||||
"in_n_minutes": "从现在开始%(num)s分钟",
|
||||
"n_days_ago": "%(num)s天前",
|
||||
"n_hours_ago": "%(num)s小时前",
|
||||
"n_minutes_ago": "%(num)s分钟前"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "下载音频时出错",
|
||||
"unnamed_audio": "未命名的音频"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/shared-components/src/i18n/strings/zh_Hant.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"action": {
|
||||
"delete": "刪除",
|
||||
"dismiss": "關閉",
|
||||
"explore_rooms": "探索聊天室",
|
||||
"pause": "暫停",
|
||||
"play": "播放",
|
||||
"search": "搜尋"
|
||||
},
|
||||
"left_panel": {
|
||||
"open_dial_pad": "開啟撥號鍵盤"
|
||||
},
|
||||
"time": {
|
||||
"about_day_ago": "大約一天前",
|
||||
"about_hour_ago": "大約一小時前",
|
||||
"about_minute_ago": "大約一分鐘前",
|
||||
"few_seconds_ago": "數秒前",
|
||||
"in_about_day": "從現在開始大約一天",
|
||||
"in_about_hour": "從現在開始大約一小時",
|
||||
"in_about_minute": "從現在開始大約一分鐘",
|
||||
"in_few_seconds": "從現在開始數秒鐘",
|
||||
"in_n_days": "從現在開始 %(num)s 天",
|
||||
"in_n_hours": "從現在開始 %(num)s 小時",
|
||||
"in_n_minutes": "從現在開始 %(num)s 分鐘",
|
||||
"n_days_ago": "%(num)s 天前",
|
||||
"n_hours_ago": "%(num)s 小時前",
|
||||
"n_minutes_ago": "%(num)s 分鐘前"
|
||||
},
|
||||
"timeline": {
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "下載音訊時發生錯誤",
|
||||
"unnamed_audio": "未命名的音訊"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,3 @@ export * from "./utils/I18nApi";
|
||||
export * from "./viewmodel";
|
||||
export * from "./useMockedViewModel";
|
||||
export * from "./useViewModel";
|
||||
|
||||
// i18n (we must export this directly in order to not confuse the type bundler, it seems,
|
||||
// otherwise it will leave it as a relative import rather than bundling it)
|
||||
export type * from "./i18nKeys.d.ts";
|
||||
|
||||
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
|
||||
import { setLanguage } from "../../src/utils/i18n";
|
||||
import en from "../../../../src/i18n/strings/en_EN.json";
|
||||
import en from "../i18n/strings/en_EN.json";
|
||||
|
||||
export function setupLanguageMock(): void {
|
||||
fetchMock
|
||||
|
||||
@ -5,14 +5,13 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type TranslationKey } from "../i18nKeys";
|
||||
import { I18nApi } from "./I18nApi";
|
||||
|
||||
describe("I18nApi", () => {
|
||||
it("can register a translation and use it", () => {
|
||||
const i18n = new I18nApi();
|
||||
i18n.register({
|
||||
"hello.world": {
|
||||
["hello.world" as TranslationKey]: {
|
||||
en: "Hello, World!",
|
||||
},
|
||||
});
|
||||
|
||||
@ -9,7 +9,6 @@ import { type I18nApi as II18nApi, type Variables, type Translations } from "@el
|
||||
|
||||
import { humanizeTime } from "./humanize";
|
||||
import { _t, getLocale, registerTranslations } from "./i18n";
|
||||
import { type TranslationKey } from "../i18nKeys";
|
||||
|
||||
export class I18nApi implements II18nApi {
|
||||
/**
|
||||
@ -24,10 +23,11 @@ export class I18nApi implements II18nApi {
|
||||
*/
|
||||
public register(translations: Partial<Translations>): void {
|
||||
const langs: Record<string, Record<string, string>> = {};
|
||||
|
||||
for (const key in translations) {
|
||||
for (const lang in translations[key]) {
|
||||
for (const lang in translations[key as keyof Translations]) {
|
||||
langs[lang] = langs[lang] || {};
|
||||
langs[lang][key] = translations[key][lang];
|
||||
langs[lang][key] = translations[key as keyof Translations]![lang];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -25,13 +25,11 @@ import React from "react";
|
||||
import { KEY_SEPARATOR } from "matrix-web-i18n";
|
||||
import counterpart from "counterpart";
|
||||
|
||||
import type { TranslationKey } from "../index";
|
||||
|
||||
// @ts-ignore - $webapp is a webpack resolve alias pointing to the output directory, see webpack config
|
||||
import webpackLangJsonUrl from "$webapp/i18n/languages.json";
|
||||
|
||||
export { KEY_SEPARATOR, normalizeLanguageKey, getNormalizedLanguageKeys } from "matrix-web-i18n";
|
||||
|
||||
// Path where we load language files from (the index plus translations for each language)
|
||||
// The filename is appended to this, so a relative path here will result in a fetch for
|
||||
// a relative URL.
|
||||
const i18nFolder = "i18n/";
|
||||
|
||||
// Control whether to also return original, untranslated strings
|
||||
@ -421,13 +419,7 @@ async function getLanguage(langPath: string): Promise<ICounterpartTranslation> {
|
||||
}
|
||||
|
||||
export async function getLangsJson(): Promise<Languages> {
|
||||
let url: string;
|
||||
if (typeof webpackLangJsonUrl === "string") {
|
||||
// in Jest this 'url' isn't a URL, so just fall through
|
||||
url = webpackLangJsonUrl;
|
||||
} else {
|
||||
url = i18nFolder + "languages.json";
|
||||
}
|
||||
const url = i18nFolder + "languages.json";
|
||||
|
||||
const res = await fetch(url, { method: "GET" });
|
||||
|
||||
|
||||
@ -647,6 +647,10 @@ test.describe("Element Call", () => {
|
||||
|
||||
// For this test we want to display the chat area alongside the widget
|
||||
await page.getByRole("button", { name: "Chat" }).click();
|
||||
// Wait for the right panel to show the timeline.
|
||||
await expect(
|
||||
page.locator(".mx_RightPanel .mx_TimelineCard").getByText("Alice created and configured the room."),
|
||||
).toBeVisible();
|
||||
|
||||
await page
|
||||
.locator('iframe[title="Element Call"]')
|
||||
@ -654,7 +658,12 @@ test.describe("Element Call", () => {
|
||||
.getByRole("button", { name: "Send Room Message" })
|
||||
.click();
|
||||
|
||||
const messageSent = await page.getByText("I sent this once!!").count();
|
||||
const timelineLocator = page.locator(".mx_RightPanel .mx_TimelineCard");
|
||||
// First wait for the message to appear in the timeline then
|
||||
// check the count. This improves test stability as we know the message has been sent.
|
||||
await expect(timelineLocator.getByText("I sent this once!!")).toBeVisible();
|
||||
|
||||
const messageSent = await timelineLocator.getByText("I sent this once!!").count();
|
||||
|
||||
expect(messageSent).toBe(1);
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 27 KiB |
@ -10,7 +10,7 @@ import {
|
||||
type StartedPostgreSqlContainer,
|
||||
} from "@element-hq/element-web-playwright-common/lib/testcontainers";
|
||||
|
||||
const TAG = "main@sha256:2c5966c2ff06458ac5cbae959f12e19d30e3ebb63c641d31ec1ae08abccb9c6d";
|
||||
const TAG = "main@sha256:48456909ce44ca9dae1a6c1abe1a2000cc2a021743d66d0b29f54077b38a09cf";
|
||||
|
||||
/**
|
||||
* MatrixAuthenticationServiceContainer which freezes the docker digest to
|
||||
|
||||
@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import { SynapseContainer as BaseSynapseContainer } from "@element-hq/element-web-playwright-common/lib/testcontainers";
|
||||
|
||||
const TAG = "develop@sha256:7c3dce1d2b44fdc4b1494c5b8f4792018733ad323f823b88aac30c883d09fb35";
|
||||
const TAG = "develop@sha256:106108a210f7194e0615a4d5df3502d34ee8962359b425f78d6d9d78d6b9599a";
|
||||
|
||||
/**
|
||||
* SynapseContainer which freezes the docker digest to stabilise tests,
|
||||
|
||||
@ -31,17 +31,25 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
.mx_EmojiPicker_anchor {
|
||||
border: none;
|
||||
padding: 8px 8px 6px;
|
||||
padding: var(--cpd-space-1x) 0;
|
||||
font-size: $font-20px;
|
||||
line-height: 1;
|
||||
border-bottom: 2px solid transparent;
|
||||
background-color: transparent;
|
||||
border-radius: 4px 4px 0 0;
|
||||
|
||||
width: 36px;
|
||||
height: 38px;
|
||||
height: 36px;
|
||||
|
||||
color: $primary-content;
|
||||
display: inline-block;
|
||||
|
||||
&:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
&:disabled {
|
||||
filter: opacity(0.3);
|
||||
}
|
||||
|
||||
&:not(:disabled):hover {
|
||||
background-color: $focus-bg-color;
|
||||
@ -49,48 +57,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
}
|
||||
}
|
||||
|
||||
.mx_EmojiPicker_anchor::before {
|
||||
background-color: $primary-content;
|
||||
content: "";
|
||||
display: inline-block;
|
||||
mask-size: 100%;
|
||||
mask-repeat: no-repeat;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.mx_EmojiPicker_anchor:disabled::before {
|
||||
background-color: $focus-bg-color;
|
||||
}
|
||||
|
||||
.mx_EmojiPicker_anchor_activity::before {
|
||||
mask-image: url("$(res)/img/emojipicker/activity.svg");
|
||||
}
|
||||
.mx_EmojiPicker_anchor_flags::before {
|
||||
mask-image: url("$(res)/img/emojipicker/flags.svg");
|
||||
}
|
||||
.mx_EmojiPicker_anchor_foods::before {
|
||||
mask-image: url("$(res)/img/emojipicker/foods.svg");
|
||||
}
|
||||
.mx_EmojiPicker_anchor_nature::before {
|
||||
mask-image: url("$(res)/img/emojipicker/nature.svg");
|
||||
}
|
||||
.mx_EmojiPicker_anchor_objects::before {
|
||||
mask-image: url("$(res)/img/emojipicker/objects.svg");
|
||||
}
|
||||
.mx_EmojiPicker_anchor_people::before {
|
||||
mask-image: url("$(res)/img/emojipicker/people.svg");
|
||||
}
|
||||
.mx_EmojiPicker_anchor_places::before {
|
||||
mask-image: url("$(res)/img/emojipicker/places.svg");
|
||||
}
|
||||
.mx_EmojiPicker_anchor_recent::before {
|
||||
mask-image: url("$(res)/img/emojipicker/recent.svg");
|
||||
}
|
||||
.mx_EmojiPicker_anchor_symbols::before {
|
||||
mask-image: url("$(res)/img/emojipicker/symbols.svg");
|
||||
}
|
||||
|
||||
.mx_EmojiPicker_anchor_visible {
|
||||
border-bottom: 2px solid $accent;
|
||||
}
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
Copyright (c) 2016, Missive
|
||||
From https://github.com/missive/emoji-mart/blob/master/src/svgs/index.js
|
||||
Licensed under BSD-3-Clause: https://github.com/missive/emoji-mart/blob/master/LICENSE
|
||||
-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
>
|
||||
<path d="M12 0C5.373 0 0 5.372 0 12c0 6.627 5.373 12 12 12 6.628 0 12-5.373 12-12 0-6.628-5.372-12-12-12m9.949 11H17.05c.224-2.527 1.232-4.773 1.968-6.113A9.966 9.966 0 0 1 21.949 11M13 11V2.051a9.945 9.945 0 0 1 4.432 1.564c-.858 1.491-2.156 4.22-2.392 7.385H13zm-2 0H8.961c-.238-3.165-1.536-5.894-2.393-7.385A9.95 9.95 0 0 1 11 2.051V11zm0 2v8.949a9.937 9.937 0 0 1-4.432-1.564c.857-1.492 2.155-4.221 2.393-7.385H11zm4.04 0c.236 3.164 1.534 5.893 2.392 7.385A9.92 9.92 0 0 1 13 21.949V13h2.04zM4.982 4.887C5.718 6.227 6.726 8.473 6.951 11h-4.9a9.977 9.977 0 0 1 2.931-6.113M2.051 13h4.9c-.226 2.527-1.233 4.771-1.969 6.113A9.972 9.972 0 0 1 2.051 13m16.967 6.113c-.735-1.342-1.744-3.586-1.968-6.113h4.899a9.961 9.961 0 0 1-2.931 6.113" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
Copyright (c) 2016, Missive
|
||||
From https://github.com/missive/emoji-mart/blob/master/src/svgs/index.js
|
||||
Licensed under BSD-3-Clause: https://github.com/missive/emoji-mart/blob/master/LICENSE
|
||||
-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
>
|
||||
<path d="M0 0l6.084 24H8L1.916 0zM21 5h-4l-1-4H4l3 12h3l1 4h13L21 5zM6.563 3h7.875l2 8H8.563l-2-8zm8.832 10l-2.856 1.904L12.063 13h3.332zM19 13l-1.5-6h1.938l2 8H16l3-2z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 537 B |
@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
Copyright (c) 2016, Missive
|
||||
From https://github.com/missive/emoji-mart/blob/master/src/svgs/index.js
|
||||
Licensed under BSD-3-Clause: https://github.com/missive/emoji-mart/blob/master/LICENSE
|
||||
-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
>
|
||||
<path d="M17 4.978c-1.838 0-2.876.396-3.68.934.513-1.172 1.768-2.934 4.68-2.934a1 1 0 0 0 0-2c-2.921 0-4.629 1.365-5.547 2.512-.064.078-.119.162-.18.244C11.73 1.838 10.798.023 9.207.023 8.579.022 7.85.306 7 .978 5.027 2.54 5.329 3.902 6.492 4.999 3.609 5.222 0 7.352 0 12.969c0 4.582 4.961 11.009 9 11.009 1.975 0 2.371-.486 3-1 .629.514 1.025 1 3 1 4.039 0 9-6.418 9-11 0-5.953-4.055-8-7-8M8.242 2.546c.641-.508.943-.523.965-.523.426.169.975 1.405 1.357 3.055-1.527-.629-2.741-1.352-2.98-1.846.059-.112.241-.356.658-.686M15 21.978c-1.08 0-1.21-.109-1.559-.402l-.176-.146c-.367-.302-.816-.452-1.266-.452s-.898.15-1.266.452l-.176.146c-.347.292-.477.402-1.557.402-2.813 0-7-5.389-7-9.009 0-5.823 4.488-5.991 5-5.991 1.939 0 2.484.471 3.387 1.251l.323.276a1.995 1.995 0 0 0 2.58 0l.323-.276c.902-.78 1.447-1.251 3.387-1.251.512 0 5 .168 5 6 0 3.617-4.187 9-7 9" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
Copyright (c) 2016, Missive
|
||||
From https://github.com/missive/emoji-mart/blob/master/src/svgs/index.js
|
||||
Licensed under BSD-3-Clause: https://github.com/missive/emoji-mart/blob/master/LICENSE
|
||||
-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
>
|
||||
<path d="M15.5 8a1.5 1.5 0 1 0 .001 3.001A1.5 1.5 0 0 0 15.5 8M8.5 8a1.5 1.5 0 1 0 .001 3.001A1.5 1.5 0 0 0 8.5 8" />
|
||||
<path d="M18.933 0h-.027c-.97 0-2.138.787-3.018 1.497-1.274-.374-2.612-.51-3.887-.51-1.285 0-2.616.133-3.874.517C7.245.79 6.069 0 5.093 0h-.027C3.352 0 .07 2.67.002 7.026c-.039 2.479.276 4.238 1.04 5.013.254.258.882.677 1.295.882.191 3.177.922 5.238 2.536 6.38.897.637 2.187.949 3.2 1.102C8.04 20.6 8 20.795 8 21c0 1.773 2.35 3 4 3 1.648 0 4-1.227 4-3 0-.201-.038-.393-.072-.586 2.573-.385 5.435-1.877 5.925-7.587.396-.22.887-.568 1.104-.788.763-.774 1.079-2.534 1.04-5.013C23.929 2.67 20.646 0 18.933 0M3.223 9.135c-.237.281-.837 1.155-.884 1.238-.15-.41-.368-1.349-.337-3.291.051-3.281 2.478-4.972 3.091-5.031.256.015.731.27 1.265.646-1.11 1.171-2.275 2.915-2.352 5.125-.133.546-.398.858-.783 1.313M12 22c-.901 0-1.954-.693-2-1 0-.654.475-1.236 1-1.602V20a1 1 0 1 0 2 0v-.602c.524.365 1 .947 1 1.602-.046.307-1.099 1-2 1m3-3.48v.02a4.752 4.752 0 0 0-1.262-1.02c1.092-.516 2.239-1.334 2.239-2.217 0-1.842-1.781-2.195-3.977-2.195-2.196 0-3.978.354-3.978 2.195 0 .883 1.148 1.701 2.238 2.217A4.8 4.8 0 0 0 9 18.539v-.025c-1-.076-2.182-.281-2.973-.842-1.301-.92-1.838-3.045-1.853-6.478l.023-.041c.496-.826 1.49-1.45 1.804-3.102 0-2.047 1.357-3.631 2.362-4.522C9.37 3.178 10.555 3 11.948 3c1.447 0 2.685.192 3.733.57 1 .9 2.316 2.465 2.316 4.48.313 1.651 1.307 2.275 1.803 3.102.035.058.068.117.102.178-.059 5.967-1.949 7.01-4.902 7.19m6.628-8.202c-.037-.065-.074-.13-.113-.195a7.587 7.587 0 0 0-.739-.987c-.385-.455-.648-.768-.782-1.313-.076-2.209-1.241-3.954-2.353-5.124.531-.376 1.004-.63 1.261-.647.636.071 3.044 1.764 3.096 5.031.027 1.81-.347 3.218-.37 3.235" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
Copyright (c) 2016, Missive
|
||||
From https://github.com/missive/emoji-mart/blob/master/src/svgs/index.js
|
||||
Licensed under BSD-3-Clause: https://github.com/missive/emoji-mart/blob/master/LICENSE
|
||||
-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
>
|
||||
<path d="M12 0a9 9 0 0 0-5 16.482V21s2.035 3 5 3 5-3 5-3v-4.518A9 9 0 0 0 12 0zm0 2c3.86 0 7 3.141 7 7s-3.14 7-7 7-7-3.141-7-7 3.14-7 7-7zM9 17.477c.94.332 1.946.523 3 .523s2.06-.19 3-.523v.834c-.91.436-1.925.689-3 .689a6.924 6.924 0 0 1-3-.69v-.833zm.236 3.07A8.854 8.854 0 0 0 12 21c.965 0 1.888-.167 2.758-.451C14.155 21.173 13.153 22 12 22c-1.102 0-2.117-.789-2.764-1.453z" />
|
||||
<path d="M14.745 12.449h-.004c-.852-.024-1.188-.858-1.577-1.824-.421-1.061-.703-1.561-1.182-1.566h-.009c-.481 0-.783.497-1.235 1.537-.436.982-.801 1.811-1.636 1.791l-.276-.043c-.565-.171-.853-.691-1.284-1.794-.125-.313-.202-.632-.27-.913-.051-.213-.127-.53-.195-.634C7.067 9.004 7.039 9 6.99 9A1 1 0 0 1 7 7h.01c1.662.017 2.015 1.373 2.198 2.134.486-.981 1.304-2.058 2.797-2.075 1.531.018 2.28 1.153 2.731 2.141l.002-.008C14.944 8.424 15.327 7 16.979 7h.032A1 1 0 1 1 17 9h-.011c-.149.076-.256.474-.319.709a6.484 6.484 0 0 1-.311.951c-.429.973-.79 1.789-1.614 1.789" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
Copyright (c) 2016, Missive
|
||||
From https://github.com/missive/emoji-mart/blob/master/src/svgs/index.js
|
||||
Licensed under BSD-3-Clause: https://github.com/missive/emoji-mart/blob/master/LICENSE
|
||||
-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
>
|
||||
<path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0m0 22C6.486 22 2 17.514 2 12S6.486 2 12 2s10 4.486 10 10-4.486 10-10 10" />
|
||||
<path d="M8 7a2 2 0 1 0-.001 3.999A2 2 0 0 0 8 7M16 7a2 2 0 1 0-.001 3.999A2 2 0 0 0 16 7M15.232 15c-.693 1.195-1.87 2-3.349 2-1.477 0-2.655-.805-3.347-2H15m3-2H6a6 6 0 1 0 12 0" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 705 B |
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
Copyright (c) 2016, Missive
|
||||
From https://github.com/missive/emoji-mart/blob/master/src/svgs/index.js
|
||||
Licensed under BSD-3-Clause: https://github.com/missive/emoji-mart/blob/master/LICENSE
|
||||
-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
>
|
||||
<path d="M6.5 12C5.122 12 4 13.121 4 14.5S5.122 17 6.5 17 9 15.879 9 14.5 7.878 12 6.5 12m0 3c-.275 0-.5-.225-.5-.5s.225-.5.5-.5.5.225.5.5-.225.5-.5.5M17.5 12c-1.378 0-2.5 1.121-2.5 2.5s1.122 2.5 2.5 2.5 2.5-1.121 2.5-2.5-1.122-2.5-2.5-2.5m0 3c-.275 0-.5-.225-.5-.5s.225-.5.5-.5.5.225.5.5-.225.5-.5.5" />
|
||||
<path d="M22.482 9.494l-1.039-.346L21.4 9h.6c.552 0 1-.439 1-.992 0-.006-.003-.008-.003-.008H23c0-1-.889-2-1.984-2h-.642l-.731-1.717C19.262 3.012 18.091 2 16.764 2H7.236C5.909 2 4.738 3.012 4.357 4.283L3.626 6h-.642C1.889 6 1 7 1 8h.003S1 8.002 1 8.008C1 8.561 1.448 9 2 9h.6l-.043.148-1.039.346a2.001 2.001 0 0 0-1.359 2.097l.751 7.508a1 1 0 0 0 .994.901H3v1c0 1.103.896 2 2 2h2c1.104 0 2-.897 2-2v-1h6v1c0 1.103.896 2 2 2h2c1.104 0 2-.897 2-2v-1h1.096a.999.999 0 0 0 .994-.901l.751-7.508a2.001 2.001 0 0 0-1.359-2.097M6.273 4.857C6.402 4.43 6.788 4 7.236 4h9.527c.448 0 .834.43.963.857L19.313 9H4.688l1.585-4.143zM7 21H5v-1h2v1zm12 0h-2v-1h2v1zm2.189-3H2.811l-.662-6.607L3 11h18l.852.393L21.189 18z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
Copyright (c) 2016, Missive
|
||||
From https://github.com/missive/emoji-mart/blob/master/src/svgs/index.js
|
||||
Licensed under BSD-3-Clause: https://github.com/missive/emoji-mart/blob/master/LICENSE
|
||||
-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
>
|
||||
<path d="M13 4h-2l-.001 7H9v2h2v2h2v-2h4v-2h-4z" />
|
||||
<path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0m0 22C6.486 22 2 17.514 2 12S6.486 2 12 2s10 4.486 10 10-4.486 10-10 10" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 575 B |
@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--
|
||||
Copyright (c) 2016, Missive
|
||||
From https://github.com/missive/emoji-mart/blob/master/src/svgs/index.js
|
||||
Licensed under BSD-3-Clause: https://github.com/missive/emoji-mart/blob/master/LICENSE
|
||||
-->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
>
|
||||
<path d="M0 0h11v2H0zM4 11h3V6h4V4H0v2h4zM15.5 17c1.381 0 2.5-1.116 2.5-2.493s-1.119-2.493-2.5-2.493S13 13.13 13 14.507 14.119 17 15.5 17m0-2.986c.276 0 .5.222.5.493 0 .272-.224.493-.5.493s-.5-.221-.5-.493.224-.493.5-.493M21.5 19.014c-1.381 0-2.5 1.116-2.5 2.493S20.119 24 21.5 24s2.5-1.116 2.5-2.493-1.119-2.493-2.5-2.493m0 2.986a.497.497 0 0 1-.5-.493c0-.271.224-.493.5-.493s.5.222.5.493a.497.497 0 0 1-.5.493M22 13l-9 9 1.513 1.5 8.99-9.009zM17 11c2.209 0 4-1.119 4-2.5V2s.985-.161 1.498.949C23.01 4.055 23 6 23 6s1-1.119 1-3.135C24-.02 21 0 21 0h-2v6.347A5.853 5.853 0 0 0 17 6c-2.209 0-4 1.119-4 2.5s1.791 2.5 4 2.5M10.297 20.482l-1.475-1.585a47.54 47.54 0 0 1-1.442 1.129c-.307-.288-.989-1.016-2.045-2.183.902-.836 1.479-1.466 1.729-1.892s.376-.871.376-1.336c0-.592-.273-1.178-.818-1.759-.546-.581-1.329-.871-2.349-.871-1.008 0-1.79.293-2.344.879-.556.587-.832 1.181-.832 1.784 0 .813.419 1.748 1.256 2.805-.847.614-1.444 1.208-1.794 1.784a3.465 3.465 0 0 0-.523 1.833c0 .857.308 1.56.924 2.107.616.549 1.423.823 2.42.823 1.173 0 2.444-.379 3.813-1.137L8.235 24h2.819l-2.09-2.383 1.333-1.135zm-6.736-6.389a1.02 1.02 0 0 1 .73-.286c.31 0 .559.085.747.254a.849.849 0 0 1 .283.659c0 .518-.419 1.112-1.257 1.784-.536-.651-.805-1.231-.805-1.742a.901.901 0 0 1 .302-.669M3.74 22c-.427 0-.778-.116-1.057-.349-.279-.232-.418-.487-.418-.766 0-.594.509-1.288 1.527-2.083.968 1.134 1.717 1.946 2.248 2.438-.921.507-1.686.76-2.3.76" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
@ -9,8 +9,10 @@ import _ from "lodash";
|
||||
import webpack from "webpack";
|
||||
import type { Translations } from "matrix-web-i18n";
|
||||
|
||||
const I18N_BASE_PATH = "src/i18n/strings/";
|
||||
const INCLUDE_LANGS = [...new Set([...fs.readdirSync(I18N_BASE_PATH)])]
|
||||
const EW_I18N_BASE_PATH = "src/i18n/strings/";
|
||||
const SC_I18N_BASE_PATH = "packages/shared-components/src/i18n/strings/";
|
||||
|
||||
const INCLUDE_LANGS = [...new Set([...fs.readdirSync(EW_I18N_BASE_PATH)])]
|
||||
.filter((fn) => fn.endsWith(".json"))
|
||||
.map((f) => f.slice(0, -5));
|
||||
|
||||
@ -41,11 +43,17 @@ const logWatch = (path: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
function prepareLangFile(lang: string, dest: string): [filename: string, json: string] {
|
||||
const path = I18N_BASE_PATH + lang + ".json";
|
||||
/*
|
||||
* Make a JSON language file for the given language by merging all translations
|
||||
* into a single file (ie. element-web and shared-components).
|
||||
* Returns the filename (including hash) and JSON content.
|
||||
*/
|
||||
function prepareLangFile(lang: string): [filename: string, json: string] {
|
||||
const ewTranslationsPath = EW_I18N_BASE_PATH + lang + ".json";
|
||||
const scTranslationsPath = SC_I18N_BASE_PATH + lang + ".json";
|
||||
|
||||
let translations: Translations = {};
|
||||
[path].forEach(function (f) {
|
||||
[ewTranslationsPath, scTranslationsPath].forEach(function (f) {
|
||||
if (fs.existsSync(f)) {
|
||||
try {
|
||||
translations = _.merge(translations, JSON.parse(fs.readFileSync(f).toString()));
|
||||
@ -99,7 +107,8 @@ function genLangList(langFileMap: Record<string, string>): void {
|
||||
* and regenerating languages.json with the new filename
|
||||
*/
|
||||
function watchLanguage(lang: string, dest: string, langFileMap: Record<string, string>): void {
|
||||
const path = I18N_BASE_PATH + lang + ".json";
|
||||
const ewTranslationsPath = EW_I18N_BASE_PATH + lang + ".json";
|
||||
const scTranslationsPath = SC_I18N_BASE_PATH + lang + ".json";
|
||||
|
||||
// XXX: Use a debounce because for some reason if we read the language
|
||||
// file immediately after the FS event is received, the file contents
|
||||
@ -110,14 +119,14 @@ function watchLanguage(lang: string, dest: string, langFileMap: Record<string, s
|
||||
clearTimeout(makeLangDebouncer);
|
||||
}
|
||||
makeLangDebouncer = setTimeout(() => {
|
||||
const [filename, json] = prepareLangFile(lang, dest);
|
||||
const [filename, json] = prepareLangFile(lang);
|
||||
genLangFile(dest, filename, json);
|
||||
langFileMap[lang] = filename;
|
||||
genLangList(langFileMap);
|
||||
}, 500);
|
||||
};
|
||||
|
||||
[path].forEach(function (f) {
|
||||
[ewTranslationsPath, scTranslationsPath].forEach(function (f) {
|
||||
chokidar
|
||||
.watch(f, { ignoreInitial: true })
|
||||
.on("ready", () => {
|
||||
@ -132,7 +141,7 @@ function watchLanguage(lang: string, dest: string, langFileMap: Record<string, s
|
||||
// language resources
|
||||
const I18N_DEST = "webapp/i18n/";
|
||||
const I18N_FILENAME_MAP = INCLUDE_LANGS.reduce<Record<string, string>>((m, l) => {
|
||||
const [filename, json] = prepareLangFile(l, I18N_DEST);
|
||||
const [filename, json] = prepareLangFile(l);
|
||||
if (!watch) {
|
||||
genLangFile(I18N_DEST, filename, json);
|
||||
}
|
||||
|
||||
14
src/@types/i18n.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
Copyright 2025 Element Creations 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 { type TranslationKey as _TranslationKey } from "matrix-web-i18n";
|
||||
|
||||
import type Translations from "../i18n/strings/en_EN.json";
|
||||
|
||||
declare global {
|
||||
type TranslationKey = _TranslationKey<typeof Translations>;
|
||||
}
|
||||
@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
// Import i18n.tsx instead of languageHandler to avoid circular deps
|
||||
import { _td, type TranslationKey } from "@element-hq/web-shared-components";
|
||||
import { _td } from "@element-hq/web-shared-components";
|
||||
|
||||
import { IS_MAC, IS_ELECTRON, Key } from "../Keyboard";
|
||||
import { type IBaseSetting } from "../settings/Settings";
|
||||
|
||||
@ -12,7 +12,7 @@ import sanitizeHtml from "sanitize-html";
|
||||
import classnames from "classnames";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { _t, type TranslationKey } from "../../languageHandler";
|
||||
import { _t } from "../../languageHandler";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
|
||||
@ -11,7 +11,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { type JSX } from "react";
|
||||
import classNames from "classnames";
|
||||
|
||||
import { _t, type TranslationKey } from "../../languageHandler";
|
||||
import { _t } from "../../languageHandler";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
import { PosthogScreenTracker, type ScreenName } from "../../PosthogTrackers";
|
||||
import { type NonEmptyArray } from "../../@types/common";
|
||||
|
||||
@ -76,6 +76,13 @@ export interface IListViewProps<Item, Context> extends Omit<
|
||||
onKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility type for the prop scrollIntoViewOnChange allowing it to be memoised by a caller without repeating types
|
||||
*/
|
||||
export type ScrollIntoViewOnChange<Item, Context = any> = NonNullable<
|
||||
VirtuosoProps<Item, ListContext<Context>>["scrollIntoViewOnChange"]
|
||||
>;
|
||||
|
||||
/**
|
||||
* A generic virtualized list component built on top of react-virtuoso.
|
||||
* Provides keyboard navigation and virtualized rendering for performance with large lists.
|
||||
|
||||
@ -15,7 +15,7 @@ import { Action } from "../../../../dispatcher/actions";
|
||||
import { asyncSome } from "../../../../utils/arrays";
|
||||
import { getUserDeviceIds } from "../../../../utils/crypto/deviceInfo";
|
||||
import { type RoomMember } from "../../../../models/rooms/RoomMember";
|
||||
import { _t, _td, type TranslationKey } from "../../../../languageHandler";
|
||||
import { _t, _td } from "../../../../languageHandler";
|
||||
import { E2EStatus } from "../../../../utils/ShieldUtils";
|
||||
|
||||
interface MemberTileViewModelProps {
|
||||
|
||||
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
|
||||
import { FilterKey } from "../../../stores/room-list-v3/skip-list/filters";
|
||||
import { _t, _td, type TranslationKey } from "../../../languageHandler";
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
import RoomListStoreV3, {
|
||||
LISTS_LOADED_EVENT,
|
||||
LISTS_UPDATE_EVENT,
|
||||
|
||||
@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { type ComponentProps, PureComponent, type Ref } from "react";
|
||||
|
||||
import Field, { type IInputProps } from "../elements/Field";
|
||||
import { _t, _td, type TranslationKey } from "../../../languageHandler";
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
import withValidation, { type IFieldState, type IValidationResult } from "../elements/Validation";
|
||||
import * as Email from "../../../email";
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import React, { type ComponentProps, PureComponent, type Ref } from "react";
|
||||
|
||||
import Field, { type IInputProps } from "../elements/Field";
|
||||
import withValidation, { type IFieldState, type IValidationResult } from "../elements/Validation";
|
||||
import { _t, _td, type TranslationKey } from "../../../languageHandler";
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
|
||||
interface IProps extends Omit<IInputProps, "onValidate" | "label" | "element"> {
|
||||
id?: string;
|
||||
|
||||
@ -12,7 +12,7 @@ import classNames from "classnames";
|
||||
import type { ZxcvbnResult } from "@zxcvbn-ts/core";
|
||||
import SdkConfig from "../../../SdkConfig";
|
||||
import withValidation, { type IFieldState, type IValidationResult } from "../elements/Validation";
|
||||
import { _t, _td, type TranslationKey } from "../../../languageHandler";
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
import Field, { type IInputProps } from "../elements/Field";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import React, { useEffect, useState } from "react";
|
||||
import MediaDeviceHandler, { MediaDeviceKindEnum } from "../../../MediaDeviceHandler";
|
||||
import IconizedContextMenu, { IconizedContextMenuOptionList, IconizedContextMenuRadio } from "./IconizedContextMenu";
|
||||
import { type IProps as IContextMenuProps } from "../../structures/ContextMenu";
|
||||
import { _t, _td, type TranslationKey } from "../../../languageHandler";
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
|
||||
const SECTION_NAMES: Record<MediaDeviceKindEnum, TranslationKey> = {
|
||||
[MediaDeviceKindEnum.AudioInput]: _td("voip|input_devices"),
|
||||
|
||||
@ -14,7 +14,7 @@ import { sleep } from "matrix-js-sdk/src/utils";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { ErrorIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { _t, _td, type TranslationKey } from "../../../languageHandler";
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import Dropdown from "../elements/Dropdown";
|
||||
import SearchBox from "../../structures/SearchBox";
|
||||
|
||||
@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { type JSX, useState } from "react";
|
||||
import { Form } from "@vector-im/compound-web";
|
||||
|
||||
import { _t, _td, type TranslationKey } from "../../../languageHandler";
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import { TimelineEventEditor } from "./devtools/Event";
|
||||
|
||||
@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { type ChangeEvent, createRef } from "react";
|
||||
|
||||
import Field from "../elements/Field";
|
||||
import { _t, _td, type TranslationKey } from "../../../languageHandler";
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
import { type IFieldState, type IValidationResult } from "../elements/Validation";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import DialogButtons from "../elements/DialogButtons";
|
||||
|
||||
@ -14,7 +14,7 @@ import BaseTool, { DevtoolsContext, type IDevtoolsProps } from "./BaseTool";
|
||||
import MatrixClientContext from "../../../../contexts/MatrixClientContext";
|
||||
import { EventEditor, EventViewer, eventTypeField, type IEditorProps, stringify } from "./Event";
|
||||
import FilteredList from "./FilteredList";
|
||||
import { _td, type TranslationKey } from "../../../../languageHandler";
|
||||
import { _td } from "../../../../languageHandler";
|
||||
|
||||
export const AccountDataEventEditor: React.FC<IEditorProps> = ({ mxEvent, onBack }) => {
|
||||
const cli = useContext(MatrixClientContext);
|
||||
|
||||
@ -11,7 +11,7 @@ import React, { createContext, type ReactNode, useState } from "react";
|
||||
import { type Room } from "matrix-js-sdk/src/matrix";
|
||||
import classNames from "classnames";
|
||||
|
||||
import { _t, type TranslationKey } from "../../../../languageHandler";
|
||||
import { _t } from "../../../../languageHandler";
|
||||
import { type XOR } from "../../../../@types/common";
|
||||
import { type Tool } from "../DevtoolsDialog";
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { type ChangeEvent, type ReactNode, useContext, useMemo, useRef, useState } from "react";
|
||||
import { type IContent, type MatrixEvent, type TimelineEvents } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { _t, _td, type TranslationKey } from "../../../../languageHandler";
|
||||
import { _t, _td } from "../../../../languageHandler";
|
||||
import Field from "../../elements/Field";
|
||||
import BaseTool, { DevtoolsContext, type IDevtoolsProps } from "./BaseTool";
|
||||
import MatrixClientContext from "../../../../contexts/MatrixClientContext";
|
||||
|
||||