diff --git a/package.json b/package.json index d2e6c31ac18..cae403b5599 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "test:playwright:open": "yarn test:playwright --ui", "test:playwright:screenshots": "yarn test:playwright:screenshots:build && yarn test:playwright:screenshots:run", "test:playwright:screenshots:build": "docker build playwright -t element-web-playwright", - "test:playwright:screenshots:run": "docker run --rm --network host -e BASE_URL -e CI -v $(pwd):/work/ -v $(node -e 'console.log(require(`path`).dirname(require.resolve(`matrix-js-sdk/package.json`)))'):/work/node_modules/matrix-js-sdk -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/:/tmp/ -it element-web-playwright", + "test:playwright:screenshots:run": "docker run --rm --network host -e BASE_URL -e CI -v $(pwd):/work/ -v $(node -e 'console.log(require(`path`).dirname(require.resolve(`matrix-js-sdk/package.json`)))'):/work/node_modules/matrix-js-sdk -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/:/tmp/ -it element-web-playwright --grep @screenshot", "coverage": "yarn test --coverage", "analyse:unused-exports": "ts-node ./scripts/analyse_unused_exports.ts", "analyse:webpack-bundles": "webpack-bundle-analyzer webpack-stats.json webapp", diff --git a/playwright/e2e/app-loading/feature-detection.spec.ts b/playwright/e2e/app-loading/feature-detection.spec.ts index 16e17a80549..ee61fb56628 100644 --- a/playwright/e2e/app-loading/feature-detection.spec.ts +++ b/playwright/e2e/app-loading/feature-detection.spec.ts @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import { test, expect } from "../../element-web-test"; -test(`shows error page if browser lacks Intl support`, async ({ page }) => { +test(`shows error page if browser lacks Intl support`, { tag: "@screenshot" }, async ({ page }) => { await page.addInitScript({ content: `delete window.Intl;` }); await page.goto("/"); @@ -21,7 +21,7 @@ test(`shows error page if browser lacks Intl support`, async ({ page }) => { await expect(page).toMatchScreenshot("unsupported-browser.png"); }); -test(`shows error page if browser lacks WebAssembly support`, async ({ page }) => { +test(`shows error page if browser lacks WebAssembly support`, { tag: "@screenshot" }, async ({ page }) => { await page.addInitScript({ content: `delete window.WebAssembly;` }); await page.goto("/"); diff --git a/playwright/e2e/audio-player/audio-player.spec.ts b/playwright/e2e/audio-player/audio-player.spec.ts index c2081dfcd80..2bb9ab0be45 100644 --- a/playwright/e2e/audio-player/audio-player.spec.ts +++ b/playwright/e2e/audio-player/audio-player.spec.ts @@ -134,18 +134,22 @@ test.describe("Audio player", () => { ).toBeVisible(); }); - test("should be correctly rendered - light theme", async ({ page, app }) => { + test("should be correctly rendered - light theme", { tag: "@screenshot" }, async ({ page, app }) => { await uploadFile(page, "playwright/sample-files/1sec-long-name-audio-file.ogg"); await takeSnapshots(page, app, "Selected EventTile of audio player (light theme)"); }); - test("should be correctly rendered - light theme with monospace font", async ({ page, app }) => { - await uploadFile(page, "playwright/sample-files/1sec-long-name-audio-file.ogg"); + test( + "should be correctly rendered - light theme with monospace font", + { tag: "@screenshot" }, + async ({ page, app }) => { + await uploadFile(page, "playwright/sample-files/1sec-long-name-audio-file.ogg"); - await takeSnapshots(page, app, "Selected EventTile of audio player (light theme, monospace font)", true); // Enable monospace - }); + await takeSnapshots(page, app, "Selected EventTile of audio player (light theme, monospace font)", true); // Enable monospace + }, + ); - test("should be correctly rendered - high contrast theme", async ({ page, app }) => { + test("should be correctly rendered - high contrast theme", { tag: "@screenshot" }, async ({ page, app }) => { // Disable system theme in case ThemeWatcher enables the theme automatically, // so that the high contrast theme can be enabled await app.settings.setValue("use_system_theme", null, SettingLevel.DEVICE, false); @@ -161,7 +165,7 @@ test.describe("Audio player", () => { await takeSnapshots(page, app, "Selected EventTile of audio player (high contrast)"); }); - test("should be correctly rendered - dark theme", async ({ page, app }) => { + test("should be correctly rendered - dark theme", { tag: "@screenshot" }, async ({ page, app }) => { // Enable dark theme await app.settings.setValue("theme", null, SettingLevel.ACCOUNT, "dark"); @@ -207,93 +211,101 @@ test.describe("Audio player", () => { expect(download.suggestedFilename()).toBe("1sec.ogg"); }); - test("should support replying to audio file with another audio file", async ({ page, app }) => { - await uploadFile(page, "playwright/sample-files/1sec.ogg"); + test( + "should support replying to audio file with another audio file", + { tag: "@screenshot" }, + async ({ page, app }) => { + await uploadFile(page, "playwright/sample-files/1sec.ogg"); - // Assert the audio player is rendered - await expect(page.locator(".mx_EventTile_last .mx_AudioPlayer_container")).toBeVisible(); + // Assert the audio player is rendered + await expect(page.locator(".mx_EventTile_last .mx_AudioPlayer_container")).toBeVisible(); - // Find and click "Reply" button on MessageActionBar - const tile = page.locator(".mx_EventTile_last"); - await tile.hover(); - await tile.getByRole("button", { name: "Reply", exact: true }).click(); + // Find and click "Reply" button on MessageActionBar + const tile = page.locator(".mx_EventTile_last"); + await tile.hover(); + await tile.getByRole("button", { name: "Reply", exact: true }).click(); - // Reply to the player with another audio file - await uploadFile(page, "playwright/sample-files/1sec.ogg"); + // Reply to the player with another audio file + await uploadFile(page, "playwright/sample-files/1sec.ogg"); - // Assert that the audio player is rendered - await expect(tile.locator(".mx_AudioPlayer_container")).toBeVisible(); + // Assert that the audio player is rendered + await expect(tile.locator(".mx_AudioPlayer_container")).toBeVisible(); - // Assert that replied audio file is rendered as file button inside ReplyChain - const button = tile.locator(".mx_ReplyChain_wrapper .mx_MFileBody_info[role='button']"); - // Assert that the file button has file name - await expect(button.locator(".mx_MFileBody_info_filename")).toBeVisible(); + // Assert that replied audio file is rendered as file button inside ReplyChain + const button = tile.locator(".mx_ReplyChain_wrapper .mx_MFileBody_info[role='button']"); + // Assert that the file button has file name + await expect(button.locator(".mx_MFileBody_info_filename")).toBeVisible(); - await takeSnapshots(page, app, "Selected EventTile of audio player with a reply"); - }); + await takeSnapshots(page, app, "Selected EventTile of audio player with a reply"); + }, + ); - test("should support creating a reply chain with multiple audio files", async ({ page, app, user }) => { - // Note: "mx_ReplyChain" element is used not only for replies which - // create a reply chain, but also for a single reply without a replied - // message. This test checks whether a reply chain which consists of - // multiple audio file replies is rendered properly. + test( + "should support creating a reply chain with multiple audio files", + { tag: "@screenshot" }, + async ({ page, app, user }) => { + // Note: "mx_ReplyChain" element is used not only for replies which + // create a reply chain, but also for a single reply without a replied + // message. This test checks whether a reply chain which consists of + // multiple audio file replies is rendered properly. - const tile = page.locator(".mx_EventTile_last"); + const tile = page.locator(".mx_EventTile_last"); - // Find and click "Reply" button - const clickButtonReply = async () => { - await tile.scrollIntoViewIfNeeded(); - await tile.hover(); - await tile.getByRole("button", { name: "Reply", exact: true }).click(); - }; + // Find and click "Reply" button + const clickButtonReply = async () => { + await tile.scrollIntoViewIfNeeded(); + await tile.hover(); + await tile.getByRole("button", { name: "Reply", exact: true }).click(); + }; - await uploadFile(page, "playwright/sample-files/upload-first.ogg"); + await uploadFile(page, "playwright/sample-files/upload-first.ogg"); - // Assert that the audio player is rendered - await expect(page.locator(".mx_EventTile_last .mx_AudioPlayer_container")).toBeVisible(); + // Assert that the audio player is rendered + await expect(page.locator(".mx_EventTile_last .mx_AudioPlayer_container")).toBeVisible(); - await clickButtonReply(); + await clickButtonReply(); - // Reply to the player with another audio file - await uploadFile(page, "playwright/sample-files/upload-second.ogg"); + // Reply to the player with another audio file + await uploadFile(page, "playwright/sample-files/upload-second.ogg"); - // Assert that the audio player is rendered - await expect(page.locator(".mx_EventTile_last .mx_AudioPlayer_container")).toBeVisible(); + // Assert that the audio player is rendered + await expect(page.locator(".mx_EventTile_last .mx_AudioPlayer_container")).toBeVisible(); - await clickButtonReply(); + await clickButtonReply(); - // Reply to the player with yet another audio file to create a reply chain - await uploadFile(page, "playwright/sample-files/upload-third.ogg"); + // Reply to the player with yet another audio file to create a reply chain + await uploadFile(page, "playwright/sample-files/upload-third.ogg"); - // Assert that the audio player is rendered - await expect(tile.locator(".mx_AudioPlayer_container")).toBeVisible(); + // Assert that the audio player is rendered + await expect(tile.locator(".mx_AudioPlayer_container")).toBeVisible(); - // Assert that there are two "mx_ReplyChain" elements - await expect(tile.locator(".mx_ReplyChain")).toHaveCount(2); + // Assert that there are two "mx_ReplyChain" elements + await expect(tile.locator(".mx_ReplyChain")).toHaveCount(2); - // Assert that one line contains the user name - await expect(tile.locator(".mx_ReplyChain .mx_ReplyTile_sender").getByText(user.displayName)).toBeVisible(); + // Assert that one line contains the user name + await expect(tile.locator(".mx_ReplyChain .mx_ReplyTile_sender").getByText(user.displayName)).toBeVisible(); - // Assert that the other line contains the file button - await expect(tile.locator(".mx_ReplyChain .mx_MFileBody")).toBeVisible(); + // Assert that the other line contains the file button + await expect(tile.locator(".mx_ReplyChain .mx_MFileBody")).toBeVisible(); - // Click "In reply to" - await tile.locator(".mx_ReplyChain .mx_ReplyChain_show", { hasText: "In reply to" }).click(); + // Click "In reply to" + await tile.locator(".mx_ReplyChain .mx_ReplyChain_show", { hasText: "In reply to" }).click(); - const replyChain = tile.locator(".mx_ReplyChain:first-of-type"); - // Assert that "In reply to" has disappeared - await expect(replyChain.getByText("In reply to")).not.toBeVisible(); + const replyChain = tile.locator(".mx_ReplyChain:first-of-type"); + // Assert that "In reply to" has disappeared + await expect(replyChain.getByText("In reply to")).not.toBeVisible(); - // Assert that the file button contains the name of the file sent at first - await expect( - replyChain - .locator(".mx_MFileBody_info[role='button']") - .locator(".mx_MFileBody_info_filename", { hasText: "upload-first.ogg" }), - ).toBeVisible(); + // Assert that the file button contains the name of the file sent at first + await expect( + replyChain + .locator(".mx_MFileBody_info[role='button']") + .locator(".mx_MFileBody_info_filename", { hasText: "upload-first.ogg" }), + ).toBeVisible(); - // Take snapshots - await takeSnapshots(page, app, "Selected EventTile of audio player with a reply chain"); - }); + // Take snapshots + await takeSnapshots(page, app, "Selected EventTile of audio player with a reply chain"); + }, + ); test("should be rendered, play, and support replying on a thread", async ({ page, app }) => { await uploadFile(page, "playwright/sample-files/1sec-long-name-audio-file.ogg"); diff --git a/playwright/e2e/chat-export/html-export.spec.ts b/playwright/e2e/chat-export/html-export.spec.ts index 9a66a4907a3..f914cccd96b 100644 --- a/playwright/e2e/chat-export/html-export.spec.ts +++ b/playwright/e2e/chat-export/html-export.spec.ts @@ -89,43 +89,47 @@ test.describe("HTML Export", () => { }, }); - test("should export html successfully and match screenshot", async ({ page, app, room }) => { - // Set a fixed time rather than masking off the line with the time in it: we don't need to worry - // about the width changing and we can actually test this line looks correct. - page.clock.setSystemTime(new Date("2024-01-01T00:00:00Z")); - - // Send a bunch of messages to populate the room - for (let i = 1; i < 10; i++) { - const respone = await app.client.sendMessage(room.roomId, { body: `Testing ${i}`, msgtype: "m.text" }); - if (i == 1) { - await app.client.reactToMessage(room.roomId, null, respone.event_id, "🙃"); + test( + "should export html successfully and match screenshot", + { tag: "@screenshot" }, + async ({ page, app, room }) => { + // Set a fixed time rather than masking off the line with the time in it: we don't need to worry + // about the width changing and we can actually test this line looks correct. + page.clock.setSystemTime(new Date("2024-01-01T00:00:00Z")); + + // Send a bunch of messages to populate the room + for (let i = 1; i < 10; i++) { + const respone = await app.client.sendMessage(room.roomId, { body: `Testing ${i}`, msgtype: "m.text" }); + if (i == 1) { + await app.client.reactToMessage(room.roomId, null, respone.event_id, "🙃"); + } } - } - - // Wait for all the messages to be displayed - await expect( - page.locator(".mx_EventTile_last .mx_MTextBody .mx_EventTile_body").getByText("Testing 9"), - ).toBeVisible(); - - await app.toggleRoomInfoPanel(); - await page.getByRole("menuitem", { name: "Export Chat" }).click(); - - const downloadPromise = page.waitForEvent("download"); - await page.getByRole("button", { name: "Export", exact: true }).click(); - const download = await downloadPromise; - - const dirPath = path.join(os.tmpdir(), "html-export-test"); - const zipPath = `${dirPath}.zip`; - await download.saveAs(zipPath); - - const zip = await extractZipFileToPath(zipPath, dirPath); - await page.goto(`file://${dirPath}/${Object.keys(zip.files)[0]}/messages.html`); - await expect(page).toMatchScreenshot("html-export.png", { - mask: [ - // We need to mask the whole thing because the width of the time part changes - page.locator(".mx_TimelineSeparator"), - page.locator(".mx_MessageTimestamp"), - ], - }); - }); + + // Wait for all the messages to be displayed + await expect( + page.locator(".mx_EventTile_last .mx_MTextBody .mx_EventTile_body").getByText("Testing 9"), + ).toBeVisible(); + + await app.toggleRoomInfoPanel(); + await page.getByRole("menuitem", { name: "Export Chat" }).click(); + + const downloadPromise = page.waitForEvent("download"); + await page.getByRole("button", { name: "Export", exact: true }).click(); + const download = await downloadPromise; + + const dirPath = path.join(os.tmpdir(), "html-export-test"); + const zipPath = `${dirPath}.zip`; + await download.saveAs(zipPath); + + const zip = await extractZipFileToPath(zipPath, dirPath); + await page.goto(`file://${dirPath}/${Object.keys(zip.files)[0]}/messages.html`); + await expect(page).toMatchScreenshot("html-export.png", { + mask: [ + // We need to mask the whole thing because the width of the time part changes + page.locator(".mx_TimelineSeparator"), + page.locator(".mx_MessageTimestamp"), + ], + }); + }, + ); }); diff --git a/playwright/e2e/crypto/crypto.spec.ts b/playwright/e2e/crypto/crypto.spec.ts index 2ab49e72ec9..668c17d931d 100644 --- a/playwright/e2e/crypto/crypto.spec.ts +++ b/playwright/e2e/crypto/crypto.spec.ts @@ -204,30 +204,29 @@ test.describe("Cryptography", function () { await expect(page.locator(".mx_Dialog")).toHaveCount(1); }); - test("creating a DM should work, being e2e-encrypted / user verification", async ({ - page, - app, - bot: bob, - user: aliceCredentials, - }) => { - await app.client.bootstrapCrossSigning(aliceCredentials); - await startDMWithBob(page, bob); - // send first message - await page.getByRole("textbox", { name: "Send a message…" }).fill("Hey!"); - await page.getByRole("textbox", { name: "Send a message…" }).press("Enter"); - await checkDMRoom(page); - const bobRoomId = await bobJoin(page, bob); - await testMessages(page, bob, bobRoomId); - await verify(app, bob); - - // Assert that verified icon is rendered - await page.getByTestId("base-card-back-button").click(); - await page.getByLabel("Room info").nth(1).click(); - await expect(page.locator('.mx_RoomSummaryCard_badges [data-kind="green"]')).toContainText("Encrypted"); - - // Take a snapshot of RoomSummaryCard with a verified E2EE icon - await expect(page.locator(".mx_RightPanel")).toMatchScreenshot("RoomSummaryCard-with-verified-e2ee.png"); - }); + test( + "creating a DM should work, being e2e-encrypted / user verification", + { tag: "@screenshot" }, + async ({ page, app, bot: bob, user: aliceCredentials }) => { + await app.client.bootstrapCrossSigning(aliceCredentials); + await startDMWithBob(page, bob); + // send first message + await page.getByRole("textbox", { name: "Send a message…" }).fill("Hey!"); + await page.getByRole("textbox", { name: "Send a message…" }).press("Enter"); + await checkDMRoom(page); + const bobRoomId = await bobJoin(page, bob); + await testMessages(page, bob, bobRoomId); + await verify(app, bob); + + // Assert that verified icon is rendered + await page.getByTestId("base-card-back-button").click(); + await page.getByLabel("Room info").nth(1).click(); + await expect(page.locator('.mx_RoomSummaryCard_badges [data-kind="green"]')).toContainText("Encrypted"); + + // Take a snapshot of RoomSummaryCard with a verified E2EE icon + await expect(page.locator(".mx_RightPanel")).toMatchScreenshot("RoomSummaryCard-with-verified-e2ee.png"); + }, + ); test("should allow verification when there is no existing DM", async ({ page, diff --git a/playwright/e2e/editing/editing.spec.ts b/playwright/e2e/editing/editing.spec.ts index 206d91982e0..e22ec250b98 100644 --- a/playwright/e2e/editing/editing.spec.ts +++ b/playwright/e2e/editing/editing.spec.ts @@ -66,126 +66,130 @@ test.describe("Editing", () => { botCreateOpts: { displayName: "Bob" }, }); - test("should render and interact with the message edit history dialog", async ({ page, user, app, room }) => { - // Click the "Remove" button on the message edit history dialog - const clickButtonRemove = async (locator: Locator) => { - const eventTileLine = locator.locator(".mx_EventTile_line"); - await eventTileLine.hover(); - await eventTileLine.getByRole("button", { name: "Remove" }).click(); - }; + test( + "should render and interact with the message edit history dialog", + { tag: "@screenshot" }, + async ({ page, user, app, room }) => { + // Click the "Remove" button on the message edit history dialog + const clickButtonRemove = async (locator: Locator) => { + const eventTileLine = locator.locator(".mx_EventTile_line"); + await eventTileLine.hover(); + await eventTileLine.getByRole("button", { name: "Remove" }).click(); + }; - await page.goto(`#/room/${room.roomId}`); - - // Send "Message" - await sendEvent(app, room.roomId); - - // Edit "Message" to "Massage" - await editLastMessage(page, "Massage"); - - // Assert that the edit label is visible - await expect(page.locator(".mx_EventTile_edited")).toBeVisible(); + await page.goto(`#/room/${room.roomId}`); - await clickEditedMessage(page, "Massage"); + // Send "Message" + await sendEvent(app, room.roomId); - // Assert that the message edit history dialog is rendered - const dialog = page.getByRole("dialog"); - const li = dialog.getByRole("listitem").last(); - // Assert CSS styles which are difficult or cannot be detected with snapshots are applied as expected - await expect(li).toHaveCSS("clear", "both"); + // Edit "Message" to "Massage" + await editLastMessage(page, "Massage"); - const timestamp = li.locator(".mx_EventTile .mx_MessageTimestamp"); - await expect(timestamp).toHaveCSS("position", "absolute"); - await expect(timestamp).toHaveCSS("inset-inline-start", "0px"); - await expect(timestamp).toHaveCSS("text-align", "center"); + // Assert that the edit label is visible + await expect(page.locator(".mx_EventTile_edited")).toBeVisible(); - // Assert that monospace characters can fill the content line as expected - await expect(li.locator(".mx_EventTile .mx_EventTile_content")).toHaveCSS("margin-inline-end", "0px"); + await clickEditedMessage(page, "Massage"); - // Assert that zero block start padding is applied to mx_EventTile as expected - // See: .mx_EventTile on _EventTile.pcss - await expect(li.locator(".mx_EventTile")).toHaveCSS("padding-block-start", "0px"); + // Assert that the message edit history dialog is rendered + const dialog = page.getByRole("dialog"); + const li = dialog.getByRole("listitem").last(); + // Assert CSS styles which are difficult or cannot be detected with snapshots are applied as expected + await expect(li).toHaveCSS("clear", "both"); - // Assert that the date separator is rendered at the top - await expect(dialog.getByRole("listitem").first().locator("h2", { hasText: "today" })).toHaveCSS( - "text-transform", - "capitalize", - ); + const timestamp = li.locator(".mx_EventTile .mx_MessageTimestamp"); + await expect(timestamp).toHaveCSS("position", "absolute"); + await expect(timestamp).toHaveCSS("inset-inline-start", "0px"); + await expect(timestamp).toHaveCSS("text-align", "center"); - { - // Assert that the edited message is rendered under the date separator - const tile = dialog.locator("li:nth-child(2) .mx_EventTile"); - // Assert that the edited message body consists of both deleted character and inserted character - // Above the first "e" of "Message" was replaced with "a" - await expect(tile.locator(".mx_EventTile_body")).toHaveText("Meassage"); - - const body = tile.locator(".mx_EventTile_content .mx_EventTile_body"); - await expect(body.locator(".mx_EditHistoryMessage_deletion").getByText("e")).toBeVisible(); - await expect(body.locator(".mx_EditHistoryMessage_insertion").getByText("a")).toBeVisible(); - } + // Assert that monospace characters can fill the content line as expected + await expect(li.locator(".mx_EventTile .mx_EventTile_content")).toHaveCSS("margin-inline-end", "0px"); - // Assert that the original message is rendered at the bottom - await expect( - dialog - .locator("li:nth-child(3) .mx_EventTile") - .locator(".mx_EventTile_content .mx_EventTile_body", { hasText: "Message" }), - ).toBeVisible(); + // Assert that zero block start padding is applied to mx_EventTile as expected + // See: .mx_EventTile on _EventTile.pcss + await expect(li.locator(".mx_EventTile")).toHaveCSS("padding-block-start", "0px"); - // Take a snapshot of the dialog - await expect(dialog).toMatchScreenshot("message-edit-history-dialog.png", { - mask: [page.locator(".mx_MessageTimestamp")], - }); + // Assert that the date separator is rendered at the top + await expect(dialog.getByRole("listitem").first().locator("h2", { hasText: "today" })).toHaveCSS( + "text-transform", + "capitalize", + ); - { - const tile = dialog.locator("li:nth-child(2) .mx_EventTile"); - await expect(tile.locator(".mx_EventTile_body")).toHaveText("Meassage"); - // Click the "Remove" button again - await clickButtonRemove(tile); - } + { + // Assert that the edited message is rendered under the date separator + const tile = dialog.locator("li:nth-child(2) .mx_EventTile"); + // Assert that the edited message body consists of both deleted character and inserted character + // Above the first "e" of "Message" was replaced with "a" + await expect(tile.locator(".mx_EventTile_body")).toHaveText("Meassage"); + + const body = tile.locator(".mx_EventTile_content .mx_EventTile_body"); + await expect(body.locator(".mx_EditHistoryMessage_deletion").getByText("e")).toBeVisible(); + await expect(body.locator(".mx_EditHistoryMessage_insertion").getByText("a")).toBeVisible(); + } - // Do nothing and close the dialog to confirm that the message edit history dialog is rendered - await app.closeDialog(); + // Assert that the original message is rendered at the bottom + await expect( + dialog + .locator("li:nth-child(3) .mx_EventTile") + .locator(".mx_EventTile_content .mx_EventTile_body", { hasText: "Message" }), + ).toBeVisible(); - { - // Assert that the message edit history dialog is rendered again after it was closed - const tile = dialog.locator("li:nth-child(2) .mx_EventTile"); - await expect(tile.locator(".mx_EventTile_body")).toHaveText("Meassage"); - // Click the "Remove" button again - await clickButtonRemove(tile); - } + // Take a snapshot of the dialog + await expect(dialog).toMatchScreenshot("message-edit-history-dialog.png", { + mask: [page.locator(".mx_MessageTimestamp")], + }); - // This time remove the message really - const textInputDialog = page.locator(".mx_TextInputDialog"); - await textInputDialog.getByRole("textbox", { name: "Reason (optional)" }).fill("This is a test."); // Reason - await textInputDialog.getByRole("button", { name: "Remove" }).click(); + { + const tile = dialog.locator("li:nth-child(2) .mx_EventTile"); + await expect(tile.locator(".mx_EventTile_body")).toHaveText("Meassage"); + // Click the "Remove" button again + await clickButtonRemove(tile); + } - // Assert that the message edit history dialog is rendered again - const messageEditHistoryDialog = page.locator(".mx_MessageEditHistoryDialog"); - // Assert that the date is rendered - await expect( - messageEditHistoryDialog.getByRole("listitem").first().locator("h2", { hasText: "today" }), - ).toHaveCSS("text-transform", "capitalize"); + // Do nothing and close the dialog to confirm that the message edit history dialog is rendered + await app.closeDialog(); - // Assert that the original message is rendered under the date on the dialog - await expect( - messageEditHistoryDialog - .locator("li:nth-child(2) .mx_EventTile") - .locator(".mx_EventTile_content .mx_EventTile_body", { hasText: "Message" }), - ).toBeVisible(); + { + // Assert that the message edit history dialog is rendered again after it was closed + const tile = dialog.locator("li:nth-child(2) .mx_EventTile"); + await expect(tile.locator(".mx_EventTile_body")).toHaveText("Meassage"); + // Click the "Remove" button again + await clickButtonRemove(tile); + } - // Assert that the edited message is gone - await expect( - messageEditHistoryDialog.locator(".mx_EventTile_content .mx_EventTile_body", { hasText: "Meassage" }), - ).not.toBeVisible(); + // This time remove the message really + const textInputDialog = page.locator(".mx_TextInputDialog"); + await textInputDialog.getByRole("textbox", { name: "Reason (optional)" }).fill("This is a test."); // Reason + await textInputDialog.getByRole("button", { name: "Remove" }).click(); + + // Assert that the message edit history dialog is rendered again + const messageEditHistoryDialog = page.locator(".mx_MessageEditHistoryDialog"); + // Assert that the date is rendered + await expect( + messageEditHistoryDialog.getByRole("listitem").first().locator("h2", { hasText: "today" }), + ).toHaveCSS("text-transform", "capitalize"); + + // Assert that the original message is rendered under the date on the dialog + await expect( + messageEditHistoryDialog + .locator("li:nth-child(2) .mx_EventTile") + .locator(".mx_EventTile_content .mx_EventTile_body", { hasText: "Message" }), + ).toBeVisible(); + + // Assert that the edited message is gone + await expect( + messageEditHistoryDialog.locator(".mx_EventTile_content .mx_EventTile_body", { hasText: "Meassage" }), + ).not.toBeVisible(); - await app.closeDialog(); + await app.closeDialog(); - // Assert that the redaction placeholder is rendered - await expect( - page - .locator(".mx_RoomView_MessageList") - .locator(".mx_EventTile_last .mx_RedactedBody", { hasText: "Message deleted" }), - ).toBeVisible(); - }); + // Assert that the redaction placeholder is rendered + await expect( + page + .locator(".mx_RoomView_MessageList") + .locator(".mx_EventTile_last .mx_RedactedBody", { hasText: "Message deleted" }), + ).toBeVisible(); + }, + ); test("should render 'View Source' button in developer mode on the message edit history dialog", async ({ page, diff --git a/playwright/e2e/file-upload/image-upload.spec.ts b/playwright/e2e/file-upload/image-upload.spec.ts index eb473d83b2a..76782e90e8b 100644 --- a/playwright/e2e/file-upload/image-upload.spec.ts +++ b/playwright/e2e/file-upload/image-upload.spec.ts @@ -25,7 +25,7 @@ test.describe("Image Upload", () => { ).toBeVisible(); }); - test("should show image preview when uploading an image", async ({ page, app }) => { + test("should show image preview when uploading an image", { tag: "@screenshot" }, async ({ page, app }) => { await page .locator(".mx_MessageComposer_actions input[type='file']") .setInputFiles("playwright/sample-files/riot.png"); diff --git a/playwright/e2e/forgot-password/forgot-password.spec.ts b/playwright/e2e/forgot-password/forgot-password.spec.ts index c148900afd4..0a12514d9ec 100644 --- a/playwright/e2e/forgot-password/forgot-password.spec.ts +++ b/playwright/e2e/forgot-password/forgot-password.spec.ts @@ -26,7 +26,7 @@ test.describe("Forgot Password", () => { }), }); - test("renders properly", async ({ page, homeserver }) => { + test("renders properly", { tag: "@screenshot" }, async ({ page, homeserver }) => { await page.goto("/"); await page.getByRole("link", { name: "Sign in" }).click(); @@ -39,7 +39,7 @@ test.describe("Forgot Password", () => { await expect(page.getByRole("main")).toMatchScreenshot("forgot-password.png"); }); - test("renders email verification dialog properly", async ({ page, homeserver }) => { + test("renders email verification dialog properly", { tag: "@screenshot" }, async ({ page, homeserver }) => { const user = await homeserver.registerUser(username, password); await homeserver.setThreepid(user.userId, "email", email); diff --git a/playwright/e2e/invite/invite-dialog.spec.ts b/playwright/e2e/invite/invite-dialog.spec.ts index c8bd8eb404b..eb434eb5b56 100644 --- a/playwright/e2e/invite/invite-dialog.spec.ts +++ b/playwright/e2e/invite/invite-dialog.spec.ts @@ -19,7 +19,7 @@ test.describe("Invite dialog", function () { const botName = "BotAlice"; - test("should support inviting a user to a room", async ({ page, app, user, bot }) => { + test("should support inviting a user to a room", { tag: "@screenshot" }, async ({ page, app, user, bot }) => { // Create and view a room await app.client.createRoom({ name: "Test Room" }); await app.viewRoomByName("Test Room"); @@ -73,52 +73,63 @@ test.describe("Invite dialog", function () { await expect(page.getByText(`${botName} joined the room`)).toBeVisible(); }); - test("should support inviting a user to Direct Messages", async ({ page, app, user, bot }) => { - await page.locator(".mx_RoomList").getByRole("button", { name: "Start chat" }).click(); + test( + "should support inviting a user to Direct Messages", + { tag: "@screenshot" }, + async ({ page, app, user, bot }) => { + await page.locator(".mx_RoomList").getByRole("button", { name: "Start chat" }).click(); - const other = page.locator(".mx_InviteDialog_other"); - // Assert that the header is rendered - await expect(other.locator(".mx_Dialog_header .mx_Dialog_title").getByText("Direct Messages")).toBeVisible(); + const other = page.locator(".mx_InviteDialog_other"); + // Assert that the header is rendered + await expect( + other.locator(".mx_Dialog_header .mx_Dialog_title").getByText("Direct Messages"), + ).toBeVisible(); - // Assert that the bar is rendered - await expect(other.locator(".mx_InviteDialog_addressBar")).toBeVisible(); + // Assert that the bar is rendered + await expect(other.locator(".mx_InviteDialog_addressBar")).toBeVisible(); - // Take a snapshot of the invite dialog - await expect(page.locator(".mx_Dialog")).toMatchScreenshot("invite-dialog-dm-without-user.png"); + // Take a snapshot of the invite dialog + await expect(page.locator(".mx_Dialog")).toMatchScreenshot("invite-dialog-dm-without-user.png"); - await other.getByTestId("invite-dialog-input").fill(bot.credentials.userId); + await other.getByTestId("invite-dialog-input").fill(bot.credentials.userId); - await expect(other.locator(".mx_InviteDialog_tile_nameStack").getByText(bot.credentials.userId)).toBeVisible(); - await other.locator(".mx_InviteDialog_tile_nameStack").getByText(botName).click(); + await expect( + other.locator(".mx_InviteDialog_tile_nameStack").getByText(bot.credentials.userId), + ).toBeVisible(); + await other.locator(".mx_InviteDialog_tile_nameStack").getByText(botName).click(); - await expect( - other.locator(".mx_InviteDialog_userTile_pill .mx_InviteDialog_userTile_name").getByText(botName), - ).toBeVisible(); + await expect( + other.locator(".mx_InviteDialog_userTile_pill .mx_InviteDialog_userTile_name").getByText(botName), + ).toBeVisible(); - // Take a snapshot of the invite dialog with a user pill - await expect(page.locator(".mx_Dialog")).toMatchScreenshot("invite-dialog-dm-with-user-pill.png"); + // Take a snapshot of the invite dialog with a user pill + await expect(page.locator(".mx_Dialog")).toMatchScreenshot("invite-dialog-dm-with-user-pill.png"); - // Open a direct message UI - await other.getByRole("button", { name: "Go" }).click(); + // Open a direct message UI + await other.getByRole("button", { name: "Go" }).click(); - // Assert that the invite dialog disappears - await expect(page.locator(".mx_InviteDialog_other")).not.toBeVisible(); + // Assert that the invite dialog disappears + await expect(page.locator(".mx_InviteDialog_other")).not.toBeVisible(); - // Assert that the hovered user name on invitation UI does not have background color - // TODO: implement the test on room-header.spec.ts - const roomHeader = page.locator(".mx_RoomHeader"); - await roomHeader.locator(".mx_RoomHeader_heading").hover(); - await expect(roomHeader.locator(".mx_RoomHeader_heading")).toHaveCSS("background-color", "rgba(0, 0, 0, 0)"); + // Assert that the hovered user name on invitation UI does not have background color + // TODO: implement the test on room-header.spec.ts + const roomHeader = page.locator(".mx_RoomHeader"); + await roomHeader.locator(".mx_RoomHeader_heading").hover(); + await expect(roomHeader.locator(".mx_RoomHeader_heading")).toHaveCSS( + "background-color", + "rgba(0, 0, 0, 0)", + ); - // Send a message to invite the bots - const composer = app.getComposer().locator("[contenteditable]"); - await composer.fill("Hello}"); - await composer.press("Enter"); + // Send a message to invite the bots + const composer = app.getComposer().locator("[contenteditable]"); + await composer.fill("Hello}"); + await composer.press("Enter"); - // Assert that they were invited and joined - await expect(page.getByText(`${botName} joined the room`)).toBeVisible(); + // Assert that they were invited and joined + await expect(page.getByText(`${botName} joined the room`)).toBeVisible(); - // Assert that the message is displayed at the bottom - await expect(page.locator(".mx_EventTile_last").getByText("Hello")).toBeVisible(); - }); + // Assert that the message is displayed at the bottom + await expect(page.locator(".mx_EventTile_last").getByText("Hello")).toBeVisible(); + }, + ); }); diff --git a/playwright/e2e/messages/messages.spec.ts b/playwright/e2e/messages/messages.spec.ts index 0d5a5da4728..1c518199a00 100644 --- a/playwright/e2e/messages/messages.spec.ts +++ b/playwright/e2e/messages/messages.spec.ts @@ -63,7 +63,7 @@ test.describe("Message rendering", () => { { direction: "ltr", displayName: "Quentin" }, { direction: "rtl", displayName: "كوينتين" }, ].forEach(({ direction, displayName }) => { - test.describe(`with ${direction} display name`, () => { + test.describe(`with ${direction} display name`, { tag: "@screenshot" }, () => { test.use({ displayName, room: async ({ user, app }, use) => { @@ -72,14 +72,18 @@ test.describe("Message rendering", () => { }, }); - test("should render a basic LTR text message", async ({ page, user, app, room }) => { - await page.goto(`#/room/${room.roomId}`); + test( + "should render a basic LTR text message", + { tag: "@screenshot" }, + async ({ page, user, app, room }) => { + await page.goto(`#/room/${room.roomId}`); - const msgTile = await sendMessage(page, "Hello, world!"); - await expect(msgTile).toMatchScreenshot(`basic-message-ltr-${direction}displayname.png`, { - mask: [page.locator(".mx_MessageTimestamp")], - }); - }); + const msgTile = await sendMessage(page, "Hello, world!"); + await expect(msgTile).toMatchScreenshot(`basic-message-ltr-${direction}displayname.png`, { + mask: [page.locator(".mx_MessageTimestamp")], + }); + }, + ); test("should render an LTR emote", async ({ page, user, app, room }) => { await page.goto(`#/room/${room.roomId}`); diff --git a/playwright/e2e/permalinks/permalinks.spec.ts b/playwright/e2e/permalinks/permalinks.spec.ts index bd7884ea78d..746e15d2880 100644 --- a/playwright/e2e/permalinks/permalinks.spec.ts +++ b/playwright/e2e/permalinks/permalinks.spec.ts @@ -24,7 +24,7 @@ test.describe("permalinks", () => { displayName: "Alice", }); - test("shoud render permalinks as expected", async ({ page, app, user, homeserver }) => { + test("shoud render permalinks as expected", { tag: "@screenshot" }, async ({ page, app, user, homeserver }) => { const bob = new Bot(page, homeserver, { displayName: "Bob" }); const charlotte = new Bot(page, homeserver, { displayName: "Charlotte" }); await bob.prepareClient(); diff --git a/playwright/e2e/pinned-messages/pinned-messages.spec.ts b/playwright/e2e/pinned-messages/pinned-messages.spec.ts index ef2c1b27d4c..06d6db80580 100644 --- a/playwright/e2e/pinned-messages/pinned-messages.spec.ts +++ b/playwright/e2e/pinned-messages/pinned-messages.spec.ts @@ -10,35 +10,38 @@ import { test } from "./index"; import { expect } from "../../element-web-test"; test.describe("Pinned messages", () => { - test("should show the empty state when there are no pinned messages", async ({ page, app, room1, util }) => { - await util.goTo(room1); - await util.openRoomInfo(); - await util.assertPinnedCountInRoomInfo(0); - await util.openPinnedMessagesList(); - await util.assertEmptyPinnedMessagesList(); - }); - - test("should pin one message and to have the pinned message badge in the timeline", async ({ - page, - app, - room1, - util, - }) => { - await util.goTo(room1); - await util.receiveMessages(room1, ["Msg1"]); - await util.pinMessages(["Msg1"]); - - const tile = util.getEventTile("Msg1"); - await expect(tile).toMatchScreenshot("pinned-message-Msg1.png", { - mask: [tile.locator(".mx_MessageTimestamp")], - // Hide the jump to bottom button in the timeline to avoid flakiness - css: ` + test( + "should show the empty state when there are no pinned messages", + { tag: "@screenshot" }, + async ({ page, app, room1, util }) => { + await util.goTo(room1); + await util.openRoomInfo(); + await util.assertPinnedCountInRoomInfo(0); + await util.openPinnedMessagesList(); + await util.assertEmptyPinnedMessagesList(); + }, + ); + + test( + "should pin one message and to have the pinned message badge in the timeline", + { tag: "@screenshot" }, + async ({ page, app, room1, util }) => { + await util.goTo(room1); + await util.receiveMessages(room1, ["Msg1"]); + await util.pinMessages(["Msg1"]); + + const tile = util.getEventTile("Msg1"); + await expect(tile).toMatchScreenshot("pinned-message-Msg1.png", { + mask: [tile.locator(".mx_MessageTimestamp")], + // Hide the jump to bottom button in the timeline to avoid flakiness + css: ` .mx_JumpToBottomButton { display: none !important; } `, - }); - }); + }); + }, + ); test("should pin messages and show them in the room info panel", async ({ page, app, room1, util }) => { await util.goTo(room1); @@ -73,7 +76,7 @@ test.describe("Pinned messages", () => { await util.assertPinnedCountInRoomInfo(2); }); - test("should unpin all messages", async ({ page, app, room1, util }) => { + test("should unpin all messages", { tag: "@screenshot" }, async ({ page, app, room1, util }) => { await util.goTo(room1); await util.receiveMessages(room1, ["Msg1", "Msg2", "Msg3", "Msg4"]); await util.pinMessages(["Msg1", "Msg2", "Msg4"]); @@ -98,7 +101,7 @@ test.describe("Pinned messages", () => { await util.assertPinnedCountInRoomInfo(0); }); - test("should display one message in the banner", async ({ page, app, room1, util }) => { + test("should display one message in the banner", { tag: "@screenshot" }, async ({ page, app, room1, util }) => { await util.goTo(room1); await util.receiveMessages(room1, ["Msg1"]); await util.pinMessages(["Msg1"]); @@ -106,7 +109,7 @@ test.describe("Pinned messages", () => { await expect(util.getBanner()).toMatchScreenshot("pinned-message-banner-1-Msg1.png"); }); - test("should display 2 messages in the banner", async ({ page, app, room1, util }) => { + test("should display 2 messages in the banner", { tag: "@screenshot" }, async ({ page, app, room1, util }) => { await util.goTo(room1); await util.receiveMessages(room1, ["Msg1", "Msg2"]); await util.pinMessages(["Msg1", "Msg2"]); @@ -123,7 +126,7 @@ test.describe("Pinned messages", () => { await expect(util.getBanner()).toMatchScreenshot("pinned-message-banner-2-Msg2.png"); }); - test("should display 4 messages in the banner", async ({ page, app, room1, util }) => { + test("should display 4 messages in the banner", { tag: "@screenshot" }, async ({ page, app, room1, util }) => { await util.goTo(room1); await util.receiveMessages(room1, ["Msg1", "Msg2", "Msg3", "Msg4"]); await util.pinMessages(["Msg1", "Msg2", "Msg3", "Msg4"]); diff --git a/playwright/e2e/polls/polls.spec.ts b/playwright/e2e/polls/polls.spec.ts index 4fd81955810..e1d3ebe7e36 100644 --- a/playwright/e2e/polls/polls.spec.ts +++ b/playwright/e2e/polls/polls.spec.ts @@ -93,7 +93,7 @@ test.describe("Polls", () => { }); }); - test("should be creatable and votable", async ({ page, app, bot, user }) => { + test("should be creatable and votable", { tag: "@screenshot" }, async ({ page, app, bot, user }) => { const roomId: string = await app.client.createRoom({}); await app.client.inviteUser(roomId, bot.credentials.userId); await page.goto("/#/room/" + roomId); @@ -219,107 +219,121 @@ test.describe("Polls", () => { await expect(page.locator(".mx_ErrorDialog")).toBeAttached(); }); - test("should be displayed correctly in thread panel", async ({ page, app, user, bot, homeserver }) => { - const botCharlie = new Bot(page, homeserver, { displayName: "BotCharlie" }); - await botCharlie.prepareClient(); - - const roomId: string = await app.client.createRoom({}); - await app.client.inviteUser(roomId, bot.credentials.userId); - await app.client.inviteUser(roomId, botCharlie.credentials.userId); - await page.goto("/#/room/" + roomId); - - // wait until the bots joined - await expect(page.getByText("BotBob and one other were invited and joined")).toBeAttached({ timeout: 10000 }); - - const locator = await app.openMessageComposerOptions(); - await locator.getByRole("menuitem", { name: "Poll" }).click(); - - const pollParams = { - title: "Does the polls feature work?", - options: ["Yes", "No", "Maybe"], - }; - await createPoll(page, pollParams); - - // Wait for message to send, get its ID and save as @pollId - const pollId = await page - .locator(".mx_RoomView_body .mx_EventTile[data-scroll-tokens]") - .filter({ hasText: pollParams.title }) - .getAttribute("data-scroll-tokens"); - - // Bob starts thread on the poll - await bot.sendMessage( - roomId, - { - body: "Hello there", - msgtype: "m.text", - }, - pollId, - ); - - // open the thread summary - await page.getByRole("button", { name: "Open thread" }).click(); - - // Bob votes 'Maybe' in the poll - await botVoteForOption(page, bot, roomId, pollId, pollParams.options[2]); - - // Charlie votes 'No' - await botVoteForOption(page, botCharlie, roomId, pollId, pollParams.options[1]); - - // no votes shown until I vote, check votes have arrived in main tl - await expect( - page - .locator(".mx_RoomView_body .mx_MPollBody_totalVotes") - .getByText("2 votes cast. Vote to see the results"), - ).toBeAttached(); - - // and thread view - await expect( - page.locator(".mx_ThreadView .mx_MPollBody_totalVotes").getByText("2 votes cast. Vote to see the results"), - ).toBeAttached(); - - // Take snapshots of poll on ThreadView - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble); - await expect(page.locator(".mx_ThreadView .mx_EventTile[data-layout='bubble']").first()).toBeVisible(); - await expect(page.locator(".mx_ThreadView")).toMatchScreenshot("ThreadView_with_a_poll_on_bubble_layout.png", { - mask: [page.locator(".mx_MessageTimestamp")], - }); - - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); - await expect(page.locator(".mx_ThreadView .mx_EventTile[data-layout='group']").first()).toBeVisible(); - - await expect(page.locator(".mx_ThreadView")).toMatchScreenshot("ThreadView_with_a_poll_on_group_layout.png", { - mask: [page.locator(".mx_MessageTimestamp")], - }); - - const roomViewLocator = page.locator(".mx_RoomView_body"); - // vote 'Maybe' in the main timeline poll - await getPollOption(page, pollId, pollParams.options[2], roomViewLocator).click(); - // both me and bob have voted Maybe - await expectPollOptionVoteCount(page, pollId, pollParams.options[2], 2, roomViewLocator); - - const threadViewLocator = page.locator(".mx_ThreadView"); - // votes updated in thread view too - await expectPollOptionVoteCount(page, pollId, pollParams.options[2], 2, threadViewLocator); - // change my vote to 'Yes' - await getPollOption(page, pollId, pollParams.options[0], threadViewLocator).click(); - - // Bob updates vote to 'No' - await botVoteForOption(page, bot, roomId, pollId, pollParams.options[1]); - - // me: yes, bob: no, charlie: no - const expectVoteCounts = async (optLocator: Locator) => { - // I voted yes - await expectPollOptionVoteCount(page, pollId, pollParams.options[0], 1, optLocator); - // Bob and Charlie voted no - await expectPollOptionVoteCount(page, pollId, pollParams.options[1], 2, optLocator); - // 0 for maybe - await expectPollOptionVoteCount(page, pollId, pollParams.options[2], 0, optLocator); - }; - - // check counts are correct in main timeline tile - await expectVoteCounts(page.locator(".mx_RoomView_body")); - - // and in thread view tile - await expectVoteCounts(page.locator(".mx_ThreadView")); - }); + test( + "should be displayed correctly in thread panel", + { tag: "@screenshot" }, + async ({ page, app, user, bot, homeserver }) => { + const botCharlie = new Bot(page, homeserver, { displayName: "BotCharlie" }); + await botCharlie.prepareClient(); + + const roomId: string = await app.client.createRoom({}); + await app.client.inviteUser(roomId, bot.credentials.userId); + await app.client.inviteUser(roomId, botCharlie.credentials.userId); + await page.goto("/#/room/" + roomId); + + // wait until the bots joined + await expect(page.getByText("BotBob and one other were invited and joined")).toBeAttached({ + timeout: 10000, + }); + + const locator = await app.openMessageComposerOptions(); + await locator.getByRole("menuitem", { name: "Poll" }).click(); + + const pollParams = { + title: "Does the polls feature work?", + options: ["Yes", "No", "Maybe"], + }; + await createPoll(page, pollParams); + + // Wait for message to send, get its ID and save as @pollId + const pollId = await page + .locator(".mx_RoomView_body .mx_EventTile[data-scroll-tokens]") + .filter({ hasText: pollParams.title }) + .getAttribute("data-scroll-tokens"); + + // Bob starts thread on the poll + await bot.sendMessage( + roomId, + { + body: "Hello there", + msgtype: "m.text", + }, + pollId, + ); + + // open the thread summary + await page.getByRole("button", { name: "Open thread" }).click(); + + // Bob votes 'Maybe' in the poll + await botVoteForOption(page, bot, roomId, pollId, pollParams.options[2]); + + // Charlie votes 'No' + await botVoteForOption(page, botCharlie, roomId, pollId, pollParams.options[1]); + + // no votes shown until I vote, check votes have arrived in main tl + await expect( + page + .locator(".mx_RoomView_body .mx_MPollBody_totalVotes") + .getByText("2 votes cast. Vote to see the results"), + ).toBeAttached(); + + // and thread view + await expect( + page + .locator(".mx_ThreadView .mx_MPollBody_totalVotes") + .getByText("2 votes cast. Vote to see the results"), + ).toBeAttached(); + + // Take snapshots of poll on ThreadView + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble); + await expect(page.locator(".mx_ThreadView .mx_EventTile[data-layout='bubble']").first()).toBeVisible(); + await expect(page.locator(".mx_ThreadView")).toMatchScreenshot( + "ThreadView_with_a_poll_on_bubble_layout.png", + { + mask: [page.locator(".mx_MessageTimestamp")], + }, + ); + + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); + await expect(page.locator(".mx_ThreadView .mx_EventTile[data-layout='group']").first()).toBeVisible(); + + await expect(page.locator(".mx_ThreadView")).toMatchScreenshot( + "ThreadView_with_a_poll_on_group_layout.png", + { + mask: [page.locator(".mx_MessageTimestamp")], + }, + ); + + const roomViewLocator = page.locator(".mx_RoomView_body"); + // vote 'Maybe' in the main timeline poll + await getPollOption(page, pollId, pollParams.options[2], roomViewLocator).click(); + // both me and bob have voted Maybe + await expectPollOptionVoteCount(page, pollId, pollParams.options[2], 2, roomViewLocator); + + const threadViewLocator = page.locator(".mx_ThreadView"); + // votes updated in thread view too + await expectPollOptionVoteCount(page, pollId, pollParams.options[2], 2, threadViewLocator); + // change my vote to 'Yes' + await getPollOption(page, pollId, pollParams.options[0], threadViewLocator).click(); + + // Bob updates vote to 'No' + await botVoteForOption(page, bot, roomId, pollId, pollParams.options[1]); + + // me: yes, bob: no, charlie: no + const expectVoteCounts = async (optLocator: Locator) => { + // I voted yes + await expectPollOptionVoteCount(page, pollId, pollParams.options[0], 1, optLocator); + // Bob and Charlie voted no + await expectPollOptionVoteCount(page, pollId, pollParams.options[1], 2, optLocator); + // 0 for maybe + await expectPollOptionVoteCount(page, pollId, pollParams.options[2], 0, optLocator); + }; + + // check counts are correct in main timeline tile + await expectVoteCounts(page.locator(".mx_RoomView_body")); + + // and in thread view tile + await expectVoteCounts(page.locator(".mx_ThreadView")); + }, + ); }); diff --git a/playwright/e2e/register/email.spec.ts b/playwright/e2e/register/email.spec.ts index 7a80f0bbf7a..665e20ef01f 100644 --- a/playwright/e2e/register/email.spec.ts +++ b/playwright/e2e/register/email.spec.ts @@ -38,34 +38,33 @@ test.describe("Email Registration", async () => { await page.goto("/#/register"); }); - test("registers an account and lands on the use case selection screen", async ({ - page, - mailhog, - request, - checkA11y, - }) => { - await expect(page.getByRole("textbox", { name: "Username" })).toBeVisible(); - // Hide the server text as it contains the randomly allocated Homeserver port - const screenshotOptions = { mask: [page.locator(".mx_ServerPicker_server")] }; + test( + "registers an account and lands on the use case selection screen", + { tag: "@screenshot" }, + async ({ page, mailhog, request, checkA11y }) => { + await expect(page.getByRole("textbox", { name: "Username" })).toBeVisible(); + // Hide the server text as it contains the randomly allocated Homeserver port + const screenshotOptions = { mask: [page.locator(".mx_ServerPicker_server")] }; - await page.getByRole("textbox", { name: "Username" }).fill("alice"); - await page.getByPlaceholder("Password", { exact: true }).fill("totally a great password"); - await page.getByPlaceholder("Confirm password").fill("totally a great password"); - await page.getByPlaceholder("Email").fill("alice@email.com"); - await page.getByRole("button", { name: "Register" }).click(); + await page.getByRole("textbox", { name: "Username" }).fill("alice"); + await page.getByPlaceholder("Password", { exact: true }).fill("totally a great password"); + await page.getByPlaceholder("Confirm password").fill("totally a great password"); + await page.getByPlaceholder("Email").fill("alice@email.com"); + await page.getByRole("button", { name: "Register" }).click(); - await expect(page.getByText("Check your email to continue")).toBeVisible(); - await expect(page).toMatchScreenshot("registration_check_your_email.png", screenshotOptions); - await checkA11y(); + await expect(page.getByText("Check your email to continue")).toBeVisible(); + await expect(page).toMatchScreenshot("registration_check_your_email.png", screenshotOptions); + await checkA11y(); - await expect(page.getByText("An error was encountered when sending the email")).not.toBeVisible(); + await expect(page.getByText("An error was encountered when sending the email")).not.toBeVisible(); - const messages = await mailhog.api.messages(); - expect(messages.items).toHaveLength(1); - expect(messages.items[0].to).toEqual("alice@email.com"); - const [emailLink] = messages.items[0].text.match(/http.+/); - await request.get(emailLink); // "Click" the link in the email + const messages = await mailhog.api.messages(); + expect(messages.items).toHaveLength(1); + expect(messages.items[0].to).toEqual("alice@email.com"); + const [emailLink] = messages.items[0].text.match(/http.+/); + await request.get(emailLink); // "Click" the link in the email - await expect(page.locator(".mx_UseCaseSelection_skip")).toBeVisible(); - }); + await expect(page.locator(".mx_UseCaseSelection_skip")).toBeVisible(); + }, + ); }); diff --git a/playwright/e2e/register/register.spec.ts b/playwright/e2e/register/register.spec.ts index 2dd3779573d..19608ee174d 100644 --- a/playwright/e2e/register/register.spec.ts +++ b/playwright/e2e/register/register.spec.ts @@ -15,66 +15,73 @@ test.describe("Registration", () => { await page.goto("/#/register"); }); - test("registers an account and lands on the home screen", async ({ homeserver, page, checkA11y, crypto }) => { - await page.getByRole("button", { name: "Edit", exact: true }).click(); - await expect(page.getByRole("button", { name: "Continue", exact: true })).toBeVisible(); - - await expect(page.locator(".mx_Dialog")).toMatchScreenshot("server-picker.png"); - await checkA11y(); - - await page.getByRole("textbox", { name: "Other homeserver" }).fill(homeserver.config.baseUrl); - await page.getByRole("button", { name: "Continue", exact: true }).click(); - // wait for the dialog to go away - await expect(page.getByRole("dialog")).not.toBeVisible(); - - await expect(page.getByRole("textbox", { name: "Username", exact: true })).toBeVisible(); - // Hide the server text as it contains the randomly allocated Homeserver port - const screenshotOptions = { mask: [page.locator(".mx_ServerPicker_server")], includeDialogBackground: true }; - await expect(page).toMatchScreenshot("registration.png", screenshotOptions); - await checkA11y(); - - await page.getByRole("textbox", { name: "Username", exact: true }).fill("alice"); - await page.getByPlaceholder("Password", { exact: true }).fill("totally a great password"); - await page.getByPlaceholder("Confirm password", { exact: true }).fill("totally a great password"); - await page.getByRole("button", { name: "Register", exact: true }).click(); - - const dialog = page.getByRole("dialog"); - await expect(dialog).toBeVisible(); - await expect(page).toMatchScreenshot("email-prompt.png", screenshotOptions); - await checkA11y(); - await dialog.getByRole("button", { name: "Continue", exact: true }).click(); - - await expect(page.locator(".mx_InteractiveAuthEntryComponents_termsPolicy")).toBeVisible(); - await expect(page).toMatchScreenshot("terms-prompt.png", screenshotOptions); - await checkA11y(); - - const termsPolicy = page.locator(".mx_InteractiveAuthEntryComponents_termsPolicy"); - await termsPolicy.getByRole("checkbox").click(); // Click the checkbox before terms of service anchor link - await expect(termsPolicy.getByLabel("Privacy Policy")).toBeVisible(); - - await page.getByRole("button", { name: "Accept", exact: true }).click(); - - await expect(page.locator(".mx_UseCaseSelection_skip")).toBeVisible(); - await expect(page).toMatchScreenshot("use-case-selection.png", screenshotOptions); - await checkA11y(); - await page.getByRole("button", { name: "Skip", exact: true }).click(); - - await expect(page).toHaveURL(/\/#\/home$/); - - /* - * Cross-signing checks - */ - // check that the device considers itself verified - await page.getByRole("button", { name: "User menu", exact: true }).click(); - await page.getByRole("menuitem", { name: "All settings", exact: true }).click(); - await page.getByRole("tab", { name: "Sessions", exact: true }).click(); - await expect(page.getByTestId("current-session-section").getByTestId("device-metadata-isVerified")).toHaveText( - "Verified", - ); - - // check that cross-signing keys have been uploaded. - await crypto.assertDeviceIsCrossSigned(); - }); + test( + "registers an account and lands on the home screen", + { tag: "@screenshot" }, + async ({ homeserver, page, checkA11y, crypto }) => { + await page.getByRole("button", { name: "Edit", exact: true }).click(); + await expect(page.getByRole("button", { name: "Continue", exact: true })).toBeVisible(); + + await expect(page.locator(".mx_Dialog")).toMatchScreenshot("server-picker.png"); + await checkA11y(); + + await page.getByRole("textbox", { name: "Other homeserver" }).fill(homeserver.config.baseUrl); + await page.getByRole("button", { name: "Continue", exact: true }).click(); + // wait for the dialog to go away + await expect(page.getByRole("dialog")).not.toBeVisible(); + + await expect(page.getByRole("textbox", { name: "Username", exact: true })).toBeVisible(); + // Hide the server text as it contains the randomly allocated Homeserver port + const screenshotOptions = { + mask: [page.locator(".mx_ServerPicker_server")], + includeDialogBackground: true, + }; + await expect(page).toMatchScreenshot("registration.png", screenshotOptions); + await checkA11y(); + + await page.getByRole("textbox", { name: "Username", exact: true }).fill("alice"); + await page.getByPlaceholder("Password", { exact: true }).fill("totally a great password"); + await page.getByPlaceholder("Confirm password", { exact: true }).fill("totally a great password"); + await page.getByRole("button", { name: "Register", exact: true }).click(); + + const dialog = page.getByRole("dialog"); + await expect(dialog).toBeVisible(); + await expect(page).toMatchScreenshot("email-prompt.png", screenshotOptions); + await checkA11y(); + await dialog.getByRole("button", { name: "Continue", exact: true }).click(); + + await expect(page.locator(".mx_InteractiveAuthEntryComponents_termsPolicy")).toBeVisible(); + await expect(page).toMatchScreenshot("terms-prompt.png", screenshotOptions); + await checkA11y(); + + const termsPolicy = page.locator(".mx_InteractiveAuthEntryComponents_termsPolicy"); + await termsPolicy.getByRole("checkbox").click(); // Click the checkbox before terms of service anchor link + await expect(termsPolicy.getByLabel("Privacy Policy")).toBeVisible(); + + await page.getByRole("button", { name: "Accept", exact: true }).click(); + + await expect(page.locator(".mx_UseCaseSelection_skip")).toBeVisible(); + await expect(page).toMatchScreenshot("use-case-selection.png", screenshotOptions); + await checkA11y(); + await page.getByRole("button", { name: "Skip", exact: true }).click(); + + await expect(page).toHaveURL(/\/#\/home$/); + + /* + * Cross-signing checks + */ + // check that the device considers itself verified + await page.getByRole("button", { name: "User menu", exact: true }).click(); + await page.getByRole("menuitem", { name: "All settings", exact: true }).click(); + await page.getByRole("tab", { name: "Sessions", exact: true }).click(); + await expect( + page.getByTestId("current-session-section").getByTestId("device-metadata-isVerified"), + ).toHaveText("Verified"); + + // check that cross-signing keys have been uploaded. + await crypto.assertDeviceIsCrossSigned(); + }, + ); test("should require username to fulfil requirements and be available", async ({ homeserver, page }) => { await page.getByRole("button", { name: "Edit", exact: true }).click(); diff --git a/playwright/e2e/release-announcement/releaseAnnouncement.spec.ts b/playwright/e2e/release-announcement/releaseAnnouncement.spec.ts index 57c27caf1a5..e18d72ddba9 100644 --- a/playwright/e2e/release-announcement/releaseAnnouncement.spec.ts +++ b/playwright/e2e/release-announcement/releaseAnnouncement.spec.ts @@ -18,7 +18,7 @@ test.describe("Release announcement", () => { labsFlags: ["threadsActivityCentre"], }); - test("should display the release announcement process", async ({ page, app, util }) => { + test("should display the release announcement process", { tag: "@screenshot" }, async ({ page, app, util }) => { // The TAC release announcement should be displayed await util.assertReleaseAnnouncementIsVisible("Threads Activity Centre"); // Hide the release announcement diff --git a/playwright/e2e/right-panel/file-panel.spec.ts b/playwright/e2e/right-panel/file-panel.spec.ts index 1cb39aad256..c535bcdfbb6 100644 --- a/playwright/e2e/right-panel/file-panel.spec.ts +++ b/playwright/e2e/right-panel/file-panel.spec.ts @@ -40,7 +40,7 @@ test.describe("FilePanel", () => { }); test.describe("render", () => { - test("should render empty state", async ({ page }) => { + test("should render empty state", { tag: "@screenshot" }, async ({ page }) => { // Wait until the information about the empty state is rendered await expect(page.locator(".mx_EmptyState")).toBeVisible(); @@ -48,7 +48,7 @@ test.describe("FilePanel", () => { await expect(page.locator(".mx_RightPanel")).toMatchScreenshot("empty.png"); }); - test("should list tiles on the panel", async ({ page }) => { + test("should list tiles on the panel", { tag: "@screenshot" }, async ({ page }) => { // Upload multiple files await uploadFile(page, "playwright/sample-files/riot.png"); // Image await uploadFile(page, "playwright/sample-files/1sec.ogg"); // Audio diff --git a/playwright/e2e/right-panel/notification-panel.spec.ts b/playwright/e2e/right-panel/notification-panel.spec.ts index 1d10af97988..55a6be04505 100644 --- a/playwright/e2e/right-panel/notification-panel.spec.ts +++ b/playwright/e2e/right-panel/notification-panel.spec.ts @@ -21,7 +21,7 @@ test.describe("NotificationPanel", () => { await app.client.createRoom({ name: ROOM_NAME }); }); - test("should render empty state", async ({ page, app }) => { + test("should render empty state", { tag: "@screenshot" }, async ({ page, app }) => { await app.viewRoomByName(ROOM_NAME); await page.getByRole("button", { name: "Notifications" }).click(); diff --git a/playwright/e2e/right-panel/right-panel.spec.ts b/playwright/e2e/right-panel/right-panel.spec.ts index 110f24a5019..1e9b8ebe1d4 100644 --- a/playwright/e2e/right-panel/right-panel.spec.ts +++ b/playwright/e2e/right-panel/right-panel.spec.ts @@ -38,7 +38,7 @@ test.describe("RightPanel", () => { }); test.describe("in rooms", () => { - test("should handle long room address and long room name", async ({ page, app }) => { + test("should handle long room address and long room name", { tag: "@screenshot" }, async ({ page, app }) => { await app.client.createRoom({ name: ROOM_NAME_LONG }); await viewRoomSummaryByName(page, app, ROOM_NAME_LONG); diff --git a/playwright/e2e/room-directory/room-directory.spec.ts b/playwright/e2e/room-directory/room-directory.spec.ts index f078a858a2a..f299a929bb7 100644 --- a/playwright/e2e/room-directory/room-directory.spec.ts +++ b/playwright/e2e/room-directory/room-directory.spec.ts @@ -47,34 +47,40 @@ test.describe("Room Directory", () => { expect(resp.chunk[0].room_id).toEqual(roomId); }); - test("should allow finding published rooms in directory", async ({ page, app, user, bot }) => { - const name = "This is a public room"; - await bot.createRoom({ - visibility: "public" as Visibility, - name, - room_alias_name: "test1234", - }); - - await page.getByRole("button", { name: "Explore rooms" }).click(); - - const dialog = page.locator(".mx_SpotlightDialog"); - await dialog.getByRole("textbox", { name: "Search" }).fill("Unknown Room"); - await expect( - dialog.getByText("If you can't find the room you're looking for, ask for an invite or create a new room."), - ).toHaveClass("mx_SpotlightDialog_otherSearches_messageSearchText"); - - await expect(page.locator(".mx_Dialog")).toMatchScreenshot("filtered-no-results.png"); - - await dialog.getByRole("textbox", { name: "Search" }).fill("test1234"); - await expect(dialog.getByText(name)).toHaveClass("mx_SpotlightDialog_result_publicRoomName"); - - await expect(page.locator(".mx_Dialog")).toMatchScreenshot("filtered-one-result.png"); - - await page - .locator(".mx_SpotlightDialog .mx_SpotlightDialog_option") - .getByRole("button", { name: "Join" }) - .click(); - - await expect(page).toHaveURL("/#/room/#test1234:localhost"); - }); + test( + "should allow finding published rooms in directory", + { tag: "@screenshot" }, + async ({ page, app, user, bot }) => { + const name = "This is a public room"; + await bot.createRoom({ + visibility: "public" as Visibility, + name, + room_alias_name: "test1234", + }); + + await page.getByRole("button", { name: "Explore rooms" }).click(); + + const dialog = page.locator(".mx_SpotlightDialog"); + await dialog.getByRole("textbox", { name: "Search" }).fill("Unknown Room"); + await expect( + dialog.getByText( + "If you can't find the room you're looking for, ask for an invite or create a new room.", + ), + ).toHaveClass("mx_SpotlightDialog_otherSearches_messageSearchText"); + + await expect(page.locator(".mx_Dialog")).toMatchScreenshot("filtered-no-results.png"); + + await dialog.getByRole("textbox", { name: "Search" }).fill("test1234"); + await expect(dialog.getByText(name)).toHaveClass("mx_SpotlightDialog_result_publicRoomName"); + + await expect(page.locator(".mx_Dialog")).toMatchScreenshot("filtered-one-result.png"); + + await page + .locator(".mx_SpotlightDialog .mx_SpotlightDialog_option") + .getByRole("button", { name: "Join" }) + .click(); + + await expect(page).toHaveURL("/#/room/#test1234:localhost"); + }, + ); }); diff --git a/playwright/e2e/room/room-header.spec.ts b/playwright/e2e/room/room-header.spec.ts index 6ecf4b3b33b..971508b25bb 100644 --- a/playwright/e2e/room/room-header.spec.ts +++ b/playwright/e2e/room/room-header.spec.ts @@ -20,7 +20,7 @@ test.describe("Room Header", () => { test.use({ labsFlags: ["feature_notifications"], }); - test("should render default buttons properly", async ({ page, app, user }) => { + test("should render default buttons properly", { tag: "@screenshot" }, async ({ page, app, user }) => { await app.client.createRoom({ name: "Test Room" }); await app.viewRoomByName("Test Room"); @@ -51,34 +51,38 @@ test.describe("Room Header", () => { await expect(header).toMatchScreenshot("room-header.png"); }); - test("should render a very long room name without collapsing the buttons", async ({ page, app, user }) => { - const LONG_ROOM_NAME = - "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore " + - "et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " + - "aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum " + - "dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui " + - "officia deserunt mollit anim id est laborum."; + test( + "should render a very long room name without collapsing the buttons", + { tag: "@screenshot" }, + async ({ page, app, user }) => { + const LONG_ROOM_NAME = + "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore " + + "et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " + + "aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum " + + "dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui " + + "officia deserunt mollit anim id est laborum."; - await app.client.createRoom({ name: LONG_ROOM_NAME }); - await app.viewRoomByName(LONG_ROOM_NAME); + await app.client.createRoom({ name: LONG_ROOM_NAME }); + await app.viewRoomByName(LONG_ROOM_NAME); - const header = page.locator(".mx_RoomHeader"); - // Wait until the room name is set - await expect(page.locator(".mx_RoomHeader_heading").getByText(LONG_ROOM_NAME)).toBeVisible(); - - // Assert the size of buttons on RoomHeader are specified and the buttons are not compressed - // Note these assertions do not check the size of mx_LegacyRoomHeader_name button - const buttons = header.locator(".mx_Flex").getByRole("button"); - await expect(buttons).toHaveCount(5); - - for (const button of await buttons.all()) { - await expect(button).toBeVisible(); - await expect(button).toHaveCSS("height", "32px"); - await expect(button).toHaveCSS("width", "32px"); - } - - await expect(header).toMatchScreenshot("room-header-long-name.png"); - }); + const header = page.locator(".mx_RoomHeader"); + // Wait until the room name is set + await expect(page.locator(".mx_RoomHeader_heading").getByText(LONG_ROOM_NAME)).toBeVisible(); + + // Assert the size of buttons on RoomHeader are specified and the buttons are not compressed + // Note these assertions do not check the size of mx_LegacyRoomHeader_name button + const buttons = header.locator(".mx_Flex").getByRole("button"); + await expect(buttons).toHaveCount(5); + + for (const button of await buttons.all()) { + await expect(button).toBeVisible(); + await expect(button).toHaveCSS("height", "32px"); + await expect(button).toHaveCSS("width", "32px"); + } + + await expect(header).toMatchScreenshot("room-header-long-name.png"); + }, + ); }); test.describe("with a video room", () => { @@ -99,30 +103,34 @@ test.describe("Room Header", () => { test.describe("and with feature_notifications enabled", () => { test.use({ labsFlags: ["feature_video_rooms", "feature_notifications"] }); - test("should render buttons for chat, room info, threads and facepile", async ({ page, app, user }) => { - await createVideoRoom(page, app); + test( + "should render buttons for chat, room info, threads and facepile", + { tag: "@screenshot" }, + async ({ page, app, user }) => { + await createVideoRoom(page, app); - const header = page.locator(".mx_RoomHeader"); + const header = page.locator(".mx_RoomHeader"); - // There's two room info button - the header itself and the i button - const infoButtons = header.getByRole("button", { name: "Room info" }); - await expect(infoButtons).toHaveCount(2); - await expect(infoButtons.first()).toBeVisible(); - await expect(infoButtons.last()).toBeVisible(); + // There's two room info button - the header itself and the i button + const infoButtons = header.getByRole("button", { name: "Room info" }); + await expect(infoButtons).toHaveCount(2); + await expect(infoButtons.first()).toBeVisible(); + await expect(infoButtons.last()).toBeVisible(); - // Facepile - await expect(header.locator(".mx_FacePile")).toBeVisible(); + // Facepile + await expect(header.locator(".mx_FacePile")).toBeVisible(); - // Chat, Threads and Notification buttons - await expect(header.getByRole("button", { name: "Chat" })).toBeVisible(); - await expect(header.getByRole("button", { name: "Threads" })).toBeVisible(); - await expect(header.getByRole("button", { name: "Notifications" })).toBeVisible(); + // Chat, Threads and Notification buttons + await expect(header.getByRole("button", { name: "Chat" })).toBeVisible(); + await expect(header.getByRole("button", { name: "Threads" })).toBeVisible(); + await expect(header.getByRole("button", { name: "Notifications" })).toBeVisible(); - // Assert that there is not a button except those buttons - await expect(header.getByRole("button")).toHaveCount(7); + // Assert that there is not a button except those buttons + await expect(header.getByRole("button")).toHaveCount(7); - await expect(header).toMatchScreenshot("room-header-video-room.png"); - }); + await expect(header).toMatchScreenshot("room-header-video-room.png"); + }, + ); }); test("should render a working chat button which opens the timeline on a right panel", async ({ diff --git a/playwright/e2e/settings/account-user-settings-tab.spec.ts b/playwright/e2e/settings/account-user-settings-tab.spec.ts index 5492094f937..7390ccfd8d1 100644 --- a/playwright/e2e/settings/account-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/account-user-settings-tab.spec.ts @@ -23,7 +23,7 @@ test.describe("Account user settings tab", () => { }, }); - test("should be rendered properly", async ({ uut, user }) => { + test("should be rendered properly", { tag: "@screenshot" }, async ({ uut, user }) => { await expect(uut).toMatchScreenshot("account.png"); // Assert that the top heading is rendered @@ -71,7 +71,7 @@ test.describe("Account user settings tab", () => { ); }); - test("should respond to small screen sizes", async ({ page, uut }) => { + test("should respond to small screen sizes", { tag: "@screenshot" }, async ({ page, uut }) => { await page.setViewportSize({ width: 700, height: 600 }); await expect(uut).toMatchScreenshot("account-smallscreen.png"); }); diff --git a/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts b/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts index de6c9c527a6..c60ecb99d25 100644 --- a/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts @@ -13,7 +13,7 @@ test.describe("Appearance user settings tab", () => { displayName: "Hanako", }); - test("should be rendered properly", async ({ page, user, app }) => { + test("should be rendered properly", { tag: "@screenshot" }, async ({ page, user, app }) => { const tab = await app.settings.openUserSettings("Appearance"); // Click "Show advanced" link button @@ -25,19 +25,23 @@ test.describe("Appearance user settings tab", () => { await expect(tab).toMatchScreenshot("appearance-tab.png"); }); - test("should support changing font size by using the font size dropdown", async ({ page, app, user }) => { - await app.settings.openUserSettings("Appearance"); + test( + "should support changing font size by using the font size dropdown", + { tag: "@screenshot" }, + async ({ page, app, user }) => { + await app.settings.openUserSettings("Appearance"); - const tab = page.getByTestId("mx_AppearanceUserSettingsTab"); - const fontDropdown = tab.locator(".mx_FontScalingPanel_Dropdown"); - await expect(fontDropdown.getByLabel("Font size")).toBeVisible(); + const tab = page.getByTestId("mx_AppearanceUserSettingsTab"); + const fontDropdown = tab.locator(".mx_FontScalingPanel_Dropdown"); + await expect(fontDropdown.getByLabel("Font size")).toBeVisible(); - // Default browser font size is 16px and the select value is 0 - // -4 value is 12px - await fontDropdown.getByLabel("Font size").selectOption({ value: "-4" }); + // Default browser font size is 16px and the select value is 0 + // -4 value is 12px + await fontDropdown.getByLabel("Font size").selectOption({ value: "-4" }); - await expect(page).toMatchScreenshot("window-12px.png", { includeDialogBackground: true }); - }); + await expect(page).toMatchScreenshot("window-12px.png", { includeDialogBackground: true }); + }, + ); test("should support enabling system font", async ({ page, app, user }) => { await app.settings.openUserSettings("Appearance"); diff --git a/playwright/e2e/settings/appearance-user-settings-tab/message-layout-panel.ts b/playwright/e2e/settings/appearance-user-settings-tab/message-layout-panel.ts index a0288baf1dd..157942a5853 100644 --- a/playwright/e2e/settings/appearance-user-settings-tab/message-layout-panel.ts +++ b/playwright/e2e/settings/appearance-user-settings-tab/message-layout-panel.ts @@ -20,20 +20,24 @@ test.describe("Appearance user settings tab", () => { await util.openAppearanceTab(); }); - test("should change the message layout from modern to bubble", async ({ page, app, user, util }) => { - await util.assertScreenshot(util.getMessageLayoutPanel(), "message-layout-panel-modern.png"); - - await util.getBubbleLayout().click(); - - // Assert that modern are irc layout are not selected - await expect(util.getBubbleLayout()).toBeChecked(); - await expect(util.getModernLayout()).not.toBeChecked(); - await expect(util.getIRCLayout()).not.toBeChecked(); - - // Assert that the room layout is set to bubble layout - await util.assertBubbleLayout(); - await util.assertScreenshot(util.getMessageLayoutPanel(), "message-layout-panel-bubble.png"); - }); + test( + "should change the message layout from modern to bubble", + { tag: "@screenshot" }, + async ({ page, app, user, util }) => { + await util.assertScreenshot(util.getMessageLayoutPanel(), "message-layout-panel-modern.png"); + + await util.getBubbleLayout().click(); + + // Assert that modern are irc layout are not selected + await expect(util.getBubbleLayout()).toBeChecked(); + await expect(util.getModernLayout()).not.toBeChecked(); + await expect(util.getIRCLayout()).not.toBeChecked(); + + // Assert that the room layout is set to bubble layout + await util.assertBubbleLayout(); + await util.assertScreenshot(util.getMessageLayoutPanel(), "message-layout-panel-bubble.png"); + }, + ); test("should enable compact layout when the modern layout is selected", async ({ page, app, user, util }) => { await expect(util.getCompactLayoutCheckbox()).not.toBeChecked(); diff --git a/playwright/e2e/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts b/playwright/e2e/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts index 4f3b75b5baa..63b53caa23e 100644 --- a/playwright/e2e/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts +++ b/playwright/e2e/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts @@ -20,31 +20,39 @@ test.describe("Appearance user settings tab", () => { await util.openAppearanceTab(); }); - test("should be rendered with the light theme selected", async ({ page, app, util }) => { - // Assert that 'Match system theme' is not checked - await expect(util.getMatchSystemThemeCheckbox()).not.toBeChecked(); - - // Assert that the light theme is selected - await expect(util.getLightTheme()).toBeChecked(); - // Assert that the dark and high contrast themes are not selected - await expect(util.getDarkTheme()).not.toBeChecked(); - await expect(util.getHighContrastTheme()).not.toBeChecked(); - - await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-light.png"); - }); - - test("should disable the themes when the system theme is clicked", async ({ page, app, util }) => { - await util.getMatchSystemThemeCheckbox().click(); - - // Assert that the themes are disabled - await expect(util.getLightTheme()).toBeDisabled(); - await expect(util.getDarkTheme()).toBeDisabled(); - await expect(util.getHighContrastTheme()).toBeDisabled(); - - await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-match-system-enabled.png"); - }); - - test("should change the theme to dark", async ({ page, app, util }) => { + test( + "should be rendered with the light theme selected", + { tag: "@screenshot" }, + async ({ page, app, util }) => { + // Assert that 'Match system theme' is not checked + await expect(util.getMatchSystemThemeCheckbox()).not.toBeChecked(); + + // Assert that the light theme is selected + await expect(util.getLightTheme()).toBeChecked(); + // Assert that the dark and high contrast themes are not selected + await expect(util.getDarkTheme()).not.toBeChecked(); + await expect(util.getHighContrastTheme()).not.toBeChecked(); + + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-light.png"); + }, + ); + + test( + "should disable the themes when the system theme is clicked", + { tag: "@screenshot" }, + async ({ page, app, util }) => { + await util.getMatchSystemThemeCheckbox().click(); + + // Assert that the themes are disabled + await expect(util.getLightTheme()).toBeDisabled(); + await expect(util.getDarkTheme()).toBeDisabled(); + await expect(util.getHighContrastTheme()).toBeDisabled(); + + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-match-system-enabled.png"); + }, + ); + + test("should change the theme to dark", { tag: "@screenshot" }, async ({ page, app, util }) => { // Assert that the light theme is selected await expect(util.getLightTheme()).toBeChecked(); @@ -63,19 +71,23 @@ test.describe("Appearance user settings tab", () => { labsFlags: ["feature_custom_themes"], }); - test("should render the custom theme section", async ({ page, app, util }) => { + test("should render the custom theme section", { tag: "@screenshot" }, async ({ page, app, util }) => { await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-custom-theme.png"); }); - test("should be able to add and remove a custom theme", async ({ page, app, util }) => { - await util.addCustomTheme(); + test( + "should be able to add and remove a custom theme", + { tag: "@screenshot" }, + async ({ page, app, util }) => { + await util.addCustomTheme(); - await expect(util.getCustomTheme()).not.toBeChecked(); - await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-custom-theme-added.png"); + await expect(util.getCustomTheme()).not.toBeChecked(); + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-custom-theme-added.png"); - await util.removeCustomTheme(); - await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-custom-theme-removed.png"); - }); + await util.removeCustomTheme(); + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-custom-theme-removed.png"); + }, + ); }); }); }); diff --git a/playwright/e2e/settings/general-room-settings-tab.spec.ts b/playwright/e2e/settings/general-room-settings-tab.spec.ts index 47582bf0c0e..828ba5285bb 100644 --- a/playwright/e2e/settings/general-room-settings-tab.spec.ts +++ b/playwright/e2e/settings/general-room-settings-tab.spec.ts @@ -20,7 +20,7 @@ test.describe("General room settings tab", () => { await app.viewRoomByName(roomName); }); - test("should be rendered properly", async ({ page, app }) => { + test("should be rendered properly", { tag: "@screenshot" }, async ({ page, app }) => { const settings = await app.settings.openRoomSettings("General"); // Assert that "Show less" details element is rendered diff --git a/playwright/e2e/settings/preferences-user-settings-tab.spec.ts b/playwright/e2e/settings/preferences-user-settings-tab.spec.ts index 0880853ee81..8dc2570b426 100644 --- a/playwright/e2e/settings/preferences-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/preferences-user-settings-tab.spec.ts @@ -23,7 +23,7 @@ test.describe("Preferences user settings tab", () => { }, }); - test("should be rendered properly", async ({ app, page, user }) => { + test("should be rendered properly", { tag: "@screenshot" }, async ({ app, page, user }) => { page.setViewportSize({ width: 1024, height: 3300 }); const tab = await app.settings.openUserSettings("Preferences"); // Assert that the top heading is rendered diff --git a/playwright/e2e/settings/security-user-settings-tab.spec.ts b/playwright/e2e/settings/security-user-settings-tab.spec.ts index 6eab8306232..e7562698c33 100644 --- a/playwright/e2e/settings/security-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/security-user-settings-tab.spec.ts @@ -36,7 +36,7 @@ test.describe("Security user settings tab", () => { }); test.describe("AnalyticsLearnMoreDialog", () => { - test("should be rendered properly", async ({ app, page }) => { + test("should be rendered properly", { tag: "@screenshot" }, async ({ app, page }) => { const tab = await app.settings.openUserSettings("Security"); await tab.getByRole("button", { name: "Learn more" }).click(); await expect(page.locator(".mx_AnalyticsLearnMoreDialog_wrapper .mx_Dialog")).toMatchScreenshot( diff --git a/playwright/e2e/share-dialog/share-dialog.spec.ts b/playwright/e2e/share-dialog/share-dialog.spec.ts index 2999b74ca03..e0993dd1bc4 100644 --- a/playwright/e2e/share-dialog/share-dialog.spec.ts +++ b/playwright/e2e/share-dialog/share-dialog.spec.ts @@ -16,7 +16,7 @@ test.describe("Share dialog", () => { }, }); - test("should share a room", async ({ page, app, room }) => { + test("should share a room", { tag: "@screenshot" }, async ({ page, app, room }) => { await app.viewRoomById(room.roomId); await app.toggleRoomInfoPanel(); await page.getByRole("menuitem", { name: "Copy link" }).click(); @@ -29,7 +29,7 @@ test.describe("Share dialog", () => { }); }); - test("should share a room member", async ({ page, app, room, user }) => { + test("should share a room member", { tag: "@screenshot" }, async ({ page, app, room, user }) => { await app.viewRoomById(room.roomId); await app.client.sendMessage(room.roomId, { body: "hello", msgtype: "m.text" }); @@ -46,7 +46,7 @@ test.describe("Share dialog", () => { }); }); - test("should share an event", async ({ page, app, room }) => { + test("should share an event", { tag: "@screenshot" }, async ({ page, app, room }) => { await app.viewRoomById(room.roomId); await app.client.sendMessage(room.roomId, { body: "hello", msgtype: "m.text" }); diff --git a/playwright/e2e/spaces/spaces.spec.ts b/playwright/e2e/spaces/spaces.spec.ts index 575450c6414..233cdee3b4b 100644 --- a/playwright/e2e/spaces/spaces.spec.ts +++ b/playwright/e2e/spaces/spaces.spec.ts @@ -55,7 +55,7 @@ test.describe("Spaces", () => { botCreateOpts: { displayName: "BotBob" }, }); - test("should allow user to create public space", async ({ page, app, user }) => { + test("should allow user to create public space", { tag: "@screenshot" }, async ({ page, app, user }) => { const contextMenu = await openSpaceCreateMenu(page); await expect(contextMenu).toMatchScreenshot("space-create-menu.png"); @@ -88,7 +88,7 @@ test.describe("Spaces", () => { await expect(page.getByRole("treeitem", { name: "Jokes" })).toBeVisible(); }); - test("should allow user to create private space", async ({ page, app, user }) => { + test("should allow user to create private space", { tag: "@screenshot" }, async ({ page, app, user }) => { const menu = await openSpaceCreateMenu(page); await menu.getByRole("button", { name: "Private" }).click(); @@ -216,49 +216,47 @@ test.describe("Spaces", () => { await expect(hierarchyList.getByRole("treeitem", { name: "Gaming" }).getByRole("button")).toBeVisible(); }); - test("should render subspaces in the space panel only when expanded", async ({ - page, - app, - user, - axe, - checkA11y, - }) => { - axe.disableRules([ - // Disable this check as it triggers on nested roving tab index elements which are in practice fine - "nested-interactive", - // XXX: We have some known contrast issues here - "color-contrast", - ]); - - const childSpaceId = await app.client.createSpace({ - name: "Child Space", - initial_state: [], - }); - await app.client.createSpace({ - name: "Root Space", - initial_state: [spaceChildInitialState(childSpaceId)], - }); - - // Find collapsed Space panel - const spaceTree = page.getByRole("tree", { name: "Spaces" }); - await expect(spaceTree.getByRole("button", { name: "Root Space" })).toBeVisible(); - await expect(spaceTree.getByRole("button", { name: "Child Space" })).not.toBeVisible(); - - await checkA11y(); - await expect(page.locator(".mx_SpacePanel")).toMatchScreenshot("space-panel-collapsed.png"); - - // This finds the expand button with the class name "mx_SpaceButton_toggleCollapse". Note there is another - // button with the same name with different class name "mx_SpacePanel_toggleCollapse". - await spaceTree.getByRole("button", { name: "Expand" }).click(); - await expect(page.locator(".mx_SpacePanel:not(.collapsed)")).toBeVisible(); // TODO: replace :not() selector - - const item = page.locator(".mx_SpaceItem", { hasText: "Root Space" }); - await expect(item).toBeVisible(); - await expect(item.locator(".mx_SpaceItem", { hasText: "Child Space" })).toBeVisible(); - - await checkA11y(); - await expect(page.locator(".mx_SpacePanel")).toMatchScreenshot("space-panel-expanded.png"); - }); + test( + "should render subspaces in the space panel only when expanded", + { tag: "@screenshot" }, + async ({ page, app, user, axe, checkA11y }) => { + axe.disableRules([ + // Disable this check as it triggers on nested roving tab index elements which are in practice fine + "nested-interactive", + // XXX: We have some known contrast issues here + "color-contrast", + ]); + + const childSpaceId = await app.client.createSpace({ + name: "Child Space", + initial_state: [], + }); + await app.client.createSpace({ + name: "Root Space", + initial_state: [spaceChildInitialState(childSpaceId)], + }); + + // Find collapsed Space panel + const spaceTree = page.getByRole("tree", { name: "Spaces" }); + await expect(spaceTree.getByRole("button", { name: "Root Space" })).toBeVisible(); + await expect(spaceTree.getByRole("button", { name: "Child Space" })).not.toBeVisible(); + + await checkA11y(); + await expect(page.locator(".mx_SpacePanel")).toMatchScreenshot("space-panel-collapsed.png"); + + // This finds the expand button with the class name "mx_SpaceButton_toggleCollapse". Note there is another + // button with the same name with different class name "mx_SpacePanel_toggleCollapse". + await spaceTree.getByRole("button", { name: "Expand" }).click(); + await expect(page.locator(".mx_SpacePanel:not(.collapsed)")).toBeVisible(); // TODO: replace :not() selector + + const item = page.locator(".mx_SpaceItem", { hasText: "Root Space" }); + await expect(item).toBeVisible(); + await expect(item.locator(".mx_SpaceItem", { hasText: "Child Space" })).toBeVisible(); + + await checkA11y(); + await expect(page.locator(".mx_SpacePanel")).toMatchScreenshot("space-panel-expanded.png"); + }, + ); test("should not soft crash when joining a room from space hierarchy which has a link in its topic", async ({ page, diff --git a/playwright/e2e/spaces/threads-activity-centre/index.ts b/playwright/e2e/spaces/threads-activity-centre/index.ts index f6ac7f95d69..b2b8473640e 100644 --- a/playwright/e2e/spaces/threads-activity-centre/index.ts +++ b/playwright/e2e/spaces/threads-activity-centre/index.ts @@ -276,7 +276,7 @@ export class Helpers { * Assert that the threads activity centre button has no indicator */ async assertNoTacIndicator() { - // Assert by checkng neither of the known indicators are visible first. This will wait + // Assert by checking neither of the known indicators are visible first. This will wait // if it takes a little time to disappear, but the screenshot comparison won't. await expect(this.getTacButton().locator("[data-indicator='success']")).not.toBeVisible(); await expect(this.getTacButton().locator("[data-indicator='critical']")).not.toBeVisible(); @@ -376,7 +376,7 @@ export class Helpers { * Clicks the button to mark all threads as read in the current room */ clickMarkAllThreadsRead() { - return this.page.getByLabel("Mark all as read").click(); + return this.page.locator("#thread-panel").getByRole("button", { name: "Mark all as read" }).click(); } } diff --git a/playwright/e2e/spaces/threads-activity-centre/threadsActivityCentre.spec.ts b/playwright/e2e/spaces/threads-activity-centre/threadsActivityCentre.spec.ts index fc66c13520d..ecf458c0600 100644 --- a/playwright/e2e/spaces/threads-activity-centre/threadsActivityCentre.spec.ts +++ b/playwright/e2e/spaces/threads-activity-centre/threadsActivityCentre.spec.ts @@ -16,16 +16,18 @@ test.describe("Threads Activity Centre", () => { labsFlags: ["threadsActivityCentre"], }); - test("should have the button correctly aligned and displayed in the space panel when expanded", async ({ - util, - }) => { - // Open the space panel - await util.expandSpacePanel(); - // The buttons in the space panel should be aligned when expanded - await expect(util.getSpacePanel()).toMatchScreenshot("tac-button-expanded.png"); - }); - - test("should not show indicator when there is no thread", async ({ room1, util }) => { + test( + "should have the button correctly aligned and displayed in the space panel when expanded", + { tag: "@screenshot" }, + async ({ util }) => { + // Open the space panel + await util.expandSpacePanel(); + // The buttons in the space panel should be aligned when expanded + await expect(util.getSpacePanel()).toMatchScreenshot("tac-button-expanded.png"); + }, + ); + + test("should not show indicator when there is no thread", { tag: "@screenshot" }, async ({ room1, util }) => { // No indicator should be shown await util.assertNoTacIndicator(); @@ -62,7 +64,7 @@ test.describe("Threads Activity Centre", () => { await util.assertHighlightIndicator(); }); - test("should show the rooms with unread threads", async ({ room1, room2, util, msg }) => { + test("should show the rooms with unread threads", { tag: "@screenshot" }, async ({ room1, room2, util, msg }) => { await util.goTo(room2); await util.populateThreads(room1, room2, msg); // The indicator should be shown @@ -79,7 +81,7 @@ test.describe("Threads Activity Centre", () => { await expect(util.getTacPanel()).toMatchScreenshot("tac-panel-mix-unread.png"); }); - test("should update with a thread is read", async ({ room1, room2, util, msg }) => { + test("should update with a thread is read", { tag: "@screenshot" }, async ({ room1, room2, util, msg }) => { await util.goTo(room2); await util.populateThreads(room1, room2, msg); @@ -128,7 +130,7 @@ test.describe("Threads Activity Centre", () => { await expect(page.locator(".mx_SpotlightDialog")).not.toBeVisible(); }); - test("should have the correct hover state", async ({ util, page }) => { + test("should have the correct hover state", { tag: "@screenshot" }, async ({ util, page }) => { await util.hoverTacButton(); await expect(util.getSpacePanel()).toMatchScreenshot("tac-hovered.png"); @@ -138,7 +140,7 @@ test.describe("Threads Activity Centre", () => { await expect(util.getSpacePanel()).toMatchScreenshot("tac-hovered-expanded.png"); }); - test("should mark all threads as read", async ({ room1, room2, util, msg, page }) => { + test("should mark all threads as read", { tag: "@screenshot" }, async ({ room1, room2, util, msg, page }) => { await util.receiveMessages(room1, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); await util.assertNotificationTac(); @@ -146,7 +148,7 @@ test.describe("Threads Activity Centre", () => { await util.openTac(); await util.clickRoomInTac(room1.name); - util.clickMarkAllThreadsRead(); + await util.clickMarkAllThreadsRead(); await util.assertNoTacIndicator(); }); diff --git a/playwright/e2e/threads/threads.spec.ts b/playwright/e2e/threads/threads.spec.ts index a2642a49d16..06ec57653c7 100644 --- a/playwright/e2e/threads/threads.spec.ts +++ b/playwright/e2e/threads/threads.spec.ts @@ -25,7 +25,7 @@ test.describe("Threads", () => { }); // Flaky: https://github.com/vector-im/element-web/issues/26452 - test.skip("should be usable for a conversation", async ({ page, app, bot }) => { + test.skip("should be usable for a conversation", { tag: "@screenshot" }, async ({ page, app, bot }) => { const roomId = await app.client.createRoom({}); await app.client.inviteUser(roomId, bot.credentials.userId); await bot.joinRoom(roomId); @@ -150,7 +150,7 @@ test.describe("Threads", () => { ).toHaveCSS("padding-inline-start", ThreadViewGroupSpacingStart); // Take snapshot of group layout (IRC layout is not available on ThreadView) - expect(page.locator(".mx_ThreadView")).toMatchScreenshot( + await expect(page.locator(".mx_ThreadView")).toMatchScreenshot( "ThreadView_with_reaction_and_a_hidden_event_on_group_layout.png", { mask: mask, @@ -174,7 +174,7 @@ test.describe("Threads", () => { .toHaveCSS("margin-inline-start", "0px"); // Take snapshot of bubble layout - expect(page.locator(".mx_ThreadView")).toMatchScreenshot( + await expect(page.locator(".mx_ThreadView")).toMatchScreenshot( "ThreadView_with_reaction_and_a_hidden_event_on_bubble_layout.png", { mask: mask, @@ -351,57 +351,61 @@ test.describe("Threads", () => { }); }); - test("should send location and reply to the location on ThreadView", async ({ page, app, bot }) => { - const roomId = await app.client.createRoom({}); - await app.client.inviteUser(roomId, bot.credentials.userId); - await bot.joinRoom(roomId); - await page.goto("/#/room/" + roomId); - - // Exclude timestamp, read marker, and maplibregl-map from snapshots - const css = - ".mx_MessageTimestamp, .mx_MessagePanel_myReadMarker, .maplibregl-map { visibility: hidden !important; }"; + test( + "should send location and reply to the location on ThreadView", + { tag: "@screenshot" }, + async ({ page, app, bot }) => { + const roomId = await app.client.createRoom({}); + await app.client.inviteUser(roomId, bot.credentials.userId); + await bot.joinRoom(roomId); + await page.goto("/#/room/" + roomId); - let locator = page.locator(".mx_RoomView_body"); - // User sends message - let textbox = locator.getByRole("textbox", { name: "Send a message…" }); - await textbox.fill("Hello Mr. Bot"); - await textbox.press("Enter"); - // Wait for message to send, get its ID and save as @threadId - const threadId = await locator - .locator(".mx_EventTile[data-scroll-tokens]") - .filter({ hasText: "Hello Mr. Bot" }) - .getAttribute("data-scroll-tokens"); + // Exclude timestamp, read marker, and maplibregl-map from snapshots + const css = + ".mx_MessageTimestamp, .mx_MessagePanel_myReadMarker, .maplibregl-map { visibility: hidden !important; }"; - // Bot starts thread - await bot.sendMessage(roomId, "Hello there", threadId); - - // User clicks thread summary - await page.locator(".mx_RoomView_body .mx_ThreadSummary").click(); - - // User sends location on ThreadView - await expect(page.locator(".mx_ThreadView")).toBeAttached(); - await (await app.openMessageComposerOptions(true)).getByRole("menuitem", { name: "Location" }).click(); - await page.getByTestId(`share-location-option-Pin`).click(); - await page.locator("#mx_LocationPicker_map").click(); - await page.getByRole("button", { name: "Share location" }).click(); - await expect(page.locator(".mx_ThreadView .mx_EventTile_last .mx_MLocationBody")).toBeAttached({ - timeout: 10000, - }); + let locator = page.locator(".mx_RoomView_body"); + // User sends message + let textbox = locator.getByRole("textbox", { name: "Send a message…" }); + await textbox.fill("Hello Mr. Bot"); + await textbox.press("Enter"); + // Wait for message to send, get its ID and save as @threadId + const threadId = await locator + .locator(".mx_EventTile[data-scroll-tokens]") + .filter({ hasText: "Hello Mr. Bot" }) + .getAttribute("data-scroll-tokens"); + + // Bot starts thread + await bot.sendMessage(roomId, "Hello there", threadId); + + // User clicks thread summary + await page.locator(".mx_RoomView_body .mx_ThreadSummary").click(); + + // User sends location on ThreadView + await expect(page.locator(".mx_ThreadView")).toBeAttached(); + await (await app.openMessageComposerOptions(true)).getByRole("menuitem", { name: "Location" }).click(); + await page.getByTestId(`share-location-option-Pin`).click(); + await page.locator("#mx_LocationPicker_map").click(); + await page.getByRole("button", { name: "Share location" }).click(); + await expect(page.locator(".mx_ThreadView .mx_EventTile_last .mx_MLocationBody")).toBeAttached({ + timeout: 10000, + }); - // User replies to the location - locator = page.locator(".mx_ThreadView"); - await locator.locator(".mx_EventTile_last").hover(); - await locator.locator(".mx_EventTile_last").getByRole("button", { name: "Reply" }).click(); - textbox = locator.getByRole("textbox", { name: "Reply to thread…" }); - await textbox.fill("Please come here"); - await textbox.press("Enter"); - // Wait until the reply is sent - await expect(locator.locator(".mx_EventTile_last .mx_EventTile_receiptSent")).toBeVisible(); + // User replies to the location + locator = page.locator(".mx_ThreadView"); + await locator.locator(".mx_EventTile_last").hover(); + await locator.locator(".mx_EventTile_last").getByRole("button", { name: "Reply" }).click(); + textbox = locator.getByRole("textbox", { name: "Reply to thread…" }); + await textbox.fill("Please come here"); + await textbox.press("Enter"); + // Wait until the reply is sent + await expect(locator.locator(".mx_EventTile_last .mx_EventTile_receiptSent")).toBeVisible(); - // Take a snapshot of reply to the shared location - await page.addStyleTag({ content: css }); - await expect(page.locator(".mx_ThreadView")).toMatchScreenshot("Reply_to_the_location_on_ThreadView.png"); - }); + // Take a snapshot of reply to the shared location + await page.addStyleTag({ content: css }); + await expect(page.locator(".mx_ThreadView")).toMatchScreenshot("Reply_to_the_location_on_ThreadView.png"); + }, + ); test("right panel behaves correctly", async ({ page, app, user }) => { // Create room diff --git a/playwright/e2e/timeline/timeline.spec.ts b/playwright/e2e/timeline/timeline.spec.ts index e8ef0e577c2..7aaabb9759d 100644 --- a/playwright/e2e/timeline/timeline.spec.ts +++ b/playwright/e2e/timeline/timeline.spec.ts @@ -137,182 +137,190 @@ test.describe("Timeline", () => { }); test.describe("configure room", () => { - test("should create and configure a room on IRC layout", async ({ page, app, room }) => { - await page.goto(`/#/room/${room.roomId}`); - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); - await expect( - page.locator( - ".mx_RoomView_body .mx_GenericEventListSummary[data-layout='irc'] .mx_GenericEventListSummary_summary", - { hasText: `${OLD_NAME} created and configured the room.` }, - ), - ).toBeVisible(); - - // wait for the date separator to appear to have a stable screenshot - await expect(page.locator(".mx_TimelineSeparator")).toHaveText("today"); - - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("configured-room-irc-layout.png"); - }); - - test("should have an expanded generic event list summary (GELS) on IRC layout", async ({ page, app, room }) => { - await page.goto(`/#/room/${room.roomId}`); - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); - - // Wait until configuration is finished - await expect( - page.locator( - ".mx_RoomView_body .mx_GenericEventListSummary[data-layout='irc'] .mx_GenericEventListSummary_summary", - { hasText: `${OLD_NAME} created and configured the room.` }, - ), - ).toBeVisible(); - - const gels = page.locator(".mx_GenericEventListSummary"); - // Click "expand" link button - await gels.getByRole("button", { name: "Expand" }).click(); - // Assert that the "expand" link button worked - await expect(gels.getByRole("button", { name: "Collapse" })).toBeVisible(); + test( + "should create and configure a room on IRC layout", + { tag: "@screenshot" }, + async ({ page, app, room }) => { + await page.goto(`/#/room/${room.roomId}`); + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); + await expect( + page.locator( + ".mx_RoomView_body .mx_GenericEventListSummary[data-layout='irc'] .mx_GenericEventListSummary_summary", + { hasText: `${OLD_NAME} created and configured the room.` }, + ), + ).toBeVisible(); + + // wait for the date separator to appear to have a stable screenshot + await expect(page.locator(".mx_TimelineSeparator")).toHaveText("today"); + + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("configured-room-irc-layout.png"); + }, + ); + + test( + "should have an expanded generic event list summary (GELS) on IRC layout", + { tag: "@screenshot" }, + async ({ page, app, room }) => { + await page.goto(`/#/room/${room.roomId}`); + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-irc-layout.png", { - mask: [page.locator(".mx_MessageTimestamp")], - css: ` + // Wait until configuration is finished + await expect( + page.locator( + ".mx_RoomView_body .mx_GenericEventListSummary[data-layout='irc'] .mx_GenericEventListSummary_summary", + { hasText: `${OLD_NAME} created and configured the room.` }, + ), + ).toBeVisible(); + + const gels = page.locator(".mx_GenericEventListSummary"); + // Click "expand" link button + await gels.getByRole("button", { name: "Expand" }).click(); + // Assert that the "expand" link button worked + await expect(gels.getByRole("button", { name: "Collapse" })).toBeVisible(); + + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-irc-layout.png", { + mask: [page.locator(".mx_MessageTimestamp")], + css: ` .mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker { display: none !important; } `, - }); - }); - - test("should have an expanded generic event list summary (GELS) on compact modern/group layout", async ({ - page, - app, - room, - }) => { - await page.goto(`/#/room/${room.roomId}`); - - // Set compact modern layout - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); - await app.settings.setValue("useCompactLayout", null, SettingLevel.DEVICE, true); + }); + }, + ); - // Wait until configuration is finished - await expect( - page.locator(".mx_RoomView_body .mx_GenericEventListSummary[data-layout='group']", { - hasText: `${OLD_NAME} created and configured the room.`, - }), - ).toBeVisible(); + test( + "should have an expanded generic event list summary (GELS) on compact modern/group layout", + { tag: "@screenshot" }, + async ({ page, app, room }) => { + await page.goto(`/#/room/${room.roomId}`); - const gels = page.locator(".mx_GenericEventListSummary"); - // Click "expand" link button - await gels.getByRole("button", { name: "Expand" }).click(); - // Assert that the "expand" link button worked - await expect(gels.getByRole("button", { name: "Collapse" })).toBeVisible(); + // Set compact modern layout + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); + await app.settings.setValue("useCompactLayout", null, SettingLevel.DEVICE, true); - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-modern-layout.png", { - mask: [page.locator(".mx_MessageTimestamp")], - css: ` + // Wait until configuration is finished + await expect( + page.locator(".mx_RoomView_body .mx_GenericEventListSummary[data-layout='group']", { + hasText: `${OLD_NAME} created and configured the room.`, + }), + ).toBeVisible(); + + const gels = page.locator(".mx_GenericEventListSummary"); + // Click "expand" link button + await gels.getByRole("button", { name: "Expand" }).click(); + // Assert that the "expand" link button worked + await expect(gels.getByRole("button", { name: "Collapse" })).toBeVisible(); + + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-modern-layout.png", { + mask: [page.locator(".mx_MessageTimestamp")], + css: ` .mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker { display: none !important; } `, - }); - }); - - test("should click 'collapse' on the first hovered info event line inside GELS on bubble layout", async ({ - page, - app, - room, - }) => { - // This test checks clickability of the "Collapse" link button, which had been covered with - // MessageActionBar's safe area - https://github.com/vector-im/element-web/issues/22864 - - await page.goto(`/#/room/${room.roomId}`); - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble); - await expect( - page.locator( - ".mx_RoomView_body .mx_GenericEventListSummary[data-layout='bubble'] .mx_GenericEventListSummary_summary", - { hasText: `${OLD_NAME} created and configured the room.` }, - ), - ).toBeVisible(); - - const gels = page.locator(".mx_GenericEventListSummary"); - // Click "expand" link button - await gels.getByRole("button", { name: "Expand" }).click(); - // Assert that the "expand" link button worked - await expect(gels.getByRole("button", { name: "Collapse" })).toBeVisible(); - - // Make sure spacer is not visible on bubble layout - await expect( - page.locator(".mx_GenericEventListSummary[data-layout=bubble] .mx_GenericEventListSummary_spacer"), - ).not.toBeVisible(); // See: _GenericEventListSummary.pcss - - // Save snapshot of expanded generic event list summary on bubble layout - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-bubble-layout.png", { - // Exclude timestamp from snapshot - mask: [page.locator(".mx_MessageTimestamp")], - }); - - // Click "collapse" link button on the first hovered info event line - const firstTile = gels.locator(".mx_GenericEventListSummary_unstyledList .mx_EventTile_info:first-of-type"); - await firstTile.hover(); - await expect(firstTile.getByRole("toolbar", { name: "Message Actions" })).toBeVisible(); - await gels.getByRole("button", { name: "Collapse" }).click(); + }); + }, + ); - // Assert that "collapse" link button worked - await expect(gels.getByRole("button", { name: "Expand" })).toBeVisible(); + test( + "should click 'collapse' on the first hovered info event line inside GELS on bubble layout", + { tag: "@screenshot" }, + async ({ page, app, room }) => { + // This test checks clickability of the "Collapse" link button, which had been covered with + // MessageActionBar's safe area - https://github.com/vector-im/element-web/issues/22864 - // Save snapshot of collapsed generic event list summary on bubble layout - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("collapsed-gels-bubble-layout.png", { - mask: [page.locator(".mx_MessageTimestamp")], - }); - }); + await page.goto(`/#/room/${room.roomId}`); + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble); + await expect( + page.locator( + ".mx_RoomView_body .mx_GenericEventListSummary[data-layout='bubble'] .mx_GenericEventListSummary_summary", + { hasText: `${OLD_NAME} created and configured the room.` }, + ), + ).toBeVisible(); + + const gels = page.locator(".mx_GenericEventListSummary"); + // Click "expand" link button + await gels.getByRole("button", { name: "Expand" }).click(); + // Assert that the "expand" link button worked + await expect(gels.getByRole("button", { name: "Collapse" })).toBeVisible(); + + // Make sure spacer is not visible on bubble layout + await expect( + page.locator(".mx_GenericEventListSummary[data-layout=bubble] .mx_GenericEventListSummary_spacer"), + ).not.toBeVisible(); // See: _GenericEventListSummary.pcss - test("should add inline start margin to an event line on IRC layout", async ({ - page, - app, - room, - axe, - checkA11y, - }) => { - axe.disableRules("color-contrast"); + // Save snapshot of expanded generic event list summary on bubble layout + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-bubble-layout.png", { + // Exclude timestamp from snapshot + mask: [page.locator(".mx_MessageTimestamp")], + }); - await page.goto(`/#/room/${room.roomId}`); - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); + // Click "collapse" link button on the first hovered info event line + const firstTile = gels.locator( + ".mx_GenericEventListSummary_unstyledList .mx_EventTile_info:first-of-type", + ); + await firstTile.hover(); + await expect(firstTile.getByRole("toolbar", { name: "Message Actions" })).toBeVisible(); + await gels.getByRole("button", { name: "Collapse" }).click(); - // Wait until configuration is finished - await expect( - page.locator( - ".mx_RoomView_body .mx_GenericEventListSummary[data-layout='irc'] .mx_GenericEventListSummary_summary", - { hasText: `${OLD_NAME} created and configured the room.` }, - ), - ).toBeVisible(); + // Assert that "collapse" link button worked + await expect(gels.getByRole("button", { name: "Expand" })).toBeVisible(); - // Click "expand" link button - await page.locator(".mx_GenericEventListSummary").getByRole("button", { name: "Expand" }).click(); + // Save snapshot of collapsed generic event list summary on bubble layout + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("collapsed-gels-bubble-layout.png", { + mask: [page.locator(".mx_MessageTimestamp")], + }); + }, + ); - // Check the event line has margin instead of inset property - // cf. _EventTile.pcss - // --EventTile_irc_line_info-margin-inline-start - // = calc(var(--name-width) + var(--icon-width) + 1 * var(--right-padding)) - // = 80 + 14 + 5 = 99px + test( + "should add inline start margin to an event line on IRC layout", + { tag: "@screenshot" }, + async ({ page, app, room, axe, checkA11y }) => { + axe.disableRules("color-contrast"); - const firstEventLineIrc = page.locator( - ".mx_EventTile_info[data-layout=irc]:first-of-type .mx_EventTile_line", - ); - await expect(firstEventLineIrc).toHaveCSS("margin-inline-start", "99px"); - await expect(firstEventLineIrc).toHaveCSS("inset-inline-start", "0px"); + await page.goto(`/#/room/${room.roomId}`); + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( - "event-line-inline-start-margin-irc-layout.png", - { - // Exclude timestamp and read marker from snapshot - mask: [page.locator(".mx_MessageTimestamp")], - css: ` + // Wait until configuration is finished + await expect( + page.locator( + ".mx_RoomView_body .mx_GenericEventListSummary[data-layout='irc'] .mx_GenericEventListSummary_summary", + { hasText: `${OLD_NAME} created and configured the room.` }, + ), + ).toBeVisible(); + + // Click "expand" link button + await page.locator(".mx_GenericEventListSummary").getByRole("button", { name: "Expand" }).click(); + + // Check the event line has margin instead of inset property + // cf. _EventTile.pcss + // --EventTile_irc_line_info-margin-inline-start + // = calc(var(--name-width) + var(--icon-width) + 1 * var(--right-padding)) + // = 80 + 14 + 5 = 99px + + const firstEventLineIrc = page.locator( + ".mx_EventTile_info[data-layout=irc]:first-of-type .mx_EventTile_line", + ); + await expect(firstEventLineIrc).toHaveCSS("margin-inline-start", "99px"); + await expect(firstEventLineIrc).toHaveCSS("inset-inline-start", "0px"); + + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( + "event-line-inline-start-margin-irc-layout.png", + { + // Exclude timestamp and read marker from snapshot + mask: [page.locator(".mx_MessageTimestamp")], + css: ` .mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker { display: none !important; } `, - }, - ); - await checkA11y(); - }); + }, + ); + await checkA11y(); + }, + ); }); test.describe("message displaying", () => { @@ -332,289 +340,311 @@ test.describe("Timeline", () => { ).toBeVisible(); }; - test("should align generic event list summary with messages and emote on IRC layout", async ({ - page, - app, - room, - }) => { - // This test aims to check: - // 1. Alignment of collapsed GELS (generic event list summary) and messages - // 2. Alignment of expanded GELS and messages - // 3. Alignment of expanded GELS and placeholder of deleted message - // 4. Alignment of expanded GELS, placeholder of deleted message, and emote + test( + "should align generic event list summary with messages and emote on IRC layout", + { tag: "@screenshot" }, + async ({ page, app, room }) => { + // This test aims to check: + // 1. Alignment of collapsed GELS (generic event list summary) and messages + // 2. Alignment of expanded GELS and messages + // 3. Alignment of expanded GELS and placeholder of deleted message + // 4. Alignment of expanded GELS, placeholder of deleted message, and emote - await page.goto(`/#/room/${room.roomId}`); - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); + await page.goto(`/#/room/${room.roomId}`); + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); - // Wait until configuration is finished - await expect( - page - .locator(".mx_GenericEventListSummary_summary") - .getByText(`${OLD_NAME} created and configured the room.`), - ).toBeVisible(); + // Wait until configuration is finished + await expect( + page + .locator(".mx_GenericEventListSummary_summary") + .getByText(`${OLD_NAME} created and configured the room.`), + ).toBeVisible(); + + // Send messages + const composer = app.getComposerField(); + await composer.fill("Hello Mr. Bot"); + await composer.press("Enter"); + await composer.fill("Hello again, Mr. Bot"); + await composer.press("Enter"); + + // Make sure the second message was sent + await expect( + page.locator(".mx_RoomView_MessageList > .mx_EventTile_last .mx_EventTile_receiptSent"), + ).toBeVisible(); + + // 1. Alignment of collapsed GELS (generic event list summary) and messages + // Check inline start spacing of collapsed GELS + // See: _EventTile.pcss + // .mx_GenericEventListSummary[data-layout="irc"] > .mx_EventTile_line + // = var(--name-width) + var(--icon-width) + var(--MessageTimestamp-width) + 2 * var(--right-padding) + // = 80 + 14 + 46 + 2 * 5 + // = 150px + await expect( + page.locator(".mx_GenericEventListSummary[data-layout=irc] > .mx_EventTile_line"), + ).toHaveCSS("padding-inline-start", "150px"); + // Check width and spacing values of elements in .mx_EventTile, which should be equal to 150px + // --right-padding should be applied + for (const locator of await page.locator(".mx_EventTile > a").all()) { + if (await locator.isVisible()) { + await expect(locator).toHaveCSS("margin-right", "5px"); + } + } + // --name-width width zero inline end margin should be applied + for (const locator of await page.locator(".mx_EventTile .mx_DisambiguatedProfile").all()) { + await expect(locator).toHaveCSS("width", "80px"); + await expect(locator).toHaveCSS("margin-inline-end", "0px"); + } + // --icon-width should be applied + for (const locator of await page.locator(".mx_EventTile .mx_EventTile_avatar > .mx_BaseAvatar").all()) { + await expect(locator).toHaveCSS("width", "14px"); + } + // var(--MessageTimestamp-width) should be applied + for (const locator of await page.locator(".mx_EventTile > a").all()) { + await expect(locator).toHaveCSS("min-width", "46px"); + } + // Record alignment of collapsed GELS and messages on messagePanel + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( + "collapsed-gels-and-messages-irc-layout.png", + { + // Exclude timestamp from snapshot of mx_MainSplit + mask: [page.locator(".mx_MessageTimestamp")], + }, + ); - // Send messages - const composer = app.getComposerField(); - await composer.fill("Hello Mr. Bot"); - await composer.press("Enter"); - await composer.fill("Hello again, Mr. Bot"); - await composer.press("Enter"); + // 2. Alignment of expanded GELS and messages + // Click "expand" link button + await page.locator(".mx_GenericEventListSummary").getByRole("button", { name: "Expand" }).click(); + // Check inline start spacing of info line on expanded GELS + // See: _EventTile.pcss + // --EventTile_irc_line_info-margin-inline-start + // = 80 + 14 + 1 * 5 + await expect( + page.locator(".mx_EventTile[data-layout=irc].mx_EventTile_info:first-of-type .mx_EventTile_line"), + ).toHaveCSS("margin-inline-start", "99px"); + // Record alignment of expanded GELS and messages on messagePanel + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( + "expanded-gels-and-messages-irc-layout.png", + { + // Exclude timestamp from snapshot of mx_MainSplit + mask: [page.locator(".mx_MessageTimestamp")], + }, + ); - // Make sure the second message was sent - await expect( - page.locator(".mx_RoomView_MessageList > .mx_EventTile_last .mx_EventTile_receiptSent"), - ).toBeVisible(); + // 3. Alignment of expanded GELS and placeholder of deleted message + // Delete the second (last) message + const lastTile = page.locator(".mx_RoomView_MessageList > .mx_EventTile_last"); + await lastTile.hover(); + await lastTile.getByRole("button", { name: "Options" }).click(); + await page.getByRole("menuitem", { name: "Remove" }).click(); + // Confirm deletion + await page.locator(".mx_Dialog_buttons").getByRole("button", { name: "Remove" }).click(); + // Make sure the dialog was closed and the second (last) message was redacted + await expect(page.locator(".mx_Dialog")).not.toBeVisible(); + await expect( + page.locator(".mx_GenericEventListSummary .mx_EventTile_last .mx_RedactedBody"), + ).toBeVisible(); + await expect( + page.locator(".mx_GenericEventListSummary .mx_EventTile_last .mx_EventTile_receiptSent"), + ).toBeVisible(); + // Record alignment of expanded GELS and placeholder of deleted message on messagePanel + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( + "expanded-gels-redaction-placeholder.png", + { + // Exclude timestamp from snapshot of mx_MainSplit + mask: [page.locator(".mx_MessageTimestamp")], + }, + ); - // 1. Alignment of collapsed GELS (generic event list summary) and messages - // Check inline start spacing of collapsed GELS - // See: _EventTile.pcss - // .mx_GenericEventListSummary[data-layout="irc"] > .mx_EventTile_line - // = var(--name-width) + var(--icon-width) + var(--MessageTimestamp-width) + 2 * var(--right-padding) - // = 80 + 14 + 46 + 2 * 5 - // = 150px - await expect(page.locator(".mx_GenericEventListSummary[data-layout=irc] > .mx_EventTile_line")).toHaveCSS( - "padding-inline-start", - "150px", - ); - // Check width and spacing values of elements in .mx_EventTile, which should be equal to 150px - // --right-padding should be applied - for (const locator of await page.locator(".mx_EventTile > a").all()) { - if (await locator.isVisible()) { - await expect(locator).toHaveCSS("margin-right", "5px"); - } - } - // --name-width width zero inline end margin should be applied - for (const locator of await page.locator(".mx_EventTile .mx_DisambiguatedProfile").all()) { - await expect(locator).toHaveCSS("width", "80px"); - await expect(locator).toHaveCSS("margin-inline-end", "0px"); - } - // --icon-width should be applied - for (const locator of await page.locator(".mx_EventTile .mx_EventTile_avatar > .mx_BaseAvatar").all()) { - await expect(locator).toHaveCSS("width", "14px"); - } - // var(--MessageTimestamp-width) should be applied - for (const locator of await page.locator(".mx_EventTile > a").all()) { - await expect(locator).toHaveCSS("min-width", "46px"); - } - // Record alignment of collapsed GELS and messages on messagePanel - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( - "collapsed-gels-and-messages-irc-layout.png", - { + // 4. Alignment of expanded GELS, placeholder of deleted message, and emote + // Send a emote + await page + .locator(".mx_RoomView_body") + .getByRole("textbox", { name: "Send a message…" }) + .fill("/me says hello to Mr. Bot"); + await page + .locator(".mx_RoomView_body") + .getByRole("textbox", { name: "Send a message…" }) + .press("Enter"); + // Check inline start margin of its avatar + // Here --right-padding is for the avatar on the message line + // See: _IRCLayout.pcss + // .mx_IRCLayout .mx_EventTile_emote .mx_EventTile_avatar + // = calc(var(--name-width) + var(--icon-width) + 1 * var(--right-padding)) + // = 80 + 14 + 1 * 5 + await expect(page.locator(".mx_EventTile_emote .mx_EventTile_avatar")).toHaveCSS("margin-left", "99px"); + // Make sure emote was sent + await expect( + page.locator(".mx_EventTile_last.mx_EventTile_emote .mx_EventTile_receiptSent"), + ).toBeVisible(); + // Record alignment of expanded GELS, placeholder of deleted message, and emote + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-emote-irc-layout.png", { // Exclude timestamp from snapshot of mx_MainSplit mask: [page.locator(".mx_MessageTimestamp")], - }, - ); - - // 2. Alignment of expanded GELS and messages - // Click "expand" link button - await page.locator(".mx_GenericEventListSummary").getByRole("button", { name: "Expand" }).click(); - // Check inline start spacing of info line on expanded GELS - // See: _EventTile.pcss - // --EventTile_irc_line_info-margin-inline-start - // = 80 + 14 + 1 * 5 - await expect( - page.locator(".mx_EventTile[data-layout=irc].mx_EventTile_info:first-of-type .mx_EventTile_line"), - ).toHaveCSS("margin-inline-start", "99px"); - // Record alignment of expanded GELS and messages on messagePanel - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-and-messages-irc-layout.png", { - // Exclude timestamp from snapshot of mx_MainSplit - mask: [page.locator(".mx_MessageTimestamp")], - }); - - // 3. Alignment of expanded GELS and placeholder of deleted message - // Delete the second (last) message - const lastTile = page.locator(".mx_RoomView_MessageList > .mx_EventTile_last"); - await lastTile.hover(); - await lastTile.getByRole("button", { name: "Options" }).click(); - await page.getByRole("menuitem", { name: "Remove" }).click(); - // Confirm deletion - await page.locator(".mx_Dialog_buttons").getByRole("button", { name: "Remove" }).click(); - // Make sure the dialog was closed and the second (last) message was redacted - await expect(page.locator(".mx_Dialog")).not.toBeVisible(); - await expect(page.locator(".mx_GenericEventListSummary .mx_EventTile_last .mx_RedactedBody")).toBeVisible(); - await expect( - page.locator(".mx_GenericEventListSummary .mx_EventTile_last .mx_EventTile_receiptSent"), - ).toBeVisible(); - // Record alignment of expanded GELS and placeholder of deleted message on messagePanel - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-redaction-placeholder.png", { - // Exclude timestamp from snapshot of mx_MainSplit - mask: [page.locator(".mx_MessageTimestamp")], - }); - - // 4. Alignment of expanded GELS, placeholder of deleted message, and emote - // Send a emote - await page - .locator(".mx_RoomView_body") - .getByRole("textbox", { name: "Send a message…" }) - .fill("/me says hello to Mr. Bot"); - await page.locator(".mx_RoomView_body").getByRole("textbox", { name: "Send a message…" }).press("Enter"); - // Check inline start margin of its avatar - // Here --right-padding is for the avatar on the message line - // See: _IRCLayout.pcss - // .mx_IRCLayout .mx_EventTile_emote .mx_EventTile_avatar - // = calc(var(--name-width) + var(--icon-width) + 1 * var(--right-padding)) - // = 80 + 14 + 1 * 5 - await expect(page.locator(".mx_EventTile_emote .mx_EventTile_avatar")).toHaveCSS("margin-left", "99px"); - // Make sure emote was sent - await expect(page.locator(".mx_EventTile_last.mx_EventTile_emote .mx_EventTile_receiptSent")).toBeVisible(); - // Record alignment of expanded GELS, placeholder of deleted message, and emote - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot("expanded-gels-emote-irc-layout.png", { - // Exclude timestamp from snapshot of mx_MainSplit - mask: [page.locator(".mx_MessageTimestamp")], - }); - }); - - test("should render EventTiles on IRC, modern (group), and bubble layout", async ({ page, app, room }) => { - const screenshotOptions = { - // Hide because flaky - See https://github.com/vector-im/element-web/issues/24957 - mask: [page.locator(".mx_MessageTimestamp")], - css: ` + }); + }, + ); + + test( + "should render EventTiles on IRC, modern (group), and bubble layout", + { tag: "@screenshot" }, + async ({ page, app, room }) => { + const screenshotOptions = { + // Hide because flaky - See https://github.com/vector-im/element-web/issues/24957 + mask: [page.locator(".mx_MessageTimestamp")], + css: ` .mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker { display: none !important; } `, - }; - - await sendEvent(app.client, room.roomId); - await sendEvent(app.client, room.roomId); // check continuation - await sendEvent(app.client, room.roomId); // check the last EventTile + }; - await page.goto(`/#/room/${room.roomId}`); - const composer = app.getComposerField(); - // Send a plain text message - await composer.fill("Hello"); - await composer.press("Enter"); - // Send a big emoji - await composer.fill("🏀"); - await composer.press("Enter"); - // Send an inline emoji - await composer.fill("This message has an inline emoji 👒"); - await composer.press("Enter"); + await sendEvent(app.client, room.roomId); + await sendEvent(app.client, room.roomId); // check continuation + await sendEvent(app.client, room.roomId); // check the last EventTile - await expect(page.locator(".mx_RoomView").getByText("This message has an inline emoji 👒")).toBeVisible(); + await page.goto(`/#/room/${room.roomId}`); + const composer = app.getComposerField(); + // Send a plain text message + await composer.fill("Hello"); + await composer.press("Enter"); + // Send a big emoji + await composer.fill("🏀"); + await composer.press("Enter"); + // Send an inline emoji + await composer.fill("This message has an inline emoji 👒"); + await composer.press("Enter"); - //////////////////////////////////////////////////////////////////////////////////////////////////////////// - // IRC layout - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + await expect( + page.locator(".mx_RoomView").getByText("This message has an inline emoji 👒"), + ).toBeVisible(); - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + // IRC layout + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Wait until configuration is finished - await expect( - page - .locator(".mx_GenericEventListSummary_summary") - .getByText(`${OLD_NAME} created and configured the room.`), - ).toBeVisible(); + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); - await app.timeline.scrollToBottom(); - await expect( - page.locator(".mx_RoomView").getByText("This message has an inline emoji 👒"), - ).toBeInViewport(); - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( - "event-tiles-irc-layout.png", - screenshotOptions, - ); + // Wait until configuration is finished + await expect( + page + .locator(".mx_GenericEventListSummary_summary") + .getByText(`${OLD_NAME} created and configured the room.`), + ).toBeVisible(); - //////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Group/modern layout - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + await app.timeline.scrollToBottom(); + await expect( + page.locator(".mx_RoomView").getByText("This message has an inline emoji 👒"), + ).toBeInViewport(); + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( + "event-tiles-irc-layout.png", + screenshotOptions, + ); - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Group/modern layout + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Check that the last EventTile is rendered - await app.timeline.scrollToBottom(); - await expect( - page.locator(".mx_RoomView").getByText("This message has an inline emoji 👒"), - ).toBeInViewport(); - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( - "event-tiles-modern-layout.png", - screenshotOptions, - ); + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); - // Check the same thing for compact layout - await app.settings.setValue("useCompactLayout", null, SettingLevel.DEVICE, true); + // Check that the last EventTile is rendered + await app.timeline.scrollToBottom(); + await expect( + page.locator(".mx_RoomView").getByText("This message has an inline emoji 👒"), + ).toBeInViewport(); + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( + "event-tiles-modern-layout.png", + screenshotOptions, + ); - // Check that the last EventTile is rendered - await app.timeline.scrollToBottom(); - await expect( - page.locator(".mx_RoomView").getByText("This message has an inline emoji 👒"), - ).toBeInViewport(); - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( - "event-tiles-compact-modern-layout.png", - screenshotOptions, - ); + // Check the same thing for compact layout + await app.settings.setValue("useCompactLayout", null, SettingLevel.DEVICE, true); - //////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Message bubble layout - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Check that the last EventTile is rendered + await app.timeline.scrollToBottom(); + await expect( + page.locator(".mx_RoomView").getByText("This message has an inline emoji 👒"), + ).toBeInViewport(); + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( + "event-tiles-compact-modern-layout.png", + screenshotOptions, + ); - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble); + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Message bubble layout + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - await app.timeline.scrollToBottom(); - await expect( - page.locator(".mx_RoomView").getByText("This message has an inline emoji 👒"), - ).toBeInViewport(); - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( - "event-tiles-bubble-layout.png", - screenshotOptions, - ); - }); + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble); - test("should set inline start padding to a hidden event line", async ({ page, app, room }) => { - test.skip( - true, - "Disabled due to screenshot test being flaky - https://github.com/element-hq/element-web/issues/26890", - ); - await sendEvent(app.client, room.roomId); - await page.goto(`/#/room/${room.roomId}`); - await app.settings.setValue("showHiddenEventsInTimeline", null, SettingLevel.DEVICE, true); - await expect( - page - .locator(".mx_GenericEventListSummary_summary") - .getByText(`${OLD_NAME} created and configured the room.`), - ).toBeVisible(); + await app.timeline.scrollToBottom(); + await expect( + page.locator(".mx_RoomView").getByText("This message has an inline emoji 👒"), + ).toBeInViewport(); + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( + "event-tiles-bubble-layout.png", + screenshotOptions, + ); + }, + ); + + test( + "should set inline start padding to a hidden event line", + { tag: "@screenshot" }, + async ({ page, app, room }) => { + test.skip( + true, + "Disabled due to screenshot test being flaky - https://github.com/element-hq/element-web/issues/26890", + ); + await sendEvent(app.client, room.roomId); + await page.goto(`/#/room/${room.roomId}`); + await app.settings.setValue("showHiddenEventsInTimeline", null, SettingLevel.DEVICE, true); + await expect( + page + .locator(".mx_GenericEventListSummary_summary") + .getByText(`${OLD_NAME} created and configured the room.`), + ).toBeVisible(); - // Edit message - await messageEdit(page); + // Edit message + await messageEdit(page); - // Click timestamp to highlight hidden event line - await page.locator(".mx_RoomView_body .mx_EventTile_info .mx_MessageTimestamp").click(); + // Click timestamp to highlight hidden event line + await page.locator(".mx_RoomView_body .mx_EventTile_info .mx_MessageTimestamp").click(); - // should not add inline start padding to a hidden event line on IRC layout - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); - await expect( - page.locator(".mx_EventTile[data-layout=irc].mx_EventTile_info .mx_EventTile_line").first(), - ).toHaveCSS("padding-inline-start", "0px"); + // should not add inline start padding to a hidden event line on IRC layout + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); + await expect( + page.locator(".mx_EventTile[data-layout=irc].mx_EventTile_info .mx_EventTile_line").first(), + ).toHaveCSS("padding-inline-start", "0px"); - // Exclude timestamp and read marker from snapshot - const screenshotOptions = { - mask: [page.locator(".mx_MessageTimestamp")], - css: ` + // Exclude timestamp and read marker from snapshot + const screenshotOptions = { + mask: [page.locator(".mx_MessageTimestamp")], + css: ` .mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker { display: none !important; } `, - }; + }; - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( - "hidden-event-line-zero-padding-irc-layout.png", - screenshotOptions, - ); + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( + "hidden-event-line-zero-padding-irc-layout.png", + screenshotOptions, + ); - // should add inline start padding to a hidden event line on modern layout - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); - // calc(var(--EventTile_group_line-spacing-inline-start) + 20px) = 64 + 20 = 84px - await expect( - page.locator(".mx_EventTile[data-layout=group].mx_EventTile_info .mx_EventTile_line").first(), - ).toHaveCSS("padding-inline-start", "84px"); + // should add inline start padding to a hidden event line on modern layout + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); + // calc(var(--EventTile_group_line-spacing-inline-start) + 20px) = 64 + 20 = 84px + await expect( + page.locator(".mx_EventTile[data-layout=group].mx_EventTile_info .mx_EventTile_line").first(), + ).toHaveCSS("padding-inline-start", "84px"); - await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( - "hidden-event-line-padding-modern-layout.png", - screenshotOptions, - ); - }); + await expect(page.locator(".mx_MainSplit")).toMatchScreenshot( + "hidden-event-line-padding-modern-layout.png", + screenshotOptions, + ); + }, + ); - test("should click view source event toggle", async ({ page, app, room }) => { + test("should click view source event toggle", { tag: "@screenshot" }, async ({ page, app, room }) => { // This test checks: // 1. clickability of top left of view source event toggle // 2. clickability of view source toggle on IRC layout @@ -712,89 +742,97 @@ test.describe("Timeline", () => { ).toBeVisible(); }); - test("should render url previews", async ({ page, app, room, axe, checkA11y, context }) => { - axe.disableRules("color-contrast"); - - // Element Web uses a Service Worker to rewrite unauthenticated media requests to authenticated ones, but - // the page can't see this happening. We intercept the route at the BrowserContext to ensure we get it - // post-worker, but we can't waitForResponse on that, so the page context is still used there. Because - // the page doesn't see the rewrite, it waits for the unauthenticated route. This is only confusing until - // the js-sdk (and thus the app as a whole) switches to using authenticated endpoints by default, hopefully. - await context.route( - "**/_matrix/client/v1/media/thumbnail/matrix.org/2022-08-16_yaiSVSRIsNFfxDnV?*", - async (route) => { - await route.fulfill({ - path: "playwright/sample-files/riot.png", - }); - }, - ); - await page.route( - "**/_matrix/media/v3/preview_url?url=https%3A%2F%2Fcall.element.io%2F&ts=*", - async (route) => { - await route.fulfill({ - json: { - "og:title": "Element Call", - "og:description": null, - "og:image:width": 48, - "og:image:height": 48, - "og:image": "mxc://matrix.org/2022-08-16_yaiSVSRIsNFfxDnV", - "og:image:type": "image/png", - "matrix:image:size": 2121, - }, - }); - }, - ); + test( + "should render url previews", + { tag: "@screenshot" }, + async ({ page, app, room, axe, checkA11y, context }) => { + axe.disableRules("color-contrast"); + + // Element Web uses a Service Worker to rewrite unauthenticated media requests to authenticated ones, but + // the page can't see this happening. We intercept the route at the BrowserContext to ensure we get it + // post-worker, but we can't waitForResponse on that, so the page context is still used there. Because + // the page doesn't see the rewrite, it waits for the unauthenticated route. This is only confusing until + // the js-sdk (and thus the app as a whole) switches to using authenticated endpoints by default, hopefully. + await context.route( + "**/_matrix/client/v1/media/thumbnail/matrix.org/2022-08-16_yaiSVSRIsNFfxDnV?*", + async (route) => { + await route.fulfill({ + path: "playwright/sample-files/riot.png", + }); + }, + ); + await page.route( + "**/_matrix/media/v3/preview_url?url=https%3A%2F%2Fcall.element.io%2F&ts=*", + async (route) => { + await route.fulfill({ + json: { + "og:title": "Element Call", + "og:description": null, + "og:image:width": 48, + "og:image:height": 48, + "og:image": "mxc://matrix.org/2022-08-16_yaiSVSRIsNFfxDnV", + "og:image:type": "image/png", + "matrix:image:size": 2121, + }, + }); + }, + ); - const requestPromises: Promise[] = [ - page.waitForResponse("**/_matrix/media/v3/preview_url?url=https%3A%2F%2Fcall.element.io%2F&ts=*"), - // see context.route above for why we listen for the unauthenticated endpoint - page.waitForResponse("**/_matrix/media/v3/thumbnail/matrix.org/2022-08-16_yaiSVSRIsNFfxDnV?*"), - ]; + const requestPromises: Promise[] = [ + page.waitForResponse("**/_matrix/media/v3/preview_url?url=https%3A%2F%2Fcall.element.io%2F&ts=*"), + // see context.route above for why we listen for the unauthenticated endpoint + page.waitForResponse("**/_matrix/media/v3/thumbnail/matrix.org/2022-08-16_yaiSVSRIsNFfxDnV?*"), + ]; - await app.client.sendMessage(room.roomId, "https://call.element.io/"); - await page.goto(`/#/room/${room.roomId}`); + await app.client.sendMessage(room.roomId, "https://call.element.io/"); + await page.goto(`/#/room/${room.roomId}`); - await expect(page.locator(".mx_LinkPreviewWidget").getByText("Element Call")).toBeVisible(); - await Promise.all(requestPromises); + await expect(page.locator(".mx_LinkPreviewWidget").getByText("Element Call")).toBeVisible(); + await Promise.all(requestPromises); - await checkA11y(); + await checkA11y(); - await app.timeline.scrollToBottom(); - await expect(page.locator(".mx_EventTile_last")).toMatchScreenshot("url-preview.png", { - // Exclude timestamp and read marker from snapshot - mask: [page.locator(".mx_MessageTimestamp")], - css: ` + await app.timeline.scrollToBottom(); + await expect(page.locator(".mx_EventTile_last")).toMatchScreenshot("url-preview.png", { + // Exclude timestamp and read marker from snapshot + mask: [page.locator(".mx_MessageTimestamp")], + css: ` .mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker { display: none !important; } `, - }); - }); + }); + }, + ); test.describe("on search results panel", () => { - test("should highlight search result words regardless of formatting", async ({ page, app, room }) => { - await sendEvent(app.client, room.roomId); - await sendEvent(app.client, room.roomId, true); - await page.goto(`/#/room/${room.roomId}`); + test( + "should highlight search result words regardless of formatting", + { tag: "@screenshot" }, + async ({ page, app, room }) => { + await sendEvent(app.client, room.roomId); + await sendEvent(app.client, room.roomId, true); + await page.goto(`/#/room/${room.roomId}`); - await app.toggleRoomInfoPanel(); + await app.toggleRoomInfoPanel(); - await page.locator(".mx_RoomSummaryCard_search").getByRole("searchbox").fill("Message"); - await page.locator(".mx_RoomSummaryCard_search").getByRole("searchbox").press("Enter"); + await page.locator(".mx_RoomSummaryCard_search").getByRole("searchbox").fill("Message"); + await page.locator(".mx_RoomSummaryCard_search").getByRole("searchbox").press("Enter"); - await expect(page.locator(".mx_RoomSearchAuxPanel")).toMatchScreenshot("search-aux-panel.png"); + await expect(page.locator(".mx_RoomSearchAuxPanel")).toMatchScreenshot("search-aux-panel.png"); - for (const locator of await page - .locator(".mx_EventTile:not(.mx_EventTile_contextual) .mx_EventTile_searchHighlight") - .all()) { - await expect(locator).toBeVisible(); - } - await expect(page.locator(".mx_RoomView_searchResultsPanel")).toMatchScreenshot( - "highlighted-search-results.png", - ); - }); + for (const locator of await page + .locator(".mx_EventTile:not(.mx_EventTile_contextual) .mx_EventTile_searchHighlight") + .all()) { + await expect(locator).toBeVisible(); + } + await expect(page.locator(".mx_RoomView_searchResultsPanel")).toMatchScreenshot( + "highlighted-search-results.png", + ); + }, + ); - test("should render a fully opaque textual event", async ({ page, app, room }) => { + test("should render a fully opaque textual event", { tag: "@screenshot" }, async ({ page, app, room }) => { const stringToSearch = "Message"; // Same with string sent with sendEvent() await sendEvent(app.client, room.roomId); @@ -918,7 +956,7 @@ test.describe("Timeline", () => { ).toHaveCount(4); }); - test("should display a reply chain", async ({ page, app, room, homeserver }) => { + test("should display a reply chain", { tag: "@screenshot" }, async ({ page, app, room, homeserver }) => { const reply2 = "Reply again"; await page.goto(`/#/room/${room.roomId}`); @@ -1031,122 +1069,121 @@ test.describe("Timeline", () => { ); }); - test("should send, reply, and display long strings without overflowing", async ({ - page, - app, - room, - homeserver, - }) => { - // Max 256 characters for display name - const LONG_STRING = - "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut " + - "et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " + - "aliquip"; - - const newDisplayName = `${LONG_STRING} 2`; - - // Set the display name to "LONG_STRING 2" in order to avoid screenshot tests from failing - // due to the generated random mxid being displayed inside the GELS summary. - // Note that we set it here as the test was failing on CI (but not locally!) if the name - // was changed afterwards. This is quite concerning, but maybe better than just disabling the - // whole test? - // https://github.com/element-hq/element-web/issues/27109 - await app.client.setDisplayName(newDisplayName); - - // Create a bot with a long display name - const bot = new Bot(page, homeserver, { - displayName: LONG_STRING, - autoAcceptInvites: false, - }); - await bot.prepareClient(); + test( + "should send, reply, and display long strings without overflowing", + { tag: "@screenshot" }, + async ({ page, app, room, homeserver }) => { + // Max 256 characters for display name + const LONG_STRING = + "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut " + + "et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " + + "aliquip"; + + const newDisplayName = `${LONG_STRING} 2`; + + // Set the display name to "LONG_STRING 2" in order to avoid screenshot tests from failing + // due to the generated random mxid being displayed inside the GELS summary. + // Note that we set it here as the test was failing on CI (but not locally!) if the name + // was changed afterwards. This is quite concerning, but maybe better than just disabling the + // whole test? + // https://github.com/element-hq/element-web/issues/27109 + await app.client.setDisplayName(newDisplayName); + + // Create a bot with a long display name + const bot = new Bot(page, homeserver, { + displayName: LONG_STRING, + autoAcceptInvites: false, + }); + await bot.prepareClient(); - // Create another room with a long name, invite the bot, and open the room - const testRoomId = await app.client.createRoom({ name: LONG_STRING }); - await app.client.inviteUser(testRoomId, bot.credentials.userId); - await bot.joinRoom(testRoomId); - await page.goto(`/#/room/${testRoomId}`); + // Create another room with a long name, invite the bot, and open the room + const testRoomId = await app.client.createRoom({ name: LONG_STRING }); + await app.client.inviteUser(testRoomId, bot.credentials.userId); + await bot.joinRoom(testRoomId); + await page.goto(`/#/room/${testRoomId}`); - // Wait until configuration is finished - await expect( - page - .locator(".mx_GenericEventListSummary_summary") - .getByText(newDisplayName + " created and configured the room."), - ).toBeVisible(); - - // Have the bot send a long message - await bot.sendMessage(testRoomId, { - body: LONG_STRING, - msgtype: "m.text", - }); + // Wait until configuration is finished + await expect( + page + .locator(".mx_GenericEventListSummary_summary") + .getByText(newDisplayName + " created and configured the room."), + ).toBeVisible(); + + // Have the bot send a long message + await bot.sendMessage(testRoomId, { + body: LONG_STRING, + msgtype: "m.text", + }); - // Wait until the message is rendered - await expect( - page.locator(".mx_EventTile_last .mx_MTextBody .mx_EventTile_body").getByText(LONG_STRING), - ).toBeVisible(); + // Wait until the message is rendered + await expect( + page.locator(".mx_EventTile_last .mx_MTextBody .mx_EventTile_body").getByText(LONG_STRING), + ).toBeVisible(); - // Reply to the message - await clickButtonReply(page); - await app.getComposerField().fill(reply); - await app.getComposerField().press("Enter"); + // Reply to the message + await clickButtonReply(page); + await app.getComposerField().fill(reply); + await app.getComposerField().press("Enter"); - // Make sure the reply tile is rendered - const eventTileLine = page.locator(".mx_EventTile_last .mx_EventTile_line"); - await expect(eventTileLine.locator(".mx_ReplyTile .mx_MTextBody").getByText(LONG_STRING)).toBeVisible(); + // Make sure the reply tile is rendered + const eventTileLine = page.locator(".mx_EventTile_last .mx_EventTile_line"); + await expect(eventTileLine.locator(".mx_ReplyTile .mx_MTextBody").getByText(LONG_STRING)).toBeVisible(); - await expect(eventTileLine.getByText(reply)).toHaveCount(1); + await expect(eventTileLine.getByText(reply)).toHaveCount(1); - // Change the viewport size - await page.setViewportSize({ width: 1600, height: 1200 }); + // Change the viewport size + await page.setViewportSize({ width: 1600, height: 1200 }); - // Exclude timestamp and read marker from snapshot - const screenshotOptions = { - mask: [page.locator(".mx_MessageTimestamp")], - css: ` + // Exclude timestamp and read marker from snapshot + const screenshotOptions = { + mask: [page.locator(".mx_MessageTimestamp")], + css: ` .mx_TopUnreadMessagesBar, .mx_MessagePanel_myReadMarker { display: none !important; } `, - }; - - // Make sure the strings do not overflow on IRC layout - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); - // Scroll to the bottom to take a snapshot of the whole viewport - await app.timeline.scrollToBottom(); - // Assert that both avatar in the introduction and the last message are visible at the same time - await expect(page.locator(".mx_NewRoomIntro .mx_BaseAvatar")).toBeVisible(); - const lastEventTileIrc = page.locator(".mx_EventTile_last[data-layout='irc']"); - await expect(lastEventTileIrc.locator(".mx_MTextBody").first()).toBeVisible(); - await expect(lastEventTileIrc.locator(".mx_EventTile_receiptSent")).toBeVisible(); // rendered at the bottom of EventTile - // Take a snapshot in IRC layout - await expect(page.locator(".mx_ScrollPanel")).toMatchScreenshot( - "long-strings-with-reply-irc-layout.png", - screenshotOptions, - ); + }; + + // Make sure the strings do not overflow on IRC layout + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); + // Scroll to the bottom to take a snapshot of the whole viewport + await app.timeline.scrollToBottom(); + // Assert that both avatar in the introduction and the last message are visible at the same time + await expect(page.locator(".mx_NewRoomIntro .mx_BaseAvatar")).toBeVisible(); + const lastEventTileIrc = page.locator(".mx_EventTile_last[data-layout='irc']"); + await expect(lastEventTileIrc.locator(".mx_MTextBody").first()).toBeVisible(); + await expect(lastEventTileIrc.locator(".mx_EventTile_receiptSent")).toBeVisible(); // rendered at the bottom of EventTile + // Take a snapshot in IRC layout + await expect(page.locator(".mx_ScrollPanel")).toMatchScreenshot( + "long-strings-with-reply-irc-layout.png", + screenshotOptions, + ); - // Make sure the strings do not overflow on modern layout - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); - await app.timeline.scrollToBottom(); // Scroll again in case - await expect(page.locator(".mx_NewRoomIntro .mx_BaseAvatar")).toBeVisible(); - const lastEventTileGroup = page.locator(".mx_EventTile_last[data-layout='group']"); - await expect(lastEventTileGroup.locator(".mx_MTextBody").first()).toBeVisible(); - await expect(lastEventTileGroup.locator(".mx_EventTile_receiptSent")).toBeVisible(); - await expect(page.locator(".mx_ScrollPanel")).toMatchScreenshot( - "long-strings-with-reply-modern-layout.png", - screenshotOptions, - ); + // Make sure the strings do not overflow on modern layout + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); + await app.timeline.scrollToBottom(); // Scroll again in case + await expect(page.locator(".mx_NewRoomIntro .mx_BaseAvatar")).toBeVisible(); + const lastEventTileGroup = page.locator(".mx_EventTile_last[data-layout='group']"); + await expect(lastEventTileGroup.locator(".mx_MTextBody").first()).toBeVisible(); + await expect(lastEventTileGroup.locator(".mx_EventTile_receiptSent")).toBeVisible(); + await expect(page.locator(".mx_ScrollPanel")).toMatchScreenshot( + "long-strings-with-reply-modern-layout.png", + screenshotOptions, + ); - // Make sure the strings do not overflow on bubble layout - await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble); - await app.timeline.scrollToBottom(); // Scroll again in case - await expect(page.locator(".mx_NewRoomIntro .mx_BaseAvatar")).toBeVisible(); - const lastEventTileBubble = page.locator(".mx_EventTile_last[data-layout='bubble']"); - await expect(lastEventTileBubble.locator(".mx_MTextBody").first()).toBeVisible(); - await expect(lastEventTileBubble.locator(".mx_EventTile_receiptSent")).toBeVisible(); - await expect(page.locator(".mx_ScrollPanel")).toMatchScreenshot( - "long-strings-with-reply-bubble-layout.png", - screenshotOptions, - ); - }); + // Make sure the strings do not overflow on bubble layout + await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble); + await app.timeline.scrollToBottom(); // Scroll again in case + await expect(page.locator(".mx_NewRoomIntro .mx_BaseAvatar")).toBeVisible(); + const lastEventTileBubble = page.locator(".mx_EventTile_last[data-layout='bubble']"); + await expect(lastEventTileBubble.locator(".mx_MTextBody").first()).toBeVisible(); + await expect(lastEventTileBubble.locator(".mx_EventTile_receiptSent")).toBeVisible(); + await expect(page.locator(".mx_ScrollPanel")).toMatchScreenshot( + "long-strings-with-reply-bubble-layout.png", + screenshotOptions, + ); + }, + ); async function testImageRendering(page: Page, app: ElementAppPage, room: { roomId: string }) { await app.viewRoomById(room.roomId); @@ -1176,7 +1213,7 @@ test.describe("Timeline", () => { ); } - test("should render images in the timeline", async ({ page, app, room, context }) => { + test("should render images in the timeline", { tag: "@screenshot" }, async ({ page, app, room, context }) => { await testImageRendering(page, app, room); }); @@ -1188,50 +1225,54 @@ test.describe("Timeline", () => { // In practice, this means this test will *always* succeed because it ends up relying on fallback behaviour tested // above (unless of course the above tests are also broken). test.describe("MSC3916 - Authenticated Media", () => { - test("should render authenticated images in the timeline", async ({ page, app, room, context }) => { - // Note: we have to use `context` instead of `page` for routing, otherwise we'll miss Service Worker events. - // See https://playwright.dev/docs/service-workers-experimental#network-events-and-routing - - // Install our mocks and preventative measures - await context.route("**/_matrix/client/versions", async (route) => { - // Force enable MSC3916/Matrix 1.11, which may require the service worker's internal cache to be cleared later. - const json = await (await route.fetch()).json(); - if (!json["versions"]) json["versions"] = []; - json["versions"].push("v1.11"); - await route.fulfill({ json }); - }); - await context.route("**/_matrix/media/*/download/**", async (route) => { - // should not be called. We don't use `abort` so that it's clearer in the logs what happened. - await route.fulfill({ - status: 500, - json: { errcode: "M_UNKNOWN", error: "Unexpected route called." }, + test( + "should render authenticated images in the timeline", + { tag: "@screenshot" }, + async ({ page, app, room, context }) => { + // Note: we have to use `context` instead of `page` for routing, otherwise we'll miss Service Worker events. + // See https://playwright.dev/docs/service-workers-experimental#network-events-and-routing + + // Install our mocks and preventative measures + await context.route("**/_matrix/client/versions", async (route) => { + // Force enable MSC3916/Matrix 1.11, which may require the service worker's internal cache to be cleared later. + const json = await (await route.fetch()).json(); + if (!json["versions"]) json["versions"] = []; + json["versions"].push("v1.11"); + await route.fulfill({ json }); }); - }); - await context.route("**/_matrix/media/*/thumbnail/**", async (route) => { - // should not be called. We don't use `abort` so that it's clearer in the logs what happened. - await route.fulfill({ - status: 500, - json: { errcode: "M_UNKNOWN", error: "Unexpected route called." }, + await context.route("**/_matrix/media/*/download/**", async (route) => { + // should not be called. We don't use `abort` so that it's clearer in the logs what happened. + await route.fulfill({ + status: 500, + json: { errcode: "M_UNKNOWN", error: "Unexpected route called." }, + }); }); - }); - await context.route("**/_matrix/client/v1/download/**", async (route) => { - expect(route.request().headers()["Authorization"]).toBeDefined(); - // we can't use route.continue() because no configured homeserver supports MSC3916 yet - await route.fulfill({ - body: NEW_AVATAR, + await context.route("**/_matrix/media/*/thumbnail/**", async (route) => { + // should not be called. We don't use `abort` so that it's clearer in the logs what happened. + await route.fulfill({ + status: 500, + json: { errcode: "M_UNKNOWN", error: "Unexpected route called." }, + }); }); - }); - await context.route("**/_matrix/client/v1/thumbnail/**", async (route) => { - expect(route.request().headers()["Authorization"]).toBeDefined(); - // we can't use route.continue() because no configured homeserver supports MSC3916 yet - await route.fulfill({ - body: NEW_AVATAR, + await context.route("**/_matrix/client/v1/download/**", async (route) => { + expect(route.request().headers()["Authorization"]).toBeDefined(); + // we can't use route.continue() because no configured homeserver supports MSC3916 yet + await route.fulfill({ + body: NEW_AVATAR, + }); + }); + await context.route("**/_matrix/client/v1/thumbnail/**", async (route) => { + expect(route.request().headers()["Authorization"]).toBeDefined(); + // we can't use route.continue() because no configured homeserver supports MSC3916 yet + await route.fulfill({ + body: NEW_AVATAR, + }); }); - }); - // We check the same screenshot because there should be no user-visible impact to using authentication. - await testImageRendering(page, app, room); - }); + // We check the same screenshot because there should be no user-visible impact to using authentication. + await testImageRendering(page, app, room); + }, + ); }); }); }); diff --git a/playwright/e2e/user-menu/user-menu.spec.ts b/playwright/e2e/user-menu/user-menu.spec.ts index 0ad21dbded9..268da00f30f 100644 --- a/playwright/e2e/user-menu/user-menu.spec.ts +++ b/playwright/e2e/user-menu/user-menu.spec.ts @@ -11,7 +11,7 @@ import { test, expect } from "../../element-web-test"; test.describe("User Menu", () => { test.use({ displayName: "Jeff" }); - test("should contain our name & userId", async ({ page, user }) => { + test("should contain our name & userId", { tag: "@screenshot" }, async ({ page, user }) => { await page.getByRole("button", { name: "User menu", exact: true }).click(); const menu = page.getByRole("menu"); diff --git a/playwright/e2e/user-onboarding/user-onboarding-new.spec.ts b/playwright/e2e/user-onboarding/user-onboarding-new.spec.ts index f561eb9615e..b89fa3ac70a 100644 --- a/playwright/e2e/user-onboarding/user-onboarding-new.spec.ts +++ b/playwright/e2e/user-onboarding/user-onboarding-new.spec.ts @@ -26,7 +26,7 @@ test.describe("User Onboarding (new user)", () => { await expect(page.locator(".mx_UserOnboardingList")).toBeVisible(); }); - test("page is shown and preference exists", async ({ page, app }) => { + test("page is shown and preference exists", { tag: "@screenshot" }, async ({ page, app }) => { await expect(page.locator(".mx_UserOnboardingPage")).toMatchScreenshot( "User-Onboarding-new-user-page-is-shown-and-preference-exists-1.png", ); @@ -34,7 +34,7 @@ test.describe("User Onboarding (new user)", () => { await expect(page.getByText("Show shortcut to welcome checklist above the room list")).toBeVisible(); }); - test("app download dialog", async ({ page }) => { + test("app download dialog", { tag: "@screenshot" }, async ({ page }) => { await page.getByRole("button", { name: "Download apps" }).click(); await expect( page.getByRole("dialog").getByRole("heading", { level: 1, name: "Download Element" }), diff --git a/playwright/e2e/user-view/user-view.spec.ts b/playwright/e2e/user-view/user-view.spec.ts index 218c63fe743..ff8e9684e93 100644 --- a/playwright/e2e/user-view/user-view.spec.ts +++ b/playwright/e2e/user-view/user-view.spec.ts @@ -14,7 +14,7 @@ test.describe("UserView", () => { botCreateOpts: { displayName: "Usman" }, }); - test("should render the user view as expected", async ({ page, homeserver, user, bot }) => { + test("should render the user view as expected", { tag: "@screenshot" }, async ({ page, homeserver, user, bot }) => { await page.goto(`/#/user/${bot.credentials.userId}`); const rightPanel = page.locator("#mx_RightPanel"); diff --git a/playwright/e2e/widgets/layout.spec.ts b/playwright/e2e/widgets/layout.spec.ts index 41cfece6e80..c80ea44078e 100644 --- a/playwright/e2e/widgets/layout.spec.ts +++ b/playwright/e2e/widgets/layout.spec.ts @@ -70,7 +70,7 @@ test.describe("Widget Layout", () => { await app.viewRoomByName(ROOM_NAME); }); - test("should be set properly", async ({ page }) => { + test("should be set properly", { tag: "@screenshot" }, async ({ page }) => { await expect(page.locator(".mx_AppsDrawer")).toMatchScreenshot("apps-drawer.png"); }); diff --git a/playwright/element-web-test.ts b/playwright/element-web-test.ts index 8d5229a5100..76e57e33f70 100644 --- a/playwright/element-web-test.ts +++ b/playwright/element-web-test.ts @@ -314,6 +314,10 @@ export const expect = baseExpect.extend({ const testInfo = test.info(); if (!testInfo) throw new Error(`toMatchScreenshot() must be called during the test`); + if (!testInfo.tags.includes("@screenshot")) { + throw new Error("toMatchScreenshot() must be used in a test tagged with @screenshot"); + } + const page = "page" in receiver ? receiver.page() : receiver; let css = ` diff --git a/playwright/plugins/homeserver/synapse/index.ts b/playwright/plugins/homeserver/synapse/index.ts index 2b386afb539..a1ee295ec9f 100644 --- a/playwright/plugins/homeserver/synapse/index.ts +++ b/playwright/plugins/homeserver/synapse/index.ts @@ -20,7 +20,7 @@ import { randB64Bytes } from "../../utils/rand"; // Docker tag to use for synapse docker image. // We target a specific digest as every now and then a Synapse update will break our CI. // This digest is updated by the playwright-image-updates.yaml workflow periodically. -const DOCKER_TAG = "develop@sha256:892793d00b70e9a92ceb929263fe734408ce7f50cb4436c65f07407048a6d4e7"; +const DOCKER_TAG = "develop@sha256:7e5aa044c65d67382f29acd424fc5eae447a951114be8b650e322145ba65d75f"; async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise> { const templateDir = path.join(__dirname, "templates", opts.template); diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts index f97dff786fa..e8122b2dbf2 100644 --- a/src/SecurityManager.ts +++ b/src/SecurityManager.ts @@ -7,8 +7,8 @@ Please see LICENSE files in the repository root for full details. */ import { lazy } from "react"; -import { ICryptoCallbacks, SecretStorage } from "matrix-js-sdk/src/matrix"; -import { deriveRecoveryKeyFromPassphrase, decodeRecoveryKey } from "matrix-js-sdk/src/crypto-api"; +import { SecretStorage } from "matrix-js-sdk/src/matrix"; +import { deriveRecoveryKeyFromPassphrase, decodeRecoveryKey, CryptoCallbacks } from "matrix-js-sdk/src/crypto-api"; import { logger } from "matrix-js-sdk/src/logger"; import Modal from "./Modal"; @@ -159,7 +159,7 @@ function cacheSecretStorageKey( } } -export const crossSigningCallbacks: ICryptoCallbacks = { +export const crossSigningCallbacks: CryptoCallbacks = { getSecretStorageKey, cacheSecretStorageKey, }; diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index 5fc4d8c3576..b739cec12fc 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -49,7 +49,6 @@ import VoipUserMapper from "./VoipUserMapper"; import { htmlSerializeFromMdIfNeeded } from "./editor/serialize"; import { leaveRoomBehaviour } from "./utils/leave-behaviour"; import { MatrixClientPeg } from "./MatrixClientPeg"; -import { getDeviceCryptoInfo } from "./utils/crypto/deviceInfo"; import { isCurrentLocalRoom, reject, singleMxcUpload, success, successSync } from "./slash-commands/utils"; import { deop, op } from "./slash-commands/op"; import { CommandCategories } from "./slash-commands/interface"; @@ -658,69 +657,6 @@ export const Commands = [ category: CommandCategories.admin, renderingTypes: [TimelineRenderingType.Room], }), - new Command({ - command: "verify", - args: " ", - description: _td("slash_command|verify"), - runFn: function (cli, roomId, threadId, args) { - if (args) { - const matches = args.match(/^(\S+) +(\S+) +(\S+)$/); - if (matches) { - const userId = matches[1]; - const deviceId = matches[2]; - const fingerprint = matches[3]; - - return success( - (async (): Promise => { - const device = await getDeviceCryptoInfo(cli, userId, deviceId); - if (!device) { - throw new UserFriendlyError("slash_command|verify_unknown_pair", { - userId, - deviceId, - cause: undefined, - }); - } - const deviceTrust = await cli.getCrypto()?.getDeviceVerificationStatus(userId, deviceId); - - if (deviceTrust?.isVerified()) { - if (device.getFingerprint() === fingerprint) { - throw new UserFriendlyError("slash_command|verify_nop"); - } else { - throw new UserFriendlyError("slash_command|verify_nop_warning_mismatch"); - } - } - - if (device.getFingerprint() !== fingerprint) { - const fprint = device.getFingerprint(); - throw new UserFriendlyError("slash_command|verify_mismatch", { - fprint, - userId, - deviceId, - fingerprint, - cause: undefined, - }); - } - - await cli.setDeviceVerified(userId, deviceId, true); - - // Tell the user we verified everything - Modal.createDialog(InfoDialog, { - title: _t("slash_command|verify_success_title"), - description: ( -
-

{_t("slash_command|verify_success_description", { userId, deviceId })}

-
- ), - }); - })(), - ); - } - } - return reject(this.getUsage()); - }, - category: CommandCategories.advanced, - renderingTypes: [TimelineRenderingType.Room], - }), new Command({ command: "discardsession", description: _td("slash_command|discardsession"), diff --git a/src/components/views/dialogs/BaseDialog.tsx b/src/components/views/dialogs/BaseDialog.tsx index 00da8b4f526..ccb162e1cba 100644 --- a/src/components/views/dialogs/BaseDialog.tsx +++ b/src/components/views/dialogs/BaseDialog.tsx @@ -119,6 +119,7 @@ export default class BaseDialog extends React.Component { diff --git a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.tsx b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.tsx deleted file mode 100644 index 76e7580e018..00000000000 --- a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.tsx +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2020 The Matrix.org Foundation C.I.C. -Copyright 2019 New Vector Ltd -Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> -Copyright 2017 Vector Creations Ltd -Copyright 2016 OpenMarket Ltd - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only -Please see LICENSE files in the repository root for full details. -*/ - -import React, { useCallback } from "react"; -import { Device } from "matrix-js-sdk/src/matrix"; - -import * as FormattingUtils from "../../../utils/FormattingUtils"; -import { _t } from "../../../languageHandler"; -import QuestionDialog from "./QuestionDialog"; -import { MatrixClientPeg } from "../../../MatrixClientPeg"; - -interface IManualDeviceKeyVerificationDialogProps { - userId: string; - device: Device; - onFinished(confirm?: boolean): void; -} - -export function ManualDeviceKeyVerificationDialog({ - userId, - device, - onFinished, -}: IManualDeviceKeyVerificationDialogProps): JSX.Element { - const mxClient = MatrixClientPeg.safeGet(); - - const onLegacyFinished = useCallback( - (confirm: boolean) => { - if (confirm) { - mxClient.setDeviceVerified(userId, device.deviceId, true); - } - onFinished(confirm); - }, - [mxClient, userId, device, onFinished], - ); - - let text; - if (mxClient?.getUserId() === userId) { - text = _t("encryption|verification|manual_device_verification_self_text"); - } else { - text = _t("encryption|verification|manual_device_verification_user_text"); - } - - const fingerprint = device.getFingerprint(); - const key = fingerprint && FormattingUtils.formatCryptoKey(fingerprint); - const body = ( -
-

{text}

-
-
    -
  • - {" "} - {device.displayName} -
  • -
  • - {" "} - - {device.deviceId} - -
  • -
  • - {" "} - - - {key} - - -
  • -
-
-

{_t("encryption|verification|manual_device_verification_footer")}

-
- ); - - return ( - - ); -} diff --git a/src/components/views/dialogs/UntrustedDeviceDialog.tsx b/src/components/views/dialogs/UntrustedDeviceDialog.tsx index c2bc92e7510..4b37032207b 100644 --- a/src/components/views/dialogs/UntrustedDeviceDialog.tsx +++ b/src/components/views/dialogs/UntrustedDeviceDialog.tsx @@ -17,9 +17,20 @@ import BaseDialog from "./BaseDialog"; import { IDevice } from "../right_panel/UserInfo"; interface IProps { + /** + * The user whose device is untrusted. + */ user: User; + /** + * The device that is untrusted. + */ device: IDevice; - onFinished(mode?: "legacy" | "sas" | false): void; + /** + * Callback for when the dialog is dismissed. + * If mode is "sas", the user wants to verify the device with SAS. Otherwise, the dialog was dismissed normally. + * @param mode The mode of dismissal. + */ + onFinished(mode?: "sas"): void; } const UntrustedDeviceDialog: React.FC = ({ device, user, onFinished }) => { @@ -56,13 +67,10 @@ const UntrustedDeviceDialog: React.FC = ({ device, user, onFinished }) =

{askToVerifyText}

- onFinished("legacy")}> - {_t("encryption|udd|manual_verification_button")} - onFinished("sas")}> {_t("encryption|udd|interactive_verification_button")} - onFinished(false)}> + onFinished()}> {_t("action|done")}
diff --git a/src/hooks/useEncryptionStatus.ts b/src/hooks/useEncryptionStatus.ts index 686f68f25e2..ed8cceb9f81 100644 --- a/src/hooks/useEncryptionStatus.ts +++ b/src/hooks/useEncryptionStatus.ts @@ -6,9 +6,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import { CryptoEvent, MatrixClient, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix"; +import { MatrixClient, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix"; import { useEffect, useMemo, useState } from "react"; import { throttle } from "lodash"; +import { CryptoEvent } from "matrix-js-sdk/src/crypto-api"; import { E2EStatus, shieldStatusForRoom } from "../utils/ShieldUtils"; import { useTypedEventEmitter } from "./useEventEmitter"; diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 7647377196b..df8a243c730 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -882,7 +882,6 @@ }, "udd": { "interactive_verification_button": "Interaktivní ověření pomocí emoji", - "manual_verification_button": "Ruční ověření pomocí textu", "other_ask_verify_text": "Požádejte tohoto uživatele, aby ověřil svou relaci, nebo jí níže můžete ověřit manuálně.", "other_new_session_text": "%(name)s (%(userId)s) se přihlásil(a) do nové relace bez ověření:", "own_ask_verify_text": "Ověřte další relaci jedním z následujících způsobů.", @@ -917,12 +916,6 @@ "incoming_sas_dialog_waiting": "Čekání na potvrzení partnerem…", "incoming_sas_user_dialog_text_1": "Po ověření bude uživatel označen jako důvěryhodný. Ověřování uživatelů vám dává větší jistotu, že je komunikace důvěrná.", "incoming_sas_user_dialog_text_2": "Ověření uživatele označí jeho relace za důvěryhodné a vaše relace budou důvěryhodné pro něj.", - "manual_device_verification_device_id_label": "ID sezení", - "manual_device_verification_device_key_label": "Klíč relace", - "manual_device_verification_device_name_label": "Název relace", - "manual_device_verification_footer": "Pokud se neshodují, bezpečnost vaší komunikace může být kompromitována.", - "manual_device_verification_self_text": "Potvrďte porovnáním následujícího s uživatelským nastavením v jiné relaci:", - "manual_device_verification_user_text": "Potvrďte relaci tohoto uživatele porovnáním následujícího s jeho uživatelským nastavením:", "no_key_or_device": "Vypadá to, že nemáte bezpečnostní klíč ani žádné jiné zařízení, které byste mohli ověřit. Toto zařízení nebude mít přístup ke starým šifrovaným zprávám. Abyste mohli na tomto zařízení ověřit svou totožnost, budete muset resetovat ověřovací klíče.", "no_support_qr_emoji": "Zařízení, které se snažíte ověřit, neumožňuje ověření QR kódem ani pomocí emotikonů, které %(brand)s podporuje. Zkuste použít jiného klienta.", "other_party_cancelled": "Druhá strana ověření zrušila.", @@ -1046,10 +1039,6 @@ }, "error_user_not_logged_in": "Uživatel není přihlášen", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s ukončil(a) hlasové vysílání", - "you": "Ukončili jste hlasové vysílání" - }, "m.call.answer": { "dm": "Probíhá hovor", "user": "%(senderName)s se připojil k hovoru", @@ -1423,8 +1412,6 @@ "video_rooms_faq2_answer": "Ano, časová osa chatu se zobrazuje vedle videa.", "video_rooms_faq2_question": "Mohu vedle videohovoru používat i textový chat?", "video_rooms_feedbackSubheading": "Děkujeme, že jste vyzkoušeli beta verzi, a prosíme vás o co nejpodrobnější informace, abychom ji mohli vylepšit.", - "voice_broadcast": "Hlasové vysílání", - "voice_broadcast_force_small_chunks": "Vynutit 15s délku bloku hlasového vysílání", "wysiwyg_composer": "Editor formátovaného textu" }, "labs_mjolnir": { @@ -1568,7 +1555,6 @@ "mute_description": "Nebudete dostávat žádná oznámení" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s zahájil(a) hlasové vysílání", "m.key.verification.request": "%(name)s žádá o ověření" }, "onboarding": { @@ -2145,7 +2131,6 @@ "error_unbanning": "Zrušení vykázání se nezdařilo", "events_default": "Posílat zprávy", "invite": "Zvát uživatele", - "io.element.voice_broadcast_info": "Hlasová vysílání", "kick": "Odebrat uživatele", "m.call": "Zahájit %(brand)s volání", "m.call.member": "Připojit se k %(brand)s volání", @@ -2788,7 +2773,6 @@ "warning": "UPOZORNĚNÍ: " }, "share": { - "link_title": "Odkaz na místnost", "permalink_message": "Odkaz na vybranou zprávu", "permalink_most_recent": "Odkaz na nejnovější zprávu", "share_call": "Odkaz na pozvánku na konferenci", @@ -2880,13 +2864,6 @@ "upgraderoom": "Aktualizuje místnost na novou verzi", "upgraderoom_permission_error": "Na provedení tohoto příkazu nemáte dostatečná oprávnění.", "usage": "Použití", - "verify": "Ověří uživatele, relaci a veřejné klíče", - "verify_mismatch": "VAROVÁNÍ: OVĚŘENÍ KLÍČE SE NEZDAŘILO! Podpisový klíč pro uživatele %(userId)s a relaci %(deviceId)s je „%(fprint)s“, což neodpovídá klíči „%(fingerprint)s“. To by mohlo znamenat, že vaše komunikace je zachycována!", - "verify_nop": "Relace je už ověřená!", - "verify_nop_warning_mismatch": "VAROVÁNÍ: relace již byla ověřena, ale klíče se NESHODUJÍ!", - "verify_success_description": "Zadaný podpisový klíč odpovídá klíči relace %(deviceId)s od uživatele %(userId)s. Relace byla označena jako ověřená.", - "verify_success_title": "Ověřený klíč", - "verify_unknown_pair": "Neznámý pár (uživatel, relace): (%(userId)s, %(deviceId)s)", "view": "Zobrazí místnost s danou adresou", "whois": "Zobrazuje informace o uživateli" }, @@ -3104,10 +3081,6 @@ "error_rendering_message": "Tuto zprávu nelze načíst", "historical_messages_unavailable": "Dřívější zprávy nelze zobrazit", "in_room_name": " v %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s ukončil(a) hlasové vysílání", - "you": "Ukončili jste hlasové vysílání" - }, "io.element.widgets.layout": "%(senderName)s aktualizoval rozvržení místnosti", "late_event_separator": "Původně odesláno %(dateTime)s", "load_error": { @@ -3640,38 +3613,6 @@ "switch_theme_dark": "Přepnout do tmavého režimu", "switch_theme_light": "Přepnout do světlého režimu" }, - "voice_broadcast": { - "30s_backward": "30s zpět", - "30s_forward": "30s vpřed", - "action": "Hlasové vysílání", - "buffering": "Ukládání do vyrovnávací paměti…", - "confirm_listen_affirm": "Ano, ukončit nahrávání", - "confirm_listen_description": "Jakmile začnete poslouchat toto živé vysílání, aktuální záznam živého vysílání bude ukončen.", - "confirm_listen_title": "Poslouchat živé vysílání?", - "confirm_stop_affirm": "Ano, zastavit vysílání", - "confirm_stop_description": "Opravdu chcete ukončit živé vysílání? Tím se vysílání ukončí a v místnosti bude k dispozici celý záznam.", - "confirm_stop_title": "Ukončit živé vysílání?", - "connection_error": "Chyba připojení - nahrávání pozastaveno", - "failed_already_recording_description": "Již nahráváte hlasové vysílání. Ukončete prosím aktuální hlasové vysílání a spusťte nové.", - "failed_already_recording_title": "Nelze spustit nové hlasové vysílání", - "failed_decrypt": "Nelze dešifrovat hlasové vysílání", - "failed_generic": "Nelze přehrát toto hlasové vysílání", - "failed_insufficient_permission_description": "Nemáte potřebná oprávnění ke spuštění hlasového vysílání v této místnosti. Obraťte se na správce místnosti, aby vám zvýšil oprávnění.", - "failed_insufficient_permission_title": "Nelze spustit nové hlasové vysílání", - "failed_no_connection_description": "Bohužel nyní nemůžeme spustit nahrávání. Zkuste to prosím později.", - "failed_no_connection_title": "Chyba připojení", - "failed_others_already_recording_description": "Hlasové vysílání už nahrává někdo jiný. Počkejte, až jeho hlasové vysílání skončí, a spusťte nové.", - "failed_others_already_recording_title": "Nelze spustit nové hlasové vysílání", - "go_live": "Přejít naživo", - "live": "Živě", - "pause": "pozastavit hlasové vysílání", - "play": "přehrát hlasové vysílání", - "resume": "obnovit hlasové vysílání" - }, - "voice_message": { - "cant_start_broadcast_description": "Hlasovou zprávu nelze spustit, protože právě nahráváte živé vysílání. Ukončete prosím živé vysílání, abyste mohli začít nahrávat hlasovou zprávu.", - "cant_start_broadcast_title": "Nelze spustit hlasovou zprávu" - }, "voip": { "already_in_call": "Již máte hovor", "already_in_call_person": "S touto osobou již telefonujete.", @@ -3691,7 +3632,6 @@ "camera_disabled": "Vaše kamera je vypnutá", "camera_enabled": "Vaše kamera je stále zapnutá", "cannot_call_yourself_description": "Nemůžete volat sami sobě.", - "change_input_device": "Změnit vstupní zařízení", "close_lobby": "Zavřít lobby", "connecting": "Spojování", "connection_lost": "Došlo ke ztrátě připojení k serveru", @@ -3710,8 +3650,6 @@ "enable_camera": "Zapnout kameru", "enable_microphone": "Zrušit ztlumení mikrofonu", "expand": "Návrat do hovoru", - "failed_call_live_broadcast_description": "Nemůžete zahájit hovor, protože právě nahráváte živé vysílání. Ukončete prosím živé vysílání, abyste mohli zahájit hovor.", - "failed_call_live_broadcast_title": "Nelze zahájit hovor", "get_call_link": "Sdílet odkaz na hovor", "hangup": "Zavěsit", "hide_sidebar_button": "Skrýt postranní panel", diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 65cb1d8660a..f8298a28e90 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -18,6 +18,7 @@ "unread_messages": "Ungelesene Nachrichten.", "user_menu": "Benutzermenü" }, + "a11y_jump_first_unread_room": "Springen Sie zum ersten ungelesenen Chatroom.", "action": { "accept": "Annehmen", "add": "Hinzufügen", @@ -258,17 +259,21 @@ "error_insecure_channel_detected": "Eine sichere Verbindung zum neuen Gerät konnte nicht hergestellt werden. Ihre vorhandenen Geräte sind weiterhin sicher und Sie müssen sich keine Sorgen um sie machen.", "error_insecure_channel_detected_instructions": "Was jetzt?", "error_insecure_channel_detected_instructions_1": "Versuchen Sie erneut, sich mit einem QR-Code auf dem anderen Gerät anzumelden, falls dies ein Netzwerkproblem war", - "error_insecure_channel_detected_instructions_2": "Falls das gleiche Problem auftritt, probiere es mit einem anderen WLAN-Netzwerk oder verwende deine Mobilen Daten.", - "error_insecure_channel_detected_instructions_3": "Falls das nicht funktioniert melde dich manuell an.", - "error_insecure_channel_detected_title": "Verbindung ist nicht sicher", + "error_insecure_channel_detected_instructions_2": "Falls das gleiche Problem auftritt, probiere Sie es bitte mit einem anderen WLAN-Netzwerk oder verwenden Sie Ihre mobilen Daten anstelle von WLAN", + "error_insecure_channel_detected_instructions_3": "Falls das nicht funktioniert, melden Sie sich bitte manuell an.", + "error_insecure_channel_detected_title": "Die Verbindung ist nicht sicher", "error_other_device_already_signed_in": "Sie brauchen nichts weiter zu tun.", "error_other_device_already_signed_in_title": "Ihr anderes Gerät ist bereits angemeldet", "error_rate_limited": "Zu viele Versuche in zu kurzer Zeit. Warte ein wenig, bevor du es erneut versuchst.", + "error_unexpected": "Es ist ein unerwarteter Fehler aufgetreten. Ihre Anfrage zum Verbinden des anderen Geräts wurde abgebrochen.", "error_unsupported_protocol": "Dieses Gerät unterstützt die Anmeldung auf einem anderen Gerät mit einem QR-Code nicht.", + "error_unsupported_protocol_title": "Anderes Gerät nicht kompatibel", "error_user_cancelled": "Der Anmeldevorgang wurde am anderen Gerät abgebrochen.", "error_user_cancelled_title": "Anmeldungsanfrage abgebrochen", - "error_user_declined": "Du oder der Kontoanbieter haben die Anmeldeanfrage abgelehnt.", + "error_user_declined": "Sie oder der Kontoanbieter haben die Anmeldeanfrage abgelehnt.", "error_user_declined_title": "Anmeldung abgelehnt", + "follow_remaining_instructions": "Folgen Sie den restlichen Anweisungen.", + "open_element_other_device": "Öffnen Sie %(brand)s auf Ihren anderen Gerät", "point_the_camera": "Scanne den hier angezeigten QR-Code", "scan_code_instruction": "Scanne den QR-Code mit einem weiteren Gerät.", "scan_qr_code": "Anmeldung mit QR-Code", @@ -288,6 +293,8 @@ "registration_disabled": "Registrierungen wurden auf diesem Heim-Server deaktiviert.", "registration_msisdn_field_required_invalid": "Telefonnummer eingeben (auf diesem Heim-Server erforderlich)", "registration_successful": "Registrierung erfolgreich", + "registration_username_in_use": "Dieser Benutzername wird bereits verwendet. Wählen Sie einen anderen Benutzernamen oder melden Sie sich unten an.", + "registration_username_unable_check": "Es kann nicht überprüft werden, ob der Benutzername bereits vergeben ist. Bitte versuchen Sie es später erneut.", "registration_username_validation": "Verwende nur Kleinbuchstaben, Zahlen, Bindestriche und Unterstriche", "reset_password": { "confirm_new_password": "Neues Passwort bestätigen", @@ -363,8 +370,8 @@ "email_resend_prompt": "Nicht angekommen? Erneut senden", "email_resent": "Verschickt!", "fallback_button": "Authentifizierung beginnen", - "mas_cross_signing_reset_cta": "Gehe zu deinem Konto", - "mas_cross_signing_reset_description": "Lasse deine Identität durch deinen Kontoanbieter zurücksetzen. Kehre dann zurück und klicke auf \"Erneut versuchen\".", + "mas_cross_signing_reset_cta": "Gehen Sie zu Ihren Konto", + "mas_cross_signing_reset_description": "Setzen Sie Ihre Identität über Ihren Kontoanbieter zurück. Kommen Sie dann zurück und klicken Sie auf „Wiederholen“.", "msisdn": "Eine Textnachricht wurde an %(msisdn)s gesendet", "msisdn_token_incorrect": "Token fehlerhaft", "msisdn_token_prompt": "Bitte gib den darin enthaltenen Code ein:", @@ -385,6 +392,7 @@ "unsupported_auth_email": "Dieser Heim-Server unterstützt die Anmeldung per E-Mail-Adresse nicht.", "unsupported_auth_msisdn": "Dieser Server unterstützt keine Authentifizierung per Telefonnummer.", "username_field_required_invalid": "Benutzername eingeben", + "username_in_use": "Dieser Benutzername wird bereits verwendet. Bitte wählen Sie einen anderen Benutzernamen.", "verify_email_explainer": "Wir müssen wissen, dass du es auch wirklich bist, bevor wir dein Passwort zurücksetzen. Klicke auf den Link in der E-Mail, die wir gerade an %(email)s gesendet haben", "verify_email_heading": "Verifiziere deine E-Mail, um fortzufahren" }, @@ -399,7 +407,7 @@ "downloading_logs": "Lade Protokolle herunter", "error_empty": "Bitte teile uns mit, was schief lief - oder besser, beschreibe das Problem auf GitHub in einem \"Issue\".", "failed_send_logs": "Senden von Protokolldateien fehlgeschlagen: ", - "github_issue": "\"Issue\" auf Github", + "github_issue": "GitHub-Problem", "introduction": "Wenn du uns einen Bug auf GitHub gemeldet hast, können uns Debug-Logs helfen, das Problem zu finden. ", "log_request": "Um uns zu helfen, dies in Zukunft zu vermeiden, sende uns bitte die Protokolldateien.", "logs_sent": "Protokolldateien gesendet", @@ -914,7 +922,6 @@ }, "udd": { "interactive_verification_button": "Interaktiv per Emoji verifizieren", - "manual_verification_button": "Manuell per Text verifizieren", "other_ask_verify_text": "Bitte diesen Nutzer, seine Sitzung zu verifizieren, oder verifiziere diese unten manuell.", "other_new_session_text": "%(name)s (%(userId)s) hat sich zu einer neuen Sitzung angemeldet, ohne sie zu verifizieren:", "own_ask_verify_text": "Verifiziere deine andere Sitzung mit einer der folgenden Optionen.", @@ -949,12 +956,6 @@ "incoming_sas_dialog_waiting": "Warte auf Bestätigung des Gesprächspartners …", "incoming_sas_user_dialog_text_1": "Überprüfe diesen Benutzer, um ihn als vertrauenswürdig zu kennzeichnen. Benutzern zu vertrauen gibt dir zusätzliche Sicherheit bei der Verwendung von Ende-zu-Ende-verschlüsselten Nachrichten.", "incoming_sas_user_dialog_text_2": "Wenn du diesen Benutzer verifizierst werden seine Sitzungen für dich und deine Sitzungen für ihn als vertrauenswürdig markiert.", - "manual_device_verification_device_id_label": "Sitzungs-ID", - "manual_device_verification_device_key_label": "Sitzungsschlüssel", - "manual_device_verification_device_name_label": "Sitzungsname", - "manual_device_verification_footer": "Wenn sie nicht übereinstimmen kann die Sicherheit eurer Kommunikation kompromittiert sein.", - "manual_device_verification_self_text": "Bestätige indem du das folgende mit deinen Benutzereinstellungen in deiner anderen Sitzung vergleichst:", - "manual_device_verification_user_text": "Bestätige die Sitzung dieses Benutzers indem du das folgende mit seinen Benutzereinstellungen vergleichst:", "no_key_or_device": "Es sieht so aus, als hättest du keinen Sicherheitsschlüssel oder andere Geräte, mit denen du dich verifizieren könntest. Dieses Gerät wird keine alten verschlüsselten Nachrichten lesen können. Um deine Identität auf diesem Gerät zu verifizieren musst du deine Verifizierungsschlüssel zurücksetzen.", "no_support_qr_emoji": "Das Gerät unterstützt weder Verifizieren mittels QR-Code noch Emoji-Verifizierung. %(brand)s benötigt dies jedoch. Bitte verwende eine andere Anwendung.", "other_party_cancelled": "Die Gegenstelle hat die Überprüfung abgebrochen.", @@ -994,6 +995,7 @@ "unverified_sessions_toast_description": "Überprüfe sie, um ein sicheres Konto gewährleisten zu können", "unverified_sessions_toast_reject": "Später", "unverified_sessions_toast_title": "Du hast nicht verifizierte Sitzungen", + "verification_description": "Verifizieren Sie Ihre Identität, um auf verschlüsselte Nachrichten zuzugreifen und sich gegenüber anderen Benutzern zu verifizieren. Falls Sie einen Handy oder ein anderes mobiles Gerät verwenden, öffnen Sie die App dort and fahren sie mit Ihrer Identifikation fort.", "verification_dialog_title_device": "Anderes Gerät verifizieren", "verification_dialog_title_user": "Verifizierungsanfrage", "verification_skip_warning": "Ohne dich zu verifizieren wirst du keinen Zugriff auf alle deine Nachrichten haben und könntest für andere als nicht vertrauenswürdig erscheinen.", @@ -1078,10 +1080,6 @@ }, "error_user_not_logged_in": "Benutzer ist nicht angemeldet", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s beendete eine Sprachübertragung", - "you": "Du hast eine Sprachübertragung beendet" - }, "m.call.answer": { "dm": "Laufendes Gespräch", "user": "%(senderName)s ist dem Anruf beigetreten", @@ -1236,6 +1234,8 @@ "incompatible_browser": { "continue": "Trotzdem fortfahren", "description": "%(brand)s verwendet einige Browser-Funktionen, die von deinem aktuellen Browser nicht unterstützt werden. %(detail)s", + "detail_can_continue": "Wenn Sie fortfahren, funktionieren einige Funktionen möglicherweise nicht mehr und es besteht das Risiko, dass Sie in Zukunft Daten verlieren.", + "detail_no_continue": "Versuchen Sie, diesen Browser zu aktualisieren, wenn Sie nicht die neueste Version verwenden, und versuchen Sie es erneut.", "learn_more": "Mehr erfahren", "linux": "Linux", "macos": "Mac", @@ -1259,7 +1259,7 @@ "integrations": { "disabled_dialog_description": "Aktiviere „%(manageIntegrations)s“ in den Einstellungen, um dies zu tun.", "disabled_dialog_title": "Integrationen sind deaktiviert", - "impossible_dialog_description": "%(brand)s erlaubt dir nicht, eine Integrationsverwaltung zu verwenden, um dies zu tun. Bitte kontaktiere einen Administrator.", + "impossible_dialog_description": "%(brand)s erlaubt es Ihnen nicht, eine Integrationsverwaltung zu verwenden. Bitte kontaktieren Sie einen Administrator.", "impossible_dialog_title": "Integrationen sind nicht erlaubt" }, "invite": { @@ -1421,7 +1421,7 @@ "dynamic_room_predecessors_description": "MSC3946 aktivieren (zur Verknüpfung von Raumarchiven nach der Raumerstellung)", "element_call_video_rooms": "Element Call-Videoräume", "exclude_insecure_devices": "Unsichere Geräte ausschließen beim senden/empfangen von Nachrichten", - "exclude_insecure_devices_description": "Bei Aktivierung dieses Modus werden verschlüsselte Nachrichten nicht mehr mit unverifizierten Geräten geteilt und Nachrichten von unverifizierten Geräten werden als Fehler angezeigt. Beachte, dass wenn du den Modus aktivierst, eine Kommunikation mit Benutzern, die keine verifizierten Geräte haben, nicht möglich ist.", + "exclude_insecure_devices_description": "Bei Aktivierung dieses Modus werden verschlüsselte Nachrichten nicht mehr mit unverifizierten Geräten geteilt und Nachrichten von unverifizierten Geräten werden als Fehler angezeigt. Beachten Sie, dass bei Aktivierung dieses Modus es nicht möglich ist, mit Benutzern, die keine verifizierten Geräte haben, zu kommunizieren.", "experimental_description": "Experimentierfreudig? Probiere unsere neuesten, sich in Entwicklung befindlichen Ideen aus. Diese Funktionen sind nicht final; Sie könnten instabil sein, sich verändern oder sogar ganz entfernt werden. Erfahre mehr.", "experimental_section": "Frühe Vorschauen", "extended_profiles_msc_support": "Erfordert die Unterstützung von MSC4133 durch den Server", @@ -1460,6 +1460,7 @@ "notifications": "Benachrichtigungen in der Kopfleiste des Raums anschalten", "oidc_native_flow": "Native OIDC Authentifizierung", "oidc_native_flow_description": "⚠ Warnung: Experimentell. Nutze OIDC native Authentifizierung wenn dies vom Server unterstützt wird.", + "release_announcement": "Release Ankündigung", "render_reaction_images": "Benutzerdefinierte Bilder in Reaktionen anzeigen", "render_reaction_images_description": "Werden manchmal auch als „benutzerdefinierte Emojis“ bezeichnet.", "report_to_moderators": "An Raummoderation melden", @@ -1467,6 +1468,7 @@ "sliding_sync": "Sliding-Sync-Modus", "sliding_sync_description": "In aktiver Entwicklung, kann nicht deaktiviert werden.", "sliding_sync_disabled_notice": "Zum Deaktivieren, melde dich ab und erneut an", + "sliding_sync_server_no_support": "Dein Server wird hier nicht unterstützt.", "under_active_development": "In aktiver Entwicklung.", "unrealiable_e2e": "Nicht zuverlässig in verschlüsselten Räumen", "video_rooms": "Videoräume", @@ -1478,8 +1480,6 @@ "video_rooms_faq2_answer": "Ja, der Verlauf wird neben dem Videoanruf angezeigt.", "video_rooms_faq2_question": "Kann ich während Videoanrufen auch Textnachrichten verschicken?", "video_rooms_feedbackSubheading": "Danke, dass Du die Beta ausprobierst. Bitte gehe soweit wie Du kannst ins Detail damit wird genau überprüfen können.", - "voice_broadcast": "Sprachübertragung", - "voice_broadcast_force_small_chunks": "Die Chunk-Länge der Sprachübertragungen auf 15 Sekunden erzwingen", "wysiwyg_composer": "Textverarbeitungs-Editor" }, "labs_mjolnir": { @@ -1520,6 +1520,8 @@ "last_person_warning": "Du bist die einzige Person im Raum. Sobald du ihn verlässt, wird niemand mehr hineingelangen, auch du nicht.", "leave_room_question": "Bist du sicher, dass du den Raum „%(roomName)s“ verlassen möchtest?", "leave_space_question": "Bist du sicher, dass du den Space „%(spaceName)s“ verlassen möchtest?", + "room_leave_admin_warning": "Sie sind der einzige Administrator in diesem Chatroom. Wenn Sie den Chatroom verlassen, wird niemand in der Lage sein, die Chatroommeinstellungen zu ändern oder andere wichtige Maßnahmen zu ergreifen.", + "room_leave_mod_warning": "Sie sind der einzige Moderator in diesem Chatroom. Wenn Sie den Chatroom verlassen, kann niemand die Raumeinstellungen ändern oder andere wichtige Maßnahmen ergreifen.", "room_rejoin_warning": "Dieser Raum ist nicht öffentlich. Du wirst ihn nicht ohne erneute Einladung betreten können.", "space_rejoin_warning": "Du wirst diesen privaten Space nur mit einer Einladung wieder betreten können." }, @@ -1623,7 +1625,6 @@ "mute_description": "Du wirst keine Benachrichtigungen erhalten" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s begann eine Sprachübertragung", "m.key.verification.request": "%(name)s fordert eine Verifizierung an" }, "onboarding": { @@ -1824,9 +1825,11 @@ "add_integrations": "Erweiterungen hinzufügen", "add_topic": "Thema hinzufügen", "extensions_button": "Erweiterungen", - "extensions_empty_description": "Wählen Sie \"%(addIntegrations)s\" um Erweiterungen zu suchen und diesem Raum hinzuzufügen", + "extensions_empty_description": "Wählen Sie \"%(addIntegrations)s\" um Erweiterungen zu suchen und diesem Chatroom hinzuzufügen", + "extensions_empty_title": "Steigern Sie die Produktivität mit mehr Tools, Widgets und Bots", "files_button": "Dateien", "pinned_messages": { + "empty_description": "Wählen Sie eine Nachricht aus und wählen Sie „%(pinAction)s “, um sie hier einzuschließen.", "empty_title": "Hefte wichtige Nachrichten an, damit sie leicht gefunden werden können.", "header": { "one": "1 angeheftete Nachricht", @@ -1838,15 +1841,18 @@ "menu": "Menü öffnen", "release_announcement": { "close": "Ok", - "description": "Alle angehefteten Nachrichten findest du hier. Bewege den Mauszeiger über eine beliebige Nachricht und wählen anheften, um sie hinzuzufügen." + "description": "Alle angepinnten Nachrichten finden Sie hier. Bewegen Sie den Mauszeiger über eine beliebige Nachricht und wählen Sie „Pin“, um die Nachricht hinzuzufügen.", + "title": "Alle neuen angehefteten Nachrichten" }, "reply_thread": "Auf Nachricht im Thread antworten", "unpin_all": { "button": "Alle Nachrichten lösen", + "content": "Stellen Sie sicher, dass Sie wirklich alle angehefteten Nachrichten entfernen möchten. Diese Aktion kann nicht rückgängig gemacht werden.", "title": "Alle Nachrichten lösen?" }, "view": "Im Nachrichtenverlauf ansehen" }, + "pinned_messages_button": "Angeheftete Nachrichten", "poll": { "active_heading": "Aktive Umfragen", "empty_active": "In diesem Raum gibt es keine aktiven Umfragen", @@ -1949,7 +1955,7 @@ }, "room_is_public": "Dieser Raum ist öffentlich" }, - "header_avatar_open_settings_label": "Raumeinstellungen öffnen", + "header_avatar_open_settings_label": "Chatroomeinstellungen öffnen", "header_face_pile_tooltip": "Personen", "header_untrusted_label": "Nicht vertrauenswürdig", "inaccessible": "Dieser Raum oder Space ist im Moment nicht zugänglich.", @@ -2024,7 +2030,7 @@ "pinned_message_banner": { "button_close_list": "Liste schließen", "button_view_all": "Alle anzeigen", - "description": "Dieser Raum hat fixierte Nachrichten. Klicke zum Anzeigen.", + "description": "In diesem Raum sind Nachrichten angeheftet. Klicken Sie hier, um sie anzusehen.", "go_to_message": "Fixierte Nachrichten im Nachrichtenverlauf anzeigen.", "title": "%(index)s of %(length)s Angeheftete Nachrichten" }, @@ -2173,8 +2179,8 @@ "error_deleting_alias_description": "Beim Entfernen dieser Adresse ist ein Fehler aufgetreten. Vielleicht existiert sie nicht mehr oder es kam zu einem temporären Fehler.", "error_deleting_alias_description_forbidden": "Du hast nicht die Berechtigung, die Adresse zu löschen.", "error_deleting_alias_title": "Fehler beim Löschen der Adresse", - "error_publishing": "Raum konnte nicht auf öffentlich gestellt werden", - "error_publishing_detail": "Bei der Freigabe des Raumes hat es einen Fehler gegeben", + "error_publishing": "Chatroom konnte nicht auf öffentlich gestellt werden", + "error_publishing_detail": "Beim Veröffentlichen dieses Chatrooms ist ein Fehler aufgetreten", "error_save_space_settings": "Spaceeinstellungen konnten nicht gespeichert werden.", "error_updating_alias_description": "Es gab einen Fehler beim Ändern des Raumalias. Entweder erlaubt es der Server nicht oder es gab ein temporäres Problem.", "error_updating_canonical_alias_description": "Es gab ein Problem beim Aktualisieren der Raum-Hauptadresse. Es kann sein, dass der Server dies verbietet oder ein temporäres Problem aufgetreten ist.", @@ -2232,7 +2238,6 @@ "error_unbanning": "Aufheben der Verbannung fehlgeschlagen", "events_default": "Nachrichten senden", "invite": "Person einladen", - "io.element.voice_broadcast_info": "Sprachübertragungen", "kick": "Benutzer entfernen", "m.call": "Beginne %(brand)s-Anrufe", "m.call.member": "Trete %(brand)s-Anrufen bei", @@ -2419,6 +2424,7 @@ "all_rooms_home_description": "Alle Räume, denen du beigetreten bist, werden auf der Startseite erscheinen.", "always_show_message_timestamps": "Nachrichtenzeitstempel immer anzeigen", "appearance": { + "bundled_emoji_font": "Verwenden Sie den mitgelieferten Emoji Font.", "compact_layout": "Kompakten Text und Nachrichten anzeigen", "compact_layout_description": "Um diese Funktion nutzen zu können, muss das moderne Nachrichtenlayout ausgewählt sein.", "custom_font": "Systemschriftart verwenden", @@ -2427,7 +2433,8 @@ "custom_font_size": "Andere Schriftgröße verwenden", "custom_theme_add": "Benutzerdefiniertes Design hinzufügen", "custom_theme_downloading": "Benutzerdefiniertes Design wird heruntergeladen...", - "custom_theme_help": "Gib die URL des einzustellenden benutzerdefinierten Designs ein.", + "custom_theme_error_downloading": "Fehler beim Herunterladen des Designs.", + "custom_theme_help": "Geben Sie die URL eines benutzerdefinierten Designs ein, das Sie anwenden möchten.", "custom_theme_invalid": "Ungültiges Designschema.", "dialog_title": "Einstellungen: Erscheinungsbild", "font_size": "Schriftgröße", @@ -2466,6 +2473,7 @@ "add_msisdn_instructions": "Gib den per SMS an +%(msisdn)s gesendeten Bestätigungscode ein.", "add_msisdn_misconfigured": "Das MSISDN-Verknüpfungsverfahren ist falsch konfiguriert", "allow_spellcheck": "Rechtschreibprüfung zulassen", + "application_language": "Anwendungssprache", "application_language_reload_hint": "Nach Änderung der Sprache wird die App neu gestartet", "avatar_remove_progress": "Bild wird entfernt...", "avatar_save_progress": "Bild wird hochgeladen...", @@ -2479,6 +2487,7 @@ "deactivate_confirm_content": "Bestätige, dass du dein Konto deaktivieren möchtest. Wenn du fortfährst, tritt folgendes ein:", "deactivate_confirm_content_1": "Du wirst dein Konto nicht reaktivieren können", "deactivate_confirm_content_2": "Du wirst dich nicht mehr anmelden können", + "deactivate_confirm_content_3": "Niemand wird in der Lage sein, Ihren Benutzernamen (MXID) wiederzuverwenden, Sie eingeschlossen: Der Benutzername wird insgesamt nur einmal vergeben.", "deactivate_confirm_content_4": "Du wirst alle Unterhaltungen verlassen, in denen du dich befindest", "deactivate_confirm_content_5": "Du wirst vom Identitäts-Server entfernt: Deine Freunde werden nicht mehr in der Lage sein, dich über deine E-Mail-Adresse oder Telefonnummer zu finden", "deactivate_confirm_content_6": "Deine alten Nachrichten werden weiterhin für Personen sichtbar bleiben, die sie erhalten haben, so wie es bei E-Mails der Fall ist. Möchtest du deine Nachrichten vor Personen verbergen, die Räume in der Zukunft betreten?", @@ -2490,6 +2499,7 @@ "discovery_email_verification_instructions": "Verifiziere den Link in deinem Posteingang", "discovery_msisdn_empty": "Optionen zum Entdecken anderer Benutzer werden angezeigt, sobald Sie Ihre Telefonnummer zu Ihrem Konto hinzugefügt haben", "discovery_needs_terms": "Stimme den Nutzungsbedingungen des Identitäts-Servers %(serverName)s zu, um per E-Mail-Adresse oder Telefonnummer auffindbar zu werden.", + "discovery_needs_terms_title": "Lassen Sie sich von anderen finden", "display_name": "Anzeigename", "display_name_error": "Anzeigename konnte nicht gesetzt werden", "email_address_in_use": "Diese E-Mail-Adresse wird bereits verwendet", @@ -2526,12 +2536,13 @@ "password_change_section": "Passwort des Nutzerkontos ändern...", "password_change_success": "Dein Passwort wurde erfolgreich geändert.", "personal_info": "Persönliche Daten", - "profile_subtitle": "So sehen dich andere in der App.", - "profile_subtitle_oidc": "Dein Konto wird separat durch einen Identitätsanbieter verwaltet. Einige persönliche Daten können hier nicht geändert werden.", + "profile_subtitle": "So werden Sie von anderen in der App gesehen", + "profile_subtitle_oidc": "Ihr Konto wird separat durch einen Identitätsanbieter verwaltet. Einige persönliche Daten können deswegen hier nicht geändert werden.", "remove_email_prompt": "%(email)s entfernen?", "remove_msisdn_prompt": "%(phone)s entfernen?", "spell_check_locale_placeholder": "Wähle ein Gebietsschema", "unable_to_load_emails": "E-Mail Adresse konnte nicht geladen werden", + "unable_to_load_msisdns": "Telefonnummern können nicht geladen werden", "username": "Benutzername" }, "image_thumbnails": "Vorschauen für Bilder", @@ -2591,6 +2602,9 @@ "dialog_title": "Einstellungen: Tastatur", "title": "Tastatur" }, + "labs": { + "dialog_title": "Einstellungen: Labore" + }, "labs_mjolnir": { "dialog_title": "Einstellungen: Blockierte Benutzer" }, @@ -2716,6 +2730,7 @@ "encryption_section": "Verschlüsselung", "error_loading_key_backup_status": "Konnte Status der Schlüsselsicherung nicht laden", "export_megolm_keys": "E2E-Raumschlüssel exportieren", + "ignore_users_empty": "Sie haben keinen Benutzer blockiert.", "ignore_users_section": "Blockierte Benutzer", "import_megolm_keys": "E2E-Raumschlüssel importieren", "key_backup_active": "Diese Sitzung sichert deine Schlüssel.", @@ -2787,6 +2802,7 @@ "device_unverified_description_current": "Verifiziere deine aktuelle Sitzung für besonders sichere Kommunikation.", "device_verified_description": "Diese Sitzung ist für sichere Kommunikation bereit.", "device_verified_description_current": "Deine aktuelle Sitzung ist für sichere Kommunikation bereit.", + "dialog_title": "Einstellungen: Sitzungen", "error_pusher_state": "Konfigurieren des Push-Dienstes fehlgeschlagen", "error_set_name": "Es konnte kein Sitzungsname gesetzt werden", "filter_all": "Alle", @@ -2828,7 +2844,8 @@ "show_details": "Details anzeigen", "sign_in_with_qr": "Neues Gerät verknüpfen", "sign_in_with_qr_button": "QR-Code anzeigen", - "sign_in_with_qr_unsupported": "Nicht unterstützt von deinem Kontoanbieter", + "sign_in_with_qr_description": "Sie können dieses Gerät dazu verwenden, um ein neues Gerät per QR-Code anzumelden und verschlüsselte Nachrichtenübermittlung einzurichten.", + "sign_in_with_qr_unsupported": "Wird von Ihrem Kontoanbieter nicht unterstützt", "sign_out": "Von dieser Sitzung abmelden", "sign_out_all_other_sessions": "Von allen anderen Sitzungen abmelden (%(otherSessionsCount)s)", "sign_out_confirm_description": { @@ -2868,7 +2885,7 @@ "show_redaction_placeholder": "Platzhalter für gelöschte Nachrichten", "show_stickers_button": "Sticker-Schaltfläche", "show_typing_notifications": "Tippbenachrichtigungen anzeigen", - "showbold": "Alle Aktivitäten in Raumliste anzeigen (Punkt oder Anzahl ungelesener Nachrichten)", + "showbold": "Alle Aktivitäten in der Chatroommliste anzeigen (Ausführungspunkte oder Anzahl ungelesener Nachrichten)", "sidebar": { "dialog_title": "Einstellungen: Seitenleiste", "metaspaces_favourites_description": "Gruppiere all deine favorisierten Unterhaltungen an einem Ort.", @@ -2881,6 +2898,8 @@ "metaspaces_subsection": "Anzuzeigende Spaces", "metaspaces_video_rooms": "Videoräume und -konferenzen", "metaspaces_video_rooms_description": "Gruppiere alle privaten Videoräume und -konferenzen.", + "metaspaces_video_rooms_description_invite_extension": "Sie können Personen außerhalb von Matrix zu Konferenzen einladen.", + "spaces_explainer": "Räume sind eine Möglichkeit, Chatrooms und Personen zu gruppieren. Abgesehen von den Räumen, in denen Sie sich gerade befinden, können Sie auch einige vorgefertigte Räume verwenden.", "title": "Seitenleiste" }, "start_automatically": "Nach Systemstart automatisch starten", @@ -2898,7 +2917,7 @@ "audio_output_empty": "Keine Audioausgabe erkannt", "auto_gain_control": "Automatische Lautstärkeregelung", "connection_section": "Verbindung", - "dialog_title": "Einstellungen: Anrufe", + "dialog_title": "Einstellungen: Sprache und Video", "echo_cancellation": "Echounterdrückung", "enable_fallback_ice_server": "Ersatz-Anrufassistenz-Server erlauben (%(server)s)", "enable_fallback_ice_server_description": "Dieser wird nur verwendet, sollte dein Heim-Server keinen bieten. Deine IP-Adresse würde während eines Anrufs geteilt werden.", @@ -2917,7 +2936,6 @@ "warning": "WARNUNG: " }, "share": { - "link_title": "Link zum Raum", "permalink_message": "Link zur ausgewählten Nachricht", "permalink_most_recent": "Link zur aktuellsten Nachricht", "share_call": "Konferenzeinladungslink", @@ -3009,13 +3027,6 @@ "upgraderoom": "Aktualisiert den Raum auf eine neue Version", "upgraderoom_permission_error": "Du hast nicht die erforderlichen Berechtigungen, diesen Befehl zu verwenden.", "usage": "Verwendung", - "verify": "Verifiziert Benutzer, Sitzung und öffentlichen Schlüsselpaare", - "verify_mismatch": "ACHTUNG: SCHLÜSSELVERIFIZIERUNG FEHLGESCHLAGEN! Der Signierschlüssel für %(userId)s und Sitzung %(deviceId)s ist \"%(fprint)s\", was nicht mit dem bereitgestellten Schlüssel \"%(fingerprint)s\" übereinstimmt. Das könnte bedeuten, dass deine Kommunikation abgehört wird!", - "verify_nop": "Sitzung bereits verifiziert!", - "verify_nop_warning_mismatch": "ACHTUNG: Sitzung bereits verifiziert, aber die Schlüssel PASSEN NICHT!", - "verify_success_description": "Dein bereitgestellter Signaturschlüssel passt zum von der Sitzung %(deviceId)s von %(userId)s empfangendem Schlüssel. Sitzung wurde als verifiziert markiert.", - "verify_success_title": "Verifizierter Schlüssel", - "verify_unknown_pair": "Unbekanntes Paar (Nutzer, Sitzung): (%(userId)s, %(deviceId)s)", "view": "Raum mit angegebener Adresse betrachten", "whois": "Zeigt Informationen über Benutzer" }, @@ -3172,7 +3183,7 @@ "other": "%(count)s Antworten" }, "empty_description": "Verwende \"%(replyInThread)s\" beim Hovern über eine Nachricht.", - "empty_title": "Threads helfen dir, deine Unterhaltungen zu einem Thema leichter zu verfolgen.", + "empty_title": "Threads helfen Ihnen, Ihre Unterhaltungen beim Thema zu halten, and sie sind auch leichter zu verfolgen.", "error_start_thread_existing_relation": "Du kannst keinen Thread in einem Thread starten", "mark_all_read": "Alle als gelesen markieren", "my_threads": "Meine Threads", @@ -3182,8 +3193,8 @@ }, "threads_activity_centre": { "header": "Thread-Aktivität", - "no_rooms_with_threads_notifs": "Sie haben noch keine Räume mit Thread-Benachrichtigungen.", - "no_rooms_with_unread_threads": "Sie haben noch keine Räume mit ungelesenen Threads.", + "no_rooms_with_threads_notifs": "Sie haben noch keine Chatrooms mit Thread-Benachrichtigungen.", + "no_rooms_with_unread_threads": "Sie haben noch keine Chatrooms mit ungelesenen Threads.", "release_announcement_description": "Die Thread-Benachrichtigungen wurden verschoben. Sie finden sie ab sofort hier.", "release_announcement_header": "Thread Aktivitätszentrum" }, @@ -3229,9 +3240,10 @@ "creation_summary_dm": "%(creator)s hat diese Direktnachricht erstellt.", "creation_summary_room": "%(creator)s hat den Raum erstellt und konfiguriert.", "decryption_failure": { + "blocked": "Der Absender hat den Empfang dieser Nachricht blockiert, da Ihr Gerät nicht verifiziert ist.", "historical_event_no_key_backup": "Der historische Nachrichtenverlauf ist auf diesem Gerät nicht verfügbar.", - "historical_event_unverified_device": "Du musst dieses Gerät verifizieren, um auf den Nachrichtenverlauf zugreifen zu können", - "historical_event_user_not_joined": "Du hast keinen Zugriff auf diese Nachricht", + "historical_event_unverified_device": "Sie müssen dieses Gerät verifizieren, um auf den Nachrichtenverlauf zugreifen zu können", + "historical_event_user_not_joined": "Sie haben keinen Zugriff auf diese Nachricht", "sender_identity_previously_verified": "Die verifizierte Identität des Absenders hat sich geändert", "sender_unsigned_device": "Von einem unsicheren Gerät verschickt.", "unable_to_decrypt": "Entschlüsselung der Nachricht nicht möglich" @@ -3251,10 +3263,6 @@ "error_rendering_message": "Diese Nachricht kann nicht geladen werden", "historical_messages_unavailable": "Du kannst keine älteren Nachrichten lesen", "in_room_name": " in %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s beendete eine Sprachübertragung", - "you": "Du hast eine Sprachübertragung beendet" - }, "io.element.widgets.layout": "%(senderName)s hat das Raumlayout geändert", "late_event_separator": "Ursprünglich gesendet %(dateTime)s", "load_error": { @@ -3673,7 +3681,8 @@ "other": "Und %(count)s weitere …" }, "unsupported_browser": { - "description": "Wenn Sie fortfahren, funktionieren einige Funktionen möglicherweise nicht mehr und es besteht das Risiko, dass Sie in Zukunft Daten verlieren. Aktualisieren Sie Ihren Browser, um die Nutzung von %(brand)s fortzusetzen." + "description": "Wenn Sie fortfahren, funktionieren einige Funktionen möglicherweise nicht mehr und es besteht das Risiko, dass Sie in Zukunft Daten verlieren. Aktualisieren Sie Ihren Browser, um die Nutzung von %(brand)s fortzusetzen.", + "title": "%(brand)s unterstützt diesen Browser nicht" }, "unsupported_server_description": "Dieser Server nutzt eine ältere Matrix-Version. Aktualisiere auf Matrix %(version)s, um %(brand)s fehlerfrei nutzen zu können.", "unsupported_server_title": "Dein Server wird nicht unterstützt", @@ -3693,8 +3702,10 @@ "unavailable": "Nicht verfügbar" }, "update_room_access_modal": { + "description": "Um einen Link zum Teilen zu erstellen, müssen Sie Gästen erlauben, diesem Chatroom beizutreten. Dadurch kann der Chatroom weniger sicher werden. Wenn Sie mit dem Anruf fertig sind, können Sie den Raum wieder privat machen.", + "dont_change_description": "Sie können den Anruf auch in einem separaten Chatroom führen.", "no_change": "Ich möchte die Zugriffsebene nicht ändern.", - "title": "Ändern Sie die Zugriffsebene des Raums" + "title": "Ändern Sie die Zugriffsebene des Chatrooms." }, "upload_failed_generic": "Die Datei „%(fileName)s“ konnte nicht hochgeladen werden.", "upload_failed_size": "Die Datei „%(fileName)s“ überschreitet das Hochladelimit deines Heim-Servers", @@ -3705,7 +3716,7 @@ "error_files_too_large": "Die Datei ist zu groß, um hochgeladen zu werden. Die maximale Dateigröße ist %(limit)s.", "error_some_files_too_large": "Einige Dateien sind zu groß, um hochgeladen zu werden. Die maximale Dateigröße ist %(limit)s.", "error_title": "Fehler beim Hochladen", - "not_image": "Die von dir ausgewählte Datei ist keine gültige Bilddatei.", + "not_image": "Die von Ihnen ausgewählte Datei ist keine gültige Bilddatei.", "title": "Dateien hochladen", "title_progress": "Dateien hochladen (%(current)s von %(total)s)", "upload_all_button": "Alle hochladen", @@ -3801,38 +3812,6 @@ "switch_theme_dark": "Zum dunklen Thema wechseln", "switch_theme_light": "Zum hellen Thema wechseln" }, - "voice_broadcast": { - "30s_backward": "30s zurückspulen", - "30s_forward": "30s vorspulen", - "action": "Sprachübertragung", - "buffering": "Puffere …", - "confirm_listen_affirm": "Ja, beende meine Aufzeichnung", - "confirm_listen_description": "Wenn du beginnst, diese Echtzeitübertragung anzuhören, wird deine aktuelle Echtzeitübertragungsaufzeichnung beendet.", - "confirm_listen_title": "Echtzeitübertragung anhören?", - "confirm_stop_affirm": "Ja, Übertragung beenden", - "confirm_stop_description": "Möchtest du deine Übertragung wirklich beenden? Dies wird die Übertragung abschließen und die vollständige Aufnahme im Raum bereitstellen.", - "confirm_stop_title": "Live-Übertragung beenden?", - "connection_error": "Verbindungsfehler − Aufnahme pausiert", - "failed_already_recording_description": "Du zeichnest bereits eine Sprachübertragung auf. Bitte beende die laufende Übertragung, um eine neue zu beginnen.", - "failed_already_recording_title": "Sprachübertragung kann nicht gestartet werden", - "failed_decrypt": "Entschlüsseln der Sprachübertragung nicht möglich", - "failed_generic": "Wiedergabe der Sprachübertragung nicht möglich", - "failed_insufficient_permission_description": "Du hast nicht die nötigen Berechtigungen, um eine Sprachübertragung in diesem Raum zu starten. Kontaktiere einen Raumadministrator, um deine Berechtigungen anzupassen.", - "failed_insufficient_permission_title": "Sprachübertragung kann nicht gestartet werden", - "failed_no_connection_description": "Leider ist es aktuell nicht möglich, eine Aufnahme zu beginnen. Bitte versuche es später erneut.", - "failed_no_connection_title": "Verbindungsfehler", - "failed_others_already_recording_description": "Jemand anderes nimmt bereits eine Sprachübertragung auf. Warte auf das Ende der Übertragung, bevor du eine neue startest.", - "failed_others_already_recording_title": "Sprachübertragung kann nicht gestartet werden", - "go_live": "Live schalten", - "live": "Live", - "pause": "Sprachübertragung pausieren", - "play": "Sprachübertragung wiedergeben", - "resume": "Sprachübertragung fortsetzen" - }, - "voice_message": { - "cant_start_broadcast_description": "Du kannst keine Sprachnachricht beginnen, da du im Moment eine Echtzeitübertragung aufzeichnest. Bitte beende deine Sprachübertragung, um ein Gespräch zu beginnen.", - "cant_start_broadcast_title": "Kann Sprachnachricht nicht beginnen" - }, "voip": { "already_in_call": "Schon im Anruf", "already_in_call_person": "Du bist schon in einem Anruf mit dieser Person.", @@ -3852,10 +3831,10 @@ "camera_disabled": "Deine Kamera ist ausgeschaltet", "camera_enabled": "Deine Kamera ist noch aktiv", "cannot_call_yourself_description": "Du kannst keinen Anruf mit dir selbst starten.", - "change_input_device": "Eingabegerät wechseln", "close_lobby": "Lobby schließen", "connecting": "Verbinden", "connection_lost": "Verbindung zum Server unterbrochen", + "connection_lost_description": "Ohne Verbindung zum Server können Sie keine Anrufe tätigen.", "consulting": "%(transferTarget)s wird angefragt. Übertragung zu %(transferee)s", "default_device": "Standardgerät", "dial": "Wählen", @@ -3870,8 +3849,6 @@ "enable_camera": "Kamera aktivieren", "enable_microphone": "Mikrofon aktivieren", "expand": "Zurück zum Anruf", - "failed_call_live_broadcast_description": "Du kannst keinen Anruf beginnen, da du im Moment eine Sprachübertragung aufzeichnest. Bitte beende deine Sprachübertragung, um ein Gespräch zu beginnen.", - "failed_call_live_broadcast_title": "Kann keinen Anruf beginnen", "get_call_link": "Anruflink teilen", "hangup": "Auflegen", "hide_sidebar_button": "Seitenleiste verbergen", @@ -4068,6 +4045,7 @@ "l33t": "Vorhersagbare Ersetzungen wie „@“ anstelle von „a“ helfen nicht besonders", "longerKeyboardPattern": "Nutze ein längeres Tastaturmuster mit mehr Abwechslung", "noNeed": "Kein Bedarf an Symbolen, Zahlen oder Großbuchstaben", + "pwned": "Falls Sie dieses Passwort anderweitig verwenden, sollten Sie es ändern.", "recentYears": "Vermeide die letzten Jahre", "repeated": "Vermeide wiederholte Worte und Zeichen", "reverseWords": "Umgedrehte Worte sind nicht schwerer zu erraten", @@ -4089,6 +4067,7 @@ "straightRow": "Gerade Reihen von Tasten sind einfach zu erraten", "topHundred": "Dies ist unter den Top 100 der häufigsten Passwörter", "topTen": "Dies ist unter den Top 10 der häufigsten Passwörter", + "userInputs": "Personenbezogene oder seitenbezogene Daten sollten hier nicht vorhanden sein.", "wordByItself": "Ein einzelnes Wort ist einfach zu erraten" } } diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index 2c042c0dc36..808aeb02eb2 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -763,12 +763,6 @@ "incoming_sas_dialog_title": "Εισερχόμενο Αίτημα Επαλήθευσης", "incoming_sas_user_dialog_text_1": "Επαληθεύστε αυτόν τον χρήστη για να τον επισημάνετε ως αξιόπιστο. Η εμπιστοσύνη των χρηστών σάς προσφέρει επιπλέον ηρεμία όταν χρησιμοποιείτε μηνύματα με κρυπτογράφηση από άκρο σε άκρο.", "incoming_sas_user_dialog_text_2": "Η επαλήθευση αυτού του χρήστη θα επισημάνει τη συνεδρία του ως αξιόπιστη και θα επισημάνει επίσης τη συνεδρία σας ως αξιόπιστη σε αυτόν.", - "manual_device_verification_device_id_label": "Αναγνωριστικό συνεδρίας", - "manual_device_verification_device_key_label": "Κλειδί συνεδρίας", - "manual_device_verification_device_name_label": "Όνομα συνεδρίας", - "manual_device_verification_footer": "Εάν δεν ταιριάζουν, η ασφάλεια της επικοινωνίας σας μπορεί να τεθεί σε κίνδυνο.", - "manual_device_verification_self_text": "Επιβεβαιώστε συγκρίνοντας τα ακόλουθα με τις Ρυθμίσεις χρήστη στην άλλη συνεδρία σας:", - "manual_device_verification_user_text": "Επιβεβαιώστε την συνεδρία αυτού του χρήστη συγκρίνοντας τα ακόλουθα με τις Ρυθμίσεις του:", "no_key_or_device": "Φαίνεται ότι δε διαθέτετε Κλειδί Ασφαλείας ή άλλες συσκευές με τις οποίες μπορείτε να επαληθεύσετε. Αυτή η συσκευή δε θα έχει πρόσβαση σε παλιά κρυπτογραφημένα μηνύματα. Για να επαληθεύσετε την ταυτότητά σας σε αυτήν τη συσκευή, θα πρέπει να επαναφέρετε τα κλειδιά επαλήθευσης.", "no_support_qr_emoji": "Η συσκευή που προσπαθείτε να επαληθεύσετε δεν υποστηρίζει τη σάρωση κωδικού QR ή επαλήθευσης emoji, κάτι που υποστηρίζει το %(brand)s. Δοκιμάστε με διαφορετικό πρόγραμμα-πελάτη.", "other_party_cancelled": "Το άλλο μέρος ακύρωσε την επαλήθευση.", @@ -2164,7 +2158,6 @@ "warn_quit": "Προειδοποιήστε πριν την παραίτηση" }, "share": { - "link_title": "Σύνδεσμος στο δωμάτιο", "permalink_message": "Σύνδεσμος στο επιλεγμένο μήνυμα", "permalink_most_recent": "Σύνδεσμος προς το πιο πρόσφατο μήνυμα", "title_message": "Κοινή χρήση Μηνύματος Δωματίου", @@ -2246,12 +2239,6 @@ "upgraderoom": "Αναβαθμίζει το δωμάτιο σε μια καινούργια έκδοση", "upgraderoom_permission_error": "Δεν διαθέτετε τις απαιτούμενες άδειες για να χρησιμοποιήσετε αυτήν την εντολή.", "usage": "Χρήση", - "verify": "Επιβεβαιώνει έναν χρήστη, συνεδρία, και pubkey tuple", - "verify_mismatch": "ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Η ΕΠΑΛΗΘΕΥΣΗ ΚΛΕΙΔΙΟΥ ΑΠΕΤΥΧΕ! Το κλειδί σύνδεσης για %(userId)s και συνεδρίας %(deviceId)s είναι \"%(fprint)s\" που δεν ταιριάζει με το παρεχόμενο κλειδί\"%(fingerprint)s\". Αυτό μπορεί να σημαίνει ότι υπάρχει υποκλοπή στις επικοινωνίες σας!", - "verify_nop": "Η συνεδρία έχει ήδη επιβεβαιωθεί!", - "verify_success_description": "Το κλειδί υπογραφής που παρείχατε ταιριάζει με το κλειδί που λάβατε από την συνεδρία %(userId)s's %(deviceId)s. Η συνεδρία σημειώνεται ως επιβεβαιωμένη.", - "verify_success_title": "Επιβεβαιωμένο κλειδί", - "verify_unknown_pair": "Άγνωστο ζευγάρι (χρήστης, συνεδρία): (%(userId)s, %(deviceId)s)", "whois": "Εμφανίζει πληροφορίες για έναν χρήστη" }, "space": { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e601a7ecd53..fe5e54e5596 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -922,7 +922,6 @@ }, "udd": { "interactive_verification_button": "Interactively verify by emoji", - "manual_verification_button": "Manually verify by text", "other_ask_verify_text": "Ask this user to verify their session, or manually verify it below.", "other_new_session_text": "%(name)s (%(userId)s) signed in to a new session without verifying it:", "own_ask_verify_text": "Verify your other session using one of the options below.", @@ -957,12 +956,6 @@ "incoming_sas_dialog_waiting": "Waiting for partner to confirm…", "incoming_sas_user_dialog_text_1": "Verify this user to mark them as trusted. Trusting users gives you extra peace of mind when using end-to-end encrypted messages.", "incoming_sas_user_dialog_text_2": "Verifying this user will mark their session as trusted, and also mark your session as trusted to them.", - "manual_device_verification_device_id_label": "Session ID", - "manual_device_verification_device_key_label": "Session key", - "manual_device_verification_device_name_label": "Session name", - "manual_device_verification_footer": "If they don't match, the security of your communication may be compromised.", - "manual_device_verification_self_text": "Confirm by comparing the following with the User Settings in your other session:", - "manual_device_verification_user_text": "Confirm this user's session by comparing the following with their User Settings:", "no_key_or_device": "It looks like you don't have a Security Key or any other devices you can verify against. This device will not be able to access old encrypted messages. In order to verify your identity on this device, you'll need to reset your verification keys.", "no_support_qr_emoji": "The device you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.", "other_party_cancelled": "The other party cancelled the verification.", @@ -3036,13 +3029,6 @@ "upgraderoom": "Upgrades a room to a new version", "upgraderoom_permission_error": "You do not have the required permissions to use this command.", "usage": "Usage", - "verify": "Verifies a user, session, and pubkey tuple", - "verify_mismatch": "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!", - "verify_nop": "Session already verified!", - "verify_nop_warning_mismatch": "WARNING: session already verified, but keys do NOT MATCH!", - "verify_success_description": "The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.", - "verify_success_title": "Verified key", - "verify_unknown_pair": "Unknown (user, session) pair: (%(userId)s, %(deviceId)s)", "view": "Views room with given address", "whois": "Displays information about a user" }, diff --git a/src/i18n/strings/eo.json b/src/i18n/strings/eo.json index 33d8e57f488..88694a3a580 100644 --- a/src/i18n/strings/eo.json +++ b/src/i18n/strings/eo.json @@ -693,12 +693,6 @@ "incoming_sas_dialog_title": "Venas kontrolpeto", "incoming_sas_user_dialog_text_1": "Kontrolu ĉi tiun uzanton por marki ĝin fidata. Fidado devas vin trankviligi dum uzado de tutvoja ĉifrado.", "incoming_sas_user_dialog_text_2": "Kontrolo de tiu ĉi uzanto markos ĝian salutaĵon fidata, kaj ankaŭ markos vian salutaĵon fidata por ĝi.", - "manual_device_verification_device_id_label": "Identigilo de salutaĵo", - "manual_device_verification_device_key_label": "Ŝlosilo de salutaĵo", - "manual_device_verification_device_name_label": "Nomo de salutaĵo", - "manual_device_verification_footer": "Se ili ne akordas, la sekureco de via komunikado eble estas rompita.", - "manual_device_verification_self_text": "Konfirmu per komparo de la sekva kun la agardoj de uzanto en via alia salutaĵo:", - "manual_device_verification_user_text": "Konfirmu la salutaĵon de ĉi tiu uzanto per komparo de la sekva kun ĝiaj agordoj de uzanto:", "other_party_cancelled": "La alia kontrolano nuligis la kontrolon.", "prompt_encrypted": "Kontrolu ĉiujn uzantojn en ĉambro por certigi, ke ĝi sekuras.", "prompt_self": "Rekomencu kontroladon el la sciigo.", @@ -795,10 +789,6 @@ } }, "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s finis voĉan elsendon", - "you": "Vi finis voĉan elsendon" - }, "m.call.answer": { "dm": "Voko okazas", "user": "%(senderName)s aliĝis al la voko", @@ -1065,7 +1055,6 @@ "video_rooms_always_on_voip_channels": "Videoĉambroj estas ĉiam ŝaltitaj VoIP-kanaloj enkonstruitaj en ĉambro en %(brand)s.", "video_rooms_faq1_answer": "Uzu la \"+\" butonon en la ĉambro sekcio de la maldekstra panelo.", "video_rooms_faq1_question": "Kiel mi povas krei videoĉambron?", - "voice_broadcast": "Voĉan elsendo", "wysiwyg_composer": "Riĉa tekstoredaktilo" }, "labs_mjolnir": { @@ -1167,7 +1156,6 @@ "message_didnt_send": "Mesaĝo ne sendiĝis. Klaku por akiri informojn." }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s komencis voĉan elsendon", "m.key.verification.request": "%(name)s petas kontrolon" }, "onboarding": { @@ -2050,13 +2038,6 @@ "upgraderoom": "Gradaltigas ĉambron al nova versio", "upgraderoom_permission_error": "Vi ne havas sufiĉajn permesojn por uzi ĉi tiun komandon.", "usage": "Uzo", - "verify": "Kontrolas opon de uzanto, salutaĵo, kaj publika ŝlosilo", - "verify_mismatch": "AVERTO: MALSUKCESIS KONTROLO DE ŜLOSILOJ! La subskriba ŝlosilo de %(userId)s kaj session %(deviceId)s estas «%(fprint)s», kiu ne akordas la donitan ŝlosilon «%(fingerprint)s». Tio povus signifi, ke via komunikado estas spionata!", - "verify_nop": "Salutaĵo jam estas kontrolita!", - "verify_nop_warning_mismatch": "AVERTO: Salutaĵo jam estas kontrolita, sed la ŝlosiloj NE AKORDAS!", - "verify_success_description": "La subskriba ŝlosilo, kiun vi donis, akordas la subskribas ŝlosilon, kinu vi ricevis de la salutaĵo %(deviceId)s de la uzanto %(userId)s. Salutaĵo estis markita kontrolita.", - "verify_success_title": "Kontrolita ŝlosilo", - "verify_unknown_pair": "Nekonata (uzanto, salutaĵo) duopo: (%(userId)s, %(deviceId)s)", "whois": "Montras informojn pri uzanto" }, "space": { @@ -2208,10 +2189,6 @@ }, "error_no_renderer": "Ĉi tiu okazo ne povis montriĝi", "error_rendering_message": "Ne povas enlegi ĉi tiun mesaĝon", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s finis voĉan elsendon", - "you": "Vi finis voĉan elsendon" - }, "io.element.widgets.layout": "%(senderName)s ĝisdatigis la aranĝon de ĉambro", "load_error": { "no_permission": "Provis enlegi certan parton de ĉi tiu historio, sed vi ne havas permeson vidi ĝin.", @@ -2626,32 +2603,6 @@ "switch_theme_dark": "Ŝalti malhelan reĝimon", "switch_theme_light": "Ŝalti helan reĝimon" }, - "voice_broadcast": { - "30s_backward": "30s. reen", - "30s_forward": "30s. antaŭen", - "action": "Voĉan elsendo", - "confirm_listen_affirm": "Jes, ĉesigu mian registradon", - "confirm_listen_description": "Se vi komencas aŭskulti ĉi tiun vivan elsendon, via nuna viva elsendo registrado estos finita.", - "confirm_listen_title": "Aŭskulti vivan elsendon?", - "confirm_stop_affirm": "Jes, ĉesu elsendon", - "confirm_stop_description": "Ĉu vi certas, ke vi volas fini la elsendon? Ĉi tio finos la transdonon kaj provizos la plenan registradon en la ĉambro.", - "confirm_stop_title": "Ĉu ĉesi rekta elsendo?", - "failed_already_recording_description": "Vi jam registras voĉan elsendon. Bonvolu fini vian nunan voĉelsendon por komenci novan.", - "failed_already_recording_title": "Ne povas komenci novan voĉan elsendon", - "failed_decrypt": "Ne eblas deĉifri voĉan elsendon", - "failed_generic": "Ne eblas ludi ĉi tiun voĉan elsendon", - "failed_insufficient_permission_description": "Vi ne havas la bezonatajn permesojn por komenci voĉan elsendon en ĉi tiu ĉambro. Kontaktu ĉambran administranton por ĝisdatigi viajn permesojn.", - "failed_insufficient_permission_title": "Ne povas komenci novan voĉan elsendon", - "failed_no_connection_description": "Bedaŭrinde ni ne povas komenci registradon nun. Bonvolu reprovi poste.", - "failed_no_connection_title": "eraro de konekto", - "failed_others_already_recording_description": "Iu alia jam registras voĉan elsendon. Atendu, ke ilia voĉa elsendo finiĝos por komenci novan.", - "failed_others_already_recording_title": "Ne povas komenci novan voĉan elsendon", - "go_live": "Iru vivi", - "live": "Vivi", - "pause": "paŭzi voĉan elsendon", - "play": "ludu voĉan elsendon", - "resume": "rekomenci voĉan elsendon" - }, "voip": { "already_in_call": "Jam vokanta", "already_in_call_person": "Vi jam vokas ĉi tiun personon.", @@ -2671,7 +2622,6 @@ "camera_disabled": "Via filmilo estas malŝaltita", "camera_enabled": "Via filmilo ankoraŭ estas ŝaltita", "cannot_call_yourself_description": "Vi ne povas voki vin mem.", - "change_input_device": "Ŝanĝu enigan aparaton", "connecting": "Konektante", "connection_lost": "Konektebleco al la servilo estas perdita", "connection_lost_description": "Vi ne povas voki sen konektaĵo al la servilo.", @@ -2683,8 +2633,6 @@ "enable_camera": "Ŝalti la filmilon", "enable_microphone": "Malsilentigi la mikrofonon", "expand": "Reveni al voko", - "failed_call_live_broadcast_description": "Vi ne povas komenci vokon ĉar vi nuntempe registras vivan elsendon. Bonvolu fini vian vivan elsendon por komenci vokon.", - "failed_call_live_broadcast_title": "Ne povas komenci vokon", "hangup": "Fini vokon", "hide_sidebar_button": "Kaŝi flankan breton", "join_button_tooltip_connecting": "Konektante", diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index cb6a8557b39..0f54ccca700 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -813,7 +813,6 @@ }, "udd": { "interactive_verification_button": "Verificar interactivamente usando emojis", - "manual_verification_button": "Verificar manualmente usando un texto", "other_ask_verify_text": "Pídele al usuario que verifique su sesión, o verifícala manualmente a continuación.", "other_new_session_text": "%(name)s (%(userId)s) inició una nueva sesión sin verificarla:", "own_ask_verify_text": "Verifica la otra sesión utilizando una de las siguientes opciones.", @@ -848,12 +847,6 @@ "incoming_sas_dialog_waiting": "Esperando a que la otra persona confirme…", "incoming_sas_user_dialog_text_1": "Verifica a este usuario para marcarlo como de confianza. Confiar en usuarios aporta tranquilidad en los mensajes cifrados de extremo a extremo.", "incoming_sas_user_dialog_text_2": "Verificar este usuario marcará su sesión como de confianza, y también marcará tu sesión como de confianza para él.", - "manual_device_verification_device_id_label": "ID de Sesión", - "manual_device_verification_device_key_label": "Código de sesión", - "manual_device_verification_device_name_label": "Nombre de sesión", - "manual_device_verification_footer": "Si no coinciden, la seguridad de su comunicación puede estar comprometida.", - "manual_device_verification_self_text": "Confirme comparando lo siguiente con los ajustes de usuario de su otra sesión:", - "manual_device_verification_user_text": "Confirma la sesión de este usuario comparando lo siguiente con su configuración:", "no_key_or_device": "Parece que no tienes una clave de seguridad u otros dispositivos para la verificación. Este dispositivo no podrá acceder los mensajes cifrados antiguos. Para verificar tu identidad en este dispositivo, tendrás que restablecer tus claves de verificación.", "no_support_qr_emoji": "El dispositivo que estás intentando verificar no es compatible con el escaneo de códigos QR o la verificación con emojis, que son las opciones que %(brand)s ofrece. Prueba con otra aplicación distinta.", "other_party_cancelled": "El otro lado canceló la verificación.", @@ -1304,7 +1297,6 @@ "video_rooms_faq1_question": "Cómo crear una sala de vídeo", "video_rooms_faq2_answer": "Sí, el historial de la sala aparece al lado del vídeo.", "video_rooms_faq2_question": "¿Puedo mandar mensajes de texto en la videollamada?", - "voice_broadcast": "Retransmisión de voz", "wysiwyg_composer": "Editor de texto enriquecido" }, "labs_mjolnir": { @@ -1955,7 +1947,6 @@ "error_unbanning": "No se pudo quitar veto", "events_default": "Enviar mensajes", "invite": "Invitar usuarios", - "io.element.voice_broadcast_info": "Retransmisiones de voz", "kick": "Sacar usuarios", "m.call": "Empezar llamadas de %(brand)s", "m.call.member": "Unirte a llamadas de %(brand)s", @@ -2529,7 +2520,6 @@ "warning": "ADVERTENCIA : " }, "share": { - "link_title": "Enlace a la sala", "permalink_message": "Enlazar al mensaje seleccionado", "permalink_most_recent": "Enlazar al mensaje más reciente", "title_message": "Compartir un mensaje de esta sala", @@ -2612,13 +2602,6 @@ "upgraderoom": "Actualiza una sala a una nueva versión", "upgraderoom_permission_error": "No tienes los permisos requeridos para usar este comando.", "usage": "Uso", - "verify": "Verifica a un usuario, sesión y tupla de clave pública", - "verify_mismatch": "¡ATENCIÓN: LA VERIFICACIÓN DE LA CLAVE HA FALLADO! La clave de firma para %(userId)s y sesión %(deviceId)s es \"%(fprint)s\", la cual no coincide con la clave proporcionada \"%(fingerprint)s\". ¡Esto podría significar que tus comunicaciones están siendo interceptadas!", - "verify_nop": "¡La sesión ya ha sido verificada!", - "verify_nop_warning_mismatch": "ADVERTENCIA: la sesión ya está verificada, pero las claves NO COINCIDEN", - "verify_success_description": "La clave de firma que proporcionaste coincide con la clave de firma que recibiste de la sesión %(deviceId)s de %(userId)s. Sesión marcada como verificada.", - "verify_success_title": "Clave verificada", - "verify_unknown_pair": "Pareja (usuario, sesión) desconocida: (%(userId)s, %(deviceId)s)", "whois": "Muestra información sobre un usuario" }, "space": { @@ -3336,29 +3319,6 @@ "switch_theme_dark": "Cambiar al tema oscuro", "switch_theme_light": "Cambiar al tema claro" }, - "voice_broadcast": { - "30s_backward": "retroceder 30s", - "30s_forward": "avanzar 30s", - "action": "Retransmisión de voz", - "buffering": "Cargando…", - "confirm_listen_affirm": "Sí, terminar grabación", - "confirm_stop_affirm": "Sí, detener retransmisión", - "confirm_stop_title": "¿Dejar de retransmitir?", - "connection_error": "Error de conexión, grabación detenida", - "failed_already_recording_title": "No se ha podido iniciar una nueva difusión de voz", - "failed_insufficient_permission_title": "No se ha podido iniciar una nueva difusión de voz", - "failed_no_connection_description": "Lamentablemente, no hemos podido empezar a grabar ahora mismo. Inténtalo de nuevo más tarde.", - "failed_no_connection_title": "Error de conexión", - "failed_others_already_recording_title": "No se ha podido iniciar una nueva difusión de voz", - "go_live": "Empezar directo", - "live": "En directo", - "pause": "pausar retransmisión de voz", - "play": "reproducir difusión de voz", - "resume": "reanudar retransmisión de voz" - }, - "voice_message": { - "cant_start_broadcast_title": "No se ha podido empezar el mensaje de voz" - }, "voip": { "already_in_call": "Ya en una llamada", "already_in_call_person": "Ya estás en una llamada con esta persona.", @@ -3378,7 +3338,6 @@ "camera_disabled": "Tu cámara está apagada", "camera_enabled": "Tu cámara todavía está encendida", "cannot_call_yourself_description": "No puedes llamarte a ti mismo.", - "change_input_device": "Cambiar dispositivo de entrada", "connecting": "Conectando", "connection_lost": "Se ha perdido la conexión con el servidor", "connection_lost_description": "No puedes llamar porque no hay conexión con el servidor.", @@ -3395,8 +3354,6 @@ "enable_camera": "Encender cámara", "enable_microphone": "Activar micrófono", "expand": "Volver a la llamada", - "failed_call_live_broadcast_description": "No puedes empezar una llamada, porque estás grabando una retransmisión en directo. Por favor, finaliza tu retransmisión en directo para empezar la llamada.", - "failed_call_live_broadcast_title": "No se ha podido empezar la llamada", "hangup": "Colgar", "hide_sidebar_button": "Ocultar menú lateral", "input_devices": "Dispositivos de entrada", diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index b05d9024c05..093dcf861ef 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -880,7 +880,6 @@ }, "udd": { "interactive_verification_button": "Verifitseeri interaktiivselt emoji abil", - "manual_verification_button": "Verifitseeri käsitsi etteantud teksti abil", "other_ask_verify_text": "Palu nimetatud kasutajal verifitseerida see sessioon või tee seda alljärgnevaga käsitsi.", "other_new_session_text": "%(name)s (%(userId)s) logis sisse uude sessiooni ilma seda verifitseerimata:", "own_ask_verify_text": "Verifitseeri oma teine sessioon kasutades üht alljärgnevatest võimalustest.", @@ -915,12 +914,6 @@ "incoming_sas_dialog_waiting": "Ootan teise osapoole kinnitust…", "incoming_sas_user_dialog_text_1": "Selle kasutaja usaldamiseks peaksid ta verifitseerima. Kui sa pruugid läbivalt krüptitud sõnumeid, siis kasutajate verifitseerimine tagab sulle täiendava meelerahu.", "incoming_sas_user_dialog_text_2": "Selle kasutaja verifitseerimisel märgitakse tema sessioon usaldusväärseks ning samuti märgitakse sinu sessioon tema jaoks usaldusväärseks.", - "manual_device_verification_device_id_label": "Sessiooni tunnus", - "manual_device_verification_device_key_label": "Sessiooni võti", - "manual_device_verification_device_name_label": "Sessiooni nimi", - "manual_device_verification_footer": "Kui nad omavahel ei klapi, siis teie suhtluse turvalisus võib olla ohus.", - "manual_device_verification_self_text": "Kinnita seda võrreldes järgnevaid andmeid oma teise sessiooni kasutajaseadetes:", - "manual_device_verification_user_text": "Kinnita selle kasutaja sessioon võrreldes järgnevaid andmeid tema kasutajaseadetes:", "no_key_or_device": "Tundub, et sul ei ole ei turvavõtit ega muid seadmeid, mida saaksid verifitseerimiseks kasutada. Siin seadmes ei saa lugeda vanu krüptitud sõnumeid. Enda tuvastamiseks selles seadmed pead oma vanad verifitseerimisvõtmed kustutama.", "no_support_qr_emoji": "See seade, mida sa tahad verifitseerida ei toeta QR-koodi ega emoji-põhist verifitseerimist, aga just neid %(brand)s oskab kasutada. Proovi mõne muu Matrix'i kliendiga.", "other_party_cancelled": "Teine osapool tühistas verifitseerimise.", @@ -1043,10 +1036,6 @@ }, "error_user_not_logged_in": "Kasutaja pole võrku loginud", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s lõpetas ringhäälingukõne", - "you": "Sa lõpetasid ringhäälingukõne" - }, "m.call.answer": { "dm": "Kõne on pooleli", "user": "%(senderName)s liitus kõnega", @@ -1415,8 +1404,6 @@ "video_rooms_faq1_question": "Kuidas ma saan luua videotoa?", "video_rooms_faq2_answer": "Jah, tekstivestluse ajajoon on kuvatud videovaate kõrval.", "video_rooms_faq2_question": "Kas ma saan videokõne ajal ka tekstisõnumeid saata?", - "voice_broadcast": "Ringhäälingukõne", - "voice_broadcast_force_small_chunks": "Kasuta ringhäälingusõnumi puhul 15-sekundilist blokipikkust", "wysiwyg_composer": "Kujundatud teksti toimeti" }, "labs_mjolnir": { @@ -1556,7 +1543,6 @@ "mute_description": "Sa ei saa üldse teavitusi" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s alustas ringhäälingukõnet", "m.key.verification.request": "%(name)s soovib verifitseerimist" }, "onboarding": { @@ -2112,7 +2098,6 @@ "error_unbanning": "Ligipääsu taastamine ei õnnestunud", "events_default": "Saada sõnumeid", "invite": "Kutsu kasutajaid", - "io.element.voice_broadcast_info": "Ringhäälingukõned", "kick": "Eemalda kasutajaid", "m.call": "Alusta helistamist %(brand)s abil", "m.call.member": "Liitu %(brand)s kõnedega", @@ -2744,7 +2729,6 @@ "warning": "HOIATUS: " }, "share": { - "link_title": "Link jututoale", "permalink_message": "Viide valitud sõnumile", "permalink_most_recent": "Viide kõige viimasele sõnumile", "title_message": "Jaga jututoa sõnumit", @@ -2831,13 +2815,6 @@ "upgraderoom": "Uuendab jututoa uue versioonini", "upgraderoom_permission_error": "Sul ei ole piisavalt õigusi selle käsu käivitamiseks.", "usage": "Kasutus", - "verify": "Verifitseerib kasutaja, sessiooni ja avalikud võtmed", - "verify_mismatch": "HOIATUS: VÕTMETE VERIFITSEERIMINE EI ÕNNESTUNUD! Kasutaja %(userId)s ja sessiooni %(deviceId)s allkirjastamise võti on „%(fprint)s“, aga see ei vasta antud sõrmejäljele „%(fingerprint)s“. See võib tähendada, et sinu kasutatavad ühendused võivad olla kolmanda osapoole poolt vahelt lõigatud!", - "verify_nop": "Sessioon on juba verifitseeritud!", - "verify_nop_warning_mismatch": "HOIATUS: Sessioon on juba verifitseeritud, aga võtmed ei klapi!", - "verify_success_description": "Sinu antud allkirjavõti vastab allkirjavõtmele, mille sa said kasutaja %(userId)s sessioonist %(deviceId)s. Sessioon on märgitud verifitseerituks.", - "verify_success_title": "Verifitseeritud võti", - "verify_unknown_pair": "Tundmatu kasutaja ja sessiooni kombinatsioon: (%(userId)s, %(deviceId)s)", "view": "Vaata sellise aadressiga jututuba", "whois": "Näitab teavet kasutaja kohta" }, @@ -3049,10 +3026,6 @@ "error_rendering_message": "Selle sõnumi laadimine ei õnnestu", "historical_messages_unavailable": "Sa ei saa näha varasemaid sõnumeid", "in_room_name": " %(room)s jututoas", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s lõpetas ringhäälingukõne", - "you": "Sa lõpetasid ringhäälingukõne" - }, "io.element.widgets.layout": "%(senderName)s on uuendanud jututoa välimust", "load_error": { "no_permission": "Üritasin laadida teatud hetke selle jututoa ajajoonelt, kuid sul ei ole õigusi selle sõnumi nägemiseks.", @@ -3580,38 +3553,6 @@ "switch_theme_dark": "Kasuta tumedat teemat", "switch_theme_light": "Kasuta heledat teemat" }, - "voice_broadcast": { - "30s_backward": "30s tagasi", - "30s_forward": "30s edasi", - "action": "Ringhäälingukõne", - "buffering": "Andmed on puhverdamisel…", - "confirm_listen_affirm": "Jah, lõpeta salvestamine", - "confirm_listen_description": "Kui hakkad kuulama seda ringhäälingukõnet, siis hetkel toimuv ringhäälingukõne salvestamine lõppeb.", - "confirm_listen_title": "Kas soovid kuulata ringhäälingukõnet?", - "confirm_stop_affirm": "Jah, lõpeta", - "confirm_stop_description": "Kas sa oled kindel, et soovid otseeetri lõpetada? Sellega ringhäälingukõne salvestamine lõppeb ja salvestis on kättesaadav kõigile jututoas.", - "confirm_stop_title": "Kas lõpetame otseeetri?", - "connection_error": "Viga võrguühenduses - salvestamine on peatatud", - "failed_already_recording_description": "Sa juba salvestad ringhäälingukõnet. Uue alustamiseks palun lõpeta eelmine salvestus.", - "failed_already_recording_title": "Uue ringhäälingukõne alustamine pole võimalik", - "failed_decrypt": "Ringhäälingukõne dekrüptimine ei õnnestu", - "failed_generic": "Selle ringhäälingukõne esitamine ei õnnestu", - "failed_insufficient_permission_description": "Sul pole piisavalt õigusi selles jututoas ringhäälingukõne algatamiseks. Õiguste lisamiseks palun võta ühendust jututoa haldajaga.", - "failed_insufficient_permission_title": "Uue ringhäälingukõne alustamine pole võimalik", - "failed_no_connection_description": "Kahjuks me ei saa hetkel salvestamist alustada. Palun proovi hiljem uuesti.", - "failed_no_connection_title": "Ühenduse viga", - "failed_others_already_recording_description": "Keegi juba salvestab ringhäälingukõnet. Uue ringhäälingukõne salvestamiseks palun oota, kuni see teine ringhäälingukõne on lõppenud.", - "failed_others_already_recording_title": "Uue ringhäälingukõne alustamine pole võimalik", - "go_live": "Alusta otseeetrit", - "live": "Otseeeter", - "pause": "peata ringhäälingukõne", - "play": "esita ringhäälingukõnet", - "resume": "jätka ringhäälingukõnet" - }, - "voice_message": { - "cant_start_broadcast_description": "Kuna sa hetkel salvestad ringhäälingukõnet, siis häälsõnumi salvestamine või esitamine ei õnnestu. Selleks palun lõpeta ringhäälingukõne.", - "cant_start_broadcast_title": "Häälsõnumi salvestamine või esitamine ei õnnestu" - }, "voip": { "already_in_call": "Kõne on juba pooleli", "already_in_call_person": "Sinul juba kõne käsil selle osapoolega.", @@ -3631,7 +3572,6 @@ "camera_disabled": "Sinu seadme kaamera on välja lülitatud", "camera_enabled": "Sinu seadme kaamera on jätkuvalt kasutusel", "cannot_call_yourself_description": "Sa ei saa iseendale helistada.", - "change_input_device": "Vaheta sisendseadet", "connecting": "Kõne on ühendamisel", "connection_lost": "Ühendus sinu serveriga on katkenud", "connection_lost_description": "Kui ühendus sinu serveriga on katkenud, siis sa ei saa helistada.", @@ -3648,8 +3588,6 @@ "enable_camera": "Lülita kaamera sisse", "enable_microphone": "Eemalda mikrofoni summutamine", "expand": "Pöördu tagasi kõne juurde", - "failed_call_live_broadcast_description": "Kuna sa hetkel salvestad ringhäälingukõnet, siis tavakõne algatamine ei õnnestu. Kõne alustamiseks palun lõpeta ringhäälingukõne.", - "failed_call_live_broadcast_title": "Kõne algatamine ei õnnestu", "hangup": "Katkesta kõne", "hide_sidebar_button": "Peida külgpaan", "input_devices": "Sisendseadmed", diff --git a/src/i18n/strings/fa.json b/src/i18n/strings/fa.json index 5541bbbfbd0..4fc031ac43d 100644 --- a/src/i18n/strings/fa.json +++ b/src/i18n/strings/fa.json @@ -654,12 +654,6 @@ "incoming_sas_dialog_title": "درخواست تأیید دریافتی", "incoming_sas_user_dialog_text_1": "این کاربر را تأیید کنید تا به عنوان کاربر مورد اعتماد علامت‌گذاری شود. اعتماد به کاربران آرامش و اطمینان بیشتری به شما در استفاده از رمزنگاری سرتاسر می‌دهد.", "incoming_sas_user_dialog_text_2": "با تأیید این کاربر ، نشست وی به عنوان مورد اعتماد علامت‌گذاری شده و همچنین نشست شما به عنوان مورد اعتماد برای وی علامت‌گذاری خواهد شد.", - "manual_device_verification_device_id_label": "شناسه‌ی نشست", - "manual_device_verification_device_key_label": "کلید نشست", - "manual_device_verification_device_name_label": "نام نشست", - "manual_device_verification_footer": "اگر آنها مطابقت نداشته‌باشند ، ممکن است امنیت ارتباطات شما به خطر افتاده باشد.", - "manual_device_verification_self_text": "از طریق مقایسه‌ی این با تنظیمات کاربری در نشست‌های دیگرتان، تائيد کنید:", - "manual_device_verification_user_text": "این نشست کاربر را از طریق مقایسه‌ی این با تنظیمات کاربری تائيد کنید:", "other_party_cancelled": "طرف مقابل فرآیند تائید را لغو کرد.", "prompt_encrypted": "برای اطمینان از امنیت اتاق، هویت همه‌ی کاربران حاضر در اتاق را تأیید کنید.", "prompt_self": "از اعلان دوباره تأیید را شروع کنید.", @@ -981,8 +975,7 @@ "latex_maths": "نمایش لاتکس ریاضیات در پیام‌ها", "leave_beta": "ترک نسخه‌ی بتا", "video_rooms": "اتاق های تصویری", - "video_rooms_a_new_way_to_chat": "راهکار جدیدی برای گفتگوی صوتی و تصویری در%(brand)sوجود دارد.", - "voice_broadcast": "صدای جمعی" + "video_rooms_a_new_way_to_chat": "راهکار جدیدی برای گفتگوی صوتی و تصویری در%(brand)sوجود دارد." }, "labs_mjolnir": { "advanced_warning": "⚠ این تنظیمات برای کاربران حرفه‌ای قرار داده شده‌است.", @@ -1073,7 +1066,6 @@ "mentions_keywords": "منشن ها و کلمات کلیدی" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s یک پخش صوتی را شروع کرد", "m.key.verification.request": "%(name)s درخواست تائید دارد" }, "onboarding": { @@ -1806,12 +1798,6 @@ "upgraderoom": "یک اتاق را به نسخه جدید ارتقا دهید", "upgraderoom_permission_error": "شما مجوزهای لازم را برای استفاده از این دستور ندارید.", "usage": "استفاده", - "verify": "یک کاربر، نشست و عبارت کلید عمومی را تائید می‌کند", - "verify_mismatch": "هشدار: تایید کلید ناموفق بود! کلید امضا کننده %(userId)s در نشست %(deviceId)s برابر %(fprint)s است که با کلید %(fingerprint)s تطابق ندارد. این می تواند به معنی رهگیری ارتباطات شما باشد!", - "verify_nop": "نشست پیش از این تائید شده‌است!", - "verify_success_description": "کلید امضای ارائه شده با کلید امضای دریافت شده از جلسه %(deviceId)s کاربر %(userId)s مطابقت دارد. نشست به عنوان تأیید شده علامت گذاری شد.", - "verify_success_title": "کلید تأیید شده", - "verify_unknown_pair": "دوتایی (کاربر و نشست) ناشناخته : ( %(userId)sو%(deviceId)s )", "whois": "اطلاعات مربوط به کاربر را نمایش می دهد" }, "space": { @@ -2312,22 +2298,6 @@ "switch_theme_dark": "انتخاب حالت تاریک", "switch_theme_light": "انتخاب حالت روشن" }, - "voice_broadcast": { - "action": "صدای جمعی", - "confirm_stop_affirm": "بله، توقف ارسال جمعی", - "confirm_stop_title": "آیا ارسال جمعی زنده متوقف شود؟", - "failed_already_recording_description": "شما در حال ضبط یک صدا برای ارسال جمعی هستید. برای تولید یک صدای جمعی دیگر ضبط فعلی را متوقف نمایید.", - "failed_already_recording_title": "امکان ارسال یک صدای جدید به صورت جمعی نیست", - "failed_insufficient_permission_description": "شما دسترسی لازم برای ارسال صدای جمعی در این اتاق را ندارید. لطفا با مدیر اتاق تماس بگیرید.", - "failed_insufficient_permission_title": "امکان ارسال یک صدای جدید به صورت جمعی نیست", - "failed_others_already_recording_description": "شخص دیگری در حال ضبط صدا برای ارسال جمعی است. برای ارسال صدای جمعی باید منتظر بمانید تا کار ایشان به پایان برسد.", - "failed_others_already_recording_title": "امکان ارسال یک صدای جدید به صورت جمعی نیست", - "go_live": "برو به زنده", - "live": "زنده", - "pause": "توقف صدای جمعی", - "play": "پخش صدای جمعی", - "resume": "بازگشت به صدای جمعی" - }, "voip": { "already_in_call": "هم‌اکنون در تماس هستید", "already_in_call_person": "شما هم‌اکنون با این فرد در تماس هستید.", diff --git a/src/i18n/strings/fi.json b/src/i18n/strings/fi.json index 091761af4b8..48fc132f002 100644 --- a/src/i18n/strings/fi.json +++ b/src/i18n/strings/fi.json @@ -778,7 +778,6 @@ }, "udd": { "interactive_verification_button": "Vahvista vuorovaikutteisesti emojilla", - "manual_verification_button": "Vahvista manuaalisesti tekstillä", "other_ask_verify_text": "Pyydä tätä käyttäjää vahvistamaan istuntonsa, tai vahvista se manuaalisesti alla.", "other_new_session_text": "%(name)s (%(userId)s) kirjautui uudella istunnolla varmentamatta sitä:", "own_ask_verify_text": "Varmenna toinen istuntosi käyttämällä yhtä seuraavista tavoista.", @@ -807,10 +806,6 @@ "incoming_sas_dialog_title": "Saapuva varmennuspyyntö", "incoming_sas_user_dialog_text_1": "Varmenna tämä käyttäjä merkitäksesi hänet luotetuksi. Käyttäjiin luottaminen antaa sinulle ylimääräistä mielenrauhaa käyttäessäsi päästä päähän -salausta.", "incoming_sas_user_dialog_text_2": "Tämän käyttäjän varmentaminen merkitsee hänen istuntonsa luotetuksi, ja myös merkkaa sinun istuntosi luotetuksi hänen laitteissaan.", - "manual_device_verification_device_id_label": "Istuntotunniste", - "manual_device_verification_device_key_label": "Istunnon tunnus", - "manual_device_verification_device_name_label": "Istunnon nimi", - "manual_device_verification_footer": "Jos ne eivät täsmää, viestinnän turvallisuus saattaa olla vaarantunut.", "other_party_cancelled": "Toinen osapuoli perui varmennuksen.", "prompt_encrypted": "Varmenna kaikki huoneen käyttäjät varmistaaksesi, että se on turvallinen.", "prompt_self": "Aloita varmennus uudelleen ilmoituksesta.", @@ -917,10 +912,6 @@ }, "error_user_not_logged_in": "Käyttäjä ei ole sisäänkirjautunut", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s lopetti äänen yleislähetyksen", - "you": "Lopetit äänen yleislähetyksen" - }, "m.call.answer": { "dm": "Puhelu käynnissä", "user": "%(senderName)s liittyi puheluun", @@ -1239,8 +1230,7 @@ "video_rooms_faq1_answer": "Käytä ”+”-painiketta vasemman paneelin huoneosiossa.", "video_rooms_faq1_question": "Miten voin luoda videohuoneen?", "video_rooms_faq2_answer": "Kyllä, keskustelun aikajana esitetään videon yhteydessä.", - "video_rooms_faq2_question": "Voinko käyttää tekstikeskustelua videopuhelussa?", - "voice_broadcast": "Äänen yleislähetys" + "video_rooms_faq2_question": "Voinko käyttää tekstikeskustelua videopuhelussa?" }, "labs_mjolnir": { "advanced_warning": "⚠ Nämä asetukset on tarkoitettu edistyneille käyttäjille.", @@ -1356,7 +1346,6 @@ "mute_description": "Et saa ilmoituksia" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s aloitti äänen yleislähetyksen", "m.key.verification.request": "%(name)s pyytää varmennusta" }, "onboarding": { @@ -1856,7 +1845,6 @@ "error_unbanning": "Porttikiellon poistaminen epäonnistui", "events_default": "Lähetä viestejä", "invite": "Kutsu käyttäjiä", - "io.element.voice_broadcast_info": "Äänen yleislähetykset", "kick": "Poista käyttäjiä", "m.call": "Aloita %(brand)s-puheluja", "m.call.member": "Liity %(brand)s-puheluihin", @@ -2415,7 +2403,6 @@ "warning": "VAROITUS: " }, "share": { - "link_title": "Linkitä huoneeseen", "permalink_message": "Linkitä valittuun viestiin", "permalink_most_recent": "Linkitä viimeisimpään viestiin", "title_message": "Jaa huoneviesti", @@ -2499,13 +2486,6 @@ "upgraderoom": "Päivittää huoneen uuteen versioon", "upgraderoom_permission_error": "Sinulla ei ole vaadittavia oikeuksia tämän komennon käyttämiseksi.", "usage": "Käyttö", - "verify": "Varmentaa käyttäjän, istunnon ja julkiset avaimet", - "verify_mismatch": "VAROITUS: AVAIMEN VARMENTAMINEN EPÄONNISTUI! Käyttäjän %(userId)s ja laitteen %(deviceId)s istunnon allekirjoitusavain on ”%(fprint)s”, mikä ei täsmää annettuun avaimeen ”%(fingerprint)s”. Tämä voi tarkoittaa, että viestintäänne siepataan!", - "verify_nop": "Istunto on jo vahvistettu!", - "verify_nop_warning_mismatch": "VAROITUS: istunto on jo vahvistettu, mutta avaimet EIVÄT TÄSMÄÄ!", - "verify_success_description": "Antamasi allekirjoitusavain täsmää käyttäjältä %(userId)s saamaasi istunnon %(deviceId)s allekirjoitusavaimeen. Istunto on varmennettu.", - "verify_success_title": "Varmennettu avain", - "verify_unknown_pair": "Tuntematon (käyttäjä, laite) (%(userId)s, %(deviceId)s)", "whois": "Näyttää tietoa käyttäjästä" }, "space": { @@ -2710,10 +2690,6 @@ "error_rendering_message": "Tätä viestiä ei voi ladata", "historical_messages_unavailable": "Et voi nähdä aiempia viestejä", "in_room_name": " huoneessa %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s lopetti äänen yleislähetyksen", - "you": "Lopetit äänen yleislähetyksen" - }, "io.element.widgets.layout": "%(senderName)s on päivittänyt huoneen asettelun", "load_error": { "no_permission": "Aikajanan tietty hetki yritettiin ladata, mutta sinulla ei ole oikeutta nähdä kyseistä viestiä.", @@ -3202,23 +3178,6 @@ "switch_theme_dark": "Vaihda tummaan teemaan", "switch_theme_light": "Vaihda vaaleaan teemaan" }, - "voice_broadcast": { - "30s_backward": "30 s taaksepäin", - "30s_forward": "30 s eteenpäin", - "action": "Äänen yleislähetys", - "buffering": "Puskuroidaan…", - "confirm_stop_affirm": "Kyllä, pysäytä yleislähetys", - "confirm_stop_title": "Pysäytetäänkö liveyleislähetys?", - "failed_already_recording_description": "Tallennat jo äänen yleislähetystä. Lopeta nykyinen äänen yleislähetys aloittaaksesi uuden.", - "failed_already_recording_title": "Uutta äänen yleislähetystä ei voi käynnistää", - "failed_insufficient_permission_title": "Uutta äänen yleislähetystä ei voi käynnistää", - "failed_no_connection_title": "Yhteysvirhe", - "failed_others_already_recording_description": "Joku toinen tallentaa jo äänen yleislähetystä. Odota äänen yleislähetyksen päättymistä, jotta voit aloittaa uuden.", - "failed_others_already_recording_title": "Uutta äänen yleislähetystä ei voi käynnistää", - "pause": "keskeytä äänen yleislähetys", - "play": "toista äänen yleislähetys", - "resume": "palaa äänen yleislähetykseen" - }, "voip": { "already_in_call": "Olet jo puhelussa", "already_in_call_person": "Olet jo puhelussa tämän henkilön kanssa.", @@ -3238,7 +3197,6 @@ "camera_disabled": "Kamerasi on pois päältä", "camera_enabled": "Kamerasi on edelleen päällä", "cannot_call_yourself_description": "Et voi soittaa itsellesi.", - "change_input_device": "Vaihda sisääntulolaitetta", "connecting": "Yhdistetään", "connection_lost": "Yhteys palvelimeen on katkennut", "connection_lost_description": "Et voi soittaa puheluja ilman yhteyttä palvelimeen.", @@ -3254,7 +3212,6 @@ "enable_camera": "Laita kamera päälle", "enable_microphone": "Poista mikrofonin mykistys", "expand": "Palaa puheluun", - "failed_call_live_broadcast_title": "Puhelua ei voi aloittaa", "hangup": "Lopeta", "hide_sidebar_button": "Piilota sivupalkki", "input_devices": "Sisääntulolaitteet", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 0462e747669..08348ba29d6 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -504,6 +504,7 @@ "matrix": "Matrix", "message": "Message", "message_layout": "Mise en page des messages", + "message_timestamp_invalid": "Horodatage non valide", "microphone": "Micro", "model": "Modèle", "modern": "Moderne", @@ -904,6 +905,8 @@ "warning": "Si vous n’avez pas activé de nouvelle méthode de récupération, un attaquant essaye peut-être d’accéder à votre compte. Changez immédiatement le mot de passe de votre compte et configurez une nouvelle méthode de récupération dans les paramètres." }, "not_supported": "", + "pinned_identity_changed": "%(displayName)sL'identité de (%(userId)s) semble avoir changé. En savoir plus ", + "pinned_identity_changed_no_displayname": "%(userId)ssemble avoir changé d'identité. En savoir plus", "recovery_method_removed": { "description_1": "Cette session a détecté que votre phrase secrète et clé de sécurité pour les messages sécurisés ont été supprimées.", "description_2": "Si vous l’avez fait accidentellement, vous pouvez configurer les messages sécurisés sur cette session ce qui re-chiffrera l’historique des messages de cette session avec une nouvelle méthode de récupération.", @@ -919,7 +922,6 @@ }, "udd": { "interactive_verification_button": "Vérifier de façon interactive avec des émojis", - "manual_verification_button": "Vérifier manuellement avec un texte", "other_ask_verify_text": "Demandez à cet utilisateur de vérifier sa session, ou vérifiez-la manuellement ci-dessous.", "other_new_session_text": "%(name)s (%(userId)s) s’est connecté à une nouvelle session sans la vérifier :", "own_ask_verify_text": "Vérifiez votre autre session en utilisant une des options ci-dessous.", @@ -954,12 +956,6 @@ "incoming_sas_dialog_waiting": "Attente de la confirmation du partenaire…", "incoming_sas_user_dialog_text_1": "Vérifier cet utilisateur pour le marquer comme fiable. Faire confiance aux utilisateurs vous permet d’être tranquille lorsque vous utilisez des messages chiffrés de bout en bout.", "incoming_sas_user_dialog_text_2": "Vérifier cet utilisateur marquera sa session comme fiable, et marquera aussi votre session comme fiable pour lui.", - "manual_device_verification_device_id_label": "Identifiant de session", - "manual_device_verification_device_key_label": "Clé de la session", - "manual_device_verification_device_name_label": "Nom de la session", - "manual_device_verification_footer": "S’ils ne correspondent pas, la sécurité de vos communications est peut-être compromise.", - "manual_device_verification_self_text": "Confirmez en comparant ceci avec les paramètres utilisateurs de votre autre session :", - "manual_device_verification_user_text": "Confirmez la session de cet utilisateur en comparant ceci avec ses paramètres utilisateur :", "no_key_or_device": "Il semblerait que vous n’avez pas de clé de sécurité ou d’autres appareils pour faire la vérification. Cet appareil ne pourra pas accéder aux anciens messages chiffrés. Afin de vérifier votre identité sur cet appareil, vous devrez réinitialiser vos clés de vérifications.", "no_support_qr_emoji": "L’appareil que vous essayez de vérifier ne prend pas en charge les QR codes ou la vérification d’émojis, qui sont les méthodes prises en charge par %(brand)s. Essayez avec un autre client.", "other_party_cancelled": "L’autre personne a annulé la vérification.", @@ -999,7 +995,7 @@ "unverified_sessions_toast_description": "Vérifiez pour assurer la sécurité de votre compte", "unverified_sessions_toast_reject": "Plus tard", "unverified_sessions_toast_title": "Vous avez des sessions non vérifiées", - "verification_description": "Vérifiez votre identité pour accéder aux messages chiffrés et prouver votre identité aux autres.", + "verification_description": "Vérifiez votre identité pour accéder aux messages chiffrés et prouver votre identité aux autres. Si vous utilisez également un appareil mobile, veuillez ouvrir l’application avant de continuer.", "verification_dialog_title_device": "Vérifier un autre appareil", "verification_dialog_title_user": "Demande de vérification", "verification_skip_warning": "Sans vérification, vous n’aurez pas accès à tous vos messages et vous n’apparaîtrez pas comme de confiance aux autres.", @@ -1084,10 +1080,6 @@ }, "error_user_not_logged_in": "L’utilisateur n’est pas identifié", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s a terminé une diffusion audio", - "you": "Vous avez terminé une diffusion audio" - }, "m.call.answer": { "dm": "Appel en cours", "user": "%(senderName)s a rejoint l’appel", @@ -1109,7 +1101,15 @@ "you": "Vous avez réagi avec %(reaction)s à %(message)s" }, "m.sticker": "%(senderName)s : %(stickerName)s", - "m.text": "%(senderName)s : %(message)s" + "m.text": "%(senderName)s : %(message)s", + "prefix": { + "audio": "Audio", + "file": "Fichier", + "image": "Image", + "poll": "Sondage", + "video": "Vidéo" + }, + "preview": "%(prefix)s: %(preview)s" }, "export_chat": { "cancelled": "Export annulé", @@ -1240,7 +1240,11 @@ "linux": "Linux", "macos": "MAC", "supported_browsers": "Pour une expérience optimale, utilisez Chrome, Firefox, Edge, ou Safari.", - "title": "Navigateur non pris en charge" + "title": "Navigateur non pris en charge", + "use_desktop_heading": "Utilisez plutôt %(brand)s Desktop", + "use_mobile_heading": "Utilisez plutôt %(brand)s sur votre appareil mobile", + "use_mobile_heading_after_desktop": "Ou utilisez notre application mobile", + "windows": "Windows (%(bits)s-bit)" }, "info_tooltip_title": "Informations", "integration_manager": { @@ -1476,8 +1480,6 @@ "video_rooms_faq2_answer": "Oui, l’historique de conversation est affiché à côté de la vidéo.", "video_rooms_faq2_question": "Est-il possible d’utiliser les messages textuels en même temps que l’appel vidéo ?", "video_rooms_feedbackSubheading": "Merci d’essayer la version bêta. Veuillez l’utiliser au maximum pour que nous puissions l’améliorer.", - "voice_broadcast": "Diffusion audio", - "voice_broadcast_force_small_chunks": "Forcer la diffusion audio à utiliser des morceaux de 15s", "wysiwyg_composer": "Éditeur de texte formaté" }, "labs_mjolnir": { @@ -1623,7 +1625,6 @@ "mute_description": "Vous n’aurez aucune notification" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s a démarré une diffusion audio", "m.key.verification.request": "%(name)s demande une vérification" }, "onboarding": { @@ -2237,7 +2238,6 @@ "error_unbanning": "Échec de la révocation du bannissement", "events_default": "Envoyer des messages", "invite": "Inviter des utilisateurs", - "io.element.voice_broadcast_info": "Diffusions audio", "kick": "Expulser des utilisateurs", "m.call": "Démarrer des appels %(brand)s", "m.call.member": "Rejoindre des appels %(brand)s", @@ -2936,7 +2936,7 @@ "warning": "ATTENTION : " }, "share": { - "link_title": "Lien vers le salon", + "link_copied": "Lien copié", "permalink_message": "Lien vers le message sélectionné", "permalink_most_recent": "Lien vers le message le plus récent", "share_call": "Lien d'invitation à la conférence", @@ -3028,13 +3028,6 @@ "upgraderoom": "Met à niveau un salon vers une nouvelle version", "upgraderoom_permission_error": "Vous n’avez pas les autorisations nécessaires pour utiliser cette commande.", "usage": "Utilisation", - "verify": "Vérifie un utilisateur, une session et une collection de clés publiques", - "verify_mismatch": "ATTENTION : ÉCHEC DE LA VÉRIFICATION DE CLÉ ! La clé de signature pour %(userId)s et la session %(deviceId)s est « %(fprint)s  ce qui ne correspond pas à la clé fournie « %(fingerprint)s ». Cela pourrait signifier que vos communications sont interceptées !", - "verify_nop": "Session déjà vérifiée !", - "verify_nop_warning_mismatch": "ATTENTION : session déjà vérifiée, mais les clés ne CORRESPONDENT PAS !", - "verify_success_description": "La clé de signature que vous avez fournie correspond à celle que vous avez reçue de la session %(deviceId)s de %(userId)s. Session marquée comme vérifiée.", - "verify_success_title": "Clé vérifiée", - "verify_unknown_pair": "Paire (utilisateur, session) inconnue : (%(userId)s, %(deviceId)s)", "view": "Affiche le salon avec cette adresse", "whois": "Affiche des informations à propos de l’utilisateur" }, @@ -3271,10 +3264,6 @@ "error_rendering_message": "Impossible de charger ce message", "historical_messages_unavailable": "Vous ne pouvez pas voir les messages plus anciens", "in_room_name": " dans %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s a terminé une diffusion audio", - "you": "Vous avez terminé une diffusion audio" - }, "io.element.widgets.layout": "%(senderName)s a mis à jour la mise en page du salon", "late_event_separator": "Initialement envoyé%(dateTime)s", "load_error": { @@ -3728,6 +3717,7 @@ "error_files_too_large": "Ces fichiers sont trop lourds pour être envoyés. La taille limite des fichiers est de %(limit)s.", "error_some_files_too_large": "Certains fichiers sont trop lourds pour être envoyés. La taille limite des fichiers est de %(limit)s.", "error_title": "Erreur d’envoi", + "not_image": "Le fichier que vous avez choisi n'est pas un fichier image valide.", "title": "Envoyer les fichiers", "title_progress": "Envoi des fichiers (%(current)s sur %(total)s)", "upload_all_button": "Tout envoyer", @@ -3823,38 +3813,6 @@ "switch_theme_dark": "Passer au mode sombre", "switch_theme_light": "Passer au mode clair" }, - "voice_broadcast": { - "30s_backward": "30s en arrière", - "30s_forward": "30s en avant", - "action": "Diffusion audio", - "buffering": "Mise en mémoire tampon…", - "confirm_listen_affirm": "Oui, terminer mon enregistrement", - "confirm_listen_description": "En commençant à écouter cette diffusion en direct, votre enregistrement de diffusion en direct actuel sera interrompu.", - "confirm_listen_title": "Écouter la diffusion en direct ?", - "confirm_stop_affirm": "Oui, arrêter la diffusion", - "confirm_stop_description": "Êtes-vous sûr de vouloir arrêter votre diffusion en direct ? Cela terminera la diffusion et l’enregistrement complet sera disponible dans le salon.", - "confirm_stop_title": "Arrêter la diffusion en direct ?", - "connection_error": "Erreur de connexion – Enregistrement en pause", - "failed_already_recording_description": "Vous êtes déjà en train de réaliser une diffusion audio. Veuillez terminer votre diffusion audio actuelle pour en démarrer une nouvelle.", - "failed_already_recording_title": "Impossible de commencer une nouvelle diffusion audio", - "failed_decrypt": "Impossible de décrypter la diffusion audio", - "failed_generic": "Impossible de lire cette diffusion audio", - "failed_insufficient_permission_description": "Vous n’avez pas les permissions requises pour démarrer une nouvelle diffusion audio dans ce salon. Contactez un administrateur du salon pour mettre-à-jour vos permissions.", - "failed_insufficient_permission_title": "Impossible de commencer une nouvelle diffusion audio", - "failed_no_connection_description": "Malheureusement, nous ne pouvons pas démarrer l’enregistrement pour le moment. Veuillez réessayer plus tard.", - "failed_no_connection_title": "Erreur de connexion", - "failed_others_already_recording_description": "Une autre personne est déjà en train de réaliser une diffusion audio. Attendez que sa diffusion audio soit terminée pour en démarrer une nouvelle.", - "failed_others_already_recording_title": "Impossible de commencer une nouvelle diffusion audio", - "go_live": "Passer en direct", - "live": "Direct", - "pause": "mettre en pause la diffusion audio", - "play": "lire la diffusion audio", - "resume": "continuer la diffusion audio" - }, - "voice_message": { - "cant_start_broadcast_description": "Vous ne pouvez pas commencer un message vocal car vous êtes en train d’enregistrer une diffusion en direct. Veuillez terminer cette diffusion pour commencer un message vocal.", - "cant_start_broadcast_title": "Impossible de commencer un message vocal" - }, "voip": { "already_in_call": "Déjà en cours d’appel", "already_in_call_person": "Vous êtes déjà en cours d’appel avec cette personne.", @@ -3874,7 +3832,6 @@ "camera_disabled": "Votre caméra est éteinte", "camera_enabled": "Votre caméra est toujours allumée", "cannot_call_yourself_description": "Vous ne pouvez pas passer d’appel avec vous-même.", - "change_input_device": "Change de périphérique d’entrée", "close_lobby": "Fermer la salle d'attente", "connecting": "Connexion", "connection_lost": "La connexion au serveur a été perdue", @@ -3893,8 +3850,6 @@ "enable_camera": "Activer la caméra", "enable_microphone": "Activer le microphone", "expand": "Revenir à l’appel", - "failed_call_live_broadcast_description": "Vous ne pouvez pas démarrer un appel car vous êtes en train d’enregistrer une diffusion en direct. Veuillez terminer cette diffusion pour démarrer un appel.", - "failed_call_live_broadcast_title": "Impossible de démarrer un appel", "get_call_link": "Partager le lien de l'appel", "hangup": "Raccrocher", "hide_sidebar_button": "Masquer la barre latérale", diff --git a/src/i18n/strings/gl.json b/src/i18n/strings/gl.json index 00277a5f3e4..50c551d6a2d 100644 --- a/src/i18n/strings/gl.json +++ b/src/i18n/strings/gl.json @@ -749,7 +749,6 @@ }, "udd": { "interactive_verification_button": "Verificar interactivamente usando emoji", - "manual_verification_button": "Verificar manualmente con texto", "other_ask_verify_text": "Pídelle a usuaria que verifique a súa sesión, ou verificaa manualmente aquí.", "other_new_session_text": "%(name)s (%(userId)s) conectouse a unha nova sesión sen verificala:", "own_ask_verify_text": "Verifica a túa outra sesión usando unha das opcións inferiores.", @@ -781,12 +780,6 @@ "incoming_sas_dialog_title": "Solicitude entrante de verificación", "incoming_sas_user_dialog_text_1": "Verifica esta usuaria para marcala como confiable. Ao confiar nas usuarias proporcionache tranquilidade extra cando usas cifrado de extremo-a-extremo.", "incoming_sas_user_dialog_text_2": "Ao verificar esta usuaria marcarás a súa sesión como confiable, e tamén marcará a túa sesión como confiable para elas.", - "manual_device_verification_device_id_label": "ID de sesión", - "manual_device_verification_device_key_label": "Chave da sesión", - "manual_device_verification_device_name_label": "Nome da sesión", - "manual_device_verification_footer": "Se non concordan, a seguridade da comunicación podería estar comprometida.", - "manual_device_verification_self_text": "Corfirma comparando o seguinte cos Axustes de Usuaria na outra sesión:", - "manual_device_verification_user_text": "Confirma a sesión desta usuaria comparando o seguinte cos seus Axustes de Usuaria:", "no_key_or_device": "Semella que non tes unha Chave de Seguridade ou outros dispositivos cos que verificar. Este dispositivo non poderá acceder a mensaxes antigas cifradas. Para poder verificar a túa identidade neste dispositivo tes que restablecer as chaves de verificación.", "no_support_qr_emoji": "Este dispositivo que intentas verificar non ten soporte para código QR nin verificación por emoji, que é o que %(brand)s soporta. Inténtao cun cliente diferente.", "other_party_cancelled": "A outra parte cancelou a verificación.", @@ -1200,8 +1193,7 @@ "video_rooms_faq1_answer": "Usa o botón \"+\" na sección da sala do panel esquerdo.", "video_rooms_faq1_question": "Como creo unha sala de vídeo?", "video_rooms_faq2_answer": "Si, a cronoloxía de texto móstrase xunto co vídeo.", - "video_rooms_faq2_question": "Podo usar chat de texto xunto á chamada de vídeo?", - "voice_broadcast": "Emisión de voz" + "video_rooms_faq2_question": "Podo usar chat de texto xunto á chamada de vídeo?" }, "labs_mjolnir": { "advanced_warning": "⚠ Estos axustes van dirixidos a usuarias avanzadas.", @@ -1811,7 +1803,6 @@ "error_unbanning": "Fallou eliminar a prohibición", "events_default": "Enviar mensaxes", "invite": "Convidar usuarias", - "io.element.voice_broadcast_info": "Emisións de voz", "kick": "Eliminar usuarias", "m.reaction": "Enviar reaccións", "m.room.avatar": "Cambiar avatar da sala", @@ -2315,7 +2306,6 @@ "warn_quit": "Aviso antes de saír" }, "share": { - "link_title": "Ligazón á sala", "permalink_message": "Ligazón á mensaxe escollida", "permalink_most_recent": "Ligazón ás mensaxes máis recentes", "title_message": "Compartir unha mensaxe da sala", @@ -2397,12 +2387,6 @@ "upgraderoom": "Subir a sala de versión", "upgraderoom_permission_error": "Non tes os permisos suficientes para usar este comando.", "usage": "Uso", - "verify": "Verifica unha usuaria, sesión e chave pública", - "verify_mismatch": "AVISO: FALLOU A VERIFICACIÓN DAS CHAVES! A chave de firma para %(userId)s na sesión %(deviceId)s é \"%(fprint)s\" que non concordan coa chave proporcionada \"%(fingerprint)s\". Esto podería significar que as túas comunicacións foron interceptadas!", - "verify_nop": "A sesión xa está verificada!", - "verify_success_description": "A chave de firma proporcionada concorda coa chave de firma recibida desde a sesión %(deviceId)s de %(userId)s. Sesión marcada como verificada.", - "verify_success_title": "Chave verificada", - "verify_unknown_pair": "Parella (usuaria, sesión) descoñecida: (%(userId)s, %(deviceId)s)", "whois": "Mostra información acerca da usuaria" }, "space": { @@ -3102,9 +3086,6 @@ "switch_theme_dark": "Cambiar a decorado escuro", "switch_theme_light": "Cambiar a decorado claro" }, - "voice_broadcast": { - "action": "Emisión de voz" - }, "voip": { "already_in_call": "Xa estás nunha chamada", "already_in_call_person": "Xa estás nunha conversa con esta persoa.", diff --git a/src/i18n/strings/he.json b/src/i18n/strings/he.json index c98d59c6597..724e17efd91 100644 --- a/src/i18n/strings/he.json +++ b/src/i18n/strings/he.json @@ -662,12 +662,6 @@ "incoming_sas_dialog_title": "בקשת אימות נכנסת", "incoming_sas_user_dialog_text_1": "אמתו את המשתמש הזה כדי לסמן אותו כאמין. אמון במשתמשים מעניק לכם שקט נפשי נוסף בשימוש בהודעות מוצפנות מקצה לקצה.", "incoming_sas_user_dialog_text_2": "אימות משתמש זה יסמן את ההפעלה שלו כאמינה, וגם יסמן את ההפעלה שלכם כאמינה להם.", - "manual_device_verification_device_id_label": "זהות מושב", - "manual_device_verification_device_key_label": "מפתח מושב", - "manual_device_verification_device_name_label": "שם מושב", - "manual_device_verification_footer": "אם הם לא תואמים, אבטחת התקשורת שלך עלולה להיפגע.", - "manual_device_verification_self_text": "אשר על ידי השוואה בין הדברים הבאים להגדרות המשתמש בפגישה האחרת שלך:", - "manual_device_verification_user_text": "אשר את הפעלת המשתמש הזה על ידי השוואה בין הדברים הבאים להגדרות המשתמש שלהם:", "other_party_cancelled": "הצד השני ביטל את האימות.", "prompt_encrypted": "אמת את כל המשתמשים בחדר כדי לוודא שהוא מאובטח.", "prompt_self": "התחל אימות שוב מההודעה.", @@ -1454,7 +1448,6 @@ "error_unbanning": "שגיאה בהסרת חסימה", "events_default": "שלח הודעות", "invite": "הזמנת משתמשים", - "io.element.voice_broadcast_info": "שליחת הקלטות קוליות", "kick": "הסר משתמשים", "m.reaction": "שלח תגובות", "m.room.avatar": "שנה אווטר של החדר", @@ -1958,11 +1951,6 @@ "upgraderoom": "משדרג את החדר לגרסא חדשה", "upgraderoom_permission_error": "אין לכם הרשאות להשתמש בפקודה זו.", "usage": "שימוש", - "verify": "מוודא משתמש, התחברות וצמד מפתח ציבורי", - "verify_mismatch": "אזהרה: אימות מפתח נכשל! חתימת המפתח של %(userId)s ושל ההתחברות של מכשיר %(deviceId)s הינו \"%(fprint)s\" אשר אינו תואם למפתח הנתון \"%(fingerprint)s\". דבר זה יכול להעיר על כך שישנו נסיון להאזין לתקשורת שלכם!", - "verify_nop": "ההתחברות כבר אושרה!", - "verify_success_description": "המפתח החתום שנתתם תואם את המפתח שקבלתם מ %(userId)s מהתחברות %(deviceId)s. ההתחברות סומנה כמאושרת.", - "verify_success_title": "מפתח מאושר", "whois": "מציג מידע אודות משתמש" }, "space": { diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index cf410fb82f3..349c4a39cdb 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -872,7 +872,6 @@ }, "udd": { "interactive_verification_button": "Interaktív ellenőrzés emodzsikkal", - "manual_verification_button": "Kézi szöveges ellenőrzés", "other_ask_verify_text": "Kérje meg a felhasználót, hogy hitelesítse a munkamenetét, vagy ellenőrizze kézzel lentebb.", "other_new_session_text": "%(name)s (%(userId)s) új munkamenetbe lépett be, anélkül, hogy ellenőrizte volna:", "own_ask_verify_text": "Ellenőrizze a másik munkamenetét a lenti lehetőségek egyikével.", @@ -907,12 +906,6 @@ "incoming_sas_dialog_waiting": "Várakozás a partner megerősítésére…", "incoming_sas_user_dialog_text_1": "Ellenőrizd ezt a felhasználót, hogy megbízhatónak lehessen tekinteni. Megbízható felhasználók további nyugalmat jelenthetnek ha végpontól végpontig titkosítást használsz.", "incoming_sas_user_dialog_text_2": "A felhasználó ellenőrzése által az ő munkamenete megbízhatónak lesz jelölve, és a te munkameneted is megbízhatónak lesz jelölve nála.", - "manual_device_verification_device_id_label": "Kapcsolat azonosító", - "manual_device_verification_device_key_label": "Munkamenetkulcs", - "manual_device_verification_device_name_label": "Munkamenet neve", - "manual_device_verification_footer": "Ha nem egyeznek akkor a kommunikációtok biztonsága veszélyben lehet.", - "manual_device_verification_self_text": "Erősítsd meg a felhasználói beállítások összehasonlításával a többi munkamenetedben:", - "manual_device_verification_user_text": "Ezt a munkamenetet hitelesítsd az ő felhasználói beállításának az összehasonlításával:", "no_key_or_device": "Úgy tűnik, hogy nem rendelkezik biztonsági kulccsal, vagy másik eszközzel, amelyikkel ellenőrizhetné. Ezzel az eszközzel nem fér majd hozzá a régi titkosított üzenetekhez. Ahhoz, hogy a személyazonosságát ezen az eszközön ellenőrizni lehessen, az ellenőrzédi kulcsokat alaphelyzetbe kell állítani.", "no_support_qr_emoji": "Az ellenőrizni kívánt eszköz nem támogatja se a QR kód beolvasást se az emodzsi ellenőrzést, amit a %(brand)s támogat. Próbálja meg egy másik klienssel.", "other_party_cancelled": "A másik fél megszakította az ellenőrzést.", @@ -1029,10 +1022,6 @@ }, "error_user_not_logged_in": "A felhasználó nincs bejelentkezve", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s befejezte a hangközvetítést", - "you": "A hangközvetítés befejeződött" - }, "m.call.answer": { "dm": "Folyamatban lévő hívás", "user": "%(senderName)s csatlakozott a hívásba", @@ -1392,8 +1381,6 @@ "video_rooms_faq1_question": "Hogy lehet videószobát készíteni?", "video_rooms_faq2_answer": "Igen, a szöveges idővonal a videóval együtt megjelenik.", "video_rooms_faq2_question": "Lehet a videóhívás közben szövegesen is csevegni?", - "voice_broadcast": "Hangközvetítés", - "voice_broadcast_force_small_chunks": "Hangközvetítések 15 másodperces darabolásának kényszerítése", "wysiwyg_composer": "Szövegszerkesztő használata" }, "labs_mjolnir": { @@ -1528,7 +1515,6 @@ "mute_description": "Nem kap semmilyen értesítést" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s hangos közvetítést indított", "m.key.verification.request": "%(name)s ellenőrzést kér" }, "onboarding": { @@ -2077,7 +2063,6 @@ "error_unbanning": "A kitiltás visszavonása sikertelen", "events_default": "Üzenetek küldése", "invite": "Felhasználók meghívása", - "io.element.voice_broadcast_info": "Hangközvetítés", "kick": "Felhasználók eltávolítása", "m.call": "%(brand)s hívás indítása", "m.call.member": "Csatlakozás ebbe a hívásba: %(brand)s", @@ -2711,7 +2696,6 @@ "warning": "FIGYELEM: " }, "share": { - "link_title": "Hivatkozás a szobához", "permalink_message": "Hivatkozás a kijelölt üzenethez", "permalink_most_recent": "Hivatkozás a legfrissebb üzenethez", "title_message": "Szoba üzenetének megosztása", @@ -2800,13 +2784,6 @@ "upgraderoom": "Új verzióra fejleszti a szobát", "upgraderoom_permission_error": "A parancs használatához nincs meg a megfelelő jogosultsága.", "usage": "Használat", - "verify": "Felhasználó, munkamenet és nyilvános kulcs hármas ellenőrzése", - "verify_mismatch": "FIGYELEM: A KULCSELLENŐRZÉS SIKERTELEN! %(userId)s aláírási kulcsa és a(z) %(deviceId)s munkamenet ujjlenyomata „%(fprint)s”, amely nem egyezik meg a megadott ujjlenyomattal: „%(fingerprint)s”. Ez azt is jelentheti, hogy a kommunikációt lehallgatják.", - "verify_nop": "A munkamenet már ellenőrzött.", - "verify_nop_warning_mismatch": "FIGYELEM: a munkamenet már ellenőrizve van, de a kulcsok NEM EGYEZNEK.", - "verify_success_description": "A megadott aláírási kulcs megegyezik %(userId)s felhasználótól kapott aláírási kulccsal ebben a munkamenetben: %(deviceId)s. A munkamenet ellenőrzöttnek lett jelölve.", - "verify_success_title": "Ellenőrzött kulcs", - "verify_unknown_pair": "Ismeretlen (felhasználó, munkamenet) páros: (%(userId)s, %(deviceId)s)", "view": "Megadott címmel rendelkező szobák megjelenítése", "whois": "Információt jelenít meg a felhasználóról" }, @@ -3018,10 +2995,6 @@ "error_rendering_message": "Ezt az üzenetet nem sikerült betölteni", "historical_messages_unavailable": "Nem tekintheted meg a régebbi üzeneteket", "in_room_name": " itt: %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s befejezte a hangközvetítést", - "you": "Befejezte a hangközvetítést" - }, "io.element.widgets.layout": "%(senderName)s frissítette a szoba kinézetét", "load_error": { "no_permission": "Megpróbálta betölteni a szoba megadott időpontjának megfelelő adatait, de nincs joga a kérdéses üzenetek megjelenítéséhez.", @@ -3551,38 +3524,6 @@ "switch_theme_dark": "Sötét módra váltás", "switch_theme_light": "Világos módra váltás" }, - "voice_broadcast": { - "30s_backward": "vissza 30 másodperccel", - "30s_forward": "előre 30 másodperccel", - "action": "Hangközvetítés", - "buffering": "Pufferelés…", - "confirm_listen_affirm": "Igen, a felvétel befejezése", - "confirm_listen_description": "Ha hallgatja ezt az élő közvetítést, akkor a jelenlegi élő közvetítésének a felvétele befejeződik.", - "confirm_listen_title": "Élő közvetítés hallgatása?", - "confirm_stop_affirm": "Igen, közvetítés megállítása", - "confirm_stop_description": "Biztos, hogy befejezi az élő közvetítést? Ez megállítja a közvetítést és a felvétel az egész szoba számára elérhető lesz.", - "confirm_stop_title": "Megszakítja az élő közvetítést?", - "connection_error": "Kapcsolódási hiba – Felvétel szüneteltetve", - "failed_already_recording_description": "Egy hangközvetítés már folyamatban van. Először fejezze be a jelenlegi közvetítést egy új indításához.", - "failed_already_recording_title": "Az új hangközvetítés nem indítható el", - "failed_decrypt": "A hangközvetítést nem lehet visszafejteni", - "failed_generic": "A hangközvetítés nem játszható le", - "failed_insufficient_permission_description": "Nincs jogosultsága hangközvetítést indítani ebben a szobában. Vegye fel a kapcsolatot a szoba adminisztrátorával a szükséges jogosultság megszerzéséhez.", - "failed_insufficient_permission_title": "Az új hangközvetítés nem indítható el", - "failed_no_connection_description": "Sajnos most nem lehet elindítani a felvételt. Próbálja meg később.", - "failed_no_connection_title": "Kapcsolati hiba", - "failed_others_already_recording_description": "Valaki már elindított egy hangközvetítést. Várja meg a közvetítés végét az új indításához.", - "failed_others_already_recording_title": "Az új hangközvetítés nem indítható el", - "go_live": "Élő közvetítés indítása", - "live": "Élő közvetítés", - "pause": "hangközvetítés szüneteltetése", - "play": "hangközvetítés lejátszása", - "resume": "hangközvetítés folytatása" - }, - "voice_message": { - "cant_start_broadcast_description": "Nem lehet hang üzenetet indítani élő közvetítés felvétele közben. Az élő közvetítés bejezése szükséges a hang üzenet indításához.", - "cant_start_broadcast_title": "Hang üzenetet nem lehet elindítani" - }, "voip": { "already_in_call": "A hívás már folyamatban van", "already_in_call_person": "Már hívásban van ezzel a személlyel.", @@ -3602,7 +3543,6 @@ "camera_disabled": "A kamerája ki van kapcsolva", "camera_enabled": "A kamerája még mindig be van kapcsolva", "cannot_call_yourself_description": "Nem hívhatja fel saját magát.", - "change_input_device": "Bemeneti eszköz megváltoztatása", "connecting": "Kapcsolódás", "connection_lost": "Megszakadt a kapcsolat a kiszolgálóval", "connection_lost_description": "Nem kezdeményezhet hívást a kiszolgálóval való kapcsolat nélkül.", @@ -3619,8 +3559,6 @@ "enable_camera": "Kamera bekapcsolása", "enable_microphone": "Mikrofon némításának feloldása", "expand": "Visszatérés a híváshoz", - "failed_call_live_broadcast_description": "Nem lehet hívást kezdeményezni élő közvetítés felvétele közben. Az élő közvetítés bejezése szükséges a hívás indításához.", - "failed_call_live_broadcast_title": "Nem sikerült hívást indítani", "hangup": "Bontás", "hide_sidebar_button": "Oldalsáv elrejtése", "input_devices": "Beviteli eszközök", diff --git a/src/i18n/strings/id.json b/src/i18n/strings/id.json index 77cdd8a78ff..9eade90bc21 100644 --- a/src/i18n/strings/id.json +++ b/src/i18n/strings/id.json @@ -870,7 +870,6 @@ }, "udd": { "interactive_verification_button": "Verifikasi secara interaktif sengan emoji", - "manual_verification_button": "Verifikasi secara manual dengan teks", "other_ask_verify_text": "Tanyakan pengguna ini untuk memverifikasi sesinya, atau verifikasi secara manual di bawah.", "other_new_session_text": "%(name)s (%(userId)s) masuk ke sesi yang baru tanpa memverifikasinya:", "own_ask_verify_text": "Verifikasi sesi Anda lainnya dengan menggunakan salah satu pilihan di bawah.", @@ -905,12 +904,6 @@ "incoming_sas_dialog_waiting": "Menunggu pengguna untuk konfirmasi…", "incoming_sas_user_dialog_text_1": "Verifikasi pengguna ini untuk menandainya sebagai terpercaya. Mempercayai pengguna memberikan Anda ketenangan saat menggunakan pesan terenkripsi secara ujung ke ujung.", "incoming_sas_user_dialog_text_2": "Memverifikasi pengguna ini akan menandai sesinya sebagai terpercaya, dan juga menandai sesi Anda sebagai terpercaya kepadanya.", - "manual_device_verification_device_id_label": "ID Sesi", - "manual_device_verification_device_key_label": "Kunci sesi", - "manual_device_verification_device_name_label": "Nama sesi", - "manual_device_verification_footer": "Jika mereka tidak cocok, keamanan komunikasi Anda mungkin dikompromikan.", - "manual_device_verification_self_text": "Konfirmasi dengan membandingkan berikut ini dengan Pengaturan Pengguna di sesi Anda yang lain:", - "manual_device_verification_user_text": "Konfirmasi sesi pengguna ini dengan membandingkan berikut ini dengan Pengaturan Pengguna:", "no_key_or_device": "Sepertinya Anda tidak memiliki Kunci Keamanan atau perangkat lainnya yang Anda dapat gunakan untuk memverifikasi. Perangkat ini tidak dapat mengakses ke pesan terenkripsi lama. Untuk membuktikan identitas Anda, kunci verifikasi harus diatur ulang.", "no_support_qr_emoji": "Perangkat yang Anda sedang verifikasi tidak mendukung pemindaian kode QR atau verifikasi emoji, yang didukung oleh %(brand)s. Coba menggunakan klien yang lain.", "other_party_cancelled": "Pengguna yang lain membatalkan proses verifikasi ini.", @@ -1027,10 +1020,6 @@ }, "error_user_not_logged_in": "Pengguna belum masuk", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s mdngakhiri sebuah siaran suara", - "you": "Anda mengakhiri sebuah siaran suara" - }, "m.call.answer": { "dm": "Panggilan sedang berjalan", "user": "%(senderName)s bergabung dengan panggilan saat ini", @@ -1399,8 +1388,6 @@ "video_rooms_faq2_answer": "Ya, lini masa obrolan akan ditampilkan di sebelah videonya.", "video_rooms_faq2_question": "Bisakah saya mengobrol dengan teks saat ada panggilan video?", "video_rooms_feedbackSubheading": "Terima kasih telah mencoba fitur beta, mohon berikan masukan sedetail mungkin supaya kami dapat menyempurnakannya.", - "voice_broadcast": "Siaran suara", - "voice_broadcast_force_small_chunks": "Paksakan panjang bagian siaran suara 15d", "wysiwyg_composer": "Editor teks kaya" }, "labs_mjolnir": { @@ -1537,7 +1524,6 @@ "mute_description": "Anda tidak akan mendapatkan notifikasi apa pun" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s memulai sebuah siaran suara", "m.key.verification.request": "%(name)s meminta verifikasi" }, "onboarding": { @@ -2104,7 +2090,6 @@ "error_unbanning": "Gagal untuk menghapus cekalan", "events_default": "Kirim pesan", "invite": "Undang pengguna", - "io.element.voice_broadcast_info": "Siaran suara", "kick": "Keluarkan pengguna", "m.call": "Mulai panggilan %(brand)s", "m.call.member": "Bergabung panggilan %(brand)s", @@ -2743,7 +2728,6 @@ "warning": "PERINGATAN: " }, "share": { - "link_title": "Tautan ke ruangan", "permalink_message": "Tautan ke pesan yang dipilih", "permalink_most_recent": "Tautan ke pesan terkini", "title_message": "Bagikan Pesan Ruangan", @@ -2832,13 +2816,6 @@ "upgraderoom": "Meningkatkan ruangan ke versi yang baru", "upgraderoom_permission_error": "Anda tidak memiliki izin yang dibutuhkan untuk menggunakan perintah ini.", "usage": "Penggunaan", - "verify": "Memverifikasi sebuah pengguna, sesi, dan tupel pubkey", - "verify_mismatch": "PERINGATAN: VERIFIKASI KUNCI GAGAL! Kunci penandatanganan untuk %(userId)s dan sesi %(deviceId)s adalah \"%(fprint)s\" yang tidak cocok dengan kunci \"%(fingerprint)s\" yang disediakan. Ini bisa saja berarti komunikasi Anda sedang disadap!", - "verify_nop": "Sesi telah diverifikasi!", - "verify_nop_warning_mismatch": "PERINGATAN: sesi telah diverifikasi, tetapi kuncinya TIDAK COCOK!", - "verify_success_description": "Kunci penandatanganan yang Anda sediakan cocok dengan kunci penandatanganan yang Anda terima dari sesi %(userId)s %(deviceId)s. Sesi ditandai sebagai terverifikasi.", - "verify_success_title": "Kunci terverifikasi", - "verify_unknown_pair": "Pasangan tidak diketahui (pengguna, sesi): (%(userId)s, %(deviceId)s)", "view": "Menampilkan ruangan dengan alamat yang ditentukan", "whois": "Menampilkan informasi tentang sebuah pengguna" }, @@ -3051,10 +3028,6 @@ "error_rendering_message": "Tidak dapat memuat pesan ini", "historical_messages_unavailable": "Anda tidak dapat melihat pesan-pesan awal", "in_room_name": " di %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s mengakhiri sebuah siaran suara", - "you": "Anda mengakhiri sebuah siaran suara" - }, "io.element.widgets.layout": "%(senderName)s telah memperbarui tata letak ruangan", "load_error": { "no_permission": "Mencoba memuat titik spesifik di lini masa ruangan ini, tetapi Anda tidak memiliki izin untuk menampilkan pesannya.", @@ -3584,38 +3557,6 @@ "switch_theme_dark": "Ubah ke mode gelap", "switch_theme_light": "Ubah ke mode terang" }, - "voice_broadcast": { - "30s_backward": "30d sebelumnya", - "30s_forward": "30d selanjutnya", - "action": "Siaran suara", - "buffering": "Memuat…", - "confirm_listen_affirm": "Ya, hentikan rekaman saya", - "confirm_listen_description": "Jika Anda mendengarkan siaran langsung ini, rekaman siaran langsung Anda saat ini akan dihentikan.", - "confirm_listen_title": "Dengarkan siaran langsung?", - "confirm_stop_affirm": "Iya, hentikan siaran", - "confirm_stop_description": "Apakah Anda ingin menghentikan siaran langsung Anda? Ini akan mengakhiri siarannya, dan rekamanan lengkap akan tersedia dalam ruangan.", - "confirm_stop_title": "Hentikan siaran langsung?", - "connection_error": "Kesalahan koneksi - Perekaman dijeda", - "failed_already_recording_description": "Anda saat ini merekam sebuah siaran suara. Mohon akhiri siaran suara Anda saat ini untuk memulai yang baru.", - "failed_already_recording_title": "Tidak dapat memulai sebuah siaran suara baru", - "failed_decrypt": "Tidak dapat mendekripsi siaran suara", - "failed_generic": "Tidak dapat memutar siaran suara ini", - "failed_insufficient_permission_description": "Anda tidak memiliki izin untuk memulai sebuah siaran suara di ruangan ini. Hubungi sebuah administrator ruangan untuk meningkatkan izin Anda.", - "failed_insufficient_permission_title": "Tidak dapat memulai sebuah siaran suara baru", - "failed_no_connection_description": "Sayangnya kami saat ini tidak dapat memulai sebuah rekaman. Silakan mencoba lagi nanti.", - "failed_no_connection_title": "Terjadi kesalahan koneksi", - "failed_others_already_recording_description": "Ada orang lain yang saat ini merekam sebuah siaran suara. Tunggu siaran suaranya berakhir untuk memulai yang baru.", - "failed_others_already_recording_title": "Tidak dapat memulai sebuah siaran suara baru", - "go_live": "Mulai siaran langsung", - "live": "Langsung", - "pause": "jeda siaran suara", - "play": "mainkan siaran suara", - "resume": "lanjutkan siaran suara" - }, - "voice_message": { - "cant_start_broadcast_description": "Anda tidak dapat memulai sebuah pesan suara karena Anda saat ini merekam sebuah siaran langsung. Silakan mengakhiri siaran langsung Anda untuk memulai merekam sebuah pesan suara.", - "cant_start_broadcast_title": "Tidak dapat memulai pesan suara" - }, "voip": { "already_in_call": "Sudah ada di panggilan", "already_in_call_person": "Anda sudah ada di panggilan dengan orang itu.", @@ -3635,7 +3576,6 @@ "camera_disabled": "Kamera Anda dimatikan", "camera_enabled": "Kamera Anda masih nyala", "cannot_call_yourself_description": "Anda tidak dapat melakukan panggilan dengan diri sendiri.", - "change_input_device": "Ubah perangkat masukan", "connecting": "Menghubungkan", "connection_lost": "Koneksi ke server telah hilang", "connection_lost_description": "Anda tidak dapat membuat panggilan tanpa terhubung ke server.", @@ -3652,8 +3592,6 @@ "enable_camera": "Nyalakan kamera", "enable_microphone": "Suarakan mikrofon", "expand": "Kembali ke panggilan", - "failed_call_live_broadcast_description": "Anda tidak dapat memulai sebuah panggilan karena Anda saat ini merekam sebuah siaran langsung. Mohon akhiri siaran langsung Anda untuk memulai sebuah panggilan.", - "failed_call_live_broadcast_title": "Tidak dapat memulai panggilan", "hangup": "Akhiri", "hide_sidebar_button": "Sembunyikan sisi bilah", "input_devices": "Perangkat masukan", diff --git a/src/i18n/strings/is.json b/src/i18n/strings/is.json index c746caef1d2..21ff743f2db 100644 --- a/src/i18n/strings/is.json +++ b/src/i18n/strings/is.json @@ -737,7 +737,6 @@ }, "udd": { "interactive_verification_button": "Sannprófa gagnvirkt með táknmyndum", - "manual_verification_button": "Sannreyna handvirkt með texta", "other_ask_verify_text": "Biddu þennan notanda að sannreyna setuna sína, eða sannreyndu hana handvirkt hér fyrir neðan.", "other_new_session_text": "%(name)s (%(userId)s) skráði sig inn í nýja setu án þess að sannvotta hana:", "own_new_session_text": "Þú skráðir inn í nýja setu án þess að sannvotta hana:", @@ -764,11 +763,6 @@ "explainer": "Örugg skilaboð við þennan notanda eru enda-í-enda dulrituð þannig að enginn annar getur lesið þau.", "in_person": "Til öryggis, gerðu þetta í eigin persónu eða notaðu einhverja samskiptaleið sem þú treystir.", "incoming_sas_dialog_title": "Innkomin beiðni um sannvottun", - "manual_device_verification_device_id_label": "Auðkenni setu", - "manual_device_verification_device_key_label": "Dulritunarlykill setu", - "manual_device_verification_device_name_label": "Nafn á setu", - "manual_device_verification_footer": "Ef þetta samsvarar ekki, getur verið að samskiptin þín séu berskjölduð.", - "manual_device_verification_self_text": "Staðfestu með því að bera eftirfarandi saman við 'Stillingar notanda' í hinni setunni þinni:", "other_party_cancelled": "Hinn aðilinn hætti við sannvottunina.", "prompt_encrypted": "Sannreyndu alla notendur á spjallrás til að tryggja að hún sé örugg.", "prompt_self": "Hefja sannvottun aftur úr tilkynningunni.", @@ -862,10 +856,6 @@ } }, "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s endaði talútsendingu", - "you": "Þú endaðir talútsendingu" - }, "m.call.answer": { "dm": "Símtal í gangi", "user": "%(senderName)s kom inn í símtalið", @@ -1164,7 +1154,6 @@ "video_rooms_faq1_question": "Hvernig bý ég til myndspjallrás?", "video_rooms_faq2_answer": "Já, tímalína spjallsins birtist við hlið myndmerkisins.", "video_rooms_faq2_question": "Get ég notað textaspjall samhliða myndsímtali?", - "voice_broadcast": "Útvörpun tals", "wysiwyg_composer": "Þróaður textaritill" }, "labs_mjolnir": { @@ -1285,7 +1274,6 @@ "mute_description": "Þú munt ekki fá neinar tilkynningar" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s hóf talútsendingu", "m.key.verification.request": "%(name)s biður um sannvottun" }, "onboarding": { @@ -1730,7 +1718,6 @@ "error_unbanning": "Tókst ekki að taka úr banni", "events_default": "Senda skilaboð", "invite": "Bjóða notendum", - "io.element.voice_broadcast_info": "Útsendingar tals", "kick": "Fjarlægja notendur", "m.call": "Byrja %(brand)s samtal", "m.call.member": "Taka þátt í %(brand)s samtali", @@ -2240,7 +2227,6 @@ "warning": "AÐVÖRUN: " }, "share": { - "link_title": "Tengill á spjallrás", "permalink_message": "Tengill í valin skilaboð", "permalink_most_recent": "Tengill í nýjustu skilaboðin", "title_message": "Deila skilaboðum spjallrásar", @@ -2321,12 +2307,6 @@ "upgraderoom": "Uppfærir spjallrás í nýja útgáfu", "upgraderoom_permission_error": "Þú hefur ekki nauðsynlegar heimildir til að nota þessa skipun.", "usage": "Notkun", - "verify": "Sannreynir auðkenni notanda, setu og dreifilykils", - "verify_mismatch": "AÐVÖRUN: SANNVOTTUN LYKILS MISTÓKST! Undirritunarlykillinn fyrir %(userId)s og setuna %(deviceId)s er \"%(fprint)s\" sem samsvarar ekki uppgefna lyklinum \"%(fingerprint)s\". Þetta gæti þýtt að einhver hafi komist inn í samskiptin þín!", - "verify_nop": "Seta er þegar sannreynd!", - "verify_success_description": "Undirritunarlykillinn sem þú gafst upp samsvarar lyklinum sem þú fékkst frá %(userId)s og setunni %(deviceId)s. Setan er því merkt sem sannreynd.", - "verify_success_title": "Staðfestur dulritunarlykill", - "verify_unknown_pair": "Óþekkt pörun (notandi, seta): (%(userId)s, %(deviceId)s)", "whois": "Birtir upplýsingar um notanda" }, "space": { @@ -2523,10 +2503,6 @@ "error_rendering_message": "Gat ekki hlaðið inn þessum skilaboðum", "historical_messages_unavailable": "Þú getur ekki séð eldri skilaboð", "in_room_name": " í %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s endaði talútsendingu", - "you": "Þú endaðir talútsendingu" - }, "io.element.widgets.layout": "%(senderName)s hefur uppfært framsetningu spjallrásarinnar", "load_error": { "no_permission": "Reyndi að hlaða inn tilteknum punkti úr tímalínu þessarar spjallrásar, en þú ert ekki með heimild til að skoða tilteknu skilaboðin.", @@ -2998,27 +2974,6 @@ "switch_theme_dark": "Skiptu yfir í dökkan ham", "switch_theme_light": "Skiptu yfir í ljósan ham" }, - "voice_broadcast": { - "30s_backward": "30s afturábak", - "30s_forward": "30s áfram", - "action": "Útvörpun tals", - "buffering": "Hleð í biðminni…", - "confirm_listen_affirm": "Já, stöðva upptökuna mína", - "confirm_listen_title": "Hlusta á beina útsendingu?", - "confirm_stop_affirm": "Já, stöðva útsendingu", - "confirm_stop_title": "Stöðva beina útsendingu?", - "connection_error": "Villa í tengingu - Upptaka í bið", - "failed_already_recording_title": "Get ekki byrjað nýja talútsendingu", - "failed_insufficient_permission_title": "Get ekki byrjað nýja talútsendingu", - "failed_no_connection_description": "Því miður tókst ekki að setja aðra upptöku í gang. Reyndu aftur síðar.", - "failed_no_connection_title": "Villa í tengingu", - "failed_others_already_recording_title": "Get ekki byrjað nýja talútsendingu", - "go_live": "Fara í beina útsendingu", - "live": "Beint", - "pause": "setja talútsendingu í bið", - "play": "spila talútsendingu", - "resume": "halda áfram með talútsendingu" - }, "voip": { "already_in_call": "Nú þegar í símtali", "already_in_call_person": "Þú ert nú þegar í símtali við þennan aðila.", @@ -3038,7 +2993,6 @@ "camera_disabled": "Slökkt er á myndavélinni þinni", "camera_enabled": "Enn er kveikt á myndavélinni þinni", "cannot_call_yourself_description": "Þú getur ekki byrjað símtal með sjálfum þér.", - "change_input_device": "skipta um inntakstæki", "connecting": "Tengist", "connection_lost": "Tenging við vefþjón hefur rofnað", "connection_lost_description": "Þú getur ekki hringt símtöl án tengingar við netþjóninn.", @@ -3055,7 +3009,6 @@ "enable_camera": "Kveikja á myndavél", "enable_microphone": "Kveikja á hljóðnema", "expand": "Fara til baka í símtal", - "failed_call_live_broadcast_title": "Get ekki hafið símtal", "hangup": "Leggja á", "hide_sidebar_button": "Fela hliðarspjald", "input_devices": "Inntakstæki", diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index 9f0ab6d4304..1ddf88e8327 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -881,7 +881,6 @@ }, "udd": { "interactive_verification_button": "Verifica interattivamente con emoji", - "manual_verification_button": "Verifica manualmente con testo", "other_ask_verify_text": "Chiedi a questo utente di verificare la sua sessione o verificala manualmente sotto.", "other_new_session_text": "%(name)s (%(userId)s) ha fatto l'accesso con una nuova sessione senza verificarla:", "own_ask_verify_text": "Verifica la tua altra sessione usando una delle opzioni sotto.", @@ -916,12 +915,6 @@ "incoming_sas_dialog_waiting": "In attesa che il partner confermi…", "incoming_sas_user_dialog_text_1": "Verifica questo utente per contrassegnarlo come affidabile. La fiducia degli utenti offre una maggiore tranquillità quando si utilizzano messaggi cifrati end-to-end.", "incoming_sas_user_dialog_text_2": "La verifica di questo utente contrassegnerà come fidata la sua sessione a te e viceversa.", - "manual_device_verification_device_id_label": "ID sessione", - "manual_device_verification_device_key_label": "Chiave sessione", - "manual_device_verification_device_name_label": "Nome sessione", - "manual_device_verification_footer": "Se non corrispondono, la sicurezza delle tue comunicazioni potrebbe essere compromessa.", - "manual_device_verification_self_text": "Conferma confrontando il seguente con le impostazioni utente nell'altra sessione:", - "manual_device_verification_user_text": "Conferma questa sessione confrontando il seguente con le sue impostazioni utente:", "no_key_or_device": "Pare che tu non abbia una chiave di sicurezza o altri dispositivi con cui poterti verificare. Questo dispositivo non potrà accedere ai vecchi messaggi cifrati. Per potere verificare la tua ideintità su questo dispositivo, dovrai reimpostare le chiavi di verifica.", "no_support_qr_emoji": "Il dispositivo che stai cercando di verificare non supporta la scansione di un codice QR o la verifica emoji, che sono supportate da %(brand)s. Prova con un client diverso.", "other_party_cancelled": "L'altra parte ha annullato la verifica.", @@ -1045,10 +1038,6 @@ }, "error_user_not_logged_in": "Utente non connesso", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s ha terminato una trasmissione vocale", - "you": "Hai terminato una trasmissione vocale" - }, "m.call.answer": { "dm": "Chiamata in corso", "user": "%(senderName)s si è unito alla chiamata", @@ -1422,8 +1411,6 @@ "video_rooms_faq2_answer": "Sì, la cronologia della chat viene mostrata assieme al video.", "video_rooms_faq2_question": "Posso usare la chat testuale assieme alla chiamata video?", "video_rooms_feedbackSubheading": "Grazie per aver provato la beta, ti preghiamo di fornire tutti i dettagli possibili in modo da poterla migliorare.", - "voice_broadcast": "Trasmissione vocale", - "voice_broadcast_force_small_chunks": "Forza lunghezza pezzo trasmissione vocale a 15s", "wysiwyg_composer": "Editor in rich text" }, "labs_mjolnir": { @@ -1567,7 +1554,6 @@ "mute_description": "Non riceverai alcuna notifica" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s ha iniziato una trasmissione vocale", "m.key.verification.request": "%(name)s sta richiedendo la verifica" }, "onboarding": { @@ -2141,7 +2127,6 @@ "error_unbanning": "Rimozione ban fallita", "events_default": "Invia messaggi", "invite": "Invita utenti", - "io.element.voice_broadcast_info": "Trasmissioni vocali", "kick": "Rimuovi utenti", "m.call": "Inizia chiamate di %(brand)s", "m.call.member": "Entra in chiamate di %(brand)s", @@ -2784,7 +2769,6 @@ "warning": "ATTENZIONE: " }, "share": { - "link_title": "Collegamento alla stanza", "permalink_message": "Link al messaggio selezionato", "permalink_most_recent": "Link al messaggio più recente", "title_message": "Condividi messaggio stanza", @@ -2873,13 +2857,6 @@ "upgraderoom": "Aggiorna una stanza ad una nuova versione", "upgraderoom_permission_error": "Non hai l'autorizzazione necessaria per usare questo comando.", "usage": "Utilizzo", - "verify": "Verifica un utente, una sessione e una tupla pubblica", - "verify_mismatch": "ATTENZIONE: VERIFICA CHIAVI FALLITA! La chiave per %(userId)s e per la sessione %(deviceId)s è \"%(fprint)s\" la quale non corriponde con la chiave \"%(fingerprint)s\" fornita. Ciò può significare che le comunicazioni vengono intercettate!", - "verify_nop": "Sessione già verificata!", - "verify_nop_warning_mismatch": "ATTENZIONE: sessione già verificata, ma le chiavi NON CORRISPONDONO!", - "verify_success_description": "La chiave che hai fornito corrisponde alla chiave che hai ricevuto dalla sessione di %(userId)s %(deviceId)s. Sessione contrassegnata come verificata.", - "verify_success_title": "Chiave verificata", - "verify_unknown_pair": "Coppia (utente, sessione) sconosciuta: (%(userId)s, %(deviceId)s)", "view": "Visualizza la stanza con l'indirizzo dato", "whois": "Mostra le informazioni di un utente" }, @@ -3097,10 +3074,6 @@ "error_rendering_message": "Impossibile caricare questo messaggio", "historical_messages_unavailable": "Non puoi vedere i messaggi precedenti", "in_room_name": " in %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s ha terminato una trasmissione vocale", - "you": "Hai terminato una trasmissione vocale" - }, "io.element.widgets.layout": "%(senderName)s ha aggiornato la disposizione della stanza", "late_event_separator": "Inviato originariamente il %(dateTime)s", "load_error": { @@ -3633,38 +3606,6 @@ "switch_theme_dark": "Passa alla modalità scura", "switch_theme_light": "Passa alla modalità chiara" }, - "voice_broadcast": { - "30s_backward": "30s indietro", - "30s_forward": "30s avanti", - "action": "Trasmissione vocale", - "buffering": "Buffer…", - "confirm_listen_affirm": "Sì, termina la mia registrazione", - "confirm_listen_description": "Se inizi ad ascoltare questa trasmissione in diretta, l'attuale registrazione della tua trasmissione in diretta finirà.", - "confirm_listen_title": "Ascoltare la trasmissione in diretta?", - "confirm_stop_affirm": "Sì, ferma la trasmissione", - "confirm_stop_description": "Vuoi davvero fermare la tua trasmissione in diretta? Verrà terminata la trasmissione e la registrazione completa sarà disponibile nella stanza.", - "confirm_stop_title": "Fermare la trasmissione in diretta?", - "connection_error": "Errore di connessione - Registrazione in pausa", - "failed_already_recording_description": "Stai già registrando una trasmissione vocale. Termina quella in corso per iniziarne una nuova.", - "failed_already_recording_title": "Impossibile iniziare una nuova trasmissione vocale", - "failed_decrypt": "Impossibile decifrare la trasmissione vocale", - "failed_generic": "Impossibile avviare questa trasmissione vocale", - "failed_insufficient_permission_description": "Non hai l'autorizzazione necessaria per iniziare una trasmissione vocale in questa stanza. Contatta un amministratore della stanza per aggiornare le tue autorizzazioni.", - "failed_insufficient_permission_title": "Impossibile iniziare una nuova trasmissione vocale", - "failed_no_connection_description": "Sfortunatamente non riusciamo ad iniziare una registrazione al momento. Riprova più tardi.", - "failed_no_connection_title": "Errore di connessione", - "failed_others_already_recording_description": "Qualcun altro sta già registrando una trasmissione vocale. Aspetta che finisca prima di iniziarne una nuova.", - "failed_others_already_recording_title": "Impossibile iniziare una nuova trasmissione vocale", - "go_live": "Vai in diretta", - "live": "In diretta", - "pause": "sospendi trasmissione vocale", - "play": "avvia trasmissione vocale", - "resume": "riprendi trasmissione vocale" - }, - "voice_message": { - "cant_start_broadcast_description": "Non puoi iniziare un messaggio vocale perché stai registrando una trasmissione in diretta. Termina la trasmissione per potere iniziare un messaggio vocale.", - "cant_start_broadcast_title": "Impossibile iniziare il messaggio vocale" - }, "voip": { "already_in_call": "Già in una chiamata", "already_in_call_person": "Sei già in una chiamata con questa persona.", @@ -3684,7 +3625,6 @@ "camera_disabled": "La tua fotocamera è spenta", "camera_enabled": "La tua fotocamera è ancora attiva", "cannot_call_yourself_description": "Non puoi chiamare te stesso.", - "change_input_device": "Cambia dispositivo di input", "close_lobby": "Chiudi sala d'attesa", "connecting": "In connessione", "connection_lost": "La connessione al server è stata persa", @@ -3703,8 +3643,6 @@ "enable_camera": "Accendi la fotocamera", "enable_microphone": "Riaccendi il microfono", "expand": "Torna alla chiamata", - "failed_call_live_broadcast_description": "Non puoi avviare una chiamata perché stai registrando una trasmissione in diretta. Termina la trasmissione per potere iniziare una chiamata.", - "failed_call_live_broadcast_title": "Impossibile avviare una chiamata", "hangup": "Riaggancia", "hide_sidebar_button": "Nascondi barra laterale", "input_devices": "Dispositivi di input", diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index 963de355ac6..4ac7672e4c8 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -833,7 +833,6 @@ }, "udd": { "interactive_verification_button": "絵文字で認証", - "manual_verification_button": "テキストを使って手動で認証", "other_ask_verify_text": "このユーザーにセッションを認証するよう依頼するか、以下から手動で認証してください。", "other_new_session_text": "%(name)s(%(userId)s)は未認証のセッションにサインインしました:", "own_ask_verify_text": "以下のどれか一つを使って他のセッションを認証します。", @@ -868,12 +867,6 @@ "incoming_sas_dialog_waiting": "相手の承認を待機しています…", "incoming_sas_user_dialog_text_1": "このユーザーを認証すると、信頼済として表示します。ユーザーを信頼すると、より一層安心してエンドツーエンド暗号化を使用することができます。", "incoming_sas_user_dialog_text_2": "このユーザーを認証すると、相手のセッションと自分のセッションを信頼済として表示します。", - "manual_device_verification_device_id_label": "セッションID", - "manual_device_verification_device_key_label": "セッションキー", - "manual_device_verification_device_name_label": "セッション名", - "manual_device_verification_footer": "一致していない場合は、コミュニケーションのセキュリティーが損なわれている可能性があります。", - "manual_device_verification_self_text": "他のセッションのユーザー設定で、以下を比較して承認してください:", - "manual_device_verification_user_text": "ユーザー設定画面で以下を比較し、このユーザーのセッションを承認してください:", "no_key_or_device": "セキュリティーキーもしくは認証可能な端末が設定されていません。この端末では、以前暗号化されたメッセージにアクセスすることができません。この端末で本人確認を行うには、認証用の鍵を再設定する必要があります。", "no_support_qr_emoji": "認証しようとしている端末は、QRコードのスキャンや絵文字による認証をサポートしていませんが、%(brand)sではサポートされています。異なるクライアントで試してください。", "other_party_cancelled": "相手が認証をキャンセルしました。", @@ -983,10 +976,6 @@ } }, "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)sが音声配信を終了しました", - "you": "音声配信を終了しました" - }, "m.call.answer": { "dm": "通話しています", "user": "%(senderName)sが通話に参加しました", @@ -1318,8 +1307,6 @@ "video_rooms_faq1_question": "ビデオ通話ルームの作成方法", "video_rooms_faq2_answer": "はい、会話のタイムラインが動画と並んで表示されます。", "video_rooms_faq2_question": "テキストによる会話も行えますか?", - "voice_broadcast": "音声配信", - "voice_broadcast_force_small_chunks": "音声配信のチャンク長を15秒に強制", "wysiwyg_composer": "リッチテキストエディター" }, "labs_mjolnir": { @@ -1455,7 +1442,6 @@ "mute_description": "通知を送信しません" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)sが音声配信を開始しました", "m.key.verification.request": "%(name)sは認証を要求しています" }, "onboarding": { @@ -1953,7 +1939,6 @@ "error_unbanning": "ブロック解除に失敗しました", "events_default": "メッセージの送信", "invite": "ユーザーの招待", - "io.element.voice_broadcast_info": "音声配信", "kick": "ユーザーの追放", "m.call": "%(brand)s通話を開始", "m.call.member": "%(brand)s通話に参加", @@ -2532,7 +2517,6 @@ "warning": "警告:" }, "share": { - "link_title": "ルームへのリンク", "permalink_message": "選択したメッセージにリンク", "permalink_most_recent": "最新のメッセージにリンク", "title_message": "ルームのメッセージを共有", @@ -2614,13 +2598,6 @@ "upgraderoom": "ルームを新しいバージョンにアップグレード", "upgraderoom_permission_error": "このコマンドを実行するのに必要な権限がありません。", "usage": "用法", - "verify": "ユーザー、セッション、およびpubkeyタプルを認証", - "verify_mismatch": "警告:鍵の認証に失敗しました!提供された鍵「%(fingerprint)s」は、%(userId)sおよびセッション %(deviceId)s の署名鍵「%(fprint)s」と一致しません。通信が傍受されているおそれがあります!", - "verify_nop": "このセッションは認証済です!", - "verify_nop_warning_mismatch": "警告:このセッションは認証済ですが、鍵が一致しません!", - "verify_success_description": "指定された署名鍵は%(userId)sのセッション %(deviceId)s から受け取った鍵と一致します。セッションは認証済です。", - "verify_success_title": "認証済の鍵", - "verify_unknown_pair": "不明な(ユーザー、セッション)ペア:(%(userId)s、%(deviceId)s)", "whois": "ユーザーの情報を表示" }, "space": { @@ -2831,10 +2808,6 @@ "error_rendering_message": "このメッセージを読み込めません", "historical_messages_unavailable": "以前のメッセージは表示できません", "in_room_name": " %(room)s内で", - "io.element.voice_broadcast_info": { - "user": "%(senderName)sが音声配信を終了しました", - "you": "音声配信を終了しました" - }, "io.element.widgets.layout": "%(senderName)sがルームのレイアウトを更新しました", "load_error": { "no_permission": "このルームのタイムラインの特定の地点を読み込もうとしましたが、問題のメッセージを閲覧する権限がありません。", @@ -3345,38 +3318,6 @@ "switch_theme_dark": "ダークテーマに切り替える", "switch_theme_light": "ライトテーマに切り替える" }, - "voice_broadcast": { - "30s_backward": "30秒戻す", - "30s_forward": "30秒進める", - "action": "音声配信", - "buffering": "バッファリングしています…", - "confirm_listen_affirm": "はい、録音を終了してください", - "confirm_listen_description": "このライブ配信の視聴を開始すると、現在のライブ配信の録音は終了します。", - "confirm_listen_title": "ライブ配信を視聴しますか?", - "confirm_stop_affirm": "はい、配信を停止します", - "confirm_stop_description": "ライブ配信を終了してよろしいですか?配信を終了し、録音をこのルームで利用できるよう設定します。", - "confirm_stop_title": "ライブ配信を停止しますか?", - "connection_error": "接続エラー - 録音を停止しました", - "failed_already_recording_description": "既に音声配信を録音しています。新しく始めるには現在の音声配信を終了してください。", - "failed_already_recording_title": "新しい音声配信を開始できません", - "failed_decrypt": "音声配信を復号化できません", - "failed_generic": "この音声配信を再生できません", - "failed_insufficient_permission_description": "このルームで音声配信を開始する権限がありません。ルームの管理者に連絡して権限の付与を依頼してください。", - "failed_insufficient_permission_title": "新しい音声配信を開始できません", - "failed_no_connection_description": "録音を開始できません。後でもう一度やり直してください。", - "failed_no_connection_title": "接続エラー", - "failed_others_already_recording_description": "他の人が既に音声配信を録音しています。新しく始めるには音声配信が終わるまで待機してください。", - "failed_others_already_recording_title": "新しい音声配信を開始できません", - "go_live": "ライブ配信", - "live": "ライブ", - "pause": "音声配信を一時停止", - "play": "音声配信を再生", - "resume": "音声配信を再開" - }, - "voice_message": { - "cant_start_broadcast_description": "ライブ配信を録音しているため、音声メッセージを開始できません。音声メッセージの録音を開始するには、ライブ配信を終了してください。", - "cant_start_broadcast_title": "音声メッセージを開始できません" - }, "voip": { "already_in_call": "既に通話中です", "already_in_call_person": "既にこの人と通話中です。", @@ -3396,7 +3337,6 @@ "camera_disabled": "カメラが無効です", "camera_enabled": "カメラがまだ有効です", "cannot_call_yourself_description": "自分自身に通話を発信することはできません。", - "change_input_device": "入力端末を変更", "connecting": "接続しています", "connection_lost": "サーバーとの接続が失われました", "connection_lost_description": "サーバーに接続していないため、通話を発信できません。", @@ -3413,8 +3353,6 @@ "enable_camera": "カメラを有効にする", "enable_microphone": "マイクのミュートを解除", "expand": "通話に戻る", - "failed_call_live_broadcast_description": "ライブ配信を録音しているため、通話を開始できません。通話を開始するには、ライブ配信を終了してください。", - "failed_call_live_broadcast_title": "通話を開始できません", "hangup": "電話を切る", "hide_sidebar_button": "サイドバーを表示しない", "input_devices": "入力装置", diff --git a/src/i18n/strings/lo.json b/src/i18n/strings/lo.json index 6310faf2005..ddbe3d17f83 100644 --- a/src/i18n/strings/lo.json +++ b/src/i18n/strings/lo.json @@ -769,12 +769,6 @@ "incoming_sas_dialog_title": "ການຮ້ອງຂໍການຢັ້ງຢືນຂາເຂົ້າ", "incoming_sas_user_dialog_text_1": "ຢັ້ງຢືນຜູ້ໃຊ້ນີ້ເພື່ອສ້າງເຄື່ອງທີ່ເຊື່ອຖືໄດ້. ຜູ້ໃຊ້ທີ່ເຊື່ອຖືໄດ້ ເຮັດໃຫ້ທ່ານອຸ່ນໃຈຂື້ນເມື່ຶຶອເຂົ້າລະຫັດຂໍ້ຄວາມແຕ່ຕົ້ນທາງເຖິງປາຍທາງ.", "incoming_sas_user_dialog_text_2": "ການຢືນຢັນຜູ້ໃຊ້ນີ້ຈະເປັນເຄື່ອງໝາຍໃນລະບົບຂອງເຂົາເຈົ້າໜ້າເຊື່ອຖືໄດ້ ແລະ ເປັນເຄື່ອງໝາຍເຖິງລະບົບຂອງທ່ານ ເປັນທີ່ເຊື່ອຖືໄດ້ຕໍ່ກັບເຂົາເຈົ້າ.", - "manual_device_verification_device_id_label": "ID ລະບົບ", - "manual_device_verification_device_key_label": "ລະຫັດລະບົບ", - "manual_device_verification_device_name_label": "ຊື່ລະບົບ", - "manual_device_verification_footer": "ຖ້າລະຫັດບໍ່ກົງກັນ, ຄວາມປອດໄພຂອງການສື່ສານຂອງທ່ານອາດຈະຖືກທໍາລາຍ.", - "manual_device_verification_self_text": "ຢືນຢັນໂດຍການປຽບທຽບສິ່ງຕໍ່ໄປນີ້ກັບການຕັ້ງຄ່າຜູ້ໃຊ້ໃນລະບົບອື່ນຂອງທ່ານ:", - "manual_device_verification_user_text": "ຢືນຢັນລະບົບຂອງຜູ້ໃຊ້ນີ້ໂດຍການປຽບທຽບສິ່ງຕໍ່ໄປນີ້ກັບການຕັ້ງຄ່າຜູ້ໃຊ້ຂອງເຂົາເຈົ້າ:", "no_key_or_device": "ເບິ່ງຄືວ່າທ່ານບໍ່ມີກະແຈຄວາມປອດໄພ ຫຼື ອຸປະກອນອື່ນໆທີ່ທ່ານສາມາດຢືນຢັນໄດ້. ອຸປະກອນນີ້ຈະບໍ່ສາມາດເຂົ້າເຖິງຂໍ້ຄວາມທີ່ເຂົ້າລະຫັດເກົ່າໄດ້. ເພື່ອຢືນຢັນຕົວຕົນຂອງທ່ານໃນອຸປະກອນນີ້, ທ່ານຈຳເປັນຕ້ອງຕັ້ງລະຫັດຢືນຢັນຂອງທ່ານ.", "no_support_qr_emoji": "ອຸປະກອນທີ່ທ່ານພະຍາຍາມກວດສອບບໍ່ຮອງຮັບການສະແກນລະຫັດ QR ຫຼື ການຢັ້ງຢືນ emoji, ຊຶ່ງເປັນສິ່ງທີ່%(brand)sສະຫນັບສະຫນູນ. ລອງໃຊ້ກັບລູກຄ້າອື່ນ.", "other_party_cancelled": "ອີກຝ່າຍໄດ້ຍົກເລີກການຢັ້ງຢືນ.", @@ -2191,7 +2185,6 @@ "warn_quit": "ເຕືອນກ່ອນຢຸດຕິ" }, "share": { - "link_title": "ເຊື່ອມຕໍ່ທີ່ຫ້ອງ", "permalink_message": "ເຊື່ອມຕໍ່ກັບຂໍ້ຄວາມທີ່ເລືອກ", "permalink_most_recent": "ເຊື່ອມຕໍ່ກັບຂໍ້ຄວາມຫຼ້າສຸດ", "title_message": "ແບ່ງປັນຂໍ້ຄວາມໃນຫ້ອງ", @@ -2273,12 +2266,6 @@ "upgraderoom": "ຍົກລະດັບຫ້ອງເປັນລຸ້ນໃໝ່", "upgraderoom_permission_error": "ທ່ານບໍ່ມີສິດໃຊ້ຄໍາສັ່ງນີ້.", "usage": "ການນໍາໃຊ້", - "verify": "ຢືນຢັນຜູ້ໃຊ້, ລະບົບ, ແລະ pubkey tuple", - "verify_mismatch": "ຄຳເຕືອນ: ການຢືນຢັນບໍ່ສຳເລັັດ! ປຸ່ມເຊັນຊື່ສຳລັບ %(userId)s ແລະ ລະບົບ %(deviceId)s ແມ່ນ \"%(fprint)s\" ບໍ່ກົງກັບລະຫັດທີ່ລະບຸໄວ້ \"%(fingerprint)s\". ນີ້ອາດຈະຫມາຍຄວາມວ່າການສື່ສານຂອງທ່ານຖືກຂັດຂວາງ!", - "verify_nop": "ການຢັ້ງຢືນລະບົບແລ້ວ!", - "verify_success_description": "ກະແຈໄຂລະຫັດທີ່ທ່ານໃຊ້ກົງກັບກະແຈໄຂລະຫັດທີ່ທ່ານໄດ້ຮັບຈາກ %(userId)s ເທິງອຸປະກອນ %(deviceId)s. ລະບົບຢັ້ງຢືນສຳເລັດແລ້ວ.", - "verify_success_title": "ກະແຈທີ່ຢືນຢັນແລ້ວ", - "verify_unknown_pair": "ບໍ່ຮູ້ຈັກ (ຜູ້ໃຊ້, ລະບົບ) ຄູ່: (%(userId)s, %(deviceId)s)", "whois": "ສະແດງຂໍ້ມູນກ່ຽວກັບຜູ້ໃຊ້" }, "space": { diff --git a/src/i18n/strings/lt.json b/src/i18n/strings/lt.json index 8f503bacdd8..1e0679bae48 100644 --- a/src/i18n/strings/lt.json +++ b/src/i18n/strings/lt.json @@ -597,12 +597,6 @@ "incoming_sas_dialog_title": "Įeinantis Patikrinimo Prašymas", "incoming_sas_user_dialog_text_1": "Patvirtinkite šį vartotoją, kad pažymėtumėte jį kaip patikimą. Vartotojų pažymėjimas patikimais suteikia jums papildomos ramybės naudojant visapusiškai užšifruotas žinutes.", "incoming_sas_user_dialog_text_2": "Patvirtinant šį vartotoją, jo seansas bus pažymėtas kaip patikimas, taip pat jūsų seansas bus pažymėtas kaip patikimas jam.", - "manual_device_verification_device_id_label": "Seanso ID", - "manual_device_verification_device_key_label": "Seanso raktas", - "manual_device_verification_device_name_label": "Seanso pavadinimas", - "manual_device_verification_footer": "Jei jie nesutampa, gali būti pažeistas jūsų komunikacijos saugumas.", - "manual_device_verification_self_text": "Patvirtinkite, palygindami tai, kas nurodyta toliau, su Vartotojo Nustatymais kitame jūsų seanse:", - "manual_device_verification_user_text": "Patvirtinkite šio vartotojo seansą, palygindami tai, kas nurodyta toliau, su jo Vartotojo Nustatymais:", "no_support_qr_emoji": "Įrenginys, kurį bandote patvirtinti, nepalaiko QR kodo nuskaitymo arba jaustukų patikrinimo, kurį palaiko %(brand)s. Pabandykite naudoti kitą klientą.", "other_party_cancelled": "Kita šalis atšaukė patvirtinimą.", "prompt_encrypted": "Patvirtinkite visus vartotojus kambaryje, kad užtikrintumėte jo saugumą.", @@ -886,8 +880,7 @@ "video_rooms_faq1_answer": "Kairiajame skydelyje esančioje kambarių skiltyje naudokite mygtuką “+”.", "video_rooms_faq1_question": "Kaip galiu sukurti vaizdo kambarį?", "video_rooms_faq2_answer": "Taip, pokalbių laiko juosta rodoma kartu su vaizdu.", - "video_rooms_faq2_question": "Ar galiu naudoti teksto pokalbius kartu su vaizdo skambučiu?", - "voice_broadcast": "Balso transliacija" + "video_rooms_faq2_question": "Ar galiu naudoti teksto pokalbius kartu su vaizdo skambučiu?" }, "labs_mjolnir": { "advanced_warning": "⚠ Šie nustatymai yra skirti pažengusiems vartotojams.", @@ -1859,11 +1852,6 @@ "upgraderoom": "Atnaujina kambarį į naują versiją", "upgraderoom_permission_error": "Jūs neturite reikalingų leidimų naudoti šią komandą.", "usage": "Naudojimas", - "verify": "Patvirtina vartotojo, seanso ir pubkey daugiadalę duomenų struktūrą", - "verify_mismatch": "ĮSPĖJIMAS: RAKTŲ PATIKRINIMAS NEPAVYKO! Pasirašymo raktas vartotojui %(userId)s ir seansui %(deviceId)s yra \"%(fprint)s\", kuris nesutampa su pateiktu raktu \"%(fingerprint)s\". Tai gali reikšti, kad jūsų komunikacijos yra perimamos!", - "verify_nop": "Seansas jau patvirtintas!", - "verify_success_description": "Jūsų pateiktas pasirašymo raktas sutampa su pasirašymo raktu, gautu iš vartotojo %(userId)s seanso %(deviceId)s. Seansas pažymėtas kaip patikrintas.", - "verify_success_title": "Patvirtintas raktas", "whois": "Parodo informaciją apie vartotoją" }, "space": { @@ -2385,15 +2373,6 @@ "user_menu": { "settings": "Visi nustatymai" }, - "voice_broadcast": { - "action": "Balso transliacija", - "confirm_stop_affirm": "Taip, sustabdyti transliaciją", - "confirm_stop_title": "Sustabdyti transliaciją gyvai?", - "live": "Gyvai", - "pause": "pristabdyti balso transliaciją", - "play": "paleisti balso transliaciją", - "resume": "tęsti balso transliaciją" - }, "voip": { "already_in_call": "Jau pokalbyje", "already_in_call_person": "Jūs jau esate pokalbyje su šiuo asmeniu.", diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index 1231a9a3303..ebc2f396232 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -774,7 +774,6 @@ }, "udd": { "interactive_verification_button": "Interactief verifiëren door emoji", - "manual_verification_button": "Handmatig verifiëren via tekst", "other_ask_verify_text": "Vraag deze persoon de sessie te verifiëren, of verifieer het handmatig hieronder.", "other_new_session_text": "%(name)s%(userId)s heeft zich aangemeld bij een nieuwe sessie zonder deze te verifiëren:", "own_ask_verify_text": "Verifieer je andere sessie op een van onderstaande wijzen.", @@ -806,12 +805,6 @@ "incoming_sas_dialog_title": "Inkomend verificatieverzoek", "incoming_sas_user_dialog_text_1": "Verifieer deze persoon om als vertrouwd te markeren. Personen vertrouwen geeft je extra zekerheid bij het gebruik van eind-tot-eind-versleutelde berichten.", "incoming_sas_user_dialog_text_2": "Deze persoon verifiëren zal de sessie als vertrouwd markeren voor jullie beide.", - "manual_device_verification_device_id_label": "Sessie-ID", - "manual_device_verification_device_key_label": "Sessiesleutel", - "manual_device_verification_device_name_label": "Sessienaam", - "manual_device_verification_footer": "Als deze niet overeenkomen, dan wordt deze sessie mogelijk door iemand anders onderschept.", - "manual_device_verification_self_text": "Bevestig door het volgende te vergelijken met de persoonsinstellingen in je andere sessie:", - "manual_device_verification_user_text": "Bevestig de sessie van deze persoon door het volgende te vergelijken met zijn persoonsinstellingen:", "no_key_or_device": "Het lijkt erop dat je geen veiligheidssleutel hebt of andere apparaten waarmee je kunt verifiëren. Dit apparaat heeft geen toegang tot oude versleutelde berichten. Om je identiteit op dit apparaat te verifiëren, moet je jouw verificatiesleutels opnieuw instellen.", "no_support_qr_emoji": "Het apparaat dat je probeert te verifiëren ondersteund niet de door %(brand)s ondersteunde methodes: scannen van een QR-code of emoji verificatie. Probeer het met een andere app.", "other_party_cancelled": "De tegenpartij heeft de verificatie geannuleerd.", @@ -1214,8 +1207,7 @@ "video_rooms_faq1_answer": "Gebruik de knop \"+\" in het kamergedeelte van het linkerpaneel.", "video_rooms_faq1_question": "Hoe kan ik een videokamer maken?", "video_rooms_faq2_answer": "Ja, de gesprekstijdslijn wordt naast de video weergegeven.", - "video_rooms_faq2_question": "Kan ik tekstberichten gebruiken naast het videogesprek?", - "voice_broadcast": "Spraakuitzending" + "video_rooms_faq2_question": "Kan ik tekstberichten gebruiken naast het videogesprek?" }, "labs_mjolnir": { "advanced_warning": "⚠ Deze instellingen zijn bedoeld voor gevorderde personen.", @@ -1824,7 +1816,6 @@ "error_unbanning": "Ontbannen mislukt", "events_default": "Berichten versturen", "invite": "Personen uitnodigen", - "io.element.voice_broadcast_info": "Spraakuitzendingen", "kick": "Personen verwijderen", "m.call": "%(brand)s oproepen starten", "m.call.member": "Deelnemen aan %(brand)s gesprekken", @@ -2363,7 +2354,6 @@ "warn_quit": "Waarschuwen voordat je afsluit" }, "share": { - "link_title": "Link naar kamer", "permalink_message": "Koppeling naar geselecteerd bericht", "permalink_most_recent": "Koppeling naar meest recente bericht", "title_message": "Bericht uit kamer delen", @@ -2445,12 +2435,6 @@ "upgraderoom": "Upgrade deze kamer naar een nieuwere versie", "upgraderoom_permission_error": "Je beschikt niet over de vereiste machtigingen om deze opdracht uit te voeren.", "usage": "Gebruik", - "verify": "Verifieert de combinatie van persoon, sessie en publieke sleutel", - "verify_mismatch": "PAS OP: sleutelverificatie MISLUKT! De combinatie %(userId)s + sessie %(deviceId)s is ondertekend met ‘%(fprint)s’ - maar de opgegeven sleutel is ‘%(fingerprint)s’. Wellicht worden jouw berichten onderschept!", - "verify_nop": "Sessie al geverifieerd!", - "verify_success_description": "De door jou verschafte sleutel en de van %(userId)ss sessie %(deviceId)s verkregen sleutels komen overeen. De sessie is daarmee geverifieerd.", - "verify_success_title": "Geverifieerde sleutel", - "verify_unknown_pair": "Onbekend paar (persoon, sessie): (%(userId)s, %(deviceId)s)", "whois": "Geeft informatie weer over een persoon" }, "space": { @@ -3155,20 +3139,6 @@ "switch_theme_dark": "Naar donkere modus wisselen", "switch_theme_light": "Naar lichte modus wisselen" }, - "voice_broadcast": { - "action": "Spraakuitzending", - "confirm_stop_affirm": "Ja, stop uitzending", - "confirm_stop_title": "Live uitzending stoppen?", - "failed_already_recording_description": "U neemt al een spraakuitzending op. Beëindig uw huidige spraakuitzending om een nieuwe te starten.", - "failed_already_recording_title": "Kan geen nieuwe spraakuitzending starten", - "failed_insufficient_permission_description": "U heeft niet de vereiste rechten om een spraakuitzending in deze kamer te starten. Neem contact op met een kamer beheerder om uw machtiging aan te passen.", - "failed_insufficient_permission_title": "Kan geen nieuwe spraakuitzending starten", - "failed_others_already_recording_description": "Iemand anders neemt al een spraakuitzending op. Wacht tot de spraakuitzending is afgelopen om een nieuwe te starten.", - "failed_others_already_recording_title": "Kan geen nieuwe spraakuitzending starten", - "pause": "spraakuitzending pauzeren", - "play": "spraakuitzending afspelen", - "resume": "hervat spraakuitzending" - }, "voip": { "already_in_call": "Al in de oproep", "already_in_call_person": "Je bent al in gesprek met deze persoon.", diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json index e148c873f12..3d5833446c1 100644 --- a/src/i18n/strings/pl.json +++ b/src/i18n/strings/pl.json @@ -923,7 +923,6 @@ }, "udd": { "interactive_verification_button": "Zweryfikuj interaktywnie za pomocą emoji", - "manual_verification_button": "Zweryfikuj ręcznie za pomocą tekstu", "other_ask_verify_text": "Poproś go/ją o zweryfikowanie tej sesji bądź zweryfikuj ją osobiście poniżej.", "other_new_session_text": "%(name)s%(userId)s zalogował się do nowej sesji bez zweryfikowania jej:", "own_ask_verify_text": "Zweryfikuj swoje pozostałe sesje używając jednej z opcji poniżej.", @@ -958,12 +957,6 @@ "incoming_sas_dialog_waiting": "Oczekiwanie na potwierdzenie partnera…", "incoming_sas_user_dialog_text_1": "Zweryfikuj tego użytkownika, aby oznaczyć go jako zaufanego. Użytkownicy zaufani dodają większej pewności, gdy korzystasz z wiadomości szyfrowanych end-to-end.", "incoming_sas_user_dialog_text_2": "Weryfikacja tego użytkownika oznaczy Twoją i jego sesję jako zaufaną.", - "manual_device_verification_device_id_label": "Identyfikator sesji", - "manual_device_verification_device_key_label": "Klucz sesji", - "manual_device_verification_device_name_label": "Nazwa sesji", - "manual_device_verification_footer": "Jeśli nie pasują, bezpieczeństwo twojego konta mogło zostać zdradzone.", - "manual_device_verification_self_text": "Potwierdź porównując następujące elementy w ustawieniach użytkownika w drugiej sesji:", - "manual_device_verification_user_text": "Potwierdź sesję tego użytkownika, porównując następujące elementy w jego ustawieniach użytkownika:", "no_key_or_device": "Wygląda na to, że nie masz klucza bezpieczeństwa ani żadnych innych urządzeń, które mogą weryfikować Twoją tożsamość. To urządzenie nie będzie mogło uzyskać dostępu do wcześniejszych zaszyfrowanych wiadomości. Aby zweryfikować swoją tożsamość na tym urządzeniu, należy zresetować klucze weryfikacyjne.", "no_support_qr_emoji": "Urządzenie, które próbujesz zweryfikować nie wspiera skanowania kodu QR lub weryfikacji emoji, czyli tego co obsługuje %(brand)s. Spróbuj użyć innego klienta.", "other_party_cancelled": "Druga strona anulowała weryfikację.", @@ -1088,10 +1081,6 @@ }, "error_user_not_logged_in": "Użytkownik nie jest zalogowany", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s zakończył transmisję głosową", - "you": "Zakończyłeś transmisje na żywo" - }, "m.call.answer": { "dm": "Połączenie w trakcie", "user": "%(senderName)s dołączył do połączenia", @@ -1490,8 +1479,6 @@ "video_rooms_faq2_answer": "Tak, oś czasu czatu jest wyświetlana wraz z wideo.", "video_rooms_faq2_question": "Czy mogę używać kanału tekstowego jednocześnie rozmawiając na kanale wideo?", "video_rooms_feedbackSubheading": "Dziękujemy za wypróbowanie wersji beta, opisz wnikliwie swoje doświadczenia i pomóż nam ulepszyć nasz produkt.", - "voice_broadcast": "Transmisja głosowa", - "voice_broadcast_force_small_chunks": "Wymuś 15s długość kawałków dla transmisji głosowej", "wysiwyg_composer": "Bogaty edytor tekstu" }, "labs_mjolnir": { @@ -1637,7 +1624,6 @@ "mute_description": "Nie otrzymasz żadnych powiadomień" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s rozpoczął transmisję głosową", "m.key.verification.request": "%(name)s prosi o weryfikację" }, "onboarding": { @@ -2255,7 +2241,6 @@ "error_unbanning": "Nie udało się odbanować", "events_default": "Wysyłanie wiadomości", "invite": "Zapraszanie użytkowników", - "io.element.voice_broadcast_info": "Transmisje głosowe", "kick": "Usuń użytkowników", "m.call": "Rozpocznij połączenie %(brand)s", "m.call.member": "Dołącz do połączeń %(brand)s", @@ -2954,7 +2939,6 @@ "warning": "OSTRZEŻENIE: " }, "share": { - "link_title": "Link do pokoju", "permalink_message": "Link do zaznaczonej wiadomości", "permalink_most_recent": "Link do najnowszej wiadomości", "share_call": "Link zaproszenia do konferencji", @@ -3046,13 +3030,6 @@ "upgraderoom": "Ulepsza pokój do nowej wersji", "upgraderoom_permission_error": "Nie posiadasz wymaganych uprawnień do użycia tego polecenia.", "usage": "Użycie", - "verify": "Weryfikuje użytkownika, sesję oraz klucz publiczny", - "verify_mismatch": "OSTRZEŻENIE: WERYFIKACJA KLUCZY NIE POWIODŁA SIĘ! Klucz podpisujący dla %(userId)s oraz sesji %(deviceId)s to \"%(fprint)s\", nie pasuje on do podanego klucza \"%(fingerprint)s\". To może oznaczać że Twoja komunikacja jest przechwytywana!", - "verify_nop": "Sesja już zweryfikowana!", - "verify_nop_warning_mismatch": "OSTRZEŻENIE: sesja została już zweryfikowana, ale klucze NIE PASUJĄ!", - "verify_success_description": "Klucz podpisujący, który podano jest taki sam jak klucz podpisujący otrzymany od %(userId)s oraz sesji %(deviceId)s. Sesja została oznaczona jako zweryfikowana.", - "verify_success_title": "Zweryfikowany klucz", - "verify_unknown_pair": "Nieznana para (użytkownik, sesja): (%(userId)s, %(deviceId)s)", "view": "Przegląda pokój z podanym adresem", "whois": "Pokazuje informacje na temat użytkownika" }, @@ -3289,10 +3266,6 @@ "error_rendering_message": "Nie można wczytać tej wiadomości", "historical_messages_unavailable": "Nie możesz widzieć poprzednich wiadomości", "in_room_name": " w %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s zakończył transmisję głosową", - "you": "Zakończyłeś transmisje głosową" - }, "io.element.widgets.layout": "%(senderName)s zmienił układ pokoju", "late_event_separator": "Pierwotnie wysłano %(dateTime)s", "load_error": { @@ -3842,38 +3815,6 @@ "switch_theme_dark": "Przełącz na tryb ciemny", "switch_theme_light": "Przełącz na tryb jasny" }, - "voice_broadcast": { - "30s_backward": "30s do tyłu", - "30s_forward": "30s do przodu", - "action": "Transmisja głosowa", - "buffering": "Buforowanie…", - "confirm_listen_affirm": "Tak, zakończ moje nagranie", - "confirm_listen_description": "Jeśli zaczniesz słuchać tej transmisji na żywo, twoja bieżąca transmisja na żywo zostanie zakończona.", - "confirm_listen_title": "Zacząć słuchać transmisji na żywo?", - "confirm_stop_affirm": "Tak, zakończ transmisję", - "confirm_stop_description": "Czy na pewno chcesz zakończyć transmisję na żywo? Transmisja zostanie zakończona, a całe nagranie będzie dostępne w pokoju.", - "confirm_stop_title": "Zakończyć transmisję na żywo?", - "connection_error": "Błąd połączenia - Nagrywanie wstrzymane", - "failed_already_recording_description": "Już nagrywasz transmisję głosową. Zakończ bieżącą transmisję głosową, aby rozpocząć nową.", - "failed_already_recording_title": "Nie można rozpocząć nowej transmisji głosowej", - "failed_decrypt": "Nie można rozszyfrować transmisji głosowej", - "failed_generic": "Nie można odtworzyć tej transmisji głosowej", - "failed_insufficient_permission_description": "Nie posiadasz wymaganych uprawnień, aby rozpocząć transmisję głosową w tym pokoju. Skontaktuj się z administratorem pokoju, aby zwiększyć swoje uprawnienia.", - "failed_insufficient_permission_title": "Nie można rozpocząć nowej transmisji głosowej", - "failed_no_connection_description": "Niestety, nie jesteśmy w stanie rozpocząć nowego nagrania. Spróbuj ponownie później.", - "failed_no_connection_title": "Błąd połączenia", - "failed_others_already_recording_description": "Ktoś już nagrywa transmisję głosową. Aby rozpocząć nową, poczekaj aż bieżąca się skończy.", - "failed_others_already_recording_title": "Nie można rozpocząć nowej transmisji głosowej", - "go_live": "Rozpocznij transmisję", - "live": "Na żywo", - "pause": "wstrzymaj transmisję głosową", - "play": "odtwórz transmisję głosową", - "resume": "wznów transmisję głosową" - }, - "voice_message": { - "cant_start_broadcast_description": "Nie możesz rozpocząć wiadomości głosowej, ponieważ już nagrywasz transmisję na żywo. Zakończ transmisję na żywo, aby rozpocząć nagrywanie wiadomości głosowej.", - "cant_start_broadcast_title": "Nie można rozpocząć wiadomości głosowej" - }, "voip": { "already_in_call": "Już dzwoni", "already_in_call_person": "Prowadzisz już rozmowę z tą osobą.", @@ -3893,7 +3834,6 @@ "camera_disabled": "Twoja kamera jest wyłączona", "camera_enabled": "Twoja kamera jest nadal włączona", "cannot_call_yourself_description": "Nie możesz wykonać połączenia do siebie.", - "change_input_device": "Zmień urządzenie wejściowe", "close_lobby": "Zamknij poczekalnię", "connecting": "Łączenie", "connection_lost": "Połączenie z serwerem zostało przerwane", @@ -3912,8 +3852,6 @@ "enable_camera": "Włącz kamerę", "enable_microphone": "Wyłącz wyciszenie mikrofonu", "expand": "Wróć do połączenia", - "failed_call_live_broadcast_description": "Nie możesz rozpocząć połączenia, ponieważ już nagrywasz transmisję na żywo. Zakończ transmisję na żywo, aby rozpocząć połączenie.", - "failed_call_live_broadcast_title": "Nie można rozpocząć połączenia", "get_call_link": "Udostępnij link do połączenia", "hangup": "Rozłącz", "hide_sidebar_button": "Ukryj pasek boczny", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 6789fb4ee66..7813d6146c0 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -674,12 +674,6 @@ "incoming_sas_dialog_title": "Recebendo solicitação de confirmação", "incoming_sas_user_dialog_text_1": "Confirme este usuário para torná-lo confiável. Confiar nos usuários fornece segurança adicional ao trocar mensagens criptografadas de ponta a ponta.", "incoming_sas_user_dialog_text_2": "Se você confirmar esse usuário, a sessão será marcada como confiável para você e para ele.", - "manual_device_verification_device_id_label": "Identificador de sessão", - "manual_device_verification_device_key_label": "Chave da sessão", - "manual_device_verification_device_name_label": "Nome da sessão", - "manual_device_verification_footer": "Se eles não corresponderem, a segurança da sua comunicação pode estar comprometida.", - "manual_device_verification_self_text": "Para confirmar, compare a seguinte informação com aquela apresentada em sua outra sessão:", - "manual_device_verification_user_text": "Confirme a sessão deste usuário comparando o seguinte com as configurações deste usuário:", "other_party_cancelled": "Seu contato cancelou a confirmação.", "prompt_encrypted": "Verifique todos os usuários em uma sala para se certificar de que ela está segura.", "prompt_self": "Iniciar a confirmação novamente, após a notificação.", @@ -765,10 +759,6 @@ } }, "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s encerrou uma transmissão de voz", - "you": "Você encerrou uma transmissão de voz" - }, "m.call.answer": { "dm": "Chamada em andamento", "user": "%(senderName)s entrou na chamada", @@ -1082,7 +1072,6 @@ "mute_description": "Você não receberá nenhuma notificação" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s iniciou uma transmissão de voz", "m.key.verification.request": "%(name)s está solicitando confirmação" }, "onboarding": { @@ -1970,12 +1959,6 @@ "upgraderoom": "Atualiza a sala para uma nova versão", "upgraderoom_permission_error": "Você não tem as permissões necessárias para usar este comando.", "usage": "Uso", - "verify": "Confirma um usuário, sessão, e chave criptografada pública", - "verify_mismatch": "ATENÇÃO: A CONFIRMAÇÃO DA CHAVE FALHOU! A chave de assinatura para %(userId)s e sessão %(deviceId)s é \"%(fprint)s\", o que não corresponde à chave fornecida \"%(fingerprint)s\". Isso pode significar que suas comunicações estejam sendo interceptadas por terceiros!", - "verify_nop": "Sessão já confirmada!", - "verify_success_description": "A chave de assinatura que você forneceu corresponde à chave de assinatura que você recebeu da sessão %(deviceId)s do usuário %(userId)s. Esta sessão foi marcada como confirmada.", - "verify_success_title": "Chave confirmada", - "verify_unknown_pair": "Par desconhecido (usuário, sessão): (%(userId)s, %(deviceId)s)", "whois": "Exibe informação sobre um usuário" }, "space": { @@ -2101,10 +2084,6 @@ "error_no_renderer": "Este evento não pôde ser exibido", "error_rendering_message": "Não foi possível carregar esta mensagem", "historical_messages_unavailable": "Você não pode ver as mensagens anteriores", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s encerrou uma transmissão de voz", - "you": "Você encerrou uma transmissão de voz" - }, "io.element.widgets.layout": "%(senderName)s atualizou o layout da sala", "load_error": { "no_permission": "Não foi possível carregar um trecho específico da conversa desta sala, porque parece que você não tem permissão para ler a mensagem em questão.", @@ -2537,21 +2516,6 @@ "switch_theme_dark": "Alternar para o modo escuro", "switch_theme_light": "Alternar para o modo claro" }, - "voice_broadcast": { - "confirm_listen_description": "Se você começar a ouvir esta tramissão ao vivo, a gravação desta transmissão, será encerrada.", - "confirm_listen_title": "Ouvir transmissão ao vivo?", - "confirm_stop_affirm": "Sim, interromper a transmissão", - "confirm_stop_title": "Parar a transmissão ao vivo?", - "failed_already_recording_description": "Você já está gravando uma transmissão de voz. Encerre sua transmissão de voz atual para iniciar uma nova.", - "failed_already_recording_title": "Não é possível iniciar uma nova transmissão de voz", - "failed_insufficient_permission_description": "Você não tem as permissões necessárias para iniciar uma transmissão de voz nesta sala. Entre em contato com um administrador de sala para atualizar suas permissões.", - "failed_insufficient_permission_title": "Não é possível iniciar uma nova transmissão de voz", - "failed_no_connection_description": "Infelizmente, não podemos iniciar uma gravação agora. Por favor, tente novamente mais tarde.", - "failed_no_connection_title": "Erro de conexão", - "failed_others_already_recording_description": "Outra pessoa já está gravando uma transmissão de voz. Aguarde o término da transmissão de voz para iniciar uma nova.", - "failed_others_already_recording_title": "Não é possível iniciar uma nova transmissão de voz", - "live": "Ao vivo" - }, "voip": { "already_in_call": "Já em um chamada", "already_in_call_person": "Você já está em uma chamada com essa pessoa.", @@ -2582,8 +2546,6 @@ "enable_camera": "Ligar câmera", "enable_microphone": "Habilitar microfone", "expand": "Retornar para a chamada", - "failed_call_live_broadcast_description": "Você não pode iniciar uma chamada porque está gravando uma transmissão ao vivo. Termine sua transmissão ao vivo para iniciar uma chamada.", - "failed_call_live_broadcast_title": "Não é possível iniciar uma chamada", "hangup": "Desligar", "hide_sidebar_button": "Esconder a barra lateral", "join_button_tooltip_connecting": "Conectando", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 50a3ee50e97..555cb3d1f9b 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -877,7 +877,6 @@ }, "udd": { "interactive_verification_button": "Интерактивная сверка по смайлам", - "manual_verification_button": "Ручная сверка по тексту", "other_ask_verify_text": "Попросите этого пользователя подтвердить сеанс или подтвердите его вручную ниже.", "other_new_session_text": "%(name)s (%(userId)s) произвел(а) вход через новый сеанс без подтверждения:", "own_ask_verify_text": "Подтвердите ваш другой сеанс, используя один из вариантов ниже.", @@ -912,12 +911,6 @@ "incoming_sas_dialog_waiting": "Ожидаем подтверждения от партнера…", "incoming_sas_user_dialog_text_1": "Проверить этого пользователя, чтобы отметить его, как доверенного. Доверенные пользователи дают вам больше уверенности при использовании шифрованных сообщений.", "incoming_sas_user_dialog_text_2": "Подтверждение этого пользователя сделает его сеанс доверенным у вас, а также сделает ваш сеанс доверенным у него.", - "manual_device_verification_device_id_label": "ID сеанса", - "manual_device_verification_device_key_label": "Ключ сеанса", - "manual_device_verification_device_name_label": "Название сеанса", - "manual_device_verification_footer": "Если они не совпадают, безопасность вашего общения может быть поставлена под угрозу.", - "manual_device_verification_self_text": "Сравните следующие параметры с \"Пользовательскими настройками\" в другом вашем сеансе:", - "manual_device_verification_user_text": "Подтвердите сеанс этого пользователя, сравнив следующие параметры с его \"Пользовательскими настройками\":", "no_key_or_device": "Похоже, у вас нет бумажного ключа, или других сеансов, с которыми вы могли бы свериться. В этом сеансе вы не сможете получить доступ к старым зашифрованным сообщениям. Чтобы подтвердить свою личность в этом сеансе, вам нужно будет сбросить свои ключи шифрования.", "no_support_qr_emoji": "Устройство, которое вы пытаетесь проверить, не поддерживает сканирование QR-кода или проверку смайликов, которые поддерживает %(brand)s. Попробуйте использовать другой клиент.", "other_party_cancelled": "Другая сторона отменила проверку.", @@ -1036,10 +1029,6 @@ }, "error_user_not_logged_in": "Пользователь не вошел в систему", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s завершил(а) голосовую трансляцию", - "you": "Вы завершили голосовую трансляцию" - }, "m.call.answer": { "dm": "Звонок в процессе", "user": "%(senderName)s присоединился(лась) к звонку", @@ -1412,8 +1401,6 @@ "video_rooms_faq2_answer": "Да, лента сообщений отображается рядом с видео.", "video_rooms_faq2_question": "Можно ли использовать текстовый чат одновременно с видеозвонком?", "video_rooms_feedbackSubheading": "Спасибо, что попробовали бета-версию. Пожалуйста, расскажите как можно подробнее, чтобы мы могли ее улучшить.", - "voice_broadcast": "Голосовая трансляция", - "voice_broadcast_force_small_chunks": "Длина фрагмента голосовой трансляции 15s", "wysiwyg_composer": "Наглядный текстовый редактор" }, "labs_mjolnir": { @@ -1550,7 +1537,6 @@ "mute_description": "Вы не будете получать никаких уведомлений" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s начал(а) голосовую трансляцию", "m.key.verification.request": "%(name)s запрашивает проверку" }, "onboarding": { @@ -2126,7 +2112,6 @@ "error_unbanning": "Не удалось разблокировать", "events_default": "Отправить сообщения", "invite": "Пригласить пользователей", - "io.element.voice_broadcast_info": "Голосовые трансляции", "kick": "Удалять пользователей", "m.call": "Начать %(brand)s звонок", "m.call.member": "Присоединяйтесь к %(brand)s звонку", @@ -2769,7 +2754,6 @@ "warning": "ВНИМАНИЕ: " }, "share": { - "link_title": "Ссылка на комнату", "permalink_message": "Ссылка на выбранное сообщение", "permalink_most_recent": "Ссылка на последнее сообщение", "title_message": "Поделиться сообщением", @@ -2858,13 +2842,6 @@ "upgraderoom": "Обновляет комнату до новой версии", "upgraderoom_permission_error": "У вас нет необходимых разрешений для использования этой команды.", "usage": "Использование", - "verify": "Проверяет пользователя, сеанс и публичные ключи", - "verify_mismatch": "ВНИМАНИЕ: ПРОВЕРКА КЛЮЧА НЕ ПРОШЛА! Ключом подписи для %(userId)s и сеанса %(deviceId)s является \"%(fprint)s\", что не соответствует указанному ключу \"%(fingerprint)s\". Это может означать, что ваши сообщения перехватываются!", - "verify_nop": "Сеанс уже подтверждён!", - "verify_nop_warning_mismatch": "ВНИМАНИЕ: сеанс уже заверен, но ключи НЕ СОВПАДАЮТ!", - "verify_success_description": "Ключ подписи, который вы предоставили, соответствует ключу подписи, который вы получили от пользователя %(userId)s через сеанс %(deviceId)s. Сеанс отмечен как подтверждённый.", - "verify_success_title": "Ключ проверен", - "verify_unknown_pair": "Неизвестная пара (пользователь, сеанс): (%(userId)s, %(deviceId)s)", "view": "Просмотр комнаты с указанным адресом", "whois": "Показать информацию о пользователе" }, @@ -3080,10 +3057,6 @@ "error_rendering_message": "Не удалось загрузить это сообщение", "historical_messages_unavailable": "Вы не можете просматривать более старые сообщения", "in_room_name": " в %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s завершил(а) голосовую трансляцию", - "you": "Вы завершили голосовую трансляцию" - }, "io.element.widgets.layout": "%(senderName)s обновил(а) макет комнаты", "late_event_separator": "Первоначально отправлено %(dateTime)s", "load_error": { @@ -3618,38 +3591,6 @@ "switch_theme_dark": "Переключить в тёмный режим", "switch_theme_light": "Переключить в светлый режим" }, - "voice_broadcast": { - "30s_backward": "30с назад", - "30s_forward": "30с вперёд", - "action": "Голосовая трансляция", - "buffering": "Буферизация…", - "confirm_listen_affirm": "Да, закончить мою запись", - "confirm_listen_description": "Если вы начнете слушать данную трансляцию, то текущая запись прямой трансляции будет завершена.", - "confirm_listen_title": "Слушать прямой эфир?", - "confirm_stop_affirm": "Да, остановить трансляцию", - "confirm_stop_description": "Вы действительно хотите прекратить прямую трансляцию? На этом трансляция закончится и полная запись будет доступна в комнате.", - "confirm_stop_title": "Закончить голосовую трансляцию?", - "connection_error": "Ошибка подключения — запись приостановлена", - "failed_already_recording_description": "Вы уже записываете голосовую трансляцию. Пожалуйста, завершите текущую голосовую трансляцию, чтобы начать новую.", - "failed_already_recording_title": "Не получилось начать новую голосовую трансляцию", - "failed_decrypt": "Невозможно расшифровать голосовую трансляцию", - "failed_generic": "Невозможно воспроизвести эту голосовую трансляцию", - "failed_insufficient_permission_description": "У вас нет необходимых разрешений, чтобы начать голосовую трансляцию в этой комнате. Свяжитесь с администратором комнаты для получения разрешений.", - "failed_insufficient_permission_title": "Не получилось начать новую голосовую трансляцию", - "failed_no_connection_description": "К сожалению, сейчас мы не можем начать запись. Пожалуйста, попробуйте позже.", - "failed_no_connection_title": "Ошибка подключения", - "failed_others_already_recording_description": "Кто-то уже записывает голосовую трансляцию. Ждите окончания их голосовой трансляции, чтобы начать новую.", - "failed_others_already_recording_title": "Не получилось начать новую голосовую трансляцию", - "go_live": "Начать эфир", - "live": "В эфире", - "pause": "приостановить голосовую трансляцию", - "play": "проиграть голосовую трансляцию", - "resume": "продолжить голосовую трансляцию" - }, - "voice_message": { - "cant_start_broadcast_description": "Вы не можете начать голосовое сообщение, так как вы сейчас записываете прямую трансляцию. Завершите прямую трансляцию, чтобы начать запись голосового сообщения.", - "cant_start_broadcast_title": "Не удается запустить голосовое сообщение" - }, "voip": { "already_in_call": "Уже в вызове", "already_in_call_person": "Вы уже разговариваете с этим человеком.", @@ -3669,7 +3610,6 @@ "camera_disabled": "Ваша камера выключена", "camera_enabled": "Ваша камера всё ещё включена", "cannot_call_yourself_description": "Вы не можете позвонить самому себе.", - "change_input_device": "Смените устройство ввода", "connecting": "Подключение", "connection_lost": "Соединение с сервером потеряно", "connection_lost_description": "Вы не можете совершать вызовы без подключения к серверу.", @@ -3686,8 +3626,6 @@ "enable_camera": "Включить камеру", "enable_microphone": "Включить микрофон", "expand": "Вернуться к звонку", - "failed_call_live_broadcast_description": "Вы не можете начать звонок, так как вы производите живое вещание. Пожалуйста, остановите вещание, чтобы начать звонок.", - "failed_call_live_broadcast_title": "Невозможно начать звонок", "hangup": "Повесить трубку", "hide_sidebar_button": "Скрыть боковую панель", "input_devices": "Устройства ввода", diff --git a/src/i18n/strings/sk.json b/src/i18n/strings/sk.json index 34ba4789bf5..eab25be92bb 100644 --- a/src/i18n/strings/sk.json +++ b/src/i18n/strings/sk.json @@ -877,7 +877,6 @@ }, "udd": { "interactive_verification_button": "Interaktívne overte pomocou emotikonov", - "manual_verification_button": "Manuálne overte pomocou textu", "other_ask_verify_text": "Poproste tohto používateľa, aby si overil svoju reláciu alebo ju nižšie manuálne overte.", "other_new_session_text": "%(name)s (%(userId)s) sa prihlásil do novej relácie bez jej overenia:", "own_ask_verify_text": "Overte svoje ostatné relácie pomocou jednej z nižšie uvedených možností.", @@ -912,12 +911,6 @@ "incoming_sas_dialog_waiting": "Čakanie na potvrdenie od partnera…", "incoming_sas_user_dialog_text_1": "Overte tohto používateľa a označte ho ako dôveryhodného. Dôveryhodní používatelia vám poskytujú dodatočný pokoj na duši pri používaní end-to-end šifrovaných správ.", "incoming_sas_user_dialog_text_2": "Overenie tohto používateľa označí jeho reláciu ako dôveryhodnú a zároveň označí vašu reláciu ako dôveryhodnú pre neho.", - "manual_device_verification_device_id_label": "ID relácie", - "manual_device_verification_device_key_label": "Kľúč relácie", - "manual_device_verification_device_name_label": "Názov relácie", - "manual_device_verification_footer": "Ak sa nezhodujú, môže byť ohrozená bezpečnosť vašej komunikácie.", - "manual_device_verification_self_text": "Potvrďte to porovnaním nasledujúcich údajov s nastaveniami používateľa v inej vašej relácii:", - "manual_device_verification_user_text": "Potvrďte reláciu tohto používateľa porovnaním nasledujúcich údajov s jeho nastaveniami používateľa:", "no_key_or_device": "Vyzerá to, že nemáte bezpečnostný kľúč ani žiadne iné zariadenie, pomocou ktorého by ste to mohli overiť. Toto zariadenie nebude mať prístup k starým zašifrovaným správam. Ak chcete overiť svoju totožnosť na tomto zariadení, budete musieť obnoviť svoje overovacie kľúče.", "no_support_qr_emoji": "Zariadenie, ktoré sa snažíte overiť, nepodporuje overenie skenovaním QR kódu ani overenie pomocou emotikonov, ktoré podporuje aplikácia %(brand)s. Skúste použiť iného klienta.", "other_party_cancelled": "Proti strana zrušila overovanie.", @@ -1037,10 +1030,6 @@ }, "error_user_not_logged_in": "Používateľ nie je prihlásený", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s ukončil/a hlasové vysielanie", - "you": "Ukončili ste hlasové vysielanie" - }, "m.call.answer": { "dm": "Práve prebieha hovor", "user": "%(senderName)s sa pridal/a do hovoru", @@ -1417,8 +1406,6 @@ "video_rooms_faq2_answer": "Áno, časová os konverzácie sa zobrazuje spolu s videom.", "video_rooms_faq2_question": "Môžem popri videohovore používať aj textovú konverzáciu?", "video_rooms_feedbackSubheading": "Ďakujeme, že ste vyskúšali beta verziu, prosím, uveďte čo najviac podrobností, aby sme ju mohli vylepšiť.", - "voice_broadcast": "Hlasové vysielanie", - "voice_broadcast_force_small_chunks": "Vynútiť 15s dĺžku sekcie hlasového vysielania", "wysiwyg_composer": "Rozšírený textový editor" }, "labs_mjolnir": { @@ -1555,7 +1542,6 @@ "mute_description": "Nebudete dostávať žiadne oznámenia" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s začal/a hlasové vysielanie", "m.key.verification.request": "%(name)s žiada o overenie" }, "onboarding": { @@ -2130,7 +2116,6 @@ "error_unbanning": "Nepodarilo sa povoliť vstup", "events_default": "Odoslať správy", "invite": "Pozvať používateľov", - "io.element.voice_broadcast_info": "Hlasové vysielania", "kick": "Odstrániť používateľov", "m.call": "Spustiť %(brand)s hovory", "m.call.member": "Pripojiť sa k %(brand)s hovorom", @@ -2772,7 +2757,6 @@ "warning": "UPOZORNENIE: " }, "share": { - "link_title": "Odkaz na miestnosť", "permalink_message": "Odkaz na vybratú správu", "permalink_most_recent": "Odkaz na najnovšiu správu", "title_message": "Zdieľať správu z miestnosti", @@ -2861,13 +2845,6 @@ "upgraderoom": "Aktualizuje miestnosť na novšiu verziu", "upgraderoom_permission_error": "Na použitie tohoto príkazu nemáte dostatočné povolenia.", "usage": "Použitie", - "verify": "Overí používateľa, reláciu a verejné kľúče", - "verify_mismatch": "VAROVANIE: OVERENIE KĽÚČOV ZLYHALO! Podpisový kľúč používateľa %(userId)s a relácia %(deviceId)s je \"%(fprint)s\" čo nezodpovedá zadanému kľúču \"%(fingerprint)s\". Môže to znamenať, že vaša komunikácia je odpočúvaná!", - "verify_nop": "Relácia je už overená!", - "verify_nop_warning_mismatch": "VAROVANIE: Relácia je už overená, ale kľúče sa NEZHODUJÚ!", - "verify_success_description": "Zadaný podpisový kľúč sa zhoduje s podpisovým kľúčom, ktorý ste dostali z relácie používateľa %(userId)s %(deviceId)s. Relácia označená ako overená.", - "verify_success_title": "Kľúč overený", - "verify_unknown_pair": "Neznámy pár (používateľ, relácia): (%(userId)s, %(deviceId)s)", "view": "Zobrazí miestnosti s danou adresou", "whois": "Zobrazuje informácie o používateľovi" }, @@ -3082,10 +3059,6 @@ "error_rendering_message": "Nemožno načítať túto správu", "historical_messages_unavailable": "Nemôžete vidieť predchádzajúce správy", "in_room_name": " v %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s ukončil/a hlasové vysielanie", - "you": "Ukončili ste hlasové vysielanie" - }, "io.element.widgets.layout": "%(senderName)s aktualizoval usporiadanie miestnosti", "late_event_separator": "Pôvodne odoslané %(dateTime)s", "load_error": { @@ -3647,38 +3620,6 @@ "switch_theme_dark": "Prepnúť na tmavý režim", "switch_theme_light": "Prepnúť na svetlý režim" }, - "voice_broadcast": { - "30s_backward": "30s späť", - "30s_forward": "30s dopredu", - "action": "Hlasové vysielanie", - "buffering": "Načítavanie do vyrovnávacej pamäte…", - "confirm_listen_affirm": "Áno, ukončiť moje nahrávanie", - "confirm_listen_description": "Ak začnete počúvať toto živé vysielanie, váš aktuálny záznam živého vysielania sa ukončí.", - "confirm_listen_title": "Počúvať živé vysielanie?", - "confirm_stop_affirm": "Áno, zastaviť vysielanie", - "confirm_stop_description": "Určite chcete zastaviť vysielanie naživo? Tým sa vysielanie ukončí a v miestnosti bude k dispozícii celý záznam.", - "confirm_stop_title": "Zastaviť vysielanie naživo?", - "connection_error": "Chyba pripojenia - nahrávanie pozastavené", - "failed_already_recording_description": "Už nahrávate hlasové vysielanie. Ukončite aktuálne hlasové vysielanie a spustite nové.", - "failed_already_recording_title": "Nemôžete spustiť nové hlasové vysielanie", - "failed_decrypt": "Hlasové vysielanie sa nedá dešifrovať", - "failed_generic": "Toto hlasové vysielanie nie je možné prehrať", - "failed_insufficient_permission_description": "Nemáte požadované oprávnenia na spustenie hlasového vysielania v tejto miestnosti. Obráťte sa na správcu miestnosti, aby vám rozšíril oprávnenia.", - "failed_insufficient_permission_title": "Nemôžete spustiť nové hlasové vysielanie", - "failed_no_connection_description": "Bohužiaľ teraz nemôžeme spustiť nahrávanie. Skúste to prosím neskôr.", - "failed_no_connection_title": "Chyba pripojenia", - "failed_others_already_recording_description": "Niekto iný už nahráva hlasové vysielanie. Počkajte, kým sa skončí jeho hlasové vysielanie, a potom spustite nové.", - "failed_others_already_recording_title": "Nemôžete spustiť nové hlasové vysielanie", - "go_live": "Prejsť naživo", - "live": "Naživo", - "pause": "pozastaviť hlasové vysielanie", - "play": "spustiť hlasové vysielanie", - "resume": "obnoviť hlasové vysielanie" - }, - "voice_message": { - "cant_start_broadcast_description": "Nemôžete spustiť hlasovú správu, pretože práve nahrávate živé vysielanie. Ukončite prosím živé vysielanie, aby ste mohli začať nahrávať hlasovú správu.", - "cant_start_broadcast_title": "Nemožno spustiť hlasovú správu" - }, "voip": { "already_in_call": "Hovor už prebieha", "already_in_call_person": "S touto osobou už hovor prebieha.", @@ -3698,7 +3639,6 @@ "camera_disabled": "Váš fotoaparát je vypnutý", "camera_enabled": "Fotoaparát je stále zapnutý", "cannot_call_yourself_description": "Nemôžete zavolať samému sebe.", - "change_input_device": "Zmeniť vstupné zariadenie", "connecting": "Pripájanie", "connection_lost": "Spojenie so serverom bolo prerušené", "connection_lost_description": "Bez pripojenia k serveru nie je možné uskutočňovať hovory.", @@ -3715,8 +3655,6 @@ "enable_camera": "Zapnúť kameru", "enable_microphone": "Zrušiť stlmenie mikrofónu", "expand": "Návrat k hovoru", - "failed_call_live_broadcast_description": "Nemôžete spustiť hovor, pretože práve nahrávate živé vysielanie. Ukončite živé vysielanie, aby ste mohli začať hovor.", - "failed_call_live_broadcast_title": "Nie je možné začať hovor", "hangup": "Zavesiť", "hide_sidebar_button": "Skryť bočný panel", "input_devices": "Vstupné zariadenia", diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index b7258c26cbf..356480535fd 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -835,7 +835,6 @@ }, "udd": { "interactive_verification_button": "Verifikojeni në mënyrë ndërvepruese përmes emoji-sh", - "manual_verification_button": "Verifikojeni dorazi përmes teksti", "other_ask_verify_text": "Kërkojini këtij përdoruesi të verifikojë sesionin e vet, ose ta verifikojë më poshtë dorazi.", "other_new_session_text": "%(name)s (%(userId)s) bëri hyrjen në një sesion të ri pa e verifikuar:", "own_ask_verify_text": "Verifikoni sesionit tuaj tjetër duke përdorur një nga mundësitë më poshtë.", @@ -870,12 +869,6 @@ "incoming_sas_dialog_waiting": "Po pritet ripohimi nga partneri…", "incoming_sas_user_dialog_text_1": "Verifikojeni këtë përdorues që t’i vihet shenjë si i besuar. Përdoruesit e besuar ju më tepër siguri kur përdorni mesazhe të fshehtëzuar skaj-më-skaj.", "incoming_sas_user_dialog_text_2": "Verifikimi i këtij përdoruesi do t’i vërë shenjë sesionit të tij si të besuar dhe sesionit tuaj si të besuar për ta.", - "manual_device_verification_device_id_label": "ID sesioni", - "manual_device_verification_device_key_label": "Kyç sesioni", - "manual_device_verification_device_name_label": "Emër sesioni", - "manual_device_verification_footer": "Nëse s’përputhen, siguria e komunikimeve tuaja mund të jetë komprometuar.", - "manual_device_verification_self_text": "Ripohojeni duke krahasuar sa vijon me Rregullimet e Përdoruesit te sesioni juaj tjetër:", - "manual_device_verification_user_text": "Ripohojeni këtë sesion përdoruesi duke krahasuar sa vijon me Rregullimet e tij të Përdoruesit:", "no_key_or_device": "Duket sikur s’keni Kyç Sigurie ose ndonjë pajisje tjetër nga e cila mund të bëni verifikimin. Kjo pajisje s’do të jetë në gjendje të hyjë te mesazhe të dikurshëm të fshehtëzuar. Që të mund të verifikohet identiteti juaj në këtë pajisje, ju duhet të riujdisni kyçet tuaj të verifikimit.", "no_support_qr_emoji": "Pajisja që po provoni të verifikoni nuk mbulon skanim të një kodi QR, apo verifikim me emoji, çka janë ato që mbulohen prej %(brand)s. Provoni me një klient tjetër.", "other_party_cancelled": "Pala tjetër e anuloi verifikimin.", @@ -991,10 +984,6 @@ } }, "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s përfundoi një transmetim zanor", - "you": "Përfunduat një transmetim zanor" - }, "m.call.answer": { "dm": "Thirrje në ecuri e sipër", "user": "%(senderName)s u bë pjesë e thirrjes", @@ -1329,8 +1318,6 @@ "video_rooms_faq1_question": "Si mund të krijoj një dhomë me video?", "video_rooms_faq2_answer": "Po, rrjedha kohore e fjalosjes shfaqet tok me videon.", "video_rooms_faq2_question": "A mund të përdor fjalosje me tekst në krah të thirrjes video?", - "voice_broadcast": "Transmetim zanor", - "voice_broadcast_force_small_chunks": "Detyro gjatësi copëzash transmetimi zanor prej 15s", "wysiwyg_composer": "Përpunues teksti të pasur" }, "labs_mjolnir": { @@ -1465,7 +1452,6 @@ "mute_description": "S’do të merrni ndonjë njoftim" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s nisi një transmetim zanor", "m.key.verification.request": "%(name)s po kërkon verifikim" }, "onboarding": { @@ -2005,7 +1991,6 @@ "error_unbanning": "S’u arrit t’i hiqej dëbimi", "events_default": "Dërgoni mesazhe", "invite": "Ftoni përdorues", - "io.element.voice_broadcast_info": "Transmetime zanore", "kick": "Hiqni përdorues", "m.call": "Nisni thirrje %(brand)s", "m.call.member": "Merrni pjesë në thirrje %(brand)s", @@ -2599,7 +2584,6 @@ "warning": "KUJDES: " }, "share": { - "link_title": "Lidhje për te dhoma", "permalink_message": "Lidhje për te mesazhi i përzgjedhur", "permalink_most_recent": "Lidhje për te mesazhet më të freskët", "title_message": "Ndani Me të Tjerë Mesazh Dhome", @@ -2684,13 +2668,6 @@ "upgraderoom": "E kalon një dhomë te një version i ri i përmirësuar", "upgraderoom_permission_error": "S’keni lejet e domosdoshme për përdorimin e këtij urdhri.", "usage": "Përdorim", - "verify": "Verifikon një përdorues, sesion dhe një set kyçesh publikë", - "verify_mismatch": "KUJDES: VERIFIKIMI I KYÇIT DËSHTOI! Kyçi i nënshkrimit për %(userId)s dhe sesionin %(deviceId)s është \"%(fprint)s\", që nuk përputhet me kyçin e dhënë \"%(fingerprint)s\". Kjo mund të jetë shenjë se komunikimet tuaja po përgjohen!", - "verify_nop": "Sesion i tashmë i verifikuar!", - "verify_nop_warning_mismatch": "KUJDES: sesion tashmë i verifikuar, por kyçet NUK PËRPUTHEN!", - "verify_success_description": "Kyçi i nënshkrimit që dhatë përputhet me kyçin e nënshkrimit që morët nga sesioni i %(userId)s %(deviceId)s. Sesionit iu vu shenjë si i verifikuar.", - "verify_success_title": "Kyç i verifikuar", - "verify_unknown_pair": "Çift (përdorues, sesion) i pavlefshëm: (%(userId)s, %(deviceId)s)", "whois": "Shfaq të dhëna rreth një përdoruesi" }, "space": { @@ -2893,10 +2870,6 @@ "error_rendering_message": "S’ngarkohet dot ky mesazh", "historical_messages_unavailable": "S’mund të shihni mesazhe më të hershëm", "in_room_name": " në %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s përfundoi një transmetim zanor", - "you": "Përfunduat një transmetim zanor" - }, "io.element.widgets.layout": "%(senderName)s ka përditësuar skemën e dhomës", "load_error": { "no_permission": "U provua të ngarkohej një pikë e caktuar në kronologjinë e kësaj dhome, por nuk keni leje për ta parë mesazhin në fjalë.", @@ -3411,36 +3384,6 @@ "switch_theme_dark": "Kalo nën mënyrën e errët", "switch_theme_light": "Kalo nën mënyrën e çelët" }, - "voice_broadcast": { - "30s_backward": "30s mbrapsht", - "30s_forward": "30s përpara", - "action": "Transmetim zanor", - "confirm_listen_affirm": "Po, përfundoje regjistrimin tim", - "confirm_listen_description": "Nëse filloni të dëgjoni te ky transmetim i drejtpërdrejtë, regjistrimi juaj i tanishëm i një transmetimi të drejtpërdrejtë do të përfundojë.", - "confirm_listen_title": "Të dëgjohet te transmetimi i drejtpërdrejtë?", - "confirm_stop_affirm": "Po, ndale transmetimin zanor", - "confirm_stop_description": "Jeni i sigurt se doni të ndalet transmetimi juaj i drejtpërdrejtë? Kjo do të përfundojë transmetimin dhe regjistrimi i plotë do të jetë i passhëm te dhoma.", - "confirm_stop_title": "Të ndalet transmetimi i drejtpërdrejtë?", - "connection_error": "Gabim lidhjeje - Regjistrimi u ndal", - "failed_already_recording_description": "Po incizoni tashmë një transmetim zanor. Ju lutemi, që të nisni një të ri, përfundoni transmetimin tuaj zanor të tanishëm.", - "failed_already_recording_title": "S’niset dot një transmetim zanor i ri", - "failed_decrypt": "S’arrihet të shfshehtëzohet transmetim zanor", - "failed_generic": "S’arrihet të luhet ky transmetim zanor", - "failed_insufficient_permission_description": "S’keni lejet e domosdoshme që të nisni një transmetim zanor në këtë dhomë. Lidhuni me një përgjegjës dhome që të përmirësoni lejet tuaja.", - "failed_insufficient_permission_title": "S’niset dot një transmetim zanor i ri", - "failed_no_connection_description": "Mjerisht, s’qemë në gjendje të nisnim tani një regjistrim. Ju lutemi, riprovoni më vonë.", - "failed_no_connection_title": "Gabim lidhjeje", - "failed_others_already_recording_description": "Dikush tjetër është duke incizuar një transmetim zanor. Që të nisni një të ri, prisni të përfundojë incizimi zanor i tij.", - "failed_others_already_recording_title": "S’niset dot një transmetim zanor i ri", - "live": "Drejtpërdrejt", - "pause": "ndal transmetim zanor", - "play": "luaj transmetim zanor", - "resume": "vazhdo transmetim zanor" - }, - "voice_message": { - "cant_start_broadcast_description": "S’mund të niset mesazh zanor, ngaqë aktualisht po incizoni një transmetim të drejtpërdrejtë. Ju lutemi, përfundoni transmetimin e drejtpërdrejtë, që të mund të nisni incizimin e një mesazhi zanor.", - "cant_start_broadcast_title": "S’niset dot mesazh zanor" - }, "voip": { "already_in_call": "Tashmë në thirrje", "already_in_call_person": "Gjendeni tashmë në thirrje me këtë person.", @@ -3460,7 +3403,6 @@ "camera_disabled": "Kamera juaj është e fikur", "camera_enabled": "Kamera juaj është ende e aktivizuar", "cannot_call_yourself_description": "S’mund të bëni thirrje me vetveten.", - "change_input_device": "Ndryshoni pajisje dhëniesh", "connecting": "Po lidhet", "connection_lost": "Humbi lidhja me shërbyesin", "connection_lost_description": "S’mund të bëni thirrje pa një lidhje te shërbyesi.", @@ -3476,8 +3418,6 @@ "enable_camera": "Aktivizo kamerën", "enable_microphone": "Çheshto mikrofonin", "expand": "Kthehu te thirrja", - "failed_call_live_broadcast_description": "S’mund të nisni një thirrje, ngaqë aktualisht jeni duke regjistruar një transmetim të drejtpërdrejtë. Që të mund të nisni një thirrje, ju lutemi, përfundoni transmetimin tuaj të drejtpërdrejtë.", - "failed_call_live_broadcast_title": "S’fillohet dot thirrje", "hangup": "Mbylle Thirrjen", "hide_sidebar_button": "Fshihe anështyllën", "input_devices": "Pajisje input-i", diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index bb4e489952a..e24878b5316 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -882,7 +882,6 @@ }, "udd": { "interactive_verification_button": "Verifiera interaktivt med emoji", - "manual_verification_button": "Verifiera manuellt med text", "other_ask_verify_text": "Be den här användaren att verifiera sin session, eller verifiera den manuellt nedan.", "other_new_session_text": "%(name)s (%(userId)s) loggade in i en ny session utan att verifiera den:", "own_ask_verify_text": "Verifiera din andra session med ett av alternativen nedan.", @@ -917,12 +916,6 @@ "incoming_sas_dialog_waiting": "Väntar på att andra parten ska bekräfta …", "incoming_sas_user_dialog_text_1": "Verifiera denna användare för att markera den som betrodd. Att lita på användare ger en extra sinnesfrid när man använder totalsträckskrypterade meddelanden.", "incoming_sas_user_dialog_text_2": "Att verifiera den här användaren kommer att markera dess session som betrodd, och markera din session som betrodd för denne.", - "manual_device_verification_device_id_label": "Sessions-ID", - "manual_device_verification_device_key_label": "Sessionsnyckel", - "manual_device_verification_device_name_label": "Sessionsnamn", - "manual_device_verification_footer": "Om de inte matchar så kan din kommunikations säkerhet vara äventyrad.", - "manual_device_verification_self_text": "Bekräfta genom att jämföra följande med användarinställningarna i din andra session:", - "manual_device_verification_user_text": "Bekräfta den här användarens session genom att jämföra följande med deras användarinställningar:", "no_key_or_device": "Det ser ut som att du inte har någon säkerhetsnyckel eller några andra enheter du kan verifiera mot. Den här enheten kommer inte kunna komma åt gamla krypterad meddelanden. För att verifiera din identitet på den här enheten så behöver du återställa dina verifieringsnycklar.", "no_support_qr_emoji": "Enheten du försöker verifiera stöder inte att skanna en QR-kod eller verifiera med emoji, vilket är var %(brand)s stöder. Pröva en annan klient.", "other_party_cancelled": "Den andra parten avbröt verifieringen.", @@ -1046,10 +1039,6 @@ }, "error_user_not_logged_in": "Användaren är inte inloggad", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s avslutade en röstsändning", - "you": "Du avslutade en röstsändning" - }, "m.call.answer": { "dm": "Samtal pågår", "user": "%(senderName)s gick med i samtalet", @@ -1423,8 +1412,6 @@ "video_rooms_faq2_answer": "Ja, chattidslinjen visas tillsammans med videon.", "video_rooms_faq2_question": "Kan jag använda textchatt tillsammans med videosamtalet?", "video_rooms_feedbackSubheading": "Tack för att du prövar betan, vänligen ge så många detaljer du kan så att vi kan förbättra den.", - "voice_broadcast": "Röstsändning", - "voice_broadcast_force_small_chunks": "Tvinga dellängd på 15s för röstsändning", "wysiwyg_composer": "Riktextredigerare" }, "labs_mjolnir": { @@ -1568,7 +1555,6 @@ "mute_description": "Du får inga aviseringar" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s startade en röstsändning", "m.key.verification.request": "%(name)s begär verifiering" }, "onboarding": { @@ -2142,7 +2128,6 @@ "error_unbanning": "Misslyckades att avbanna", "events_default": "Skicka meddelanden", "invite": "Bjuda in användare", - "io.element.voice_broadcast_info": "Röstsändning", "kick": "Ta bort användare", "m.call": "Starta %(brand)s samtal", "m.call.member": "Gå med i %(brand)s samtal", @@ -2784,7 +2769,6 @@ "warning": "VARNING: " }, "share": { - "link_title": "Länk till rum", "permalink_message": "Länk till valt meddelande", "permalink_most_recent": "Länk till senaste meddelandet", "title_message": "Dela rumsmeddelande", @@ -2873,13 +2857,6 @@ "upgraderoom": "Uppgraderar ett rum till en ny version", "upgraderoom_permission_error": "Du har inte de behörigheter som krävs för att använda det här kommandot.", "usage": "Användande", - "verify": "Verifierar en användar-, sessions- och pubkey-tupel", - "verify_mismatch": "VARNING: NYCKELVERIFIERING MISSLYCKADES! Den signerade nyckeln för %(userId)s och sessionen %(deviceId)s är \"%(fprint)s\" vilket inte matchar den givna nyckeln \"%(fingerprint)s\". Detta kan betyda att kommunikationen är övervakad!", - "verify_nop": "Sessionen är redan verifierad!", - "verify_nop_warning_mismatch": "VARNING: sessionen är redan verifierad, men nycklarna MATCHAR INTE!", - "verify_success_description": "Signeringsnyckeln du gav matchar signeringsnyckeln du fick av %(userId)ss session %(deviceId)s. Sessionen markerades som verifierad.", - "verify_success_title": "Verifierade nyckeln", - "verify_unknown_pair": "Okänt (användare, session)-par: (%(userId)s, %(deviceId)s)", "view": "Visar rum med den angivna adressen", "whois": "Visar information om en användare" }, @@ -3097,10 +3074,6 @@ "error_rendering_message": "Kan inte ladda det här meddelandet", "historical_messages_unavailable": "Du kan inte se tidigare meddelanden", "in_room_name": " i %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s avslutade en röstsändning", - "you": "Du avslutade en röstsändning" - }, "io.element.widgets.layout": "%(senderName)s har uppdaterat rummets arrangemang", "late_event_separator": "Ursprungligen skickad %(dateTime)s", "load_error": { @@ -3633,38 +3606,6 @@ "switch_theme_dark": "Byt till mörkt läge", "switch_theme_light": "Byt till ljust läge" }, - "voice_broadcast": { - "30s_backward": "30s bakåt", - "30s_forward": "30s framåt", - "action": "Röstsändning", - "buffering": "Buffrar…", - "confirm_listen_affirm": "Ja, avsluta min inspelning", - "confirm_listen_description": "Om du börjar lyssna på den här direktsändningen så kommer din nuvarande direktsändningsinspelning att avslutas.", - "confirm_listen_title": "Lyssna på direktsändning?", - "confirm_stop_affirm": "Ja, avsluta sändning", - "confirm_stop_description": "Är du säker på att du vill avsluta din direktsändning? Det här kommer att avsluta sändningen och den fulla inspelningen kommer att bli tillgänglig i rummet.", - "confirm_stop_title": "Avsluta livesändning?", - "connection_error": "Anslutningsfel - Inspelning pausad", - "failed_already_recording_description": "Du spelar redan in en röstsändning. Avsluta din nuvarande röstsändning för att påbörja en ny.", - "failed_already_recording_title": "Kan inte starta en ny röstsändning", - "failed_decrypt": "Kunde inte kryptera röstsändning", - "failed_generic": "Kan inte spela den här röstsändningen", - "failed_insufficient_permission_description": "Du är inte behörig att starta en röstsändning i det här rummet. Kontakta en rumsadministratör för att uppgradera dina behörigheter.", - "failed_insufficient_permission_title": "Kan inte starta en ny röstsändning", - "failed_no_connection_description": "Tyvärr kunde vi inte starta en inspelning just nu. Vänligen pröva igen senare.", - "failed_no_connection_title": "Anslutningsfel", - "failed_others_already_recording_description": "Någon annan spelar redan in en röstsändning. Vänta på att deras röstsändning tar slut för att starta en ny.", - "failed_others_already_recording_title": "Kan inte starta en ny röstsändning", - "go_live": "Börja sända", - "live": "Sänder", - "pause": "pausa röstsändning", - "play": "spela röstsändning", - "resume": "återuppta röstsändning" - }, - "voice_message": { - "cant_start_broadcast_description": "Du kan inte starta ett röstmeddelande eftersom du spelar in en direktsändning. Vänligen avsluta din direktsändning för att starta inspelning av ett röstmeddelande.", - "cant_start_broadcast_title": "Kan inte starta röstmeddelanden" - }, "voip": { "already_in_call": "Redan i samtal", "already_in_call_person": "Du är redan i ett samtal med den här personen.", @@ -3684,7 +3625,6 @@ "camera_disabled": "Din kamera är av", "camera_enabled": "Din kamera är fortfarande på", "cannot_call_yourself_description": "Du kan inte ringa till dig själv.", - "change_input_device": "Byt ingångsenhet", "close_lobby": "Stäng lobbyn", "connecting": "Ansluter", "connection_lost": "Anslutningen till servern har förlorats", @@ -3703,8 +3643,6 @@ "enable_camera": "Sätt på kamera", "enable_microphone": "Slå på mikrofonen", "expand": "Återgå till samtal", - "failed_call_live_broadcast_description": "Du kan inte starta ett samtal eftersom att du spelar in en direktsändning. Vänligen avsluta din direktsändning för att starta ett samtal.", - "failed_call_live_broadcast_title": "Kunde inte starta ett samtal", "hangup": "Lägg på", "hide_sidebar_button": "Göm sidopanel", "input_devices": "Ingångsenheter", diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 7d438ec2a41..8af8d0b2ea2 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -864,7 +864,6 @@ }, "udd": { "interactive_verification_button": "Звірити інтерактивно за допомогою емоджі", - "manual_verification_button": "Звірити вручну за допомогою тексту", "other_ask_verify_text": "Попросіть цього користувача звірити сеанс, або звірте його власноруч унизу.", "other_new_session_text": "%(name)s (%(userId)s) починає новий сеанс без його звірення:", "own_ask_verify_text": "Звірте інший сеанс за допомогою одного з варіантів знизу.", @@ -899,12 +898,6 @@ "incoming_sas_dialog_waiting": "Очікування підтвердження партнером…", "incoming_sas_user_dialog_text_1": "Звірте цього користувача щоб позначити його довіреним. Довіряння користувачам додає спокою якщо ви користуєтесь наскрізно зашифрованими повідомленнями.", "incoming_sas_user_dialog_text_2": "Звірка цього користувача позначить його сеанс довіреним вам, а ваш йому.", - "manual_device_verification_device_id_label": "ID сеансу", - "manual_device_verification_device_key_label": "Ключ сеансу", - "manual_device_verification_device_name_label": "Назва сеансу", - "manual_device_verification_footer": "Якщо вони не збігаються, безпека вашого спілкування ймовірно скомпрометована.", - "manual_device_verification_self_text": "Підтвердьте шляхом порівняння наступного рядка з рядком у користувацьких налаштуваннях вашого іншого сеансу:", - "manual_device_verification_user_text": "Підтвердьте сеанс цього користувача шляхом порівняння наступного рядка з рядком з їхніх користувацьких налаштувань:", "no_key_or_device": "Схоже, у вас немає ключа безпеки або будь-яких інших пристроїв, які ви можете підтвердити. Цей пристрій не зможе отримати доступ до старих зашифрованих повідомлень. Щоб підтвердити свою справжність на цьому пристрої, вам потрібно буде скинути ключі перевірки.", "no_support_qr_emoji": "Пристрій, який ви намагаєтесь звірити, не підтримує сканування QR-коду або звірення за допомогою емоджі, що є підтримувані %(brand)s. Спробуйте використати інший клієнт.", "other_party_cancelled": "Друга сторона скасувала звірення.", @@ -1021,10 +1014,6 @@ }, "error_user_not_logged_in": "Користувач не увійшов", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s завершує голосову трансляцію", - "you": "Ви завершили голосову трансляцію" - }, "m.call.answer": { "dm": "Виклик триває", "user": "%(senderName)s приєднується до виклику", @@ -1376,8 +1365,6 @@ "video_rooms_faq1_question": "Як створити відеокімнату?", "video_rooms_faq2_answer": "Так, стрічка бесіди показана поряд із відео.", "video_rooms_faq2_question": "Чи можу я писати текстові повідомлення під час відеовиклику?", - "voice_broadcast": "Голосові трансляції", - "voice_broadcast_force_small_chunks": "Примусово обмежити тривалість голосових трансляцій до 15 с", "wysiwyg_composer": "Розширений текстовий редактор" }, "labs_mjolnir": { @@ -1516,7 +1503,6 @@ "mute_description": "Ви не отримуватимете жодних сповіщень" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s розпочинає голосову трансляцію", "m.key.verification.request": "%(name)s робить запит на звірення" }, "onboarding": { @@ -2072,7 +2058,6 @@ "error_unbanning": "Не вдалося розблокувати", "events_default": "Надіслати повідомлення", "invite": "Запросити користувачів", - "io.element.voice_broadcast_info": "Голосові трансляції", "kick": "Вилучити користувачів", "m.call": "Розпочати %(brand)s викликів", "m.call.member": "Приєднатися до %(brand)s викликів", @@ -2709,7 +2694,6 @@ "warning": "ПОПЕРЕДЖЕННЯ: " }, "share": { - "link_title": "Посилання на кімнату", "permalink_message": "Посилання на вибране повідомлення", "permalink_most_recent": "Посилання на останнє повідомлення", "title_message": "Поділитися повідомленням кімнати", @@ -2796,13 +2780,6 @@ "upgraderoom": "Поліпшує кімнату до нової версії", "upgraderoom_permission_error": "Вам бракує дозволу на використання цієї команди.", "usage": "Використання", - "verify": "Звіряє користувача, сеанс та супровід відкритого ключа", - "verify_mismatch": "УВАГА: НЕ ВДАЛОСЯ ЗВІРИТИ КЛЮЧ! Ключем для %(userId)s та сеансу %(deviceId)s є «%(fprint)s», що не збігається з наданим ключем «%(fingerprint)s». Це може означати, що ваші повідомлення перехоплюють!", - "verify_nop": "Сеанс вже звірено!", - "verify_nop_warning_mismatch": "ПОПЕРЕДЖЕННЯ: сеанс вже звірено, але ключі НЕ ЗБІГАЮТЬСЯ!", - "verify_success_description": "Наданий вами ключ підпису збігається з ключем підпису, що ви отримали від сеансу %(deviceId)s %(userId)s. Сеанс позначено звіреним.", - "verify_success_title": "Звірений ключ", - "verify_unknown_pair": "Невідома пара (користувач, сеанс): (%(userId)s, %(deviceId)s)", "view": "Перегляд кімнати з вказаною адресою", "whois": "Показує відомості про користувача" }, @@ -3014,10 +2991,6 @@ "error_rendering_message": "Не вдалося завантажити це повідомлення", "historical_messages_unavailable": "Ви не можете переглядати давніші повідомлення", "in_room_name": " в %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s завершує голосову трансляцію", - "you": "Ви завершили голосову трансляцію" - }, "io.element.widgets.layout": "%(senderName)s оновлює макет кімнати", "load_error": { "no_permission": "У вас нема дозволу на перегляд повідомлення за вказаною позицією в стрічці цієї кімнати.", @@ -3545,38 +3518,6 @@ "switch_theme_dark": "Темна тема", "switch_theme_light": "Світла тема" }, - "voice_broadcast": { - "30s_backward": "Назад на 30 с", - "30s_forward": "Уперед на 30 с", - "action": "Голосові трансляції", - "buffering": "Буферизація…", - "confirm_listen_affirm": "Так, завершити мій запис", - "confirm_listen_description": "Якщо ви почнете слухати цю трансляцію наживо, ваш поточний запис трансляції наживо завершиться.", - "confirm_listen_title": "Слухати трансляцію наживо?", - "confirm_stop_affirm": "Так, припинити трансляцію", - "confirm_stop_description": "Ви впевнені, що хочете припинити пряму трансляцію? Це призведе до завершення трансляції, а повний запис буде доступний у кімнаті.", - "confirm_stop_title": "Припинити голосову трансляцію?", - "connection_error": "Помилка з'єднання - Запис призупинено", - "failed_already_recording_description": "Ви вже записуєте голосову трансляцію. Завершіть поточний запис, щоб розпочати новий.", - "failed_already_recording_title": "Не вдалося розпочати нову голосову трансляцію", - "failed_decrypt": "Невдалося розшифрувати голосову трансляцію", - "failed_generic": "Неможливо відтворити цю голосову трансляцію", - "failed_insufficient_permission_description": "Ви не маєте необхідних дозволів для початку голосової трансляції в цю кімнату. Зверніться до адміністратора кімнати, щоб розширити ваші дозволи.", - "failed_insufficient_permission_title": "Не вдалося розпочати нову голосову трансляцію", - "failed_no_connection_description": "На жаль, ми не можемо розпочати запис прямо зараз. Будь ласка, спробуйте пізніше.", - "failed_no_connection_title": "Помилка з'єднання", - "failed_others_already_recording_description": "Хтось інший вже записує голосову трансляцію. Зачекайте, поки запис завершиться, щоб розпочати новий.", - "failed_others_already_recording_title": "Не вдалося розпочати нову голосову трансляцію", - "go_live": "Слухати", - "live": "Наживо", - "pause": "призупинити голосову трансляцію", - "play": "відтворити голосову трансляцію", - "resume": "поновити голосову трансляцію" - }, - "voice_message": { - "cant_start_broadcast_description": "Ви не можете розпочати запис голосового повідомлення, оскільки зараз відбувається запис трансляції наживо. Завершіть трансляцію, щоб розпочати запис голосового повідомлення.", - "cant_start_broadcast_title": "Не можливо запустити запис голосового повідомлення" - }, "voip": { "already_in_call": "Вже у виклику", "already_in_call_person": "Ви вже спілкуєтесь із цією особою.", @@ -3596,7 +3537,6 @@ "camera_disabled": "Вашу камеру вимкнено", "camera_enabled": "Ваша камера досі увімкнена", "cannot_call_yourself_description": "Ви не можете подзвонити самим собі.", - "change_input_device": "Змінити пристрій вводу", "connecting": "З'єднання", "connection_lost": "Втрачено зʼєднання з сервером", "connection_lost_description": "Неможливо здійснювати виклики без з'єднання з сервером.", @@ -3613,8 +3553,6 @@ "enable_camera": "Увімкнути камеру", "enable_microphone": "Увімкнути мікрофон", "expand": "Повернутися до виклику", - "failed_call_live_broadcast_description": "Ви не можете розпочати виклик, оскільки зараз ведеться запис прямої трансляції. Будь ласка, заверште її, щоб розпочати виклик.", - "failed_call_live_broadcast_title": "Не вдалося розпочати виклик", "hangup": "Покласти слухавку", "hide_sidebar_button": "Сховати бічну панель", "input_devices": "Пристрої вводу", diff --git a/src/i18n/strings/vi.json b/src/i18n/strings/vi.json index 5ce36aed05f..3e1eaeaec14 100644 --- a/src/i18n/strings/vi.json +++ b/src/i18n/strings/vi.json @@ -792,7 +792,6 @@ }, "udd": { "interactive_verification_button": "Xác thực có tương tác bằng biểu tượng cảm xúc", - "manual_verification_button": "Xác thực thủ công bằng văn bản", "other_ask_verify_text": "Yêu cầu người dùng này xác thực phiên của họ hoặc xác minh theo cách thủ công bên dưới.", "other_new_session_text": "%(name)s (%(userId)s) đã đăng nhập vào một phiên mới mà không xác thực:", "own_ask_verify_text": "Xác minh phiên khác của bạn bằng một trong các tùy chọn bên dưới.", @@ -827,12 +826,6 @@ "incoming_sas_dialog_waiting": "Đang đợi bên kia xác nhận…", "incoming_sas_user_dialog_text_1": "Xác thực người dùng này để đánh dấu họ là đáng tin cậy. Người dùng đáng tin cậy giúp bạn yên tâm hơn khi sử dụng các tin nhắn được mã hóa end-to-end.", "incoming_sas_user_dialog_text_2": "Việc xác thực người dùng này sẽ đánh dấu phiên của họ là đáng tin cậy và cũng đánh dấu phiên của bạn là đáng tin cậy đối với họ.", - "manual_device_verification_device_id_label": "Định danh (ID) phiên", - "manual_device_verification_device_key_label": "Khóa phiên", - "manual_device_verification_device_name_label": "Tên phiên", - "manual_device_verification_footer": "Nếu chúng không khớp, sự bảo mật của việc giao tiếp của bạn có thể bị can thiệp.", - "manual_device_verification_self_text": "Xác nhận bằng cách so sánh những điều sau đây với Cài đặt người dùng trong phiên làm việc kia của bạn:", - "manual_device_verification_user_text": "Xác nhận phiên của người dùng này bằng cách so sánh phần sau với Cài đặt người dùng của họ:", "no_key_or_device": "Có vẻ như bạn không có Khóa Bảo mật hoặc bất kỳ thiết bị nào bạn có thể xác thực. Thiết bị này sẽ không thể truy cập vào các tin nhắn mã hóa cũ. Để xác minh danh tính của bạn trên thiết bị này, bạn sẽ cần đặt lại các khóa xác thực của mình.", "no_support_qr_emoji": "Thiết bị bạn đang cố xác thực không hỗ trợ quét mã QR hoặc xác minh biểu tượng cảm xúc, đó là những gì %(brand)s hỗ trợ. Hãy thử với một thiết bị đầu cuối khác.", "other_party_cancelled": "Người kia đã hủy xác thực.", @@ -949,10 +942,6 @@ }, "error_user_not_logged_in": "Người dùng đang không đăng nhập", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s đã kết thúc một cuộc phát thanh", - "you": "Bạn đã kết thúc một cuộc phát thanh" - }, "m.call.answer": { "dm": "Cuộc gọi đang diễn ra", "user": "%(senderName)s đã tham gia cuộc gọi", @@ -1288,7 +1277,6 @@ "video_rooms_faq1_question": "Tôi có thể tạo một phòng video bằng cách nào?", "video_rooms_faq2_answer": "Vâng, dòng thời gian trò chuyện được hiển thị cùng với video.", "video_rooms_faq2_question": "Tôi có thể sử dụng nhắn tin cùng lúc với gọi video không?", - "voice_broadcast": "Phát thanh", "wysiwyg_composer": "Trình soạn thảo văn bản giàu tính chất" }, "labs_mjolnir": { @@ -1400,7 +1388,6 @@ "mute_description": "Bạn sẽ không nhận bất kỳ thông báo nào" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s đã bắt đầu phát thanh", "m.key.verification.request": "%(name)s đang yêu cầu xác thực" }, "onboarding": { @@ -1895,7 +1882,6 @@ "error_unbanning": "Không thể bỏ cấm", "events_default": "Gửi tin nhắn", "invite": "Mời người dùng", - "io.element.voice_broadcast_info": "Phát thanh", "kick": "Loại bỏ người dùng", "m.call": "Bắt đầu %(brand)s cuộc gọi", "m.call.member": "Tham gia %(brand)s cuộc gọi", @@ -2496,7 +2482,6 @@ "warn_quit": "Cảnh báo trước khi bỏ thuốc lá" }, "share": { - "link_title": "Liên kết đến phòng", "permalink_message": "Liên kết đến tin nhắn đã chọn", "permalink_most_recent": "Liên kết đến tin nhắn gần đây nhất", "title_message": "Chia sẻ tin nhắn trong phòng", @@ -2583,13 +2568,6 @@ "upgraderoom": "Nâng cấp phòng lên phiên bản mới", "upgraderoom_permission_error": "Bạn không có quyền để dùng lệnh này.", "usage": "Cách sử dụng", - "verify": "Xác thực người dùng, thiết bị và tuple pubkey", - "verify_mismatch": "CẢNH BÁO: XÁC THỰC KHÓA THẤT BẠI! Khóa đăng nhập cho %(userId)s và thiết bị %(deviceId)s là \"%(fprint)s\" không khớp với khóa được cung cấp \"%(fingerprint)s\". Điều này có nghĩa là các thông tin liên lạc của bạn đang bị chặn!", - "verify_nop": "Thiết bị đã được xác thực rồi!", - "verify_nop_warning_mismatch": "CẢNH BÁO: phiên đã được xác thực, nhưng các khóa KHÔNG KHỚP!", - "verify_success_description": "Khóa đăng nhập bạn cung cấp khớp với khóa đăng nhập bạn nhận từ thiết bị %(deviceId)s của %(userId)s. Thiết bị được đánh dấu là đã được xác minh.", - "verify_success_title": "Khóa được xác thực", - "verify_unknown_pair": "Cặp (người dùng, phiên) không xác định: (%(userId)s, %(deviceId)s)", "view": "Phòng truyền hình với địa chỉ đã cho", "whois": "Hiển thị thông tin về người dùng" }, @@ -2786,10 +2764,6 @@ "error_rendering_message": "Không thể tải tin nhắn này", "historical_messages_unavailable": "Bạn khồng thể thấy các tin nhắn trước", "in_room_name": " ở %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s đã kết thúc một cuộc phát thanh", - "you": "Bạn đã kết thúc một cuộc phát thanh" - }, "io.element.widgets.layout": "%(senderName)s đã cập nhật bố trí của phòng", "load_error": { "no_permission": "Đã cố gắng tải một điểm cụ thể trong dòng thời gian của phòng này, nhưng bạn không có quyền xem tin nhắn được đề cập.", @@ -3280,34 +3254,6 @@ "switch_theme_dark": "Chuyển sang chế độ tối", "switch_theme_light": "Chuyển sang chế độ ánh sáng" }, - "voice_broadcast": { - "30s_backward": "30 giây trước", - "30s_forward": "30 giây kế tiếp", - "action": "Phát thanh", - "buffering": "Đang khởi tạo bộ đệm…", - "confirm_listen_affirm": "Vâng, ngừng ghi âm tôi", - "confirm_listen_description": "Nếu bạn bắt đầu nghe chương trình phát thanh trực tiếp này, quá trình ghi chương trình phát thanh trực tiếp hiện tại của bạn sẽ kết thúc.", - "confirm_listen_title": "Nghe phát thanh trực tiếp không?", - "confirm_stop_affirm": "Đúng rồi, dừng phát thanh", - "confirm_stop_description": "Bạn có chắc chắn muốn dừng phát sóng trực tiếp của mình không? Điều này sẽ kết thúc chương trình phát sóng và bản ghi đầy đủ sẽ có sẵn trong phòng.", - "confirm_stop_title": "Ngừng phát thanh trực tiếp?", - "connection_error": "Lỗi kết nối - Đã tạm dừng ghi âm", - "failed_already_recording_description": "Bạn hiện đang ghi một cuộc phát thanh. Kết thúc phát thanh để thực hiện một cái mới.", - "failed_already_recording_title": "Không thể bắt đầu cuộc phát thanh mới", - "failed_decrypt": "Không thể giải mã cuộc phát thanh", - "failed_generic": "Không thể nghe phát thanh", - "failed_insufficient_permission_description": "Bạn không có quyền để phát thanh trong phòng này. Hỏi một quản trị viên của phòng để nâng quyền của bạn.", - "failed_insufficient_permission_title": "Không thể bắt đầu cuộc phát thanh mới", - "failed_no_connection_description": "Thật không may là chúng tôi không thể bắt đầu ghi âm. Vui lòng thử lại.", - "failed_no_connection_title": "Lỗi kết nối", - "failed_others_already_recording_description": "Một người khác đang phát thanh. Hãy chờ cho đến khi họ ngừng rồi bạn mới bắt đầu phát thanh.", - "failed_others_already_recording_title": "Không thể bắt đầu cuộc phát thanh mới", - "go_live": "Phát trực tiếp", - "live": "Trực tiếp", - "pause": "Tạm dừng phát thanh", - "play": "nghe phát thanh", - "resume": "Tiếp tục phát thanh" - }, "voip": { "already_in_call": "Đang trong cuộc gọi", "already_in_call_person": "Bạn đang trong cuộc gọi với người này rồi.", @@ -3327,7 +3273,6 @@ "camera_disabled": "Camera của bạn đã tắt", "camera_enabled": "Camera của bạn vẫn đang được bật", "cannot_call_yourself_description": "Bạn không thể tự gọi chính mình.", - "change_input_device": "Đổi thiết bị đầu vào", "connecting": "Đang kết nối", "connection_lost": "Mất kết nối đến máy chủ", "connection_lost_description": "Bạn không thể gọi khi không có kết nối tới máy chủ.", @@ -3344,8 +3289,6 @@ "enable_camera": "Bật máy ghi hình", "enable_microphone": "Mở âm micrô", "expand": "Quay về cuộc gọi", - "failed_call_live_broadcast_description": "Bạn không thể bắt đầu gọi vì bạn đang ghi âm để cuộc phát thanh trực tiếp. Hãy ngừng phát thanh để bắt đầu gọi.", - "failed_call_live_broadcast_title": "Không thể bắt đầu cuộc gọi", "hangup": "Dập máy", "hide_sidebar_button": "Ẩn thanh bên", "input_devices": "Thiết bị đầu vào", diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index 99d5586a5cc..1ddb47fcc44 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -809,7 +809,6 @@ }, "udd": { "interactive_verification_button": "用表情符号交互式验证", - "manual_verification_button": "用文本手动验证", "other_ask_verify_text": "要求此用户验证其会话,或在下面手动进行验证。", "other_new_session_text": "%(name)s(%(userId)s)登录到未验证的新会话:", "own_ask_verify_text": "使用以下选项之一验证你的其他会话。", @@ -841,12 +840,6 @@ "incoming_sas_dialog_title": "收到验证请求", "incoming_sas_user_dialog_text_1": "验证此用户并将其标记为已信任。在收发端到端加密消息时,信任用户可让你更加放心。", "incoming_sas_user_dialog_text_2": "验证此用户会将其会话标记为已信任,与此同时,你的会话也会被此用户标记为已信任。", - "manual_device_verification_device_id_label": "会话 ID", - "manual_device_verification_device_key_label": "会话密钥", - "manual_device_verification_device_name_label": "会话名称", - "manual_device_verification_footer": "如果它们不匹配,你通讯的安全性可能已受损。", - "manual_device_verification_self_text": "通过比较下方内容和你别的会话中的用户设置来确认:", - "manual_device_verification_user_text": "通过比较下方内容和对方用户设置来确认此用户会话:", "no_key_or_device": "看起来你没有安全密钥或者任何其他可以验证的设备。 此设备将无法访问旧的加密消息。为了在这个设备上验证你的身份,你需要重置你的验证密钥。", "no_support_qr_emoji": "你正在尝试验证的设备不支持扫码QR码或表情符号验证,这是%(brand)s所支持的。用不同的客户端试试。", "other_party_cancelled": "另一方取消了验证。", @@ -1296,7 +1289,6 @@ "video_rooms_faq1_question": "我如何创建视频房间?", "video_rooms_faq2_answer": "是的,聊天时间线显示在视频旁。", "video_rooms_faq2_question": "我能在视频通话的同时使用文字聊天吗?", - "voice_broadcast": "语音广播", "wysiwyg_composer": "富文本编辑器" }, "labs_mjolnir": { @@ -1426,7 +1418,6 @@ "mute_description": "你不会收到任何通知" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s开始了语音广播", "m.key.verification.request": "%(name)s 正在请求验证" }, "onboarding": { @@ -1917,7 +1908,6 @@ "error_unbanning": "解除封禁失败", "events_default": "发送消息", "invite": "邀请用户", - "io.element.voice_broadcast_info": "语音广播", "kick": "移除用户", "m.call": "开始%(brand)s呼叫", "m.call.member": "加入%(brand)s呼叫", @@ -2457,7 +2447,6 @@ "warning": "警告:" }, "share": { - "link_title": "房间链接", "permalink_message": "选中消息的链接", "permalink_most_recent": "最新消息的链接", "title_message": "分享房间消息", @@ -2544,13 +2533,6 @@ "upgraderoom": "将房间升级到新版本", "upgraderoom_permission_error": "你没有权限使用此命令。", "usage": "用法", - "verify": "验证用户、会话和公钥元组", - "verify_mismatch": "警告:密钥验证失败!%(userId)s 的会话 %(deviceId)s 的签名密钥为 %(fprint)s,与提供的密钥 %(fingerprint)s 不符。这可能表示你的通讯已被截获!", - "verify_nop": "会话已验证!", - "verify_nop_warning_mismatch": "警告:会话已验证,然而密钥不匹配!", - "verify_success_description": "你提供的签名密钥与你从 %(userId)s 的会话 %(deviceId)s 获取的一致。此会话被标为已验证。", - "verify_success_title": "已验证的密钥", - "verify_unknown_pair": "未知用户会话配对:(%(userId)s:%(deviceId)s)", "whois": "显示关于用户的信息" }, "space": { @@ -3256,27 +3238,6 @@ "switch_theme_dark": "切换到深色模式", "switch_theme_light": "切换到浅色模式" }, - "voice_broadcast": { - "30s_backward": "后退30秒", - "30s_forward": "前进30秒", - "action": "语音广播", - "buffering": "正在缓冲……", - "confirm_stop_affirm": "是的,停止广播", - "confirm_stop_title": "停止直播吗?", - "failed_already_recording_description": "你已经在录制一个语音广播。请结束你当前的语音广播以开始新的语音广播。", - "failed_already_recording_title": "无法开始新的语音广播", - "failed_insufficient_permission_description": "你没有必要的权限在这个房间开始语音广播。请联系房间管理员以提升你的权限。", - "failed_insufficient_permission_title": "无法开始新的语音广播", - "failed_no_connection_description": "很遗憾,我们现在无法开始录音。请稍后再试。", - "failed_no_connection_title": "连接错误", - "failed_others_already_recording_description": "别人已经在录制语音广播了。等到他们的语音广播结束后再开始新的广播。", - "failed_others_already_recording_title": "无法开始新的语音广播", - "go_live": "开始直播", - "live": "实时", - "pause": "暂停语音广播", - "play": "播放语音广播", - "resume": "恢复语音广播" - }, "voip": { "already_in_call": "正在通话中", "already_in_call_person": "你正在与其通话。", @@ -3296,7 +3257,6 @@ "camera_disabled": "你的摄像头已关闭", "camera_enabled": "你的摄像头仍然处于启用状态", "cannot_call_yourself_description": "你不能打给自己。", - "change_input_device": "变更输入设备", "connecting": "连接中", "connection_lost": "已丢失与服务器的连接", "connection_lost_description": "你不能在未连接到服务器时进行呼叫。", @@ -3313,7 +3273,6 @@ "enable_camera": "启动相机", "enable_microphone": "取消静音麦克风", "expand": "返回通话", - "failed_call_live_broadcast_title": "无法开始通话", "hangup": "挂断", "hide_sidebar_button": "隐藏侧边栏", "input_devices": "输入设备", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 68b3694ee8c..584852748b1 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -865,7 +865,6 @@ }, "udd": { "interactive_verification_button": "透過表情符號互動來驗證", - "manual_verification_button": "透過文字手動驗證", "other_ask_verify_text": "要求此使用者驗證他們的工作階段,或在下方手動驗證。", "other_new_session_text": "%(name)s (%(userId)s)登入到未驗證的新工作階段:", "own_ask_verify_text": "使用下方的其中一個選項來驗證您其他工作階段。", @@ -900,12 +899,6 @@ "incoming_sas_dialog_waiting": "正在等待夥伴確認…", "incoming_sas_user_dialog_text_1": "驗證此工作階段,並標記為可受信任。由您將工作階段標記為可受信任後,可讓聊天夥伴傳送端到端加密訊息時能更加放心。", "incoming_sas_user_dialog_text_2": "驗證此使用者將會把他們的工作階段標記為受信任,並同時為他們標記您的工作階段為可信任。", - "manual_device_verification_device_id_label": "工作階段 ID", - "manual_device_verification_device_key_label": "工作階段金鑰", - "manual_device_verification_device_name_label": "工作階段名稱", - "manual_device_verification_footer": "如果它們不相符,則可能會威脅到您的通訊安全。", - "manual_device_verification_self_text": "透過將下列內容與您其他工作階段中的「使用者設定」所顯示的內容來確認:", - "manual_device_verification_user_text": "將以下內容與對方的「使用者設定」當中顯示的內容進行比對,來確認對方的工作階段:", "no_key_or_device": "您似乎沒有安全金鑰或其他可以驗證的裝置。此裝置將無法存取舊的加密訊息。為了在此裝置上驗證您的身分,您必須重設您的驗證金鑰。", "no_support_qr_emoji": "您正在嘗試驗證的裝置不支援掃描 QR Code 或表情符號驗證,這是 %(brand)s 所支援的。請嘗試使用其他客戶端。", "other_party_cancelled": "另一方取消了驗證。", @@ -1022,10 +1015,6 @@ }, "error_user_not_logged_in": "使用者未登入", "event_preview": { - "io.element.voice_broadcast_info": { - "user": "%(senderName)s 已結束語音廣播", - "you": "您結束了語音廣播" - }, "m.call.answer": { "dm": "通話進行中", "user": "%(senderName)s 已加入通話", @@ -1379,8 +1368,6 @@ "video_rooms_faq1_question": "我要如何建立視訊聊天室?", "video_rooms_faq2_answer": "可以,會在視訊畫面旁顯示聊天時間軸。", "video_rooms_faq2_question": "我可以在視訊通話的同時使用文字聊天嗎?", - "voice_broadcast": "語音廣播", - "voice_broadcast_force_small_chunks": "強制 15 秒語音廣播區塊長度", "wysiwyg_composer": "格式化文字編輯器" }, "labs_mjolnir": { @@ -1519,7 +1506,6 @@ "mute_description": "不會收到任何通知" }, "notifier": { - "io.element.voice_broadcast_chunk": "%(senderName)s 開始了語音廣播", "m.key.verification.request": "%(name)s 正在要求驗證" }, "onboarding": { @@ -2074,7 +2060,6 @@ "error_unbanning": "無法解除封鎖", "events_default": "傳送訊息", "invite": "邀請使用者", - "io.element.voice_broadcast_info": "語音廣播", "kick": "移除使用者", "m.call": "開始 %(brand)s 通話", "m.call.member": "加入 %(brand)s 通話", @@ -2704,7 +2689,6 @@ "warning": "警告: " }, "share": { - "link_title": "連結到聊天室", "permalink_message": "連結到選定的訊息", "permalink_most_recent": "連結到最近的訊息", "title_message": "分享聊天室訊息", @@ -2791,13 +2775,6 @@ "upgraderoom": "升級聊天室到新版本", "upgraderoom_permission_error": "您沒有使用此指令的必要權限。", "usage": "使用方法", - "verify": "驗證使用者、工作階段與公開金鑰組合", - "verify_mismatch": "警告:無法驗證金鑰!%(userId)s 與工作階段 %(deviceId)s 簽署的金鑰是「%(fprint)s」,並不符合提供的金鑰「%(fingerprint)s」。這可能代表您的通訊已被攔截!", - "verify_nop": "工作階段已驗證!", - "verify_nop_warning_mismatch": "警告:工作階段已驗證,但金鑰不相符!", - "verify_success_description": "您提供的簽署金鑰符合您從 %(userId)s 的工作階段收到的簽署金鑰 %(deviceId)s。工作階段標記為已驗證。", - "verify_success_title": "已驗證的金鑰", - "verify_unknown_pair": "未知(使用者,工作階段)配對:(%(userId)s, %(deviceId)s)", "view": "檢視指定聊天室的地址", "whois": "顯示關於使用者的資訊" }, @@ -3005,10 +2982,6 @@ "error_rendering_message": "無法載入此訊息", "historical_messages_unavailable": "您看不到更早的訊息", "in_room_name": " 在 %(room)s", - "io.element.voice_broadcast_info": { - "user": "%(senderName)s 結束了語音廣播", - "you": "您結束了語音廣播" - }, "io.element.widgets.layout": "%(senderName)s 已更新聊天室佈局", "load_error": { "no_permission": "嘗試載入此聊天室時間軸上的特定時間點,但您沒有權限檢視相關的訊息。", @@ -3536,38 +3509,6 @@ "switch_theme_dark": "切換至深色模式", "switch_theme_light": "切換至淺色模式" }, - "voice_broadcast": { - "30s_backward": "快退30秒", - "30s_forward": "快轉30秒", - "action": "語音廣播", - "buffering": "正在緩衝…", - "confirm_listen_affirm": "是的,結束我的錄製", - "confirm_listen_description": "若您開始收聽本次直播,您目前的直播錄製將會結束。", - "confirm_listen_title": "聆聽直播?", - "confirm_stop_affirm": "是的,停止廣播", - "confirm_stop_description": "您真的要停止即時廣播嗎?將會結束廣播,完整錄音存檔稍後將在聊天室中提供。", - "confirm_stop_title": "停止即時廣播?", - "connection_error": "連線錯誤 - 已暫停錄音", - "failed_already_recording_description": "您已經開始錄製語音廣播。請結束您目前的語音廣播以開始新的語音廣播。", - "failed_already_recording_title": "無法啟動新的語音廣播", - "failed_decrypt": "無法解密語音廣播", - "failed_generic": "無法播放此語音廣播", - "failed_insufficient_permission_description": "您沒有權限在此聊天室內開始語音廣播。請聯絡聊天室管理員升級您的權限。", - "failed_insufficient_permission_title": "無法啟動新的語音廣播", - "failed_no_connection_description": "很抱歉,現在無法錄音。請稍後再試。", - "failed_no_connection_title": "連線錯誤", - "failed_others_already_recording_description": "其他人已在錄製語音廣播。等待他們的語音廣播結束以開始新的。", - "failed_others_already_recording_title": "無法啟動新的語音廣播", - "go_live": "開始直播", - "live": "直播", - "pause": "暫停語音廣播", - "play": "播放語音廣播", - "resume": "恢復語音廣播" - }, - "voice_message": { - "cant_start_broadcast_description": "您無法開始語音訊息,因為您目前正在錄製直播。請結束您的直播以開始錄製語音訊息。", - "cant_start_broadcast_title": "無法開始語音訊息" - }, "voip": { "already_in_call": "已在通話中", "already_in_call_person": "您正在與此人通話。", @@ -3587,7 +3528,6 @@ "camera_disabled": "您的相機已關閉", "camera_enabled": "您的相機開啟中", "cannot_call_yourself_description": "您不能打電話給自己。", - "change_input_device": "變更輸入裝置", "connecting": "連線中", "connection_lost": "與伺服器的連線已遺失", "connection_lost_description": "您無法在未連線至伺服器的情況下通話。", @@ -3604,8 +3544,6 @@ "enable_camera": "開啟相機", "enable_microphone": "取消麥克風靜音", "expand": "回到通話", - "failed_call_live_broadcast_description": "您無法開始通話,因為您正在錄製直播。請結束您的直播以便開始通話。", - "failed_call_live_broadcast_title": "無法開始通話", "hangup": "掛斷", "hide_sidebar_button": "隱藏側邊欄", "input_devices": "輸入裝置", diff --git a/src/rageshake/submit-rageshake.ts b/src/rageshake/submit-rageshake.ts index ec529336d1e..0c00cc777a2 100644 --- a/src/rageshake/submit-rageshake.ts +++ b/src/rageshake/submit-rageshake.ts @@ -9,7 +9,8 @@ Please see LICENSE files in the repository root for full details. */ import { logger } from "matrix-js-sdk/src/logger"; -import { Method, MatrixClient, Crypto } from "matrix-js-sdk/src/matrix"; +import { Method, MatrixClient } from "matrix-js-sdk/src/matrix"; +import { CryptoApi } from "matrix-js-sdk/src/crypto-api"; import type * as Pako from "pako"; import { MatrixClientPeg } from "../MatrixClientPeg"; @@ -169,7 +170,7 @@ async function collectSynapseSpecific(client: MatrixClient, body: FormData): Pro /** * Collects crypto related information. */ -async function collectCryptoInfo(cryptoApi: Crypto.CryptoApi, body: FormData): Promise { +async function collectCryptoInfo(cryptoApi: CryptoApi, body: FormData): Promise { body.append("crypto_version", cryptoApi.getVersion()); const ownDeviceKeys = await cryptoApi.getOwnDeviceKeys(); @@ -198,7 +199,7 @@ async function collectCryptoInfo(cryptoApi: Crypto.CryptoApi, body: FormData): P /** * Collects information about secret storage and backup. */ -async function collectRecoveryInfo(client: MatrixClient, cryptoApi: Crypto.CryptoApi, body: FormData): Promise { +async function collectRecoveryInfo(client: MatrixClient, cryptoApi: CryptoApi, body: FormData): Promise { const secretStorage = client.secretStorage; body.append("secret_storage_ready", String(await cryptoApi.isSecretStorageReady())); body.append("secret_storage_key_in_account", String(await secretStorage.hasKey())); diff --git a/src/utils/device/dehydration.ts b/src/utils/device/dehydration.ts index f18c4c5c7cd..b27b3c54c26 100644 --- a/src/utils/device/dehydration.ts +++ b/src/utils/device/dehydration.ts @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import { logger } from "matrix-js-sdk/src/logger"; -import { Crypto } from "matrix-js-sdk/src/matrix"; +import { CryptoApi } from "matrix-js-sdk/src/crypto-api"; import { MatrixClientPeg } from "../../MatrixClientPeg"; @@ -21,7 +21,7 @@ import { MatrixClientPeg } from "../../MatrixClientPeg"; * * Dehydration can currently only be enabled by setting a flag in the .well-known file. */ -async function deviceDehydrationEnabled(crypto: Crypto.CryptoApi | undefined): Promise { +async function deviceDehydrationEnabled(crypto: CryptoApi | undefined): Promise { if (!crypto) { return false; } diff --git a/src/verification.ts b/src/verification.ts index 9c14a64c515..9f774964998 100644 --- a/src/verification.ts +++ b/src/verification.ts @@ -15,7 +15,6 @@ import { RightPanelPhases } from "./stores/right-panel/RightPanelStorePhases"; import { accessSecretStorage } from "./SecurityManager"; import UntrustedDeviceDialog from "./components/views/dialogs/UntrustedDeviceDialog"; import { IDevice } from "./components/views/right_panel/UserInfo"; -import { ManualDeviceKeyVerificationDialog } from "./components/views/dialogs/ManualDeviceKeyVerificationDialog"; import RightPanelStore from "./stores/right-panel/RightPanelStore"; import { IRightPanelCardState } from "./stores/right-panel/RightPanelStoreIPanelState"; import { findDMForUser } from "./utils/dm/findDMForUser"; @@ -53,11 +52,6 @@ export async function verifyDevice(matrixClient: MatrixClient, user: User, devic .getCrypto() ?.requestDeviceVerification(user.userId, device.deviceId); setRightPanel({ member: user, verificationRequestPromise }); - } else if (action === "legacy") { - Modal.createDialog(ManualDeviceKeyVerificationDialog, { - userId: user.userId, - device, - }); } }, }); diff --git a/test/unit-tests/components/views/dialogs/ManualDeviceKeyVerificationDialog-test.tsx b/test/unit-tests/components/views/dialogs/ManualDeviceKeyVerificationDialog-test.tsx deleted file mode 100644 index cb01b346dee..00000000000 --- a/test/unit-tests/components/views/dialogs/ManualDeviceKeyVerificationDialog-test.tsx +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * Copyright 2023 The Matrix.org Foundation C.I.C. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only - * Please see LICENSE files in the repository root for full details. - */ - -import React from "react"; -import { render, screen } from "jest-matrix-react"; -import { Device, MatrixClient } from "matrix-js-sdk/src/matrix"; - -import { stubClient } from "../../../../test-utils"; -import { ManualDeviceKeyVerificationDialog } from "../../../../../src/components/views/dialogs/ManualDeviceKeyVerificationDialog"; -import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext"; - -describe("ManualDeviceKeyVerificationDialog", () => { - let mockClient: MatrixClient; - - function renderDialog(userId: string, device: Device, onLegacyFinished: (confirm: boolean) => void) { - return render( - - - , - ); - } - - beforeEach(() => { - mockClient = stubClient(); - }); - - it("should display the device", () => { - // When - const deviceId = "XYZ"; - const device = new Device({ - userId: mockClient.getUserId()!, - deviceId, - displayName: "my device", - algorithms: [], - keys: new Map([[`ed25519:${deviceId}`, "ABCDEFGH"]]), - }); - const { container } = renderDialog(mockClient.getUserId()!, device, jest.fn()); - - // Then - expect(container).toMatchSnapshot(); - }); - - it("should display the device of another user", () => { - // When - const userId = "@alice:example.com"; - const deviceId = "XYZ"; - const device = new Device({ - userId, - deviceId, - displayName: "my device", - algorithms: [], - keys: new Map([[`ed25519:${deviceId}`, "ABCDEFGH"]]), - }); - const { container } = renderDialog(userId, device, jest.fn()); - - // Then - expect(container).toMatchSnapshot(); - }); - - it("should call onFinished and matrixClient.setDeviceVerified", () => { - // When - const deviceId = "XYZ"; - const device = new Device({ - userId: mockClient.getUserId()!, - deviceId, - displayName: "my device", - algorithms: [], - keys: new Map([[`ed25519:${deviceId}`, "ABCDEFGH"]]), - }); - const onFinished = jest.fn(); - renderDialog(mockClient.getUserId()!, device, onFinished); - - screen.getByRole("button", { name: "Verify session" }).click(); - - // Then - expect(onFinished).toHaveBeenCalledWith(true); - expect(mockClient.setDeviceVerified).toHaveBeenCalledWith(mockClient.getUserId(), deviceId, true); - }); - - it("should call onFinished and not matrixClient.setDeviceVerified", () => { - // When - const deviceId = "XYZ"; - const device = new Device({ - userId: mockClient.getUserId()!, - deviceId, - displayName: "my device", - algorithms: [], - keys: new Map([[`ed25519:${deviceId}`, "ABCDEFGH"]]), - }); - const onFinished = jest.fn(); - renderDialog(mockClient.getUserId()!, device, onFinished); - - screen.getByRole("button", { name: "Cancel" }).click(); - - // Then - expect(onFinished).toHaveBeenCalledWith(false); - expect(mockClient.setDeviceVerified).not.toHaveBeenCalled(); - }); -}); diff --git a/test/unit-tests/components/views/dialogs/UntrustedDeviceDialog-test.tsx b/test/unit-tests/components/views/dialogs/UntrustedDeviceDialog-test.tsx new file mode 100644 index 00000000000..3bfafa394bf --- /dev/null +++ b/test/unit-tests/components/views/dialogs/UntrustedDeviceDialog-test.tsx @@ -0,0 +1,59 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only + * Please see LICENSE files in the repository root for full details. + */ + +import React from "react"; +import { Device, MatrixClient, User } from "matrix-js-sdk/src/matrix"; +import { render, screen } from "jest-matrix-react"; + +import { stubClient } from "../../../../test-utils"; +import UntrustedDeviceDialog from "../../../../../src/components/views/dialogs/UntrustedDeviceDialog.tsx"; + +describe("", () => { + let client: MatrixClient; + let user: User; + let device: Device; + const onFinished = jest.fn(); + + beforeEach(() => { + client = stubClient(); + user = User.createUser("@alice:example.org", client); + user.setDisplayName("Alice"); + device = new Device({ deviceId: "device_id", userId: user.userId, algorithms: [], keys: new Map() }); + }); + + afterEach(() => { + onFinished.mockReset(); + }); + + function renderComponent() { + return render(); + } + + it("should display the dialog for the device of another user", () => { + const { asFragment } = renderComponent(); + expect(asFragment()).toMatchSnapshot(); + }); + + it("should display the dialog for the device of the current user", () => { + jest.spyOn(client, "getUserId").mockReturnValue(user.userId); + + const { asFragment } = renderComponent(); + expect(asFragment()).toMatchSnapshot(); + }); + + it("should call onFinished without parameter when Done is clicked", () => { + renderComponent(); + screen.getByRole("button", { name: "Done" }).click(); + expect(onFinished).toHaveBeenCalledWith(); + }); + + it("should call onFinished with sas when Interactively verify by emoji is clicked", () => { + renderComponent(); + screen.getByRole("button", { name: "Interactively verify by emoji" }).click(); + expect(onFinished).toHaveBeenCalledWith("sas"); + }); +}); diff --git a/test/unit-tests/components/views/dialogs/__snapshots__/ManualDeviceKeyVerificationDialog-test.tsx.snap b/test/unit-tests/components/views/dialogs/__snapshots__/ManualDeviceKeyVerificationDialog-test.tsx.snap deleted file mode 100644 index 1186f06f386..00000000000 --- a/test/unit-tests/components/views/dialogs/__snapshots__/ManualDeviceKeyVerificationDialog-test.tsx.snap +++ /dev/null @@ -1,231 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ManualDeviceKeyVerificationDialog should display the device 1`] = ` -
-
-