Compare commits

...

123 Commits

Author SHA1 Message Date
Timo
ae330deaf3 Only show to device encryption label if developer mode on (#3231)
Co-authored-by: Valere <bill.carson@valrsoft.com>
2025-04-24 11:50:59 +02:00
Robin
52aa0e916e Return to latest livekit-client version (2.11.3) (#3232)
This latest release of livekit-client fixes the regression observed in https://github.com/element-hq/element-call/issues/3219.
2025-04-24 11:49:48 +02:00
Timo
8be7c9a4dd Bump js-sdk (#3230) (part of: Fix matrixRTC js-sdk logs in rageshakes) 2025-04-24 10:01:39 +02:00
Timo
920fa217d5 Set ratchetWindowSize > 0, to enable rachet compatibility. (#3225) 2025-04-22 21:40:36 +02:00
Timo
1997502127 Fix matrixRTC js-sdk logs in rageshakes 2025-04-22 21:11:38 +02:00
Robin
389c8ccb30 Merge pull request #3223 from element-hq/robin/backport-revert-livekit
(Backport to v0.10.0) Revert livekit-client to 2.10.0
2025-04-22 17:49:29 +02:00
Robin
c528744ffb Revert livekit-client to 2.10.0
Closes https://github.com/element-hq/element-call/issues/3219.
2025-04-22 17:22:23 +02:00
Timo
8c555a1c97 bump js sdk to version that fixes logging (not on develop branch) (#3216) 2025-04-16 19:46:01 +02:00
Timo
0218ba03a6 Fix to-device encryption info label (#3209)
The label was shown also without checking that we use PerParticipantE2EE. Which is a prerequisite for toDevice transport. As a result the label was shown when not desired.
2025-04-16 19:41:51 +02:00
Timo
269a73b807 Improve tagging of Release versions of platform specific embedded packages (#3203) (#3212) 2025-04-15 12:28:50 +02:00
Timo
b0cae6277c Bump js-sdk to develop branch (#3207) 2025-04-15 10:04:48 +02:00
Timo
b2b933aa4a Update developer key transport setting description (#3195) 2025-04-14 09:56:11 +02:00
Timo
770b94eb44 Add RoomAndToDeviceKeyTransport and enable as default. (#3185) 2025-04-11 17:05:57 +02:00
Andrew Ferrazzutti
8c8a5e28a0 Fix Docker image tag in release notes (#3190)
The version tag of published Docker images includes a leading "v", so
include it in release notes.
2025-04-11 08:45:55 -04:00
fkwp
d0c76139a8 Merge pull request #3189 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.11.2
2025-04-11 13:52:13 +02:00
renovate[bot]
9c9d38cd95 Update dependency livekit-client to v2.11.2 2025-04-11 11:47:19 +00:00
Timo
3c0d81844f Add option to enable to-device-encryption (#3167)
* enable to-device-encryption

* add logging for key provider

* make rooms encrypted

* add dev setting to choose to-device or room encryption

* add indicator when to-device is used.
2025-04-11 10:07:50 +02:00
fkwp
1702b15abe Merge pull request #3179 from element-hq/fkwp/doc_update
Update  self-hosting.md
2025-04-11 00:15:31 +02:00
fkwp
e98b0ed1ed indentation 2025-04-11 00:06:03 +02:00
fkwp
ba22be175d Merge pull request #3183 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.11.1
2025-04-10 21:15:27 +02:00
renovate[bot]
e166f36ab5 Update dependency livekit-client to v2.11.1 2025-04-10 19:10:55 +00:00
fkwp
055f4d0193 Merge pull request #3181 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.11.0
2025-04-10 16:23:47 +02:00
renovate[bot]
7977101578 Update dependency livekit-client to v2.11.0 2025-04-10 14:09:33 +00:00
ElementRobot
5267940a8a Merge pull request #3180 from element-hq/actions/localazy-download
Localazy Download
2025-04-09 23:34:40 +02:00
fkwp
cb174aeaa6 Translations updates 2025-04-09 21:30:25 +00:00
fkwp
d97332f47a Merge branch 'livekit' into fkwp/doc_update 2025-04-09 20:30:24 +02:00
fkwp
6551ce8e18 Merge pull request #3178 from nordeck/fix-selfhosting-docs
Update self-hosting.md docs formatting
2025-04-09 20:30:01 +02:00
fkwp
3c5594b7e1 prettier 2025-04-09 13:34:58 +02:00
fkwp
eb9593a4e5 add information about CORS headers 2025-04-09 13:16:25 +02:00
fkwp
078f36c14a add Community Guides & How-Tos section 2025-04-09 13:04:41 +02:00
Kim Brose
7297dbcc00 Update self-hosting.md docs formatting 2025-04-09 11:32:56 +02:00
fkwp
ba382eef75 Merge pull request #3175 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.10.0
2025-04-08 16:45:36 +02:00
fkwp
23b1a5fff5 cleanup yarn.lock 2025-04-08 16:39:09 +02:00
fkwp
95fed3fc2d bump to 2.10.0 2025-04-08 09:52:48 +02:00
renovate[bot]
6398fd2783 Update dependency livekit-client to v2.9.9 2025-04-08 07:15:13 +00:00
fkwp
e8f0398f59 Merge pull request #3165 from element-hq/fkwp/update_readme
Update readme
2025-04-08 08:52:01 +02:00
Timo
a7dc289b2d Add yarn and bundled element call renovate group. (#3173) 2025-04-07 17:52:19 +02:00
fkwp
db10903ea0 Update README.md
Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>
2025-04-07 16:58:07 +02:00
fkwp
ca1410bc85 hint towards cs api 2025-04-07 11:30:34 +02:00
fkwp
c78360fce2 Update README.md
Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>
2025-04-05 19:29:08 +02:00
renovate[bot]
e5358e8609 Update dependency vite to v6.2.5 [SECURITY] (#3169)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-04 23:26:09 +02:00
Valere Fedronic
bc0ea20343 Default vite config to support using local build of crypto wasm (#3038)
* Devex: Default vite config to support using local build of crypto wasm

* use realpathSync and make it work with linked and not-linked
We need to use sync because an async defineConfig fails for the embedded exports.

* also allow just linking matrix-sdk-crypto-wasm (without js-sdk linking)
---------

Co-authored-by: Timo <toger5@hotmail.de>
Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>
Co-authored-by: Robin <robin@robin.town>
2025-04-04 23:24:42 +02:00
fkwp
ab8a86e451 prettier 2025-04-04 23:12:41 +02:00
fkwp
45b0a5c2a6 reordering 2025-04-04 23:12:41 +02:00
fkwp
c20aa5c1c8 rephrase Packaging and adding Figures 2025-04-04 23:12:41 +02:00
fkwp
d5481d8c20 indentation 2025-04-04 23:12:41 +02:00
fkwp
bef57b677c center images 2025-04-04 23:12:41 +02:00
fkwp
ce1c5437fc add note about in-app calling requirements 2025-04-04 23:12:41 +02:00
fkwp
46f059947b Merge pull request #3168 from element-hq/toger5/add-link-disable-enable-scripts
Add yarn scripts for disabling/enabling `.links.yaml`
2025-04-04 15:31:00 +02:00
fkwp
cf0cb2ebd2 Merge pull request #3153 from element-hq/renovate/github-actions
Pin dependencies
2025-04-04 15:28:57 +02:00
fkwp
2b35db3f39 Merge pull request #3145 from element-hq/toger5/github-release-note-categories
Add simple release note automation
2025-04-04 15:26:51 +02:00
Timo
a3f01a35c8 Add yarn scripts for disabling/enabling .links.yaml 2025-04-04 12:35:21 +02:00
Timo
14b3e49de6 Use PR- labels 2025-04-04 11:34:44 +02:00
Timo
6ceaa073a9 Add simple release note automation 2025-04-04 11:34:44 +02:00
Valere Fedronic
deac07dd13 Merge pull request #3163 from element-hq/valere/add_missing_to_device_permission
Widget: Add missing to device permission for encryption keys
2025-04-04 09:37:40 +02:00
Valere
f0126f41fb Widget: Add missing to device permission for encryption keys 2025-04-04 09:32:34 +02:00
Valere Fedronic
8bd44344e7 Merge pull request #3164 from element-hq/toger5/fix-src-js-sdk-imports
Fix lint and playwright errors caused by matrix-js-sdk/src import
2025-04-04 09:31:24 +02:00
Valere
9b945d00f7 cleaning: Remove deprecated config option for EC url 2025-04-04 09:18:58 +02:00
Valere
e9e82ca3e1 Cleaning + update docker compose pull policy for eweb 2025-04-04 09:12:27 +02:00
Timo
c91d9e5790 do the setting set later 2025-04-03 18:06:38 +02:00
Timo
7561e33e38 use localhost ew 2025-04-03 18:01:43 +02:00
Timo
afced3eb73 test fix experiment 2025-04-03 17:02:48 +02:00
Timo
70c97fa8be Fix lint errors caused by matrix-js-sdl/src import 2025-04-03 15:51:47 +02:00
Valere Fedronic
9acc1d1fe9 Merge pull request #3123 from element-hq/valere/playwright_widget_tests
Test: End to end integrated test for ElementCall in widget mode
2025-04-03 09:52:45 +02:00
renovate[bot]
622d91d7cc Update dependency vite to v6.2.4 [SECURITY] (#3151)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 11:12:25 +02:00
renovate[bot]
e7086ff8fc Pin dependencies 2025-04-01 02:20:37 +00:00
ElementRobot
5f0c3435fa Merge pull request #3152 from element-hq/actions/localazy-download
Localazy Download
2025-03-31 22:36:50 +02:00
fkwp
18972c2fb9 Translations updates 2025-03-31 20:33:53 +00:00
Hugh Nimmo-Smith
d1753c33f5 Use correct rageshake URL when running in embedded package + tests (#3132)
* Use correct rageshake URL when running in embedded package

It was incorrectly trying to use the one from config.json

* Refactor to add tests

* Empty mock config
2025-03-31 16:38:25 +01:00
Hugh Nimmo-Smith
e4c222a4e8 Expose version string in embedded SwiftPM and AAR (#3144)
* Expose version string in embedded SwiftPM and AAR

Implements https://github.com/element-hq/element-call/issues/3143

* Fix filename

* Fix location of `Version.kt`

* Use the right path for the sed replacement in the publishing workflow for Android

---------

Co-authored-by: Jorge Martín <jorgem@element.io>
2025-03-31 14:55:20 +01:00
fkwp
d12d616e28 Merge pull request #3136 from element-hq/fkwp/update_readme
Fix example JWT service .well-known endpoints in self-hosting.md
2025-03-31 15:08:57 +02:00
Timo
2073cd3ac1 Rename EULA to SSLA (#3135)
* Change EULA to SSLA
 - rename i18n fields
 - update the config property to `ssla` and deprecate `eula`
 - use `eula` instead of ssla in case it is provided in the config.

* fix default config

* completely remove eula fallback
2025-03-31 14:18:45 +02:00
Hugh Nimmo-Smith
9f2f1d8641 Improve documentation for how to use the embedded package (#3146) 2025-03-28 18:26:22 +00:00
Hugh Nimmo-Smith
fd2c1f6410 Clarify who is responsible for compliance and consent in relation to analytics (#3116)
It varies depending on if you are using the full or embedded package.
2025-03-28 14:18:53 +00:00
Hugh Nimmo-Smith
1be0733011 Always run build CI workflow (#3139)
As identified in https://github.com/element-hq/element-call/pull/3116#issuecomment-2759148857 depending on the contents of a PR it may not be possible to merge due to required workflows not actually being run.

This change will mean that the build CI workflow is run irrespective of the contents.
2025-03-28 15:06:00 +01:00
Hugh Nimmo-Smith
bfd4bb2ec1 Show URL params and environment variables in developer tab (#3134) 2025-03-27 16:35:31 -04:00
Robin
f845397b87 Merge pull request #3093 from element-hq/toger5/src-to-lib-import
Transition from consuming js-sdk source to `lib` (build output)
2025-03-27 16:13:05 -04:00
Robin
aab4efe03a Use type imports consistently 2025-03-27 16:09:59 -04:00
Robin
eb18cbef78 Consolidate imports 2025-03-27 16:04:03 -04:00
Robin
ae339ea5cc Fix formatting issues 2025-03-27 14:47:01 -04:00
Robin
33700d1529 Merge branch 'livekit' into toger5/src-to-lib-import 2025-03-27 14:35:08 -04:00
Robin
21140f6f2c Merge pull request #3095 from element-hq/robin/berry
Upgrade to Yarn v4 (Berry)
2025-03-27 14:21:10 -04:00
Robin
6927a92ad3 Improve comments in linker plugin 2025-03-27 14:16:16 -04:00
Robin
f99eb3c88f Merge branch 'livekit' into robin/berry 2025-03-27 14:07:24 -04:00
Robin
a993d8cd26 Streamline the linker hook messages 2025-03-27 14:05:10 -04:00
fkwp
53fa21b97a update .well-known example using the proposed endpoint routing 2025-03-26 22:36:47 +01:00
fkwp
a4f86492f9 Merge pull request #3130 from element-hq/fkwp/update_readme
Add endpoint routing to README.md
2025-03-26 13:48:09 +01:00
fkwp
79404fcb18 Update README.md
Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>
2025-03-26 13:20:51 +01:00
fkwp
defe880515 Update README.md
Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>
2025-03-26 13:20:27 +01:00
fkwp
fa0365c409 added MatrixRTC backend for completness 2025-03-26 00:07:13 +01:00
Timo
6a5b79143e Make pre-commit message more alerting 2025-03-25 20:26:23 +01:00
Timo
f868eca938 Add docs and git hooks 2025-03-25 20:13:34 +01:00
Timo
6fa218dd91 add links.disabled.yaml to yarn lock 2025-03-25 19:34:30 +01:00
fkwp
117b99d967 prettier 2025-03-25 17:14:18 +01:00
fkwp
7003e1f7d2 add section about endpoint routing 2025-03-25 17:09:54 +01:00
fkwp
ae7188cd65 added endpoint routing 2025-03-25 17:09:31 +01:00
fkwp
7de7886453 indentation 2025-03-25 17:07:58 +01:00
fkwp
efd08b4997 use MatrixRTC suggestion wrt. hostname and endpoints 2025-03-25 17:03:25 +01:00
Valere
0fbde40359 test: End to end integrated test for call widget 2025-03-25 16:09:38 +01:00
renovate[bot]
3ce9d71983 Update dependency vite to v6.2.3 [SECURITY] (#3125)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 15:53:30 +01:00
Hugh Nimmo-Smith
238bdea2b0 Fix compilation error when trying to use SwiftPM embedded package (#3124)
* Test SwiftPM build as part of release process

* Fix iOS embedded platform version as v17
2025-03-25 14:26:28 +00:00
Robin
fe382cfc0b Merge pull request #3053 from element-hq/robin/posthog-logout
Enable analytics only while authenticated
2025-03-24 10:14:48 -04:00
Robin
0ed1564d3e Merge branch 'livekit' into robin/posthog-logout 2025-03-24 10:10:28 -04:00
Robin
1138a21b57 Merge pull request #3118 from element-hq/robin/errors-outside-boundary
Fix join errors mistakenly showing a generic error screen
2025-03-21 17:20:52 -04:00
Robin
cd5ecb2352 Rename error boundary hook
It doesn't check whether it's actually used inside a GroupCallErrorBoundary, and it's generally useful for interacting with any error boundary, so I'm giving it a generic name to reflect this.
2025-03-21 15:17:41 -04:00
Robin
9a5dd10e27 Show errors that occur in GroupCallView using the error boundary
We were previously using the useGroupCallErrorBoundary hook to surface errors that happened during joining, but because that part is outside the GroupCallErrorBoundary it just ended up sending them to the app-level error boundary where they got displayed with a more generic message.
2025-03-21 14:59:27 -04:00
fkwp
eaf067f0dc Merge pull request #3117 from element-hq/fkwp/remove_fallback_matrixrtc-backend_from_netlify
remove fallback MatrixRTC backend from netlify PR builds
2025-03-21 19:00:32 +01:00
fkwp
41044ce974 remove fallback MatrixRTC backend 2025-03-21 18:55:43 +01:00
Hugh Nimmo-Smith
ff6365cfed One more --immutable 2025-03-21 17:19:34 +00:00
Hugh Nimmo-Smith
f820506184 Fix up CI 2025-03-21 17:17:23 +00:00
Hugh Nimmo-Smith
9bf046b714 Merge branch 'livekit' into robin/berry 2025-03-21 17:14:10 +00:00
Robin
cb14b727ba Merge branch 'livekit' into robin/berry 2025-03-14 11:59:21 -04:00
Robin
d633ec5fcd Update docs for Yarn Berry 2025-03-14 03:23:37 -04:00
Robin
0b26dc2f43 Create a plugin for linking other packages 2025-03-14 03:23:37 -04:00
Robin
31fb916b9d Enable CI to use Yarn Berry 2025-03-14 03:23:37 -04:00
Robin
95b37ea341 Upgrade to Yarn Berry 2025-03-14 03:23:37 -04:00
Robin
fee9841183 Remove the dependency on buffer
It's not generally available in browser environments / certain Yarn modes and can easily be replaced by TextEncoder.
2025-03-14 02:09:48 -04:00
Timo
6f93a037cf import cleanups 2025-03-13 18:00:24 -04:00
Timo
f0545ced65 make it work withotu js-sdk changes 2025-03-13 18:00:24 -04:00
Timo
46f5c44db0 temp2 2025-03-13 18:00:07 -04:00
Timo
adb5934f0b temp 2025-03-13 17:51:41 -04:00
Robin
65304473df Enable analytics only while authenticated
The one place where we should log out of PostHog and reset our analytics ID is when the user is logging out. This matches the behavior in Element Web and makes sense, I think, because logging out is essentially a request for the app to forget who you are. This means we should also start analytics at the point of logging in / reauthenticating.

I noticed while making this change that there was an unused branch in setClient, so I cleaned it up rather than making myself update it.
2025-03-05 09:12:18 -05:00
Robin
4919410ff0 Don't reset analytics ID when leaving calls
We shouldn't be calling PosthogAnalytics.instance.logout() when leaving the call in widget mode, because all this does is reset your analytics ID. In the big picture this is probably inflating our user count metrics.
2025-03-05 08:55:47 -05:00
174 changed files with 16672 additions and 9959 deletions

11
.githooks/post-commit Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/sh
FILE=.links.disabled.yaml
if test -f "$FILE"; then
# echo "$FILE exists. -> moving to .links.disabled.yaml"
mv .links.disabled.yaml .links.yaml
# echo "running yarn"
yarnLog=$(yarn)
echo "[yarn-linker] The post-commit hook has re-enabled .links.yaml."
exit 1
fi

12
.githooks/pre-commit Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/sh
FILE=".links.yaml"
if test -f "$FILE"; then
# echo "$FILE exists. -> moving to .links.disabled.yaml"
mv .links.yaml .links.disabled.yaml
# echo "running yarn"
x=$(yarn)
y=$(git add yarn.lock)
echo "[yarn-linker] The pre-commit hook has disabled .links.yaml and MODIFIED the yarn.lock file. Review the staged changes (the hook added yarn.lock, was this desired?) and run \`git commit \` again if they look okay. The post-commit hook will re-enable your links."
exit 1
fi

30
.github/realease.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
changelog:
categories:
- title: 🛠 Breaking Changes
labels:
- PR-Breaking-Change
- title: ✨ Features
labels:
- PR-Feature
- title: 🙌 Improvements
labels:
- PR-Improvement
- title: 📄 Documentation
labels:
- PR-Documentation
- title: 🐛 Bugfixes
labels:
- PR-Bug-Fix
- title: 💾 Developer Experience
labels:
- PR-Developer-Experience
- title: Others
labels:
- "*"
exclude:
labels:
- PR-Task
- dependencies
- title: 👒 Dependencies
labels:
- dependencies

View File

@@ -10,7 +10,7 @@ jobs:
pull-requests: read
steps:
- name: Add notice
uses: actions/github-script@v7
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
if: contains(github.event.pull_request.labels.*.name, 'X-Blocked')
with:
script: |

View File

@@ -26,7 +26,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: 📥 Download artifact
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ inputs.artifact_run_id }}
@@ -34,7 +34,7 @@ jobs:
path: dist
- name: Log in to container registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}

View File

@@ -28,13 +28,15 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Enable Corepack
run: corepack enable
- name: Yarn cache
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
cache: "yarn"
node-version-file: ".node-version"
- name: Install dependencies
run: "yarn install --frozen-lockfile"
run: "yarn install --immutable"
- name: Build full version
if: ${{ inputs.package == 'full' }}
run: "yarn run build:full"
@@ -58,7 +60,7 @@ jobs:
VITE_APP_VERSION: ${{ inputs.vite_app_version }}
NODE_OPTIONS: "--max-old-space-size=4096"
- name: Upload Artifact
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: build-output-${{ inputs.package }}
path: dist

View File

@@ -5,16 +5,8 @@ on:
- synchronize
- opened
- labeled
paths-ignore:
- ".github/ISSUE_TEMPLATE/**"
- ".github/CODEOWNERS"
- "docs/**"
push:
branches: [livekit, full-mesh]
paths-ignore:
- ".github/ISSUE_TEMPLATE/**"
- ".github/CODEOWNERS"
- "docs/**"
jobs:
build_full_element_call:
# Use the full package vite build

View File

@@ -46,7 +46,7 @@ jobs:
Exercise caution. Use test accounts.
- name: 📥 Download artifact
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
run-id: ${{ inputs.artifact_run_id }}

View File

@@ -8,13 +8,15 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Enable Corepack
run: corepack enable
- name: Yarn cache
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
cache: "yarn"
node-version-file: ".node-version"
- name: Install dependencies
run: "yarn install --frozen-lockfile"
run: "yarn install --immutable"
- name: Prettier
run: "yarn run prettier:check"
- name: i18n

View File

@@ -11,19 +11,48 @@ on:
push:
branches: [livekit]
env:
# We perform a dry run for all events except releases.
# This is to help make sure that we notice if the packaging process has become
# broken ahead of a release.
DRY_RUN: ${{ github.event_name != 'release' }}
# We should only use the hard coded test value for a dry run
VERSION: ${{ github.event_name == 'release' && github.event.release.tag_name || 'v0.0.0-pre.0' }}
jobs:
versioning:
name: Versioning
runs-on: ubuntu-latest
outputs:
DRY_RUN: ${{ steps.dry_run.outputs.DRY_RUN }}
PREFIXED_VERSION: ${{ steps.prefixed_version.outputs.PREFIXED_VERSION }}
UNPREFIXED_VERSION: ${{ steps.unprefixed_version.outputs.UNPREFIXED_VERSION }}
TAG: ${{ steps.tag.outputs.TAG }}
steps:
- name: Calculate VERSION
# We should only use the hard coded test value for a dry run
run: echo "VERSION=${{ github.event_name == 'release' && github.event.release.tag_name || 'v0.0.0-pre.0' }}" >> "$GITHUB_ENV"
- id: dry_run
name: Set DRY_RUN
# We perform a dry run for all events except releases.
# This is to help make sure that we notice if the packaging process has become
# broken ahead of a release.
run: echo "DRY_RUN=${{ github.event_name != 'release' }}" >> "$GITHUB_OUTPUT"
- id: prefixed_version
name: Set PREFIXED_VERSION
run: echo "PREFIXED_VERSION=${VERSION}" >> "$GITHUB_OUTPUT"
- id: unprefixed_version
name: Set UNPREFIXED_VERSION
# This just strips the leading character
run: echo "UNPREFIXED_VERSION=${VERSION:1}" >> "$GITHUB_OUTPUT"
- id: tag
# latest = a proper release
# other = anything else
name: Set tag
run: |
if [[ "${VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "TAG=latest" >> "$GITHUB_OUTPUT"
else
echo "TAG=other" >> "$GITHUB_OUTPUT"
fi
build_element_call:
needs: versioning
uses: ./.github/workflows/build-element-call.yaml
with:
vite_app_version: embedded-${{ github.event.release.tag_name || 'v0.0.0-pre.0' }} # Using ${{ env.VERSION }} here doesn't work
vite_app_version: embedded-${{ needs.versioning.outputs.PREFIXED_VERSION }}
package: embedded
secrets:
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
@@ -32,7 +61,7 @@ jobs:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
publish_tarball:
needs: build_element_call
needs: [build_element_call, versioning]
if: always()
name: Publish tarball
runs-on: ubuntu-latest
@@ -40,9 +69,9 @@ jobs:
contents: write # required to upload release asset
steps:
- name: Determine filename
run: echo "FILENAME_PREFIX=element-call-embedded-${VERSION:1}" >> "$GITHUB_ENV"
run: echo "FILENAME_PREFIX=element-call-embedded-${{ needs.versioning.outputs.UNPREFIXED_VERSION }}" >> "$GITHUB_ENV"
- name: 📥 Download built element-call artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id || github.run_id }}
@@ -53,7 +82,7 @@ jobs:
- name: Create Checksum
run: find ${{ env.FILENAME_PREFIX }} -type f -print0 | sort -z | xargs -0 sha256sum | tee ${{ env.FILENAME_PREFIX }}.sha256
- name: Upload
if: ${{ env.DRY_RUN == 'false' }}
if: ${{ needs.versioning.outputs.DRY_RUN == 'false' }}
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2
with:
files: |
@@ -61,10 +90,12 @@ jobs:
${{ env.FILENAME_PREFIX }}.sha256
publish_npm:
needs: build_element_call
needs: [build_element_call, versioning]
if: always()
name: Publish NPM
runs-on: ubuntu-latest
outputs:
ARTIFACT_VERSION: ${{ steps.artifact_version.outputs.ARTIFACT_VERSION }}
permissions:
contents: read
id-token: write # required for the provenance flag on npm publish
@@ -73,15 +104,16 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: 📥 Download built element-call artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id || github.run_id }}
name: build-output-embedded
path: embedded/web/dist
# n.b. We don't enable corepack here because we are using plain npm
- name: Setup node
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
node-version-file: .node-version
registry-url: "https://registry.npmjs.org"
@@ -89,17 +121,23 @@ jobs:
- name: Publish npm
working-directory: embedded/web
run: |
npm version ${{ env.VERSION }} --no-git-tag-version
npm version ${{ needs.versioning.outputs.PREFIXED_VERSION }} --no-git-tag-version
echo "ARTIFACT_VERSION=$(jq '.version' --raw-output package.json)" >> "$GITHUB_ENV"
npm publish --provenance --access public ${{ env.DRY_RUN == 'true' && '--dry-run' || '' }}
npm publish --provenance --access public --tag ${{ needs.versioning.outputs.TAG }} ${{ needs.versioning.outputs.DRY_RUN == 'true' && '--dry-run' || '' }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_RELEASE_TOKEN }}
- id: artifact_version
name: Output artifact version
run: echo "ARTIFACT_VERSION=${{env.ARTIFACT_VERSION}}" >> "$GITHUB_OUTPUT"
publish_android:
needs: build_element_call
needs: [build_element_call, versioning]
if: always()
name: Publish Android AAR
runs-on: ubuntu-latest
outputs:
ARTIFACT_VERSION: ${{ steps.artifact_version.outputs.ARTIFACT_VERSION }}
permissions:
contents: read
steps:
@@ -107,7 +145,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: 📥 Download built element-call artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id || github.run_id }}
@@ -121,7 +159,16 @@ jobs:
java-version: "17"
- name: Get artifact version
run: echo "ARTIFACT_VERSION=${VERSION:1}" >> "$GITHUB_ENV"
# Anything that is not a final release will be tagged as a snapshot
run: |
if [[ "${{ needs.versioning.outputs.TAG }}" == "latest" ]]; then
echo "ARTIFACT_VERSION=${{ needs.versioning.outputs.UNPREFIXED_VERSION }}" >> "$GITHUB_ENV"
else
echo "ARTIFACT_VERSION=${{ needs.versioning.outputs.UNPREFIXED_VERSION }}-SNAPSHOT" >> "$GITHUB_ENV"
fi
- name: Set version string
run: sed -i "s/0.0.0/${{ env.ARTIFACT_VERSION }}/g" embedded/android/lib/src/main/kotlin/io/element/android/call/embedded/Version.kt
- name: Publish AAR
working-directory: embedded/android
@@ -131,13 +178,19 @@ jobs:
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_RELEASE_PASSWORD }}
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_SIGNING_KEY_PASSWORD }}
run: ./gradlew publishAndReleaseToMavenCentral --no-daemon ${{ env.DRY_RUN == 'true' && '--dry-run' || '' }}
run: ./gradlew publishToMavenCentral --no-daemon ${{ needs.versioning.outputs.DRY_RUN == 'true' && '--dry-run' || '' }}
- id: artifact_version
name: Output artifact version
run: echo "ARTIFACT_VERSION=${{env.ARTIFACT_VERSION}}" >> "$GITHUB_OUTPUT"
publish_ios:
needs: build_element_call
needs: [build_element_call, versioning]
if: always()
name: Publish SwiftPM Library
runs-on: ubuntu-latest
outputs:
ARTIFACT_VERSION: ${{ steps.artifact_version.outputs.ARTIFACT_VERSION }}
permissions:
contents: read
steps:
@@ -147,7 +200,7 @@ jobs:
path: element-call
- name: 📥 Download built element-call artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id || github.run_id }}
@@ -165,7 +218,14 @@ jobs:
run: rsync -a --delete --exclude .git element-call/embedded/ios/ element-call-swift
- name: Get artifact version
run: echo "ARTIFACT_VERSION=${VERSION:1}" >> "$GITHUB_ENV"
run: echo "ARTIFACT_VERSION=${{ needs.versioning.outputs.UNPREFIXED_VERSION }}" >> "$GITHUB_ENV"
- name: Set version string
run: sed -i "s/0.0.0/${{ env.ARTIFACT_VERSION }}/g" element-call-swift/Sources/EmbeddedElementCall/EmbeddedElementCall.swift
- name: Test build
working-directory: element-call-swift
run: swift build
- name: Commit and tag
working-directory: element-call-swift
@@ -173,27 +233,33 @@ jobs:
git config --global user.email "ci@element.io"
git config --global user.name "Element CI"
git add -A
git commit -am "Release ${{ env.VERSION }}"
git commit -am "Release ${{ needs.versioning.outputs.PREFIXED_VERSION }}"
git tag -a ${{ env.ARTIFACT_VERSION }} -m "${{ github.event.release.html_url }}"
- name: Push
working-directory: element-call-swift
run: |
git push --tags ${{ env.DRY_RUN == 'true' && '--dry-run' || '' }}
git push --tags ${{ needs.versioning.outputs.DRY_RUN == 'true' && '--dry-run' || '' }}
- id: artifact_version
name: Output artifact version
run: echo "ARTIFACT_VERSION=${{env.ARTIFACT_VERSION}}" >> "$GITHUB_OUTPUT"
release_notes:
needs: [publish_npm, publish_android, publish_ios]
needs: [versioning, publish_npm, publish_android, publish_ios]
if: always()
name: Update release notes
runs-on: ubuntu-latest
permissions:
contents: write # to update release notes
steps:
- name: Get artifact version
run: echo "ARTIFACT_VERSION=${VERSION:1}" >> "$GITHUB_ENV"
- name: Log versions
run: |
echo "NPM: ${{ needs.publish_npm.outputs.ARTIFACT_VERSION }}"
echo "Android: ${{ needs.publish_android.outputs.ARTIFACT_VERSION }}"
echo "iOS: ${{ needs.publish_ios.outputs.ARTIFACT_VERSION }}"
- name: Add release notes
if: ${{ env.DRY_RUN == 'false' }}
if: ${{ needs.versioning.outputs.DRY_RUN == 'false' }}
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2
with:
append_body: true
@@ -207,19 +273,19 @@ jobs:
### NPM
```
npm install @element-hq/element-call-embedded@${{ env.ARTIFACT_VERSION }}
npm install @element-hq/element-call-embedded@${{ needs.publish_npm.outputs.ARTIFACT_VERSION }}
```
### Android AAR
```
dependencies {
implementation 'io.element.android:element-call-embedded:${{ env.ARTIFACT_VERSION }}'
implementation 'io.element.android:element-call-embedded:${{ needs.publish_android.outputs.ARTIFACT_VERSION }}'
}
```
### SwiftPM
```
.package(url: "https://github.com/element-hq/element-call-swift.git", from: "${{ env.ARTIFACT_VERSION }}")
.package(url: "https://github.com/element-hq/element-call-swift.git", from: "${{ needs.publish_ios.outputs.ARTIFACT_VERSION }}")
```

View File

@@ -31,7 +31,7 @@ jobs:
- name: Determine filename
run: echo "FILENAME_PREFIX=element-call-${VERSION:1}" >> "$GITHUB_ENV"
- name: 📥 Download built element-call artifact
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id || github.run_id }}
@@ -66,8 +66,6 @@ jobs:
name: Add docker release note
runs-on: ubuntu-latest
steps:
- name: Get artifact version
run: echo "ARTIFACT_VERSION=${VERSION:1}" >> "$GITHUB_ENV"
- name: Add release note
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2
with:
@@ -79,5 +77,5 @@ jobs:
The image provides a full build of Element Call that can be used both in standalone and as a widget (on a remote URL).
```
docker pull ghcr.io/element-hq/element-call:${{ env.ARTIFACT_VERSION }}
docker pull ghcr.io/element-hq/element-call:${{ env.VERSION }}
```

View File

@@ -10,13 +10,15 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Enable Corepack
run: corepack enable
- name: Yarn cache
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
cache: "yarn"
node-version-file: ".node-version"
- name: Install dependencies
run: "yarn install --frozen-lockfile"
run: "yarn install --immutable"
- name: Vitest
run: "yarn run test:coverage"
- name: Upload to codecov
@@ -31,13 +33,15 @@ jobs:
timeout-minutes: 10
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Enable Corepack
run: corepack enable
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
cache: "yarn"
node-version-file: ".node-version"
- name: Install dependencies
run: yarn install --frozen-lockfile
run: yarn install --immutable
- name: Install Playwright Browsers
run: yarn playwright install --with-deps
- name: Run backend components
@@ -48,7 +52,7 @@ jobs:
run: cp config/config.devenv.json public/config.json
- name: Run Playwright tests
run: yarn playwright test
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
if: ${{ !cancelled() }}
with:
name: playwright-report

View File

@@ -15,13 +15,16 @@ jobs:
- name: Checkout the code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
- name: Enable Corepack
run: corepack enable
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
cache: "yarn"
node-version-file: ".node-version"
- name: Install Deps
run: "yarn install --frozen-lockfile"
run: "yarn install --immutable"
- name: Prune i18n
run: "rm -R locales"
@@ -39,7 +42,7 @@ jobs:
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@dd2324fc52d5d43c699a5636bcf19fceaa70c284 # v7.0.7
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with:
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
branch: actions/localazy-download

13
.gitignore vendored
View File

@@ -9,10 +9,21 @@ dist-ssr
public/config.json
backend/synapse_tmp/*
/coverage
# Yarn
yarn-error.log
/.pnp.*
/.yarn/*
!/.yarn/patches
!/.yarn/plugins
!/.yarn/releases
!/.yarn/sdks
!/.yarn/versions
/.links.yaml
/.links.disabled.yaml
# Playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.cache/

91
.yarn/plugins/linker.cjs vendored Normal file
View File

@@ -0,0 +1,91 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
module.exports = {
name: "linker",
factory: (require) => ({
hooks: {
// Yarn's plugin system is very light on documentation. The best we have
// for this hook is simply the type definition in
// https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-core/sources/Plugin.ts
registerPackageExtensions: async (config, registerPackageExtension) => {
const { structUtils } = require("@yarnpkg/core");
const { parseSyml } = require("@yarnpkg/parsers");
const path = require("path");
const fs = require("fs");
const process = require("process");
// Create a descriptor that we can use to target our direct dependencies
const projectPath = config.projectCwd
.replace(/\\/g, "/")
.replace("/C:/", "C:/");
const manifestPath = path.join(projectPath, "package.json");
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
const selfDescriptor = structUtils.parseDescriptor(
`${manifest.name}@*`,
true,
);
// Load the list of linked packages
const linksPath = path.join(projectPath, ".links.yaml");
let linksFile;
try {
linksFile = fs.readFileSync(linksPath, "utf8");
} catch (e) {
return; // File doesn't exist, there's nothing to link
}
let links;
try {
links = parseSyml(linksFile);
} catch (e) {
console.error(".links.yaml has invalid syntax", e);
process.exit(1);
}
// Resolve paths and turn them into a Yarn package extension
const overrides = Object.fromEntries(
Object.entries(links).map(([name, link]) => [
name,
`portal:${path.resolve(config.projectCwd, link)}`,
]),
);
const overrideIdentHashes = new Set();
for (const name of Object.keys(overrides))
overrideIdentHashes.add(
structUtils.parseDescriptor(`${name}@*`, true).identHash,
);
// Extend our own package's dependencies with these local overrides
registerPackageExtension(selfDescriptor, { dependencies: overrides });
// Filter out the original dependencies from the package spec so Yarn
// actually respects the overrides
const filterDependencies = (original) => {
const pkg = structUtils.copyPackage(original);
pkg.dependencies = new Map(
Array.from(pkg.dependencies.entries()).filter(
([, value]) => !overrideIdentHashes.has(value.identHash),
),
);
return pkg;
};
// Patch Yarn's own normalizePackage method to use the above filter
const originalNormalizePackage = config.normalizePackage;
config.normalizePackage = function (pkg, extensions) {
return originalNormalizePackage.call(
this,
pkg.identHash === selfDescriptor.identHash
? filterDependencies(pkg)
: pkg,
extensions,
);
};
},
},
}),
};

3
.yarnrc.yml Normal file
View File

@@ -0,0 +1,3 @@
nodeLinker: node-modules
plugins:
- .yarn/plugins/linker.cjs

116
README.md
View File

@@ -45,30 +45,35 @@ organize the flow of the meeting.
**Emoji Reactions** Users can react with emojis 👍️ 🎉 👏 🤘, adding
engagement and interactivity to the conversation.
## 🚀 Deployment Options
## 🚀 Deployment & Packaging Options
Element Call can be packaged in two ways:
Element Call is developed using the
[Matrix js-sdk](https://github.com/matrix-org/matrix-js-sdk) with Matroska mode.
This allows the app to run either as a Standalone App directly connected to a
homeserver with login interfaces or it can be used as a widget within a Matrix
client.
**Full Package** Supports both **Standalone** and **Widget** mode. Hosted as
a static web page and accessed via a URL when used as a widget.
### 🖥️ Standalone Mode
**Embedded Package** Designed for **Widget mode** only. Bundled with a
messenger app for seamless integration. This is the recommended method for
embedding Element Call into a messenger app.
<p align="center">
<img src="./docs/element_call_standalone.drawio.png" alt="Element Call in Standalone Mode">
</p>
See the [here](./docs/embedded-standalone.md) for more information on the packages.
### Standalone mode
![Element Call in Standalone Mode](./docs/element_call_standalone.drawio.png)
In Standalone mode Element Call operates as an independent, full-featured video
conferencing web application, allowing users to join or host calls without
In Standalone mode, Element Call operates as an independent, full-featured video
conferencing web application, enabling users to join or host calls without
requiring a separate Matrix client.
### Widget mode embedded in Messenger Apps
### 📲 In-App Calling (Widget Mode in Messenger Apps)
![Element Call in Widget Mode](./docs/element_call_widget.drawio.png)
When used as a widget 🧩, Element Call is solely responsible on the core calling
functionality (MatrixRTC). Authentication, event handling, and room state
updates (via the Client-Server API) are handled by the hosting client.
Communication between Element Call and the client is managed through the widget
API.
<p align="center">
<img src="./docs/element_call_widget.drawio.png" alt="Element Call in Widget Mode">
</p>
Element Call can be embedded as a widget inside apps like
[**Element Web**](https://github.com/element-hq/element-web) or **Element X
@@ -80,6 +85,30 @@ and voice calls within Matrix rooms.
> [!IMPORTANT]
> Embedded packaging is recommended for Element Call in widget mode!
### 📦 Element Call Packaging
Element Call offers two packaging options: one for standalone or widget
deployment, and another for seamless widget-based integration into messenger
apps. Below is an overview of each option.
**Full Package** Supports both **Standalone** and **Widget** mode. It is
hosted as a static web page and can be accessed via a URL when used as a widget.
<p align="center">
<img src="./docs/full_package.drawio.png" alt="Element Call Full Package">
</p>
**Embedded Package** Designed specifically for **Widget mode** only. It is
bundled with a messenger app for seamless integration and this is the
recommended method for embedding Element Call.
<p align="center">
<img src="./docs/embedded_package.drawio.png" alt="Element Call Embedded Package">
</p>
For more details on the packages, see the
[Embedded vs. Standalone Guide](./docs/embedded-standalone.md).
## 🛠️ Self-Hosting
For operating and deploying Element Call on your own server, refer to the
@@ -91,20 +120,22 @@ For proper Element Call operation each site deployment needs a MatrixRTC backend
setup as outlined in the [Self-Hosting](#self-hosting). A typical federated site
deployment for three different sites A, B and C is depicted below.
![Element Call federated setup](./docs/Federated_Setup.drawio.png)
<p align="center">
<img src="./docs/Federated_Setup.drawio.png" alt="Element Call federated setup">
</p>
### Backend Discovery
MatrixRTC backend (according to
[MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143))
is announced by the homeserver's `.well-known/matrix/client` file and discovered
[MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143)) is
announced by the Matrix site's `.well-known/matrix/client` file and discovered
via the `org.matrix.msc4143.rtc_foci` key, e.g.:
```json
"org.matrix.msc4143.rtc_foci": [
{
"type": "livekit",
"livekit_service_url": "https://someurl.com"
"livekit_service_url": "https://matrix-rtc.example.com/livekit/jwt"
},
]
```
@@ -130,8 +161,11 @@ points them to a Matrix LiveKit JWT Auth Service via `livekit_service_url`.
The example below illustrates how backend selection works across **Matrix
federation**, using the setup from sites A, B, and C. It demonstrates backend
selection for **Matrix rooms 123 and 456**, which include users from different
homeservers.
![Element Call SFU selection over Matrix federation](./docs/SFU_selection.drawio.png)
homeservers.
<p align="center">
<img src="./docs/SFU_selection.drawio.png" alt="Element Call SFU selection over Matrix federation">
</p>
## 🌍 Translation
@@ -149,6 +183,7 @@ To get started clone and set up this project:
```sh
git clone https://github.com/element-hq/element-call.git
cd element-call
corepack enable
yarn
```
@@ -168,6 +203,10 @@ You're now ready to launch the development server:
yarn dev
```
See also:
- [Developing with linked packages](./linking.md)
### Backend
A docker compose file `dev-backend-docker-compose.yml` is provided to start the
@@ -193,21 +232,23 @@ yarn backend
### Playwright tests
Our Playwright tests run automatically as part of our CI along with our other tests,
on every pull request.
Our Playwright tests run automatically as part of our CI along with our other
tests, on every pull request.
You may need to follow instructions to set up your development environment for running
Playwright by following <https://playwright.dev/docs/browsers#install-browsers> and
You may need to follow instructions to set up your development environment for
running Playwright by following
<https://playwright.dev/docs/browsers#install-browsers> and
<https://playwright.dev/docs/browsers#install-system-dependencies>.
However the Playwright tests are run, an element-call instance must be running on
https://localhost:3000 (this is configured in `playwright.config.ts`) - this is what will
be tested.
However the Playwright tests are run, an element-call instance must be running
on https://localhost:3000 (this is configured in `playwright.config.ts`) - this
is what will be tested.
The local backend environment should be running for the test to work:
`yarn backend`
There are a few different ways to run the tests yourself. The simplest is to run:
There are a few different ways to run the tests yourself. The simplest is to
run:
```shell
yarn run test:playwright
@@ -227,13 +268,13 @@ The easiest way to develop new test is to use the codegen feature of Playwright:
npx playwright codegen
```
This will record your action and write the test code for you. Use the tool bar to test visibility, text content,
clicking.
This will record your action and write the test code for you. Use the tool bar
to test visibility, text content and clicking.
##### Investigate a failed test from the CI
In the failed action page, click on the failed job, then scroll down to the `upload-artifact` step.
You will find a link to download the zip report, as per:
In the failed action page, click on the failed job, then scroll down to the
`upload-artifact` step. You will find a link to download the zip report, as per:
```
Artifact playwright-report has been successfully uploaded! Final size is 1360358 bytes. Artifact ID is 2746265841
@@ -246,8 +287,9 @@ Unzip the report then use this command to open the report in your browser:
npx playwright show-report ~/Downloads/playwright-report/
```
Under the failed test there is a small icon looking like "3 columns" (next to test name file name),
click on it to see the live screenshots/console output.
Under the failed test there is a small icon looking like "3 columns" (next to
the test name file name), click on it to see the live screenshots/console
output.
### Test Coverage

28
WIDGET_TEST.md Normal file
View File

@@ -0,0 +1,28 @@
# Testing Element-Call in widget mode
When running `yarn backend` the latest element-web develop will be deployed and served on `http://localhost:8081`.
In a development environment, you might prefer to just use the `element-web` repo directly, but this setup is useful for CI/CD testing.
## Setup
The element-web configuration is modified to:
- Enable to use the local widget instance (`element_call.url` https://localhost:3000).
- Enable the labs features (`feature_group_calls`, `feature_element_call_video_rooms`).
The default configuration used by docker-compose is in `test-container/config.json`. There is a fixture for playwright
that uses
## Running the element-web instance
It is part of the existing backend setup. To start the backend, run:
```sh
yarn backend
```
Then open `http://localhost:8081` in your browser.
## Basic fixture
A base fixture is provided in `/playwright/fixtures/widget-user.ts` that will register two users that shares a room.

View File

@@ -0,0 +1,53 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "http://synapse.localhost:8008",
"server_name": "synapse.localhost"
}
},
"disable_custom_urls": false,
"disable_guests": false,
"disable_login_language_selector": false,
"disable_3pid_login": false,
"force_verification": false,
"brand": "Element",
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"default_widget_container_height": 280,
"default_country_code": "GB",
"show_labs_settings": false,
"features": {
"feature_element_call_video_rooms": true,
"feature_video_rooms": true,
"feature_group_calls": true,
"feature_release_announcement": false
},
"default_federate": true,
"default_theme": "light",
"room_directory": {
"servers": ["matrix.org"]
},
"enable_presence_by_hs_url": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
},
"setting_defaults": {
"breadcrumbs": true,
"feature_group_calls": true
},
"jitsi": {
"preferred_domain": "meet.element.io"
},
"element_call": {
"participant_limit": 8,
"brand": "Element Call"
},
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
}

View File

@@ -11,5 +11,5 @@
"features": {
"feature_use_device_session_member_events": true
},
"eula": "https://static.element.io/legal/online-EULA.pdf"
"ssla": "https://static.element.io/legal/element-software-and-services-license-agreement-uk-1.pdf"
}

View File

@@ -11,5 +11,5 @@
"features": {
"feature_use_device_session_member_events": true
},
"eula": "https://static.element.io/legal/online-EULA.pdf"
"ssla": "https://static.element.io/legal/element-software-and-services-license-agreement-uk-1.pdf"
}

View File

@@ -5,12 +5,6 @@
"server_name": "call-unstable.ems.host"
}
},
"livekit": {
"livekit_service_url": "https://livekit-jwt.call.element.dev"
},
"features": {
"feature_use_device_session_member_events": true
},
"posthog": {
"api_key": "phc_rXGHx9vDmyEvyRxPziYtdVIv0ahEv8A9uLWFcCi1WcU",
"api_host": "https://posthog-element-call.element.io"

View File

@@ -68,6 +68,18 @@ services:
networks:
- ecbackend
element-web:
image: ghcr.io/element-hq/element-web:develop
pull_policy: always
volumes:
- ./backend/ew.test.config.json:/app/config.json
environment:
ELEMENT_WEB_PORT: 81
ports:
- "8081:81"
networks:
- ecbackend
nginx:
# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout tls_localhost_key.pem -out tls_localhost_cert.pem -subj "/C=GB/ST=London/L=London/O=Alros/OU=IT Department/CN=localhost"
hostname: synapse.localhost

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 67 KiB

View File

@@ -1,8 +1,9 @@
## Element Call Docs
This folder contains documentation for Element Call setup and usage.
This folder contains documentation for setup, usage, and development of Element Call.
- [Embedded vs standalone mode](./embedded-standalone.md)
- [Url format and parameters](./url-params.md)
- [Global JS controls](./controls.md)
- [Self-Hosting](./self-hosting.md)
- [Developing with linked packages](./linking.md)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 909 KiB

After

Width:  |  Height:  |  Size: 929 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 868 KiB

After

Width:  |  Height:  |  Size: 886 KiB

View File

@@ -1,17 +1,32 @@
## Element Call packages
Element Call is available as two different packages: Full Package and Embedded Package. The Full Package is designed for standalone use, while the Embedded Package is designed for widget mode only. The table below provides a comparison of the two packages:
Element Call is available as two different packages: Full Package and Embedded Package.
| | Full Package | Embedded Package |
| ------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------- |
| **Supports use as standalone** | ✅ | ❌ |
| **Supports use as widget** | ✅ | ✅ |
| **Deployment mode** | Hosted as a static web page and accessed via a URL when used as a widget | Bundled within a messenger app for seamless integration |
| **Release artifacts** | Docker Image, Tarball | Tarball, NPM for Web, Android AAR, SwiftPM for iOS |
| **Recommended for** | Standalone/guest access usage | Embedding within messenger apps |
The Full Package is designed for standalone use, while the Embedded Package is designed for widget mode only.
For examples of how to use the platform specific release artifacts (e.g. Android AAR) see
the Element Messenger apps for: [Web](https://github.com/element-hq/element-web), [iOS](https://github.com/element-hq/element-x-ios) and [Android](https://github.com/element-hq/element-x-android).
The table below provides a comparison of the two packages:
| | Full Package | Embedded Package |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Supports use as standalone** | ✅ | ❌ |
| **Supports use as widget** | ✅ | ✅ |
| **Deployment mode** | Hosted as a static web page and accessed via a URL when used as a widget | Bundled within a messenger app for seamless integration |
| **Release artifacts** | Docker Image, Tarball | Tarball, NPM for Web, Android AAR, SwiftPM for iOS |
| **Recommended for** | Standalone/guest access usage | Embedding within messenger apps |
| **Responsibility for regulatory compliance** | The administrator that is deploying the app is responsible for compliance with any applicable regulations (e.g. privacy) | The developer of the messenger app is responsible for compliance |
| **Analytics consent** | Element Call will show a consent UI. | Element Call will not show a consent UI. The messenger app should only provide the embedded Element Call with the [analytics URL parameters](./url-params.md#embedded-only-parameters) if consent has been granted. |
| **Analytics data** | Element Call will send data to the Posthog, Sentry and Open Telemetry targets specified by the administrator in the `config.json` | Element Call will send data to the Posthog and Sentry targets specified in the URL parameters by the messenger app |
### Using the embedded package within a messenger app
Currently the best way to understand the necessary steps is to look at the implementations in the Element Messenger apps: [Web](https://github.com/element-hq/element-web/pull/29309), [iOS](https://github.com/element-hq/element-x-ios/pull/3939) and [Android](https://github.com/element-hq/element-x-android/pull/4470).
The basics are:
1. Add the appropriate platform dependency as given for a [release](https://github.com/element-hq/element-call/releases), or use the embedded tarball. e.g. `npm install @element-hq/element-call-embedded@0.9.0`
2. Include the assets from the platform dependency in the build process. e.g. copy the assets during a [Webpack](https://github.com/element-hq/element-web/blob/247cd8d56d832d006d7dfb919d1042529d712b59/webpack.config.js#L677-L682) build.
3. Use the `index.html` entrypointof the imported assets when you are constructing the WebView or iframe. e.g. using a [relative path in a webapp](https://github.com/element-hq/element-web/blob/247cd8d56d832d006d7dfb919d1042529d712b59/src/models/Call.ts#L680), or on the the Android [WebViewAssetLoader](https://github.com/element-hq/element-x-android/blob/fe5aab6588ecdcf9354a3bfbd9e97c1b31175a8f/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt#L20)
4. Set any of the [embedded-only URL parameters](./url-params.md#embedded-only-parameters) that you need.
## Widget vs standalone mode

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

39
docs/linking.md Normal file
View File

@@ -0,0 +1,39 @@
# Developing with linked packages
If you want to make changes to a package that Element Call depends on and see those changes applied in real time, you can create a link to a local copy of the package. Yarn has a command for this (`yarn link`), but it's not recommended to use it as it ends up modifying package.json with details specific to your development environment.
Instead, you can use our little 'linker' plugin. Create a file named `.links.yaml` in the Element Call project directory, listing the names and paths of any dependencies you want to link. For example:
```yaml
matrix-js-sdk: ../path/to/matrix-js-sdk
"@vector-im/compound-web": /home/alice/path/to/compound-web
```
Then run `yarn install`.
## Hooks
Changes in `.links.yaml` will also update `yarn.lock` when `yarn` is executed. The lockfile will then contain the local
version of the package which would not work on others dev setups or the github CI.
One always needs to run:
```bash
mv .links.yaml .links.disabled.yaml
yarn
```
before committing a change.
To make it more convenient to work with this linking system we added git hooks for your conviniece.
A `pre-commit` hook will run `mv .links.yaml .links.disabled.yaml`, `yarn` and `git add yarn.lock` if it detects
a `.links.yaml` file and abort the commit.
You will than need to check if the resulting changes are appropriate and commit again.
A `post-commit` hook will setup the linking as it was
before if a `.links.disabled.yaml` is present. It runs `mv .links.disabled.yaml .links.yaml` and `yarn`.
To activate the hooks automatically configure git with
```bash
git config --local core.hooksPath .githooks/
```

View File

@@ -1,5 +1,9 @@
# Self-Hosting Element Call
> [!NOTE]
> For In-App calling (Element X, Element Web, Element Desktop) use-case only
> section [Prerequisites](#Prerequisites) is required.
## Prerequisites
> [!IMPORTANT]
@@ -30,8 +34,9 @@ required for Element Call to work properly:
sync v2 API that allows them to correctly track the state of the room. This is
required by Element Call to track room state reliably.
If you're using [Synapse](https://github.com/element-hq/synapse/) as your homeserver, you'll need
to additionally add the following config items to `homeserver.yaml` to comply with Element Call:
If you're using [Synapse](https://github.com/element-hq/synapse/) as your
homeserver, you'll need to additionally add the following config items to
`homeserver.yaml` to comply with Element Call:
```yaml
experimental_features:
@@ -50,9 +55,10 @@ rc_message:
# Note key sharing events are bursty
per_second: 0.5
burst_count: 30
rc_delayed_event_mgmt:
# This needs to match at least the heart-beat frequency plus a bit of headroom
# Currently the heart-beat is every 5 seconds which translates into a rate of 0.2s
rc_delayed_event_mgmt:
per_second: 1
burst_count: 20
```
@@ -64,35 +70,99 @@ required for each site deployment.
![MSC4195 compatible setup](MSC4195_setup.drawio.png)
As depicted above, Element Call requires a
As depicted above in the `example.com` site deployment, Element Call requires a
[Livekit SFU](https://github.com/livekit/livekit) alongside a
[Matrix Livekit JWT auth service](https://github.com/element-hq/lk-jwt-service)
to implement
[MSC4195: MatrixRTC using LiveKit backend](https://github.com/hughns/matrix-spec-proposals/blob/hughns/matrixrtc-livekit/proposals/4195-matrixrtc-livekit.md).
#### Matrix site endpoint routing
In the context of MatrixRTC, we suggest using a single hostname for backend
communication by implementing endpoint routing within a reverse proxy setup. For
the example above, this results in:
| Service | Endpoint | Example |
| -------- | ------- | ------- |
| [Livekit SFU](https://github.com/livekit/livekit) WebSocket signalling connection | `/livekit/sfu` | `matrix-rtc.example.com/livekit/sfu` |
| [Matrix Livekit JWT auth service](https://github.com/element-hq/lk-jwt-service) | `/livekit/jwt` | `matrix-rtc.example.com/livekit/jwt` |
Using Nginx, you can achieve this by:
```jsonc
server {
...
location ^~ /livekit/jwt/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# JWT Service running at port 8080
proxy_pass http://localhost:8080/;
}
location ^~ /livekit/sfu/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_send_timeout 120;
proxy_read_timeout 120;
proxy_buffering off;
proxy_set_header Accept-Encoding gzip;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# LiveKit SFU websocket connection running at port 7880
proxy_pass http://localhost:7880/;
}
}
```
#### MatrixRTC backend announcement
> [!IMPORTANT]
> As defined in
> [MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143)
> MatrixRTC backend must be announced to the client via your **homeserver's
> `.well-known/matrix/client`**. The configuration is a list of Foci configs:
> MatrixRTC backend must be announced to the client via your **Matrix site's
> `.well-known/matrix/client`** file (e.g.
> `example.com/.well-known/matrix/client` matching the site deployment example
> from above). The configuration is a list of Foci configs:
```json
"org.matrix.msc4143.rtc_foci": [
{
"type": "livekit",
"livekit_service_url": "https://someurl.com"
},
{
"type": "livekit",
"livekit_service_url": "https://livekit2.com"
"livekit_service_url": "https://matrix-rtc.example.com/livekit/jwt"
},
{
"type": "another_foci",
"props_for_another_foci": "val"
"type": "livekit",
"livekit_service_url": "https://matrix-rtc-2.example.com/livekit/jwt"
},
{
"type": "nextgen_new_foci_type",
"props_for_nextgen_foci": "val"
}
]
```
Make sure this file is served with the correct MIME type (`application/json`).
Additionally, ensure the appropriate CORS headers are set to allow web clients
to access it across origins. For more details, refer to the
[Matrix Client-Server API: 2. Web Browser Clients](https://spec.matrix.org/latest/client-server-api/#web-browser-clients).
```
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: X-Requested-With, Content-Type, Authorization
```
> [!NOTE]
> Most `org.matrix.msc4143.rtc_foci` configurations will only have one entry in
> the array
## Building Element Call
> [!NOTE]
@@ -105,6 +175,7 @@ source. First, clone and install the package:
```sh
git clone https://github.com/element-hq/element-call.git
cd element-call
corepack enable
yarn
yarn build
```
@@ -164,3 +235,30 @@ federation, so as to prevent spam registrations (if you keep registrations open)
and to ensure Element Call continues to work in case any user decides to log in
to their Element Call account using the standard Element app and joins normal
rooms that Element Call cannot handle.
# 📚 Community Guides & How-Tos
Looking for real-world tips, tutorials, and experiences from the community?
Below is a collection of blog posts, walkthroughs, and how-tos created by other
self-hosters and developers working with Element Call.
> [!NOTE]
> These resources are community-created and may reflect different setups or
> versions. Use them alongside the official documentation for best results.
## 🌐 Blog Posts & Articles
- [How to resolve stuck MatrixRTC calls](https://sspaeth.de/2025/02/how-to-resolve-stuck-matrixrtc-calls/)
## 🛠️ How-Tos & Tutorials
- [MatrixRTC aka Element-call setup (Geek warning)](https://sspaeth.de/2024/11/sfu/)
- [MatrixRTC with Synology Container Manager (Docker)](https://ztfr.de/matrixrtc-with-synology-container-manager-docker/)
- [Encrypted & Scalable Video Calls: How to deploy an Element Call backend with Synapse Using Docker-Compose](https://willlewis.co.uk/blog/posts/deploy-element-call-backend-with-synapse-and-docker-compose/)
- [Element Call einrichten: Verschlüsselte Videoanrufe mit Element X und Matrix Synapse](https://www.cleveradmin.de/blog/2025/04/matrixrtc-element-call-backend-einrichten/)
## 🤝 Want to Contribute?
Have a guide or blog post you'd like to share? Open a
[PR](https://github.com/element-hq/element-call/pulls) to add it here, or drop a
link in the [#webrtc:matrix.org](https://matrix.to/#/#webrtc:matrix.org) room.

View File

@@ -27,7 +27,7 @@ android {
}
mavenPublishing {
publishToMavenCentral(SonatypeHost.S01)
publishToMavenCentral(SonatypeHost.S01, automaticRelease = true)
signAllPublications()

View File

@@ -0,0 +1,8 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
const val VERSION = "0.0.0"

View File

@@ -5,7 +5,7 @@ import PackageDescription
let package = Package(
name: "EmbeddedElementCall",
platforms: [.iOS(.v17_6)],
platforms: [.iOS(.v17)],
products: [
.library(
name: "EmbeddedElementCall",

View File

@@ -1,5 +1,14 @@
//
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import Foundation
public let appURL = Bundle.module.url(forResource: "index", withExtension: "html", subdirectory: "dist")
public let bundle = Bundle.module
public let version = "0.0.0"

View File

@@ -4,7 +4,9 @@
},
"action": {
"close": "Затвори",
"copy_link": "Копиране на връзката",
"go": "Напред",
"invite": "Покана",
"no": "Не",
"register": "Регистрация",
"remove": "Премахни",

View File

@@ -4,40 +4,139 @@
},
"action": {
"close": "Zavřít",
"go": "Pokračovat",
"copy_link": "Kopírovat odkaz",
"edit": "Upravit",
"go": "Přejít",
"invite": "Pozvat",
"lower_hand": "Snížení ruky",
"no": "Ne",
"pick_reaction": "Vybrat reakci",
"raise_hand": "Zvednutí ruky",
"register": "Registrace",
"remove": "Odstranit",
"show_less": "Zobrazit méně",
"show_more": "Zobrazit více",
"sign_in": "Přihlásit se",
"sign_out": "Odhlásit se"
"sign_out": "Odhlásit se",
"submit": "Odeslat",
"upload_file": "Nahrát soubor"
},
"analytics_notice": "Účastí v této beta verzi souhlasíte se shromažďováním anonymních údajů, které používáme ke zlepšování produktu. Více informací o tom, které údaje sledujeme, najdete v našich <2>Zásadách ochrany osobních údajů</2> a <6>Zásadách používání souborů cookie</6>.",
"app_selection_modal": {
"continue_in_browser": "Pokračovat v prohlížeči",
"open_in_app": "Otevřít v aplikaci",
"text": "Jste připraveni se připojit?",
"title": "Vybrat aplikaci"
},
"call_ended_view": {
"create_account_button": "Vytvořit účet",
"create_account_prompt": "<0>Proč neskončit nastavením hesla, abyste mohli účet použít znovu?</0><1>Budete si moci nechat své jméno a nastavit si avatar pro budoucí hovory </1>",
"not_now_button": "Teď ne, vrátit se na domovskou obrazovku"
"feedback_done": "<0>Děkujeme za vaši zpětnou vazbu! </0>",
"feedback_prompt": "<0>Rádi si vyslechneme vaši zpětnou vazbu, abychom mohli vaše prostředí vylepšit. </0>",
"headline": "{{displayName}}, váš hovor skončil.",
"not_now_button": "Teď ne, vrátit se na domovskou obrazovku",
"reconnect_button": "Znovu připojit",
"survey_prompt": "Jak to probíhalo?"
},
"call_name": "Název hovoru",
"common": {
"analytics": "Analytika",
"audio": "Zvuk",
"avatar": "Avatar",
"back": "Zpět",
"display_name": "Zobrazované jméno",
"encrypted": "Šifrováno",
"home": "Domov",
"loading": "Načítání…",
"next": "Další",
"options": "Možnosti",
"password": "Heslo",
"preferences": "Předvolby",
"profile": "Profil",
"reaction": "Reakce",
"reactions": "Reakce",
"settings": "Nastavení",
"username": "Uživatelské jméno"
"unencrypted": "Nešifrováno",
"username": "Uživatelské jméno",
"video": "Video"
},
"developer_mode": {
"crypto_version": "Kryptografická verze: {{version}}",
"debug_tile_layout_label": "Ladění rozložení dlaždic",
"device_id": "ID zařízení: {{id}}",
"duplicate_tiles_label": "Počet dalších kopií dlaždic na účastníka",
"environment_variables": "Proměnné prostředí",
"hostname": "Název hostitele: {{hostname}}",
"livekit_server_info": "Informace o serveru LiveKit",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix ID: {{id}}",
"show_connection_stats": "Zobrazit statistiky připojení",
"show_non_member_tiles": "Zobrazit dlaždice pro nečlenská média",
"url_params": "Parametry URL",
"use_new_membership_manager": "Použijte novou implementaci volání MembershipManager"
},
"disconnected_banner": "Připojení k serveru bylo ztraceno.",
"error": {
"call_is_not_supported": "Volání není podporováno",
"call_not_found": "Volání nebylo nalezeno",
"call_not_found_description": "<0>Zdá se, že tento odkaz nepatří k žádnému existujícímu volání. Zkontrolujte, zda máte správný odkaz, nebo <1>vytvořte nový</1>.</0>",
"connection_lost": "Spojení ztraceno",
"connection_lost_description": "Hovor byl přerušen.",
"e2ee_unsupported": "Nekompatibilní prohlížeč",
"e2ee_unsupported_description": "Váš webový prohlížeč nepodporuje šifrované hovory. Mezi podporované prohlížeče patří Chrome, Safari a Firefox 117+.",
"generic": "Něco se pokazilo.",
"generic_description": "Odeslání protokolů ladění nám pomůže vystopovat problém.",
"insufficient_capacity": "Nedostatečná kapacita",
"insufficient_capacity_description": "Server dosáhl své maximální kapacity a v tuto chvíli se nemůžete připojit k hovoru. Zkuste to později nebo se obraťte na správce serveru, pokud problém přetrvává.",
"matrix_rtc_focus_missing": "Server není nakonfigurován pro práci s {{brand}}. Obraťte se na správce serveru (Doména: {{domain}}, Kód chyby: {{ errorCode }}).",
"open_elsewhere": "Otevřeno na jiné kartě",
"open_elsewhere_description": "{{brand}} byl otevřen v jiné záložce. Pokud to nezní správně, zkuste stránku znovu načíst.",
"unexpected_ec_error": "Došlo k neočekávané chybě (<0>Error Code:</0> <1>{{ errorCode }}</1>). Obraťte se prosím na správce serveru."
},
"group_call_loader": {
"banned_body": "Byl jste vykázán z místnosti.",
"banned_heading": "Zabanován",
"call_ended_body": "Byl jste vyřazen z hovoru.",
"call_ended_heading": "Hovor ukončen",
"knock_reject_body": "Vaše žádost o připojení byla zamítnuta.",
"knock_reject_heading": "Přístup odepřen",
"reason": "Důvod"
},
"hangup_button_label": "Ukončit hovor",
"header_label": "Domov Element Call",
"header_participants_label": "Účastníci",
"invite_modal": {
"link_copied_toast": "Odkaz zkopírován do schránky",
"title": "Pozvat na tento hovor"
},
"join_existing_call_modal": {
"join_button": "Ano, připojit se",
"text": "Tento hovor již existuje, chcete se připojit?",
"title": "Připojit se k existujícimu hovoru?"
},
"layout_grid_label": "Mřížka",
"layout_spotlight_label": "Soustředěný mód",
"lobby": {
"join_button": "Připojit se k hovoru"
"ask_to_join": "Žádost o připojení k hovoru",
"join_as_guest": "Připojte se jako host",
"join_button": "Připojit se k hovoru",
"leave_button": "Zpět na poslední",
"waiting_for_invite": "Žádost odeslána! Čekáme na povolení k připojení..."
},
"log_in": "Přihlášení",
"logging_in": "Přihlašování se…",
"login_auth_links": "<0>Vytvořit účet</0> Or <2>Jako host</2>",
"login_auth_links_prompt": "Ještě nejste zaregistrováni?",
"login_subheading": "Chcete-li pokračovat na Element",
"login_title": "Přihlášení",
"microphone_off": "Mikrofon vypnutý",
"microphone_on": "Mikrofon zapnutý",
"mute_microphone_button_label": "Ztlumit mikrofon",
"participant_count_one": "{{count, number}}",
"participant_count_few": "{{count, number}}",
"participant_count_other": "{{count, number}}",
"qr_code": "QR kód",
"rageshake_button_error_caption": "Znovu zkusit odeslat protokoly",
"rageshake_request_modal": {
"body": "Jiný uživatel v tomto hovoru má problémy. Abychom mohli diagnostikovat problém, rádi bychom shromáždili protokoly ladění.",
"title": "Žádost o protokoly ladění"
@@ -45,22 +144,79 @@
"rageshake_send_logs": "Poslat ladící záznam",
"rageshake_sending": "Posílání…",
"rageshake_sending_logs": "Posílání ladícího záznamu…",
"rageshake_sent": "Díky!",
"recaptcha_dismissed": "Recaptcha byla zamítnuta",
"recaptcha_not_loaded": "Recaptcha se nenačetla",
"recaptcha_ssla_caption": "Tato stránka je chráněna ReCAPTCHA a platí zde <2>Ochrana osobních údajů</2> a <6>Podmínky služby</6> od Google.<9></9>Kliknutím na \"Registrovat\" souhlasíte s naší <12>Licenční smlouvou na software a služby (SSLA)</12>",
"register": {
"passwords_must_match": "Hesla se musí shodovat",
"registering": "Registrování…"
},
"register_auth_links": "<0>Už máte účet?</0><1><0>Přihlásit se</0> Or <2>Jako host</2></1>",
"register_confirm_password_label": "Potvrdit heslo",
"register_heading": "Vytvořte si účet",
"return_home_button": "Vrátit se na domácí obrazovku",
"room_auth_view_continue_button": "Pokračovat",
"room_auth_view_ssla_caption": "Kliknutím na „Připojit se k hovoru nyní“ souhlasíte s naší <2>Licenční smlouvou o softwaru a službách (SSLA) </2>",
"screenshare_button_label": "Sdílet obrazovku",
"settings": {
"audio_tab": {
"effect_volume_description": "Upravit hlasitost přehrávání reakcí a efektů zvednutých rukou.",
"effect_volume_label": "Hlasitost zvukového efektu"
},
"developer_tab_title": "Vývojář",
"devices": {
"camera": "Fotoaparát",
"camera_numbered": "Fotoaparát {{n}}",
"default": "Výchozí",
"default_named": "Výchozí <2> ({{name}}) </2>",
"microphone": "Mikrofon",
"microphone_numbered": "Mikrofon {{n}}",
"speaker": "Reproduktor",
"speaker_numbered": "Reproduktor {{n}}"
},
"feedback_tab_body": "Pokud se potýkáte s problémy nebo byste nám jen chtěli poskytnout zpětnou vazbu, pošlete nám prosím krátký popis níže.",
"feedback_tab_description_label": "Vaše zpětná vazba",
"feedback_tab_h4": "Dát feedback",
"feedback_tab_send_logs_label": "Zahrnout ladící záznamy"
"feedback_tab_send_logs_label": "Zahrnout ladící záznamy",
"feedback_tab_thank_you": "Děkujeme, obdrželi jsme vaši zpětnou vazbu!",
"feedback_tab_title": "Zpětná vazba",
"opt_in_description": "<0></0><1></1>Souhlas můžete odvolat zrušením zaškrtnutí tohoto políčka. Pokud jste právě v hovoru, toto nastavení se projeví po jeho skončení.",
"preferences_tab": {
"developer_mode_label": "Vývojářský režim",
"developer_mode_label_description": "Povolte vývojářský režim a zobrazte kartu nastavení vývojáře.",
"introduction": "Zde můžete nakonfigurovat další možnosti pro lepší zážitek.",
"reactions_play_sound_description": "Přehrát zvukový efekt, když někdo odešle reakci do hovoru.",
"reactions_play_sound_label": "Přehrát reakční zvuky",
"reactions_show_description": "Zobrazit animaci, když někdo pošle reakci.",
"reactions_show_label": "Zobrazit reakce",
"show_hand_raised_timer_description": "Zobrazit časovač, když účastník zvedne ruku",
"show_hand_raised_timer_label": "Zobrazit dobu trvání zvednutí ruky"
}
},
"star_rating_input_label_one": "{{count}} hvězdička",
"star_rating_input_label_few": "{{count}} hvězdičky",
"star_rating_input_label_other": "{{count}} hvězdiček",
"start_new_call": "Zahájit nový hovor",
"start_video_button_label": "Spustit video",
"stop_screenshare_button_label": "Sdílení obrazovky",
"stop_video_button_label": "Zastavit video",
"submitting": "Odeslání...",
"switch_camera": "Přepnout kameru",
"unauthenticated_view_body": "Nejste registrovaní? <2>Vytvořit účet</2>",
"unauthenticated_view_login_button": "Přihlásit se ke svému účtu",
"version": "Verze: {{version}}"
"unauthenticated_view_ssla_caption": "Kliknutím na tlačítko \"Přejít\" souhlasíte s naší <2>Licenční smlouvou na software a služby (SSLA)</2>",
"unmute_microphone_button_label": "Zrušit ztlumení mikrofonu",
"version": "{{productName}}verze: {{version}}",
"video_tile": {
"always_show": "Vždy zobrazit",
"camera_starting": "Načítání videa...",
"change_fit_contain": "Přizpůsobit rámu",
"collapse": "Sbalit",
"expand": "Rozbalit",
"mute_for_me": "Pro mě ztlumit",
"muted_for_me": "Pro mě ztlumené",
"volume": "Hlasitost",
"waiting_for_media": "Čekání na média..."
}
}

View File

@@ -65,12 +65,14 @@
"debug_tile_layout_label": "Kachel-Layout debuggen",
"device_id": "Geräte-ID: {{id}}",
"duplicate_tiles_label": "Anzahl zusätzlicher Kachelkopien pro Teilnehmer",
"environment_variables": "Umgebungsvariablen",
"hostname": "Hostname: {{hostname}}",
"livekit_server_info": "LiveKit-Server Informationen",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix-ID: {{id}}",
"show_connection_stats": "Verbindungsstatistiken anzeigen",
"show_non_member_tiles": "Kacheln für Nicht-Mitgliedermedien anzeigen",
"url_params": "URL-Parameter",
"use_new_membership_manager": "Neuen MembershipManager verwenden"
},
"disconnected_banner": "Die Verbindung zum Server wurde getrennt.",
@@ -142,9 +144,9 @@
"rageshake_sending": "Senden …",
"rageshake_sending_logs": "Sende Debug-Protokolle …",
"rageshake_sent": "Danke!",
"recaptcha_caption": "Diese Seite wird durch reCAPTCHA geschützt und es gelten Googles <2>Datenschutzerklärung</2> und <6>Nutzungsbedingungen</6>. <9></9>Mit einem Klick auf „Registrieren“ akzeptierst du unseren <2>Endbenutzer-Lizenzvertrag (EULA)</2>",
"recaptcha_dismissed": "Recaptcha abgelehnt",
"recaptcha_not_loaded": "Recaptcha nicht geladen",
"recaptcha_ssla_caption": "Diese Website wird durch ReCAPTCHA geschützt, und es gelten die Google <2>Datenschutzbestimmungen</2> sowie die <6>Nutzungsbedingungen</6>.<9></9> Durch das Klicken auf \"Registrieren\" wird der <12>Software- und Dienstleistungslizenzvereinbarung (SSLA)</12> zugestimmt.",
"register": {
"passwords_must_match": "Passwörter müssen übereinstimmen",
"registering": "Registrierung …"
@@ -154,7 +156,7 @@
"register_heading": "Erstelle Dein Konto",
"return_home_button": "Zurück zur Startseite",
"room_auth_view_continue_button": "Weiter",
"room_auth_view_eula_caption": "Mit einem Klick auf „Weiter“ akzeptierst du unseren <2>Endbenutzer-Lizenzvertrag (EULA)</2>",
"room_auth_view_ssla_caption": "Durch das Klicken auf \"Anruf jetzt beitreten\" wird dem <2>Software and Services License Agreement (SSLA)</2> zugestimmt.",
"screenshare_button_label": "Bildschirm teilen",
"settings": {
"audio_tab": {
@@ -200,8 +202,8 @@
"submitting": "Sende …",
"switch_camera": "Kamera wechseln",
"unauthenticated_view_body": "Noch nicht registriert? <2>Konto erstellen</2>",
"unauthenticated_view_eula_caption": "Mit einem Klick auf „Los gehts“ akzeptierst du unseren <2>Endbenutzer-Lizenzvertrag (EULA)</2>",
"unauthenticated_view_login_button": "Melde dich mit deinem Konto an",
"unauthenticated_view_ssla_caption": "Durch das Klicken auf \"Weiter\" wird dem <2>Software and Services License Agreement (SSLA)</2> zugestimmt.",
"unmute_microphone_button_label": "Mikrofon einschalten",
"version": "{{productName}} Version: {{version}}",
"video_tile": {

View File

@@ -65,13 +65,16 @@
"debug_tile_layout_label": "Debug tile layout",
"device_id": "Device ID: {{id}}",
"duplicate_tiles_label": "Number of additional tile copies per participant",
"environment_variables": "Environment variables",
"hostname": "Hostname: {{hostname}}",
"livekit_server_info": "LiveKit Server Info",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix ID: {{id}}",
"show_connection_stats": "Show connection statistics",
"show_non_member_tiles": "Show tiles for non-member media",
"use_new_membership_manager": "Use the new implementation of the call MembershipManager"
"url_params": "URL parameters",
"use_new_membership_manager": "Use the new implementation of the call MembershipManager",
"use_to_device_key_transport": "Use to device key transport. This will fallback to room key transport when another call member sent a room key"
},
"disconnected_banner": "Connectivity to the server has been lost.",
"error": {
@@ -142,9 +145,9 @@
"rageshake_sending": "Sending…",
"rageshake_sending_logs": "Sending debug logs…",
"rageshake_sent": "Thanks!",
"recaptcha_caption": "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy</2> and <6>Terms of Service</6> apply.<9></9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)</12>",
"recaptcha_dismissed": "Recaptcha dismissed",
"recaptcha_not_loaded": "Recaptcha not loaded",
"recaptcha_ssla_caption": "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy</2> and <6>Terms of Service</6> apply.<9></9>By clicking \"Register\", you agree to our <12>Software and Services License Agreement (SSLA)</12>",
"register": {
"passwords_must_match": "Passwords must match",
"registering": "Registering…"
@@ -154,7 +157,7 @@
"register_heading": "Create your account",
"return_home_button": "Return to home screen",
"room_auth_view_continue_button": "Continue",
"room_auth_view_eula_caption": "By clicking \"Continue\", you agree to our <2>End User Licensing Agreement (EULA)</2>",
"room_auth_view_ssla_caption": "By clicking \"Join call now\", you agree to our <2>Software and Services License Agreement (SSLA)</2>",
"screenshare_button_label": "Share screen",
"settings": {
"audio_tab": {
@@ -200,8 +203,8 @@
"submitting": "Submitting…",
"switch_camera": "Switch camera",
"unauthenticated_view_body": "Not registered yet? <2>Create an account</2>",
"unauthenticated_view_eula_caption": "By clicking \"Go\", you agree to our <2>End User Licensing Agreement (EULA)</2>",
"unauthenticated_view_login_button": "Login to your account",
"unauthenticated_view_ssla_caption": "By clicking \"Go\", you agree to our <2>Software and Services License Agreement (SSLA)</2>",
"unmute_microphone_button_label": "Unmute microphone",
"version": "{{productName}} version: {{version}}",
"video_tile": {

View File

@@ -4,7 +4,10 @@
},
"action": {
"close": "Cerrar",
"copy_link": "Copiar vínculo",
"go": "Comenzar",
"invite": "Invitar",
"no": "No",
"register": "Registrarse",
"remove": "Eliminar",
"sign_in": "Iniciar sesión",
@@ -12,6 +15,12 @@
"submit": "Enviar"
},
"analytics_notice": "Al participar en esta beta, consientes a la recogida de datos anónimos, los cuales usaremos para mejorar el producto. Puedes encontrar más información sobre que datos recogemos en nuestra <2>Política de privacidad</2> y en nuestra <5>Política sobre Cookies</5>.",
"app_selection_modal": {
"continue_in_browser": "Continuar en el navegador",
"open_in_app": "Abrir en la aplicación",
"text": "¿Listo para unirte?",
"title": "Selecciona aplicación"
},
"call_ended_view": {
"create_account_button": "Crear cuenta",
"create_account_prompt": "<0>¿Por qué no mantienes tu cuenta estableciendo una contraseña?</0><1>Podrás mantener tu nombre y establecer un avatar para usarlo en futuras llamadas</1>",
@@ -50,7 +59,6 @@
"rageshake_send_logs": "Enviar registros de depuración",
"rageshake_sending": "Enviando…",
"rageshake_sending_logs": "Enviando registros de depuración…",
"recaptcha_caption": "Este sitio está protegido por ReCAPTCHA y se aplican la <2>Política de Privacidad</2> y los <6>Términos de Servicio de Google.<9></9>Al hacer clic en \"Registrar\", aceptas nuestro <12>Contrato de Licencia de Usuario Final (CLUF)</12>",
"recaptcha_dismissed": "Recaptcha cancelado",
"recaptcha_not_loaded": "No se ha cargado el Recaptcha",
"register": {
@@ -60,7 +68,6 @@
"register_auth_links": "<0>¿Ya tienes una cuenta?</0><1><0>Iniciar sesión</0> o <2>Acceder como invitado</2></1>",
"register_confirm_password_label": "Confirmar contraseña",
"return_home_button": "Volver a la pantalla de inicio",
"room_auth_view_eula_caption": "Al hacer clic en \"Unirse a la llamada ahora\", aceptas nuestro <2>Contrato de Licencia de Usuario Final (CLUF)</2>",
"screenshare_button_label": "Compartir pantalla",
"settings": {
"developer_tab_title": "Desarrollador",
@@ -76,7 +83,6 @@
"star_rating_input_label_other": "{{count}} estrellas",
"submitting": "Enviando…",
"unauthenticated_view_body": "¿No estás registrado todavía? <2>Crear una cuenta</2>",
"unauthenticated_view_eula_caption": "Al hacer clic en \"Comenzar\", aceptas nuestro <2>Contrato de Licencia de Usuario Final (CLUF)</2>",
"unauthenticated_view_login_button": "Iniciar sesión en tu cuenta",
"version": "Versión: {{version}}"
}

View File

@@ -5,16 +5,23 @@
"action": {
"close": "Sulge",
"copy_link": "Kopeeri link",
"edit": "Muuda",
"go": "Jätka",
"invite": "Kutsu",
"lower_hand": "Lase käsi alla",
"no": "Ei",
"pick_reaction": "Vali reaktsioon",
"raise_hand": "Anna käega märku",
"register": "Registreeru",
"remove": "Eemalda",
"show_less": "Näita vähem",
"show_more": "Näita rohkem",
"sign_in": "Logi sisse",
"sign_out": "Logi välja",
"submit": "Saada"
"submit": "Saada",
"upload_file": "Laadi fail üles"
},
"analytics_notice": "Nõustudes selle beetaversiooni kasutamisega sa nõustud ka toote arendamiseks kasutatavate anonüümsete andmete kogumisega. Täpsemat teavet kogutavate andmete kohta leiad meie <2>Privaatsuspoliitikast</2> ja meie <5>Küpsiste kasutamise reeglitest</5>.",
"analytics_notice": "Nõustudes selle beetaversiooni kasutamisega, sa nõustud ka toote arendamiseks kasutatavate anonüümsete andmete kogumisega. Täpsemat teavet kogutavate andmete kohta leiad meie <2>Privaatsuspoliitikast</2> ja meie <6>Küpsiste kasutamise reeglitest</6>.",
"app_selection_modal": {
"continue_in_browser": "Jätka veebibrauseris",
"open_in_app": "Ava rakenduses",
@@ -33,20 +40,70 @@
},
"call_name": "Kõne nimi",
"common": {
"analytics": "Analüütika",
"audio": "Heli",
"avatar": "Tunnuspilt",
"back": "Tagasi",
"display_name": "Kuvatav nimi",
"encrypted": "Krüptitud",
"home": "Avavaatesse",
"home": "Kodu",
"loading": "Laadimine …",
"next": "Edasi",
"options": "Valikud",
"password": "Salasõna",
"preferences": "Eelistused",
"profile": "Profiil",
"reaction": "Reaktsioon",
"reactions": "Reageerimised",
"settings": "Seadistused",
"unencrypted": "Krüptimata",
"username": "Kasutajanimi"
"username": "Kasutajanimi",
"video": "Video"
},
"developer_mode": {
"crypto_version": "Krüptoteekide versioon: {{version}}",
"debug_tile_layout_label": "Meediapaanide paigutus",
"device_id": "Seadme tunnus: {{id}}",
"duplicate_tiles_label": "Täiendavaid vaadete koopiaid osaleja kohta",
"environment_variables": "Keskkonnamuutujad",
"hostname": "Hosti nimi: {{hostname}}",
"livekit_server_info": "LiveKiti serveri teave",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrixi kasutajatunnus: {{id}}",
"show_connection_stats": "Näita ühenduse statistikat",
"show_non_member_tiles": "Näita ka mitteseotud meedia paane",
"url_params": "Võrguaadressi parameetrid",
"use_new_membership_manager": "Kasuta kõne liikmelisuse halduri (MembershipManager) uut implementatsiooni"
},
"disconnected_banner": "Võrguühendus serveriga on katkenud.",
"error": {
"call_is_not_supported": "Kõne pole toetatud",
"call_not_found": "Kõnet ei leidu",
"call_not_found_description": "<0>See link ei tundu olema seotud ühegi olemasoleva kõnega. Kontrolli, et sul on õige link või <1>loo uus</1>.</0>",
"connection_lost": "Ühendus on katkenud",
"connection_lost_description": "Sinu ühendus selle kõnega on katkenud.",
"e2ee_unsupported": "Mitteühilduv brauser",
"e2ee_unsupported_description": "Sinu veebibrauser ei toeta krüptitud kõnesid. Toimivad veebibrauserid on Chrome, Safari, ja Firefox 117+.",
"generic": "Midagi läks valesti",
"generic_description": "Silumis- ja vealogide saatmine võib aidata meid vea põhjuseni jõuda.",
"insufficient_capacity": "Mittepiisav jõudlus",
"insufficient_capacity_description": "Serveri jõudluse ülempiir on hetkel ületatud ja sa ei saa hetkel selle kõnega liituda. Proovi hiljem uuesti või kui probleem kestab kauem, siis võta ühendust serveri haldajaga.",
"matrix_rtc_focus_missing": "See server pole seadistatud töötama rakendusega {{brand}}. Palun võta ühendust serveri halduriga (domeen: {{domain}}, veakood: {{ errorCode }}).",
"open_elsewhere": "Avatud teisel vahekaardil",
"open_elsewhere_description": "{{brand}} on avatud teisel vahekaardil. Kui see ei tundu olema õige, proovi selle lehe uuesti laadimist.",
"unexpected_ec_error": "Tekkis ootamatu viga (<0>Veakood:</0> <1>{{ errorCode }}</1>). Palun võta ühendust serveri haldajaga."
},
"group_call_loader": {
"banned_body": "Sa oled saanud selles jututoas suhtluskeelu",
"banned_heading": "Suhtluskeeld",
"call_ended_body": "Sa oled sellest kõnest eemaldatud.",
"call_ended_heading": "Kõne lõppes",
"knock_reject_body": "Jututoa liikmed ei nõustunud sinu liitumispalvega.",
"knock_reject_heading": "Liitumine pole lubatud",
"reason": "Põhjus"
},
"hangup_button_label": "Lõpeta kõne",
"header_label": "Avaleht: Element Call",
"header_participants_label": "Osalejad",
"invite_modal": {
"link_copied_toast": "Link on kopeeritud lõikelauale",
@@ -60,15 +117,24 @@
"layout_grid_label": "Ruudustik",
"layout_spotlight_label": "Rambivalgus",
"lobby": {
"join_button": "Kõnega liitumine",
"leave_button": "Tagasi hiljutiste kõnede juurde"
"ask_to_join": "Küsi võimalust liituda kõnega",
"join_as_guest": "Liitu külalisena",
"join_button": "Liitu kõnega",
"leave_button": "Tagasi hiljutiste kõnede juurde",
"waiting_for_invite": "Päring on saadetud"
},
"logging_in": "Sisselogimine …",
"login_auth_links": "<0>Loo konto</0> Või <2>Sisene külalisena</2>",
"log_in": "Logi sisse",
"logging_in": "Logime sisse…",
"login_auth_links": "<0>Loo konto</0> või <2>Sisene külalisena</2>",
"login_auth_links_prompt": "Sa pole veel registreerunud?",
"login_subheading": "Jätka rakenduses Element",
"login_title": "Sisselogimine",
"microphone_off": "Mikrofon ei tööta",
"microphone_on": "Mikrofon töötab",
"mute_microphone_button_label": "Summuta mikrofon",
"participant_count_one": "{{count, number}}",
"participant_count_other": "{{count, number}}",
"qr_code": "QR-kood",
"rageshake_button_error_caption": "Proovi uuesti logisid saata",
"rageshake_request_modal": {
"body": "Ühel teisel selles kõnes osalejal on lahenduse kasutamisel tekkinud probleem ning selle põhjuse leidmiseks me sooviksime koguda silumislogisid.",
@@ -78,38 +144,77 @@
"rageshake_sending": "Saatmine…",
"rageshake_sending_logs": "Veaotsingulogide saatmine…",
"rageshake_sent": "Tänud!",
"recaptcha_caption": "Selles saidis on kasutusel ReCAPTCHA ja kehtivad Google'i <2>Privaatsuspoliitika</2> ning <6>Teenusetingimused</6>.<9></9>Klõpsides „Registreeru“, sa nõustud meie <12>Lõppkasutaja litsentsilepingu (EULA) tingimustega</12>",
"recaptcha_dismissed": "Robotilõks on vahele jäetud",
"recaptcha_not_loaded": "Robotilõks pole laetud",
"recaptcha_ssla_caption": "Selle saidi kaitsmiseks on kasutusel ReCAPTCHA ning rakenduvad Google'i <2>Privaatusreeglid</2> ja <6>Kasutustingimused</6>.<9></9>Klõpsides „Registreeru“ nõustud sa meie <12>Tarkvara ja teenuste litsentseerimise lepinguga (Software and Services License Agreement - SSLA)</12>",
"register": {
"passwords_must_match": "Salasõnad ei klapi",
"registering": "Registreerimine…"
},
"register_auth_links": "<0>On sul juba konto?</0><1><0>Logi sisse</0> Või <2>Logi sisse külalisena</2></1>",
"register_auth_links": "<0>On sul juba konto?</0><1><0>Logi sisse</0> või <2>Logi sisse külalisena</2></1>",
"register_confirm_password_label": "Kinnita salasõna",
"register_heading": "Loo omale konto",
"return_home_button": "Tagasi avalehele",
"room_auth_view_eula_caption": "Klõpsides „Liitu kõnega kohe“, nõustud sa meie <2>Lõppkasutaja litsentsilepinguga (EULA)</2>",
"room_auth_view_continue_button": "Jätka",
"room_auth_view_ssla_caption": "Klõpsides „Liitu kõnega“ nõustud sa meie <2>Tarkvara ja teenuste litsentseerimise lepinguga (Software and Services License Agreement - SSLA)</2>",
"screenshare_button_label": "Jaga ekraani",
"settings": {
"audio_tab": {
"effect_volume_description": "Häälesta helivaljust, mida kasutatakse käe tõstmisel ja regeerimisel",
"effect_volume_label": "Efektide helivajlus"
},
"developer_tab_title": "Arendaja",
"devices": {
"camera": "Kaamera",
"camera_numbered": "Kaamera {{n}}",
"default": "Vaikimisi",
"default_named": "Vaikimisi <2>({{name}})</2>",
"microphone": "Mikrofon",
"microphone_numbered": "Mikrofon {{n}}",
"speaker": "Kõlar",
"speaker_numbered": "Kõlar {{n}}"
},
"feedback_tab_body": "Kui selle rakenduse kasutamisel tekib sul probleeme või lihtsalt soovid oma arvamust avaldada, siis palun täida alljärgnev lühike kirjeldus.",
"feedback_tab_description_label": "Sinu tagasiside",
"feedback_tab_h4": "Jaga tagasisidet",
"feedback_tab_send_logs_label": "Lisa veatuvastuslogid",
"feedback_tab_thank_you": "Tänud, me oleme sinu tagasiside kätte saanud!",
"feedback_tab_title": "Tagasiside",
"opt_in_description": "<0></0><1></1>Sa võid selle valiku eelmaldamisega alati oma nõusoleku tagasi võtta. Kui sul parasjagu on kõne pooleli, siis seadistuste muudatus jõustub pärast kõne lõppu."
"opt_in_description": "<0></0><1></1>Sa võid selle valiku eelmaldamisega alati oma nõusoleku tagasi võtta. Kui sul parasjagu on kõne pooleli, siis seadistuste muudatus jõustub pärast kõne lõppu.",
"preferences_tab": {
"developer_mode_label": "Arendajate režiim",
"developer_mode_label_description": "Kasuta arendusrežiimi ja näita asjakohaseid seadistusi.",
"introduction": "Parema kasutuskogemuse nimel saad siin seadistada täiendavaid eelistusi.",
"reactions_play_sound_description": "Kui keegi lisab käimasolevale kõnele reaktsiooni, siis täienda seda heliefektiga.",
"reactions_play_sound_label": "Lisa reageerimistele heli",
"reactions_show_description": "Näita reageerimisi",
"reactions_show_label": "Kui keegi reageerib, siis näita seda animatsioonina",
"show_hand_raised_timer_description": "Kui osaleja annab käetõstmisega märku, siis kuva ka kestuse taimer",
"show_hand_raised_timer_label": "Näita käega märkuandmise kestust"
}
},
"star_rating_input_label_one": "{{count}} tärni",
"star_rating_input_label_one": "{{count}} tärn",
"star_rating_input_label_other": "{{count}} tärni",
"start_new_call": "Algata uus kõne",
"start_video_button_label": "Lülita videovoog sisse",
"stop_screenshare_button_label": "Ekraanivaade on jagamisel",
"stop_video_button_label": "Peata videovoog",
"submitting": "Saadan…",
"switch_camera": "Vaheta kaamerat",
"unauthenticated_view_body": "Sa pole veel registreerunud? <2>Loo kasutajakonto</2>",
"unauthenticated_view_eula_caption": "Klõpsides „Jätka“, nõustud sa meie <2>Lõppkasutaja litsentsilepinguga (EULA)</2>",
"unauthenticated_view_login_button": "Logi oma kontosse sisse",
"unauthenticated_view_ssla_caption": "Klõpsides „Jätka“ nõustud sa meie <2>Tarkvara ja teenuste litsentseerimise lepinguga (Software and Services License Agreement - SSLA)</2>",
"unmute_microphone_button_label": "Lülita mikrofon sisse",
"version": "Versioon: {{version}}"
"version": "{{productName}}, versioon: {{version}}",
"video_tile": {
"always_show": "Näita alati",
"camera_starting": "Video on laadimisel...",
"change_fit_contain": "Mahuta aknasse",
"collapse": "Näita vähem",
"expand": "Näita rohkem",
"mute_for_me": "Summuta minu jaoks",
"muted_for_me": "Minule summutatud",
"volume": "Helivaljus",
"waiting_for_media": "Ootame kuni meedia on olemas..."
}
}

View File

@@ -77,7 +77,6 @@
"rageshake_sending": "Envoi…",
"rageshake_sending_logs": "Envoi des journaux de débogage…",
"rageshake_sent": "Merci !",
"recaptcha_caption": "Ce site est protégé par ReCAPTCHA, la <2>politique de confidentialité</2> et les <6>conditions dutilisation</6> de Google sappliquent.<9></9>En cliquant sur « Senregistrer » vous acceptez également notre <12>Contrat de Licence Utilisateur Final (CLUF)</12>",
"recaptcha_dismissed": "Recaptcha refusé",
"recaptcha_not_loaded": "Recaptcha non chargé",
"register": {
@@ -87,7 +86,6 @@
"register_auth_links": "<0>Vous avez déjà un compte ?</0><1><0>Se connecter</0> Ou <2>Accès invité</2></1>",
"register_confirm_password_label": "Confirmer le mot de passe",
"return_home_button": "Retour à laccueil",
"room_auth_view_eula_caption": "En cliquant sur « Rejoindre lappel maintenant », vous acceptez notre <2>Contrat de Licence Utilisateur Final (CLUF)</2>",
"screenshare_button_label": "Partage décran",
"settings": {
"developer_tab_title": "Développeur",
@@ -107,7 +105,6 @@
"stop_video_button_label": "Arrêter la vidéo",
"submitting": "Envoi…",
"unauthenticated_view_body": "Pas encore de compte ? <2>En créer un</2>",
"unauthenticated_view_eula_caption": "En cliquant sur « Commencer », vous acceptez notre <2>Contrat de Licence Utilisateur Final (CLUF)</2>",
"unauthenticated_view_login_button": "Connectez vous à votre compte",
"unmute_microphone_button_label": "Allumer le microphone",
"version": "Version : {{version}}"

View File

@@ -77,7 +77,6 @@
"rageshake_sending": "Mengirimkan…",
"rageshake_sending_logs": "Mengirimkan catatan pengawakutuan…",
"rageshake_sent": "Terima kasih!",
"recaptcha_caption": "Situs ini dilindungi oleh reCAPTCHA dan <2>Kebijakan Privasi</2> dan <6>Ketentuan Layanan</6> Google berlaku.<9></9>Dengan mengeklik \"Daftar\", Anda menyetujui <12>Perjanjian Lisensi Pengguna Akhir (EULA)</12> kami",
"recaptcha_dismissed": "Recaptcha ditutup",
"recaptcha_not_loaded": "Recaptcha tidak dimuat",
"register": {
@@ -87,7 +86,6 @@
"register_auth_links": "<0>Sudah punya akun?</0><1><0>Masuk</0> Atau <2>Akses sebagai tamu</2></1>",
"register_confirm_password_label": "Konfirmasi kata sandi",
"return_home_button": "Kembali ke layar beranda",
"room_auth_view_eula_caption": "Dengan mengeklik \"Bergabung ke panggilan sekarang\", Anda menyetujui <2>Perjanjian Lisensi Pengguna Akhir (EULA)</2> kami",
"screenshare_button_label": "Bagikan layar",
"settings": {
"developer_tab_title": "Pengembang",
@@ -107,7 +105,6 @@
"stop_video_button_label": "Matikan video",
"submitting": "Mengirim…",
"unauthenticated_view_body": "Belum terdaftar? <2>Buat sebuah akun</2>",
"unauthenticated_view_eula_caption": "Dengan mengeklik \"Bergabung\", Anda menyetujui <2>Perjanjian Lisensi Pengguna Akhir (EULA)</2>",
"unauthenticated_view_login_button": "Masuk ke akun Anda",
"unmute_microphone_button_label": "Nyalakan mikrofon",
"version": "Versi: {{version}}"

View File

@@ -5,13 +5,21 @@
"action": {
"close": "Chiudi",
"copy_link": "Copia collegamento",
"edit": "Modifica",
"go": "Vai",
"invite": "Invita",
"lower_hand": "Abbassa la mano",
"no": "No",
"pick_reaction": "Scegli una reazione",
"raise_hand": "Alza la mano",
"register": "Registra",
"remove": "Rimuovi",
"show_less": "Mostra meno",
"show_more": "Mostra altro",
"sign_in": "Accedi",
"sign_out": "Disconnetti",
"submit": "Invia"
"submit": "Invia",
"upload_file": "Carica file"
},
"analytics_notice": "Partecipando a questa beta, acconsenti alla raccolta di dati anonimi che usiamo per migliorare il prodotto. Puoi trovare più informazioni su quali dati monitoriamo nella nostra <2>informativa sulla privacy</2> e nell'<5>informativa sui cookie</5>.",
"app_selection_modal": {
@@ -32,16 +40,66 @@
},
"call_name": "Nome della chiamata",
"common": {
"analytics": "Statistiche",
"audio": "Audio",
"avatar": "Avatar",
"back": "Indietro",
"display_name": "Il tuo nome",
"encrypted": "Cifrata",
"home": "Pagina iniziale",
"loading": "Caricamento…",
"next": "Avanti",
"options": "Opzioni",
"password": "Password",
"preferences": "Preferenze",
"profile": "Profilo",
"reaction": "Reazione",
"reactions": "Reazioni",
"settings": "Impostazioni",
"unencrypted": "Non cifrata",
"username": "Nome utente"
"username": "Nome utente",
"video": "Video"
},
"developer_mode": {
"crypto_version": "Versione crittografica: {{version}}",
"debug_tile_layout_label": "Debug della disposizione dei riquadri",
"device_id": "ID dispositivo: {{id}}",
"duplicate_tiles_label": "Numero di copie di riquadri aggiuntivi per partecipante",
"hostname": "Nome host: {{hostname}}",
"livekit_server_info": "Informazioni sul server LiveKit",
"livekit_sfu": "SFU LiveKit: {{url}}",
"matrix_id": "ID Matrix: {{id}}",
"show_connection_stats": "Mostra le statistiche di connessione",
"show_non_member_tiles": "Mostra i riquadri per i file multimediali non-membri",
"use_new_membership_manager": "Usa la nuova implementazione della chiamata MembershipManager"
},
"disconnected_banner": "La connessione al server è stata persa.",
"error": {
"call_is_not_supported": "La chiamata non è supportata",
"call_not_found": "Chiamata non trovata",
"call_not_found_description": "<0>Quel link non sembra appartenere a nessuna chiamata esistente. Controlla di avere il link giusto, oppure <1> creane uno nuovo</1> .</0>",
"connection_lost": "Connessione persa",
"connection_lost_description": "Sei stato disconnesso dalla chiamata.",
"e2ee_unsupported": "Browser incompatibile",
"e2ee_unsupported_description": "Il tuo browser non supporta le chiamate crittografate. I browser supportati sono Chrome, Safari e Firefox 117+.",
"generic": "Qualcosa è andato storto",
"generic_description": "L'invio dei registri di debug ci aiuterà a rintracciare il problema.",
"insufficient_capacity": "Capacità insufficiente",
"insufficient_capacity_description": "Il server ha raggiunto la capacità massima e non è possibile partecipare alla chiamata in questo momento. Riprova più tardi o contatta l'amministratore del server se il problema persiste.",
"matrix_rtc_focus_missing": "Il server non è configurato per funzionare con {{brand}}. Contatta l'amministratore del tuo server (Dominio: {{domain}}, codice di errore: {{ errorCode }}).",
"open_elsewhere": "Aperto in un'altra scheda",
"open_elsewhere_description": "{{brand}} è stato aperto in un'altra scheda. Se non ti sembra corretto, prova a ricaricare la pagina.",
"unexpected_ec_error": "Si è verificato un errore imprevisto (<0>Codice errore:</0> <1>{{ errorCode }}</1>). Contatta l'amministratore del tuo server."
},
"group_call_loader": {
"banned_body": "Sei stato bandito dalla stanza.",
"banned_heading": "Bandito",
"call_ended_body": "Sei stato rimosso dalla chiamata.",
"call_ended_heading": "Chiamata terminata",
"knock_reject_body": "I membri della stanza hanno rifiutato la tua richiesta di partecipazione.",
"knock_reject_heading": "Partecipazione non consentita",
"reason": "Motivo"
},
"hangup_button_label": "Termina chiamata",
"header_label": "Inizio di Element Call",
"header_participants_label": "Partecipanti",
@@ -57,15 +115,24 @@
"layout_grid_label": "Griglia",
"layout_spotlight_label": "In primo piano",
"lobby": {
"ask_to_join": "Chiedi di partecipare alla chiamata",
"join_as_guest": "Partecipa come ospite",
"join_button": "Entra in chiamata",
"leave_button": "Torna ai recenti"
"leave_button": "Torna ai recenti",
"waiting_for_invite": "Richiesta inviata"
},
"log_in": "Accedi",
"logging_in": "Accesso…",
"login_auth_links": "<0>Crea un profilo</0> o <2>Accedi come ospite</2>",
"login_auth_links_prompt": "Non sei ancora registrato?",
"login_subheading": "Per continuare su Element",
"login_title": "Accedi",
"microphone_off": "Microfono spento",
"microphone_on": "Microfono acceso",
"mute_microphone_button_label": "Spegni il microfono",
"participant_count_one": "{{count, number}}",
"participant_count_other": "{{count, number}}",
"qr_code": "Codice QR",
"rageshake_button_error_caption": "Riprova l'invio dei registri",
"rageshake_request_modal": {
"body": "Un altro utente in questa chiamata sta avendo problemi. Per diagnosticare meglio questi problemi, vorremmo raccogliere un registro di debug.",
@@ -75,7 +142,6 @@
"rageshake_sending": "Invio…",
"rageshake_sending_logs": "Invio dei registri di debug…",
"rageshake_sent": "Grazie!",
"recaptcha_caption": "Questo sito è protetto da ReCAPTCHA e si applicano l'<2>informativa sulla privacy</2> e i <6>termini di servizio</6> di Google.<9></9>Cliccando \"Registra\", accetti il nostro <12>accordo di licenza con l'utente finale (EULA)</12>",
"recaptcha_dismissed": "Recaptcha annullato",
"recaptcha_not_loaded": "Recaptcha non caricato",
"register": {
@@ -84,17 +150,44 @@
},
"register_auth_links": "<0>Hai già un profilo?</0><1><0>Accedi</0> o <2>Accedi come ospite</2></1>",
"register_confirm_password_label": "Conferma password",
"register_heading": "Crea il tuo account",
"return_home_button": "Torna alla schermata di iniziale",
"room_auth_view_eula_caption": "Cliccando \"Entra in chiamata ora\", accetti il nostro <2>accordo di licenza con l'utente finale (EULA)</2>",
"room_auth_view_continue_button": "Continua",
"screenshare_button_label": "Condividi schermo",
"settings": {
"audio_tab": {
"effect_volume_description": "Regola il volume delle reazioni e degli effetti di alzata di mani.",
"effect_volume_label": "Volume degli effetti sonori"
},
"developer_tab_title": "Sviluppatore",
"devices": {
"camera": "Fotocamera",
"camera_numbered": "Fotocamera {{n}}",
"default": "Predefinito",
"default_named": "Predefinito <2>({{name}})</2>",
"microphone": "Microfono",
"microphone_numbered": "Microfono {{n}}",
"speaker": "Altoparlante",
"speaker_numbered": "Altoparlante {{n}}"
},
"feedback_tab_body": "Se stai riscontrando problemi o semplicemente vuoi dare un'opinione, inviaci una breve descrizione qua sotto.",
"feedback_tab_description_label": "Il tuo commento",
"feedback_tab_h4": "Invia commento",
"feedback_tab_send_logs_label": "Includi registri di debug",
"feedback_tab_thank_you": "Grazie, abbiamo ricevuto il tuo commento!",
"opt_in_description": "<0></0><1></1>Puoi revocare il consenso deselezionando questa casella. Se attualmente sei in una chiamata, avrà effetto al termine di essa."
"feedback_tab_title": "Commenti",
"opt_in_description": "<0></0><1></1>Puoi revocare il consenso deselezionando questa casella. Se attualmente sei in una chiamata, avrà effetto al termine di essa.",
"preferences_tab": {
"developer_mode_label": "Modalità sviluppatore",
"developer_mode_label_description": "Attiva la modalità sviluppatore e mostra la scheda di impostazioni sviluppatore.",
"introduction": "Qui puoi configurare opzioni extra per un'esperienza migliore.",
"reactions_play_sound_description": "Riprodurre un effetto sonoro quando qualcuno invia una reazione in una chiamata.",
"reactions_play_sound_label": "Riproduci suoni di reazione",
"reactions_show_description": "Mostra un'animazione quando qualcuno invia una reazione.",
"reactions_show_label": "Mostra reazioni",
"show_hand_raised_timer_description": "Mostra un contatore quando un partecipante alza la mano",
"show_hand_raised_timer_label": "Mostra la durata dell'alzata di mano"
}
},
"star_rating_input_label_one": "{{count}} stelle",
"star_rating_input_label_other": "{{count}} stelle",
@@ -103,9 +196,20 @@
"stop_screenshare_button_label": "Condivisione schermo",
"stop_video_button_label": "Ferma video",
"submitting": "Invio…",
"switch_camera": "Cambia fotocamera",
"unauthenticated_view_body": "Non hai ancora un profilo? <2>Creane uno</2>",
"unauthenticated_view_eula_caption": "Cliccando \"Vai\", accetti il nostro <2>accordo di licenza con l'utente finale (EULA)</2>",
"unauthenticated_view_login_button": "Accedi al tuo profilo",
"unmute_microphone_button_label": "Riaccendi il microfono",
"version": "Versione: {{version}}"
"version": "Versione: {{version}}",
"video_tile": {
"always_show": "Mostra sempre",
"camera_starting": "Caricamento del video...",
"change_fit_contain": "Adatta al frame",
"collapse": "Riduci",
"expand": "Espandi",
"mute_for_me": "Disattiva l'audio per me",
"muted_for_me": "Muto per me",
"volume": "Volume",
"waiting_for_media": "In attesa dei media..."
}
}

View File

@@ -4,61 +4,120 @@
},
"action": {
"close": "閉じる",
"copy_link": "リンクをコピー",
"go": "続行",
"invite": "招待",
"no": "いいえ",
"register": "登録",
"remove": "削除",
"sign_in": "サインイン",
"sign_out": "サインアウト"
"sign_out": "サインアウト",
"submit": "送信"
},
"analytics_notice": "ベータ版への参加と同時に、製品の改善のために匿名データを収集することに同意したことになります。追跡するデータの詳細については、<2>プライバシーポリシー</2>と<6>クッキーポリシー</6>をご確認下さい。",
"app_selection_modal": {
"continue_in_browser": "ブラウザで続行",
"open_in_app": "アプリで開く",
"text": "準備完了?",
"title": "アプリを選択"
},
"call_ended_view": {
"create_account_button": "アカウントを作成"
"create_account_button": "アカウントを作成",
"create_account_prompt": "<0>パスワードを設定してアカウント設定を保持してみませんか?</0><1>名前とアバターの設定を次の通話に利用する事ができます。</1>",
"feedback_done": "<0>フィードバックありがとうございます!</0>",
"feedback_prompt": "<0>品質向上のため、皆様のフィードバックをお待ちしております。</0>",
"headline": "{{displayName}} さんの通話は終了しました。",
"not_now_button": "終了せずホーム画面に戻る",
"reconnect_button": "再接続",
"survey_prompt": "通話はどうでしたか?"
},
"call_name": "通話名",
"common": {
"analytics": "分析",
"audio": "音声",
"avatar": "アバター",
"display_name": "表示名",
"encrypted": "暗号化済み",
"home": "ホーム",
"loading": "読み込んでいます…",
"options": "オプション",
"password": "パスワード",
"profile": "プロフィール",
"settings": "設定",
"unencrypted": "暗号化されていません",
"username": "ユーザー名",
"video": "ビデオ"
},
"disconnected_banner": "サーバーへの接続が失われました。",
"hangup_button_label": "通話終了",
"header_label": "Element Call ホーム",
"header_participants_label": "参加者",
"invite_modal": {
"link_copied_toast": "リンクがクリップボードにコピーされました",
"title": "この通話に招待する"
},
"join_existing_call_modal": {
"join_button": "はい、通話に参加",
"text": "この通話は既に存在します。参加しますか?",
"title": "既存の通話に参加しますか?"
},
"layout_grid_label": "グリッド",
"layout_spotlight_label": "スポットライト",
"lobby": {
"join_button": "通話に参加"
"join_button": "通話に参加",
"leave_button": "最近に戻る"
},
"log_in": "ログイン",
"logging_in": "ログインしています…",
"login_auth_links": "<0>アカウントを作成</0>または<2>ゲストとしてアクセス</2>",
"login_auth_links_prompt": "登録はまだですか?",
"login_subheading": "Element を続けるには",
"login_title": "ログイン",
"microphone_off": "マイクオフ",
"microphone_on": "マイクオン",
"mute_microphone_button_label": "ミュート",
"rageshake_button_error_caption": "ログ送信の再試行",
"rageshake_request_modal": {
"body": "この通話に参加している別のユーザーに問題が発生しています。この問題のより良い診断のため、デバッグ ログを収集したいと考えています。",
"title": "デバッグログを要求"
},
"rageshake_send_logs": "デバッグログを送信",
"rageshake_sending": "送信しています…",
"rageshake_sending_logs": "デバッグログを送信しています…",
"rageshake_sent": "ありがとうございます!",
"recaptcha_dismissed": "Recaptcha は却下されました",
"recaptcha_not_loaded": "Recaptcha が読み込まれませんでした",
"register": {
"passwords_must_match": "パスワードが一致する必要があります",
"registering": "登録しています…"
},
"register_auth_links": "<0>既にアカウントをお持ちですか?</0><1><0>ログイン</0>または<2>ゲストとしてアクセス</2></1>",
"register_confirm_password_label": "パスワードを確認",
"register_heading": "アカウントを作成",
"return_home_button": "ホーム画面に戻る",
"screenshare_button_label": "画面共有",
"settings": {
"developer_tab_title": "開発者",
"feedback_tab_body": "問題が発生している場合、もしくはフィードバックを提供したい場合は、以下に簡単な説明を入力してお送りください。",
"feedback_tab_description_label": "フィードバック",
"feedback_tab_h4": "フィードバックを送信",
"feedback_tab_send_logs_label": "デバッグログを含める"
"feedback_tab_send_logs_label": "デバッグログを含める",
"feedback_tab_thank_you": "ありがとうございます。フィードバックを受け取りました!",
"feedback_tab_title": "フィードバック",
"opt_in_description": "<0></0><1></1>このボックスのチェックを外すと同意を取り消すことができます。現在通話中の場合、この変更は通話終了後に有効になります。"
},
"start_new_call": "新しい通話を開始",
"start_video_button_label": "ビデオを開始",
"stop_screenshare_button_label": "共有画面",
"stop_video_button_label": "ビデオを停止",
"submitting": "送信中…",
"unauthenticated_view_body": "アカウントがありませんか? <2>アカウントを作成</2>",
"unauthenticated_view_login_button": "アカウントにログイン",
"version": "バージョン:{{version}}"
"unmute_microphone_button_label": "マイクのミュート解除",
"version": "バージョン:{{version}}",
"video_tile": {
"change_fit_contain": "フレームに合わせる",
"mute_for_me": "ミュートする",
"volume": "ボリューム"
}
}

View File

@@ -57,7 +57,6 @@
"rageshake_sending": "Nosūta…",
"rageshake_sending_logs": "Nosūta atkļūdošanas žurnāla ierakstus…",
"rageshake_sent": "Paldies!",
"recaptcha_caption": "Šo vietni aizsargā ReCAPTCHA, un ir attiecināmi Google <2>privātuma nosacījumi</2> un <6>pakalpojuma noteikumi</6>.<9></9>Klikšķināšana uz \"Reģistrēties\" sniedz piekrišanu mūsu <12>galalietotāja licencēšanas nolīgumam (GLLN)</12>",
"recaptcha_dismissed": "ReCaptcha atmesta",
"recaptcha_not_loaded": "ReCaptcha nav ielādēta",
"register": {
@@ -67,7 +66,6 @@
"register_auth_links": "<0>Jau ir konts?</0><1><0>Pieteikties</0> vai <2>Piekļūt kā viesim</2></1>",
"register_confirm_password_label": "Apstiprināt paroli",
"return_home_button": "Atgriezties sākuma ekrānā",
"room_auth_view_eula_caption": "Klikšķināšana uz \"Pievienoties zvanam tagad\" apliecina piekrišanu mūsu <2>galalietotāja licencēšanas nolīgumam (GLLN)</2>",
"screenshare_button_label": "Kopīgot ekrānu",
"settings": {
"developer_tab_title": "Izstrādātājs",
@@ -83,7 +81,6 @@
"star_rating_input_label_other": "{{count}} zvaigznes",
"submitting": "Iesniedz…",
"unauthenticated_view_body": "Vēl neesi reģistrējies? <2>Izveidot kontu</2>",
"unauthenticated_view_eula_caption": "Klikšķināšana uz \"Aiziet\" apliecina piekrišanu mūsu <2>galalietotāja licencēšanas nolīgumam (GLLN)</2>",
"unauthenticated_view_login_button": "Pieteikties kontā",
"version": "Versija: {{version}}"
}

View File

@@ -5,14 +5,21 @@
"action": {
"close": "Zamknij",
"copy_link": "Kopiuj link",
"edit": "Edytuj",
"go": "Przejdź",
"invite": "Zaproś",
"lower_hand": "Opuść rękę",
"no": "Nie",
"pick_reaction": "Wybierz reakcję",
"raise_hand": "Podnieś rękę",
"register": "Zarejestruj",
"remove": "Usuń",
"show_less": "Pokaż mniej",
"show_more": "Pokaż więcej",
"sign_in": "Zaloguj się",
"sign_out": "Wyloguj się",
"submit": "Wyślij"
"submit": "Wyślij",
"upload_file": "Prześlij plik"
},
"analytics_notice": "Uczestnicząc w tej becie, upoważniasz nas do zbierania anonimowych danych, które wykorzystamy do ulepszenia produktu. Dowiedz się więcej na temat danych, które zbieramy w naszej <2>Polityce prywatności</2> i <5>Polityce ciasteczek</5>.",
"app_selection_modal": {
@@ -33,20 +40,68 @@
},
"call_name": "Nazwa połączenia",
"common": {
"analytics": "Dane analityczne",
"audio": "Dźwięk",
"avatar": "Awatar",
"back": "Wstecz",
"display_name": "Nazwa wyświetlana",
"encrypted": "Szyfrowane",
"home": "Strona domowa",
"loading": "Ładowanie…",
"next": "Dalej",
"options": "Opcje",
"password": "Hasło",
"preferences": "Preferencje",
"profile": "Profil",
"reaction": "Reakcja",
"reactions": "Reakcje",
"settings": "Ustawienia",
"unencrypted": "Nie szyfrowane",
"username": "Nazwa użytkownika",
"video": "Wideo"
},
"developer_mode": {
"crypto_version": "Wersja krypto: {{version}}",
"debug_tile_layout_label": "Układ kafelków Debug",
"device_id": "ID urządzenia: {{id}}",
"duplicate_tiles_label": "Liczba dodatkowych kopii kafelków na uczestnika",
"environment_variables": "Zmienne środowiskowe",
"hostname": "Nazwa hosta: {{hostname}}",
"livekit_server_info": "Informacje serwera LiveKit",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "ID Matrix: {{id}}",
"show_connection_stats": "Pokaż statystyki połączenia",
"show_non_member_tiles": "Pokaż kafelki dla mediów, które nie są od członków",
"url_params": "Parametry URL",
"use_new_membership_manager": "Użyj nowej implementacji połączenia MembershipManager"
},
"disconnected_banner": "Utracono połączenie z serwerem.",
"error": {
"call_is_not_supported": "Połączenie nie jest obsługiwane",
"call_not_found": "Nie znaleziono połączenia",
"call_not_found_description": "<0>Wygląda na to, że ten link nie należy do żadnego istniejącego połączenia. Sprawdź, czy posiadasz prawidłowy link lub <1>utwórz nowy</1>.</0>",
"connection_lost": "Utracono połączenie",
"connection_lost_description": "Zostałeś rozłączony z rozmowy.",
"e2ee_unsupported": "Niekompatybilna przeglądarka",
"e2ee_unsupported_description": "Twoja przeglądarka nie wspiera szyfrowanych połączeń. Obsługiwane przeglądarki obejmują Chrome, Safari i Firefox 117+.",
"generic": "Coś poszło nie tak",
"generic_description": "Wysłanie dziennika debug, pozwoli nam namierzyć problem.",
"insufficient_capacity": "Za mało miejsca",
"insufficient_capacity_description": "Serwer osiągnął maksymalną pojemność, przez co nie możesz dołączyć do połączenia. Spróbuj ponownie później lub skontaktuj się z administratorem serwera, jeśli problem nie zniknie.",
"matrix_rtc_focus_missing": "Serwer nie jest skonfigurowany do pracy z {{brand}}. Prosimy o kontakt z administratorem serwera (Domena: {{domain}}, Kod błędu: {{ errorCode }}).",
"open_elsewhere": "Otwarto w innej karcie",
"open_elsewhere_description": "{{brand}} został otwarty w innej karcie. Jeśli tak nie jest, spróbuj odświeżyć stronę.",
"unexpected_ec_error": "Wystąpił nieoczekiwany błąd (<0>Kod błędu:</0> <1>{{ errorCode }}</1>). Skontaktuj się z administratorem serwera."
},
"group_call_loader": {
"banned_body": "Zostałeś zbanowany z pokoju.",
"banned_heading": "Zbanowany",
"call_ended_body": "Zostałeś usunięty z rozmowy.",
"call_ended_heading": "Połączenie zakończone",
"knock_reject_body": "Członkowie pokoju odrzucili Twoją prośbę o dołączenie.",
"knock_reject_heading": "Nie możesz dołączyć",
"reason": "Powód: {{reason}}"
},
"hangup_button_label": "Zakończ połączenie",
"header_label": "Strona główna Element Call",
"header_participants_label": "Uczestnicy",
@@ -62,15 +117,25 @@
"layout_grid_label": "Siatka",
"layout_spotlight_label": "Centrum uwagi",
"lobby": {
"ask_to_join": "Poproś o dołączenie do rozmowy",
"join_as_guest": "Dołącz jako gość",
"join_button": "Dołącz do połączenia",
"leave_button": "Wróć do ostatnie"
"leave_button": "Wróć do ostatnie",
"waiting_for_invite": "Żądanie wysłane"
},
"log_in": "Zaloguj",
"logging_in": "Logowanie…",
"login_auth_links": "<0>Utwórz konto</0> lub <2>Dołącz jako gość</2>",
"login_auth_links_prompt": "Nie masz konta?",
"login_subheading": "Aby przejść do Element",
"login_title": "Zaloguj się",
"microphone_off": "Mikrofon wyłączony",
"microphone_on": "Mikrofon włączony",
"mute_microphone_button_label": "Wycisz mikrofon",
"participant_count_one": "{{count, number}}",
"participant_count_few": "{{count, number}}",
"participant_count_many": "{{count, number}}",
"qr_code": "Kod QR",
"rageshake_button_error_caption": "Wyślij logi ponownie",
"rageshake_request_modal": {
"body": "Inny użytkownik w tym połączeniu napotkał problem. Aby lepiej zdiagnozować tę usterkę, chcielibyśmy zebrać dzienniki debugowania.",
@@ -80,27 +145,54 @@
"rageshake_sending": "Wysyłanie…",
"rageshake_sending_logs": "Wysyłanie dzienników debugowania…",
"rageshake_sent": "Dziękujemy!",
"recaptcha_caption": "Ta witryna jest chroniona przez ReCAPTCHA, więc obowiązują <2>Polityka prywatności</2> i <6>Warunki usług</6> Google. Klikając \"Zarejestruj\", zgadzasz się na naszą <12>Umowę licencyjną (EULA)</12>",
"recaptcha_dismissed": "Recaptcha odrzucona",
"recaptcha_not_loaded": "Recaptcha nie została załadowana",
"recaptcha_ssla_caption": "Ta strona jest chroniona przez reCAPTCHA i obowiązują <2> Polityka prywatności Google </2> i <6>Warunki korzystania z usługi</6>. <9></9>Klikając „Zarejestruj się”, wyrażasz zgodę na naszą <12>umowę licencyjną oprogramowania i usług (SSLA)</12>",
"register": {
"passwords_must_match": "Hasła muszą pasować",
"registering": "Rejestrowanie…"
},
"register_auth_links": "<0>Masz już konto?</0><1><0>Zaloguj się</0> lub <2>Dołącz jako gość</2></1>",
"register_confirm_password_label": "Potwierdź hasło",
"register_heading": "Utwórz konto",
"return_home_button": "Powróć do strony głównej",
"room_auth_view_eula_caption": "Klikając \"Dołącz teraz do rozmowy\", zgadzasz się na naszą <2>Umowę licencyjną (EULA)</2>",
"room_auth_view_continue_button": "Kontynuuj",
"room_auth_view_ssla_caption": "Klikając \"Dołącz teraz do połączenia\", wyrażasz zgodę na naszą <2>Umowę licencyjną oprogramowania i usług (SSLA)</2>",
"screenshare_button_label": "Udostępnij ekran",
"settings": {
"audio_tab": {
"effect_volume_description": "Dostosuj głośność, z jaką odtwarzane są efekty reakcji i podniesionej ręki",
"effect_volume_label": "Głośność efektu dźwiękowego"
},
"developer_tab_title": "Programista",
"devices": {
"camera": "Kamera",
"camera_numbered": "Kamera {{n}}",
"default": "Domyślne",
"default_named": "Domyślne <2>({{name}})</2>",
"microphone": "Mikrofon",
"microphone_numbered": "Mikrofon {{n}}",
"speaker": "Głośnik",
"speaker_numbered": "Głośnik {{n}}"
},
"feedback_tab_body": "Jeśli posiadasz problemy lub chciałbyś zgłosić swoją opinię, wyślij nam krótki opis.",
"feedback_tab_description_label": "Twoje opinie",
"feedback_tab_h4": "Prześlij opinię",
"feedback_tab_send_logs_label": "Dołącz dzienniki debugowania",
"feedback_tab_thank_you": "Dziękujemy, otrzymaliśmy Twoją opinię!",
"feedback_tab_title": "Opinia użytkownika",
"opt_in_description": "<0></0><1></1>Możesz wycofać swoją zgodę poprzez odznaczenie tego pola. Jeśli już jesteś w trakcie rozmowy, opcja zostanie zastosowana po jej zakończeniu."
"opt_in_description": "<0></0><1></1>Możesz wycofać swoją zgodę poprzez odznaczenie tego pola. Jeśli już jesteś w trakcie rozmowy, opcja zostanie zastosowana po jej zakończeniu.",
"preferences_tab": {
"developer_mode_label": "Tryb programisty",
"developer_mode_label_description": "Włącz tryb programisty i wyświetl kartę ustawień programisty.",
"introduction": "Tutaj możesz skonfigurować dodatkowe opcje dla lepszych doświadczeń.",
"reactions_play_sound_description": "Odtwórz efekt dźwiękowy, gdy ktoś wyślę reakcję w trakcie połączenia.",
"reactions_play_sound_label": "Odtwórz dźwięki reakcji",
"reactions_show_description": "Odtwórz animację, gdy ktoś wyślę reakcję.",
"reactions_show_label": "Pokaż reakcje",
"show_hand_raised_timer_description": "Pokaż licznik, gdy uczestnik podniesie rękę",
"show_hand_raised_timer_label": "Pokaż czas po podniesieniu ręki"
}
},
"star_rating_input_label_one": "{{count}} gwiazdki",
"star_rating_input_label_other": "{{count}} gwiazdki",
@@ -109,9 +201,21 @@
"stop_screenshare_button_label": "Udostępnianie ekranu",
"stop_video_button_label": "Zakończ wideo",
"submitting": "Wysyłanie…",
"switch_camera": "Przełącz kamerę",
"unauthenticated_view_body": "Nie masz konta? <2>Utwórz je</2>",
"unauthenticated_view_eula_caption": "Klikając \"Przejdź\", zgadzasz się na naszą <2>Umowę licencyjną (EULA)</2>",
"unauthenticated_view_login_button": "Zaloguj się do swojego konta",
"unauthenticated_view_ssla_caption": "Klikając \"Przejdź\", wyrażasz zgodę na naszą <2>Umowę licencyjną oprogramowania i usług (SSLA)</2>",
"unmute_microphone_button_label": "Odcisz mikrofon",
"version": "Wersja: {{version}}"
"version": "Wersja: {{version}}",
"video_tile": {
"always_show": "Zawsze pokazuj",
"camera_starting": "Wczytywanie wideo...",
"change_fit_contain": "Dopasuj do obramowania",
"collapse": "Zwiń",
"expand": "Rozwiń",
"mute_for_me": "Wycisz dla mnie",
"muted_for_me": "Wyciszone dla mnie",
"volume": "Głośność",
"waiting_for_media": "Oczekiwanie na media..."
}
}

View File

@@ -117,7 +117,6 @@
"rageshake_sending": "Trimiterea...",
"rageshake_sending_logs": "Trimiterea jurnalelor de depanare...",
"rageshake_sent": "Multumesc!",
"recaptcha_caption": "Acest site este protejat de reCAPTCHA și se aplică Politica de <2> confidențialitate Google </2> și <6> Termenii și condițiile. </6> <9></9>Făcând clic pe „Înregistrare”, sunteți de acord cu Acordul nostru de licențiere pentru utilizatorul <12> final (EULA) </12>",
"recaptcha_dismissed": "Recaptcha a fost respins",
"recaptcha_not_loaded": "Recaptcha nu a fost încărcat",
"register": {
@@ -129,7 +128,6 @@
"register_heading": "Creează-ți contul",
"return_home_button": "Reveniți la ecranul de pornire",
"room_auth_view_continue_button": "Continuă",
"room_auth_view_eula_caption": "Făcând clic pe „Continuați”, sunteți de acord cu Acordul nostru de licențiere pentru utilizatorul <2> final (EULA) </2>",
"screenshare_button_label": "Partajare ecran",
"settings": {
"audio_tab": {
@@ -145,10 +143,13 @@
"feedback_tab_title": "Feedback",
"opt_in_description": "<0></0><1></1>Puteți retrage consimțământul debifând această casetă. Dacă sunteți în prezent la un apel, această setare va intra în vigoare la sfârșitul apelului.",
"preferences_tab": {
"introduction": "Aici puteți configura opțiuni suplimentare pentru o experiență îmbunătățită.",
"reactions_play_sound_description": "Redați un efect sonor atunci când cineva trimite o reacție la un apel.",
"reactions_play_sound_label": "Redați sunete de reacție",
"reactions_show_description": "Afișați o animație atunci când cineva trimite o reacție.",
"reactions_show_label": "Afișați reacțiile"
"reactions_show_label": "Afișați reacțiile",
"show_hand_raised_timer_description": "Afișați un cronometru atunci când un participant ridică mâna.",
"show_hand_raised_timer_label": "Afișați durata ridicării mâinii"
}
},
"start_new_call": "Începe un nou apel",
@@ -158,7 +159,6 @@
"submitting": "Trimiterea...",
"switch_camera": "Comutați camera",
"unauthenticated_view_body": "Nu sunteți încă înregistrat? <2>Creați un cont </2>",
"unauthenticated_view_eula_caption": "Făcând clic pe „Go”, sunteți de acord cu Acordul nostru de licențiere pentru utilizatorul <2> final (EULA) </2>",
"unauthenticated_view_login_button": "Conectați-vă la contul dvs.",
"unmute_microphone_button_label": "Anulează microfonul",
"version": "{{productName}}Versiune: {{version}}",

View File

@@ -4,15 +4,30 @@
},
"action": {
"close": "Закрыть",
"copy_link": "Скопировать ссылку",
"edit": "Редактировать",
"go": "Далее",
"invite": "Пригласить",
"lower_hand": "Опустить руку",
"no": "Нет",
"pick_reaction": "Выберите реакцию",
"raise_hand": "Поднять руку",
"register": "Зарегистрироваться",
"remove": "Удалить",
"show_less": "Показать меньше",
"show_more": "Показать больше",
"sign_in": "Войти",
"sign_out": "Выйти",
"submit": "Отправить"
"submit": "Отправить",
"upload_file": "Загрузить файл"
},
"analytics_notice": "Участвуя в этой бета-версии, вы соглашаетесь на сбор анонимных данных, которые мы используем для улучшения продукта. Более подробную информацию о том, какие данные мы отслеживаем, вы можете найти в нашей <2> Политике конфиденциальности</2> и нашей <5> Политике использования файлов cookie</5>.",
"app_selection_modal": {
"continue_in_browser": "Продолжить в браузере",
"open_in_app": "Открыть в приложении",
"text": "Готовы присоединиться?",
"title": "Выбрать приложение"
},
"call_ended_view": {
"create_account_button": "Создать аккаунт",
"create_account_prompt": "<0>Почему бы не задать пароль, тем самым сохранив аккаунт?</0><1>Так вы можете оставить своё имя и задать аватар для будущих звонков.</1>",
@@ -20,33 +35,106 @@
"feedback_prompt": "<0>Мы будем рады видеть ваши отзывы, чтобы мы могли улучшить ваш опыт.</0>",
"headline": "{{displayName}}, ваш звонок окончен.",
"not_now_button": "Не сейчас, вернуться в Начало",
"reconnect_button": "Переподключиться",
"survey_prompt": "Как всё прошло?"
},
"call_name": "Название звонка",
"common": {
"analytics": "Аналитика",
"audio": "Аудио",
"avatar": "Аватар",
"back": "Назад",
"display_name": "Видимое имя",
"encrypted": "Зашифровано",
"home": "Начало",
"loading": "Загрузка…",
"next": "Далее",
"options": "Параметры",
"password": "Пароль",
"preferences": "Настройки",
"profile": "Профиль",
"reaction": "Реакция",
"reactions": "Реакции",
"settings": "Настройки",
"unencrypted": "Не зашифровано",
"username": "Имя пользователя",
"video": "Видео"
},
"developer_mode": {
"crypto_version": "Версия криптографии: {{version}}",
"debug_tile_layout_label": "Отладка расположения плиток",
"device_id": "Идентификатор устройства: {{id}}",
"duplicate_tiles_label": "Количество дополнительных копий плиток на участника",
"hostname": "Имя хоста: {{hostname}}",
"livekit_server_info": "Информация о сервере LiveKit",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix ID: {{id}}",
"show_connection_stats": "Показать статистику подключений",
"show_non_member_tiles": "Показать плитки для медиафайлов, не являющихся участниками",
"use_new_membership_manager": "Используйте новую реализацию вызова MembershipManager"
},
"disconnected_banner": "Связь с сервером была потеряна.",
"error": {
"call_is_not_supported": "Вызов не поддерживается",
"call_not_found": "Звонок не найден",
"call_not_found_description": "<0>Эта ссылка, похоже, не принадлежит ни к одному существующему звонку. Убедитесь, что у вас есть нужная ссылка, или <1>создайте новую</1>.</0>",
"connection_lost": "Соединение потеряно",
"connection_lost_description": "Вы были отключены от звонка.",
"e2ee_unsupported": "Несовместимый браузер",
"e2ee_unsupported_description": "Ваш веб-браузер не поддерживает зашифрованные звонки. Поддерживаются следующие браузеры: Chrome, Safari и Firefox 117+.",
"generic": "Произошла ошибка",
"generic_description": "Отправка журналов отладки поможет нам отследить проблему.",
"insufficient_capacity": "Недостаточная пропускная способность",
"insufficient_capacity_description": "Сервер достиг максимальной пропускной способности, и вы не можете присоединиться к звонку в данный момент. Повторите попытку позже или обратитесь к администратору сервера, если проблема сохраняется.",
"matrix_rtc_focus_missing": "Сервер не настроен для работы с {{brand}}. Пожалуйста, свяжитесь с администратором вашего сервера (Домен: {{domain}}, Код ошибки: {{ errorCode }}).",
"open_elsewhere": "Открыто в другой вкладке",
"open_elsewhere_description": "{{brand}} был открыт в другой вкладке. Если это неверно, попробуйте перезагрузить страницу.",
"unexpected_ec_error": "Произошла непредвиденная ошибка (<0> Код ошибки:</0><1>{{ errorCode }}</1> ). Обратитесь к администратору вашего сервера."
},
"group_call_loader": {
"banned_body": "Вас заблокировали в этой комнате",
"banned_heading": "Заблокирован",
"call_ended_body": "Вы были удалены из звонка.",
"call_ended_heading": "Вызов завершен",
"knock_reject_body": "Участники комнаты отклонили ваш запрос на присоединение.",
"knock_reject_heading": "Не разрешено присоединиться",
"reason": "Причина"
},
"hangup_button_label": "Завершить звонок",
"header_label": "Главная Element Call",
"header_participants_label": "Участники",
"invite_modal": {
"link_copied_toast": "Ссылка скопирована в буфер обмена",
"title": "Пригласить в этот звонок"
},
"join_existing_call_modal": {
"join_button": "Да, присоединиться",
"text": "Этот звонок уже существует, хотите присоединиться?",
"title": "Присоединиться к существующему звонку?"
},
"layout_grid_label": "Сетка",
"layout_spotlight_label": "Внимание",
"lobby": {
"join_button": "Присоединиться"
"ask_to_join": "Запрос на подключение к звонку",
"join_as_guest": "Присоединиться в качестве гостя",
"join_button": "Присоединиться",
"leave_button": "Вернуться к списку недавних",
"waiting_for_invite": "Запрос отправлен"
},
"log_in": "Войти",
"logging_in": "Вход…",
"login_auth_links": "<0>Создать аккаунт</0> или <2>Зайти как гость</2>",
"login_auth_links_prompt": "Еще не зарегистрированы?",
"login_subheading": "Продолжить в Element",
"login_title": "Вход",
"microphone_off": "Микрофон выключен",
"microphone_on": "Микрофон включен",
"mute_microphone_button_label": "Отключить микрофон",
"participant_count_one": "{{count, number}}",
"participant_count_few": "{{count, number}}",
"participant_count_many": "{{count, number}}",
"qr_code": "QR код",
"rageshake_button_error_caption": "Повторить отправку журналов",
"rageshake_request_modal": {
"body": "У одного из участников звонка есть неполадки. Чтобы лучше диагностировать похожие проблемы, нам нужен журнал отладки.",
"title": "Запрос журнала отладки"
@@ -54,6 +142,7 @@
"rageshake_send_logs": "Отправить журнал отладки",
"rageshake_sending": "Отправка…",
"rageshake_sending_logs": "Отправка журнала отладки…",
"rageshake_sent": "Спасибо!",
"recaptcha_dismissed": "Проверка не пройдена",
"recaptcha_not_loaded": "Невозможно начать проверку",
"register": {
@@ -62,22 +151,66 @@
},
"register_auth_links": "<0>Уже есть аккаунт?</0><1><0>Войти с ним</0> или <2>Зайти как гость</2></1>",
"register_confirm_password_label": "Подтвердите пароль",
"register_heading": "Создать учетную запись",
"return_home_button": "Вернуться в Начало",
"room_auth_view_continue_button": "Продолжить",
"screenshare_button_label": "Поделиться экраном",
"settings": {
"audio_tab": {
"effect_volume_description": "Отрегулируйте громкость воспроизведения реакций и эффектов поднятия руки.",
"effect_volume_label": "Громкость звукового эффекта"
},
"developer_tab_title": "Разработчику",
"devices": {
"camera": "Камера",
"camera_numbered": "Камера {{n}}",
"default": "По умолчанию",
"default_named": "По умолчанию <2>({{name}})</2>",
"microphone": "Микрофон",
"microphone_numbered": "Микрофон {{n}}",
"speaker": "Динамик",
"speaker_numbered": "Динамик {{n}}"
},
"feedback_tab_body": "Если у вас возникли проблемы или вы просто хотите оставить отзыв, отправьте нам краткое описание ниже.",
"feedback_tab_description_label": "Ваш отзыв",
"feedback_tab_h4": "Отправить отзыв",
"feedback_tab_send_logs_label": "Приложить журнал отладки",
"feedback_tab_thank_you": "Спасибо. Мы получили ваш отзыв!",
"feedback_tab_title": "Отзыв",
"opt_in_description": "<0></0><1></1>Вы можете отозвать согласие, сняв этот флажок. Если вы в данный момент находитесь в разговоре, эта настройка вступит в силу по окончании разговора."
"opt_in_description": "<0></0><1></1>Вы можете отозвать согласие, сняв этот флажок. Если вы в данный момент находитесь в разговоре, эта настройка вступит в силу по окончании разговора.",
"preferences_tab": {
"developer_mode_label": "Режим разработчика",
"developer_mode_label_description": "Включить режим разработчика и показать настройки.",
"introduction": "Здесь вы можете настроить дополнительные параметры для улучшения качества работы.",
"reactions_play_sound_description": "Воспроизведите звуковой эффект, когда кто-либо отреагирует на звонок.",
"reactions_play_sound_label": "Воспроизводить звуки реакции",
"reactions_show_description": "Показать реакции",
"reactions_show_label": "Показывать анимацию, когда кто-либо отправляет реакцию.",
"show_hand_raised_timer_description": "Показывать таймер, когда участник поднимает руку",
"show_hand_raised_timer_label": "Показать продолжительность поднятия руки"
}
},
"star_rating_input_label_one": "{{count}} отмечен",
"star_rating_input_label_other": "{{count}} отмеченных",
"start_new_call": "Начать новый звонок",
"start_video_button_label": "Начать видео",
"stop_screenshare_button_label": "Демонстрация экрана",
"stop_video_button_label": "Остановить видео",
"submitting": "Отправляем…",
"switch_camera": "Переключить камеру",
"unauthenticated_view_body": "Ещё не зарегистрированы? <2>Создайте аккаунт</2>",
"unauthenticated_view_login_button": "Войдите в свой аккаунт",
"version": "Версия: {{version}}"
"unmute_microphone_button_label": "Включить микрофон",
"version": "Версия: {{version}}",
"video_tile": {
"always_show": "Показывать всегда",
"camera_starting": "Загрузка видео...",
"change_fit_contain": "По размеру окна",
"collapse": "Свернуть",
"expand": "Развернуть",
"mute_for_me": "Заглушить звук для меня",
"muted_for_me": "Приглушить для меня",
"volume": "Громкость",
"waiting_for_media": "В ожидании медиа..."
}
}

View File

@@ -5,14 +5,21 @@
"action": {
"close": "Zatvoriť",
"copy_link": "Kopírovať odkaz",
"edit": "Upraviť",
"go": "Prejsť",
"invite": "Pozvať",
"lower_hand": "Dať dole ruku",
"no": "Nie",
"pick_reaction": "Vybrať reakciu",
"raise_hand": "Zdvihnúť ruku",
"register": "Registrovať sa",
"remove": "Odstrániť",
"show_less": "Zobraziť menej",
"show_more": "Zobraziť viac",
"sign_in": "Prihlásiť sa",
"sign_out": "Odhlásiť sa",
"submit": "Odoslať"
"submit": "Odoslať",
"upload_file": "Nahrať súbor"
},
"analytics_notice": "Účasťou v tejto beta verzii súhlasíte so zhromažďovaním anonymných údajov, ktoré použijeme na zlepšenie produktu. Viac informácií o tom, ktoré údaje sledujeme, nájdete v našich <2>Zásadách ochrany osobných údajov</2> a <5>Zásadách používania súborov cookie</5>.",
"app_selection_modal": {
@@ -33,18 +40,66 @@
},
"call_name": "Názov hovoru",
"common": {
"analytics": "Analytika",
"audio": "Zvuk",
"avatar": "Obrázok",
"back": "Späť",
"display_name": "Zobrazované meno",
"encrypted": "Šifrované",
"home": "Domov",
"loading": "Načítanie…",
"next": "Ďalej",
"options": "Možnosti",
"password": "Heslo",
"preferences": "Predvoľby",
"profile": "Profil",
"reaction": "Reakcia",
"reactions": "Reakcie",
"settings": "Nastavenia",
"unencrypted": "Nie je zašifrované",
"username": "Meno používateľa"
"username": "Meno používateľa",
"video": "Video"
},
"developer_mode": {
"crypto_version": "Krypto verzia: {{version}}",
"debug_tile_layout_label": "Ladenie rozloženia dlaždíc",
"device_id": "ID zariadenia: {{id}}",
"duplicate_tiles_label": "Počet ďalších kópií dlaždíc na účastníka",
"hostname": "Názov hostiteľa: {{hostname}}",
"livekit_server_info": "Informácie o serveri LiveKit",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix ID: {{id}}",
"show_connection_stats": "Zobraziť štatistiky pripojenia",
"show_non_member_tiles": "Zobraziť dlaždice pre nečlenské médiá",
"use_new_membership_manager": "Použiť novú implementáciu hovoru MembershipManager"
},
"disconnected_banner": "Spojenie so serverom sa stratilo.",
"error": {
"call_is_not_supported": "Hovor nie je podporovaný",
"call_not_found": "Hovor nebol nájdený",
"call_not_found_description": "<0>Zdá sa, že tento odkaz nepatrí k žiadnemu existujúcemu hovoru. Skontrolujte, či máte správny odkaz, alebo <1> vytvorte nový</1>. </0>",
"connection_lost": "Strata spojenia",
"connection_lost_description": "Boli ste odpojení od hovoru.",
"e2ee_unsupported": "Nekompatibilný prehliadač",
"e2ee_unsupported_description": "Váš webový prehliadač nepodporuje šifrované hovory. Medzi podporované prehliadače patria Chrome, Safari a Firefox 117+.",
"generic": "Niečo sa pokazilo",
"generic_description": "Odoslanie záznamov ladenia nám pomôže nájsť problém.",
"insufficient_capacity": "Nedostatočná kapacita",
"insufficient_capacity_description": "Server dosiahol svoju maximálnu kapacitu a momentálne sa nemôžete pripojiť k hovoru. Skúste to znova neskôr alebo kontaktujte správcu servera, ak problém pretrváva.",
"matrix_rtc_focus_missing": "Server nie je nakonfigurovaný na prácu s aplikáciou {{brand}}. Kontaktujte správcu svojho servera (Doména:{{domain}}, Kód chyby:{{ errorCode }}).",
"open_elsewhere": "Otvorené na inej karte",
"open_elsewhere_description": "Aplikácia {{brand}} bola otvorená na inej karte. Ak sa vám to nezdá, skúste znovu načítať stránku.",
"unexpected_ec_error": "Vyskytla sa neočakávaná chyba (<0>Kód chyby:</0> <1>{{ errorCode }}</1>). Kontaktujte prosím správcu vášho servera."
},
"group_call_loader": {
"banned_body": "Dostali ste zákaz vstupu do miestnosti.",
"banned_heading": "Zakázané",
"call_ended_body": "Boli ste odstránení z hovoru.",
"call_ended_heading": "Hovor bol ukončený",
"knock_reject_body": "Členovia miestnosti odmietli vašu žiadosť o pripojenie.",
"knock_reject_heading": "Nie je povolené pripojiť sa",
"reason": "Dôvod"
},
"hangup_button_label": "Ukončiť hovor",
"header_label": "Domov Element Call",
"header_participants_label": "Účastníci",
@@ -60,15 +115,25 @@
"layout_grid_label": "Sieť",
"layout_spotlight_label": "Stredobod",
"lobby": {
"ask_to_join": "Požiadať o pripojenie k hovoru",
"join_as_guest": "Pripojiť sa ako hosť",
"join_button": "Pripojiť sa k hovoru",
"leave_button": "Späť k nedávnym"
"leave_button": "Späť k nedávnym",
"waiting_for_invite": "Žiadosť odoslaná"
},
"log_in": "Prihlásiť sa",
"logging_in": "Prihlasovanie…",
"login_auth_links": "<0>Vytvoriť konto</0> Alebo <2>Prihlásiť sa ako hosť</2>",
"login_auth_links_prompt": "Nie ste ešte zaregistrovaní?",
"login_subheading": "Ak chcete pokračovať na Element",
"login_title": "Prihlásiť sa",
"microphone_off": "Mikrofón vypnutý",
"microphone_on": "Mikrofón zapnutý",
"mute_microphone_button_label": "Stlmiť mikrofón",
"participant_count_one": "{{count, number}}",
"participant_count_few": "{{count, number}}",
"participant_count_other": "{{count, number}}",
"qr_code": "QR kód",
"rageshake_button_error_caption": "Opakovať odoslanie záznamov",
"rageshake_request_modal": {
"body": "Ďalší používateľ v tomto hovore má problém. Aby sme mohli lepšie diagnostikovať tieto problémy, chceli by sme získať záznam o ladení.",
@@ -78,7 +143,6 @@
"rageshake_sending": "Odosielanie…",
"rageshake_sending_logs": "Odosielanie záznamov o ladení…",
"rageshake_sent": "Ďakujeme!",
"recaptcha_caption": "Táto stránka je chránená systémom ReCAPTCHA a platia na ňu <2>Pravidlá ochrany osobných údajov spoločnosti Google</2> a <6>Podmienky poskytovania služieb</6>.<9></9>Kliknutím na tlačidlo \"Registrovať sa\" súhlasíte s našou <12>Licenčnou zmluvou s koncovým používateľom (EULA)</12>",
"recaptcha_dismissed": "Recaptcha zamietnutá",
"recaptcha_not_loaded": "Recaptcha sa nenačítala",
"register": {
@@ -87,18 +151,44 @@
},
"register_auth_links": "<0>Už máte konto?</0><1><0>Prihláste sa</0> Alebo <2>Prihlásiť sa ako hosť</2></1>",
"register_confirm_password_label": "Potvrdiť heslo",
"register_heading": "Vytvorte si účet",
"return_home_button": "Návrat na domovskú obrazovku",
"room_auth_view_eula_caption": "Kliknutím na \"Pripojiť sa k hovoru teraz\" súhlasíte s našou <2>Licenčnou zmluvou s koncovým používateľom (EULA)</2>",
"room_auth_view_continue_button": "Pokračovať",
"screenshare_button_label": "Zdieľať obrazovku",
"settings": {
"audio_tab": {
"effect_volume_description": "Upraviť hlasitosť, pri ktorej sa prehrávajú reakcie a efekty zdvihnutia ruky.",
"effect_volume_label": "Hlasitosť zvukového efektu"
},
"developer_tab_title": "Vývojár",
"devices": {
"camera": "Kamera",
"camera_numbered": "Kamera {{n}}",
"default": "Predvolené",
"default_named": "Predvolené <2>({{name}})</2>",
"microphone": "Mikrofón",
"microphone_numbered": "Mikrofón {{n}}",
"speaker": "Reproduktor",
"speaker_numbered": "Reproduktor {{n}}"
},
"feedback_tab_body": "Ak máte problémy alebo jednoducho chcete poskytnúť spätnú väzbu, pošlite nám krátky popis nižšie.",
"feedback_tab_description_label": "Vaša spätná väzba",
"feedback_tab_h4": "Odoslať spätnú väzbu",
"feedback_tab_send_logs_label": "Zahrnúť záznamy o ladení",
"feedback_tab_thank_you": "Ďakujeme, dostali sme vašu spätnú väzbu!",
"feedback_tab_title": "Spätná väzba",
"opt_in_description": "<0></0><1></1>Súhlas môžete odvolať zrušením označenia tohto políčka. Ak práve prebieha hovor, toto nastavenie nadobudne platnosť po skončení hovoru."
"opt_in_description": "<0></0><1></1>Súhlas môžete odvolať zrušením označenia tohto políčka. Ak práve prebieha hovor, toto nastavenie nadobudne platnosť po skončení hovoru.",
"preferences_tab": {
"developer_mode_label": "Režim vývojára",
"developer_mode_label_description": "Povoliť režim vývojára a zobraziť kartu Nastavenia vývojára.",
"introduction": "Tu môžete nastaviť ďalšie možnosti pre lepší zážitok.",
"reactions_play_sound_description": "Prehrať zvukový efekt, keď niekto odošle reakciu na hovor.",
"reactions_play_sound_label": "Prehrať zvuky reakcie",
"reactions_show_description": "Zobraziť animáciu, keď niekto odošle reakciu.",
"reactions_show_label": "Zobraziť reakcie",
"show_hand_raised_timer_description": "Zobraziť časovač, keď účastník zdvihne ruku",
"show_hand_raised_timer_label": "Zobraziť trvanie zdvihnutia ruky"
}
},
"star_rating_input_label_one": "{{count}} hviezdička",
"star_rating_input_label_other": "{{count}} hviezdičiek",
@@ -107,9 +197,20 @@
"stop_screenshare_button_label": "Zdieľanie obrazovky",
"stop_video_button_label": "Zastaviť video",
"submitting": "Odosielanie…",
"switch_camera": "Prepnúť fotoaparát",
"unauthenticated_view_body": "Ešte nie ste zaregistrovaný? <2>Vytvorte si účet</2>",
"unauthenticated_view_eula_caption": "Kliknutím na tlačidlo \"Prejsť\" vyjadrujete súhlas s našou <2>Licenčnou zmluvou s koncovým používateľom (EULA)</2>",
"unauthenticated_view_login_button": "Prihláste sa do svojho konta",
"unmute_microphone_button_label": "Zrušiť stlmenie mikrofónu",
"version": "Verzia: {{version}}"
"version": "Verzia: {{version}}",
"video_tile": {
"always_show": "Vždy zobraziť",
"camera_starting": "Načítavanie videa...",
"change_fit_contain": "Orezať na mieru",
"collapse": "Zbaliť",
"expand": "Rozbaliť",
"mute_for_me": "Pre mňa stlmiť",
"muted_for_me": "Pre mňa stlmené",
"volume": "Hlasitosť",
"waiting_for_media": "Čaká sa na médiá..."
}
}

View File

@@ -1,7 +1,220 @@
{
"a11y": {
"user_menu": "Användarmeny"
},
"action": {
"close": "Stäng",
"copy_link": "Kopiera länk",
"edit": "Redigera",
"go": "Gå",
"invite": "Bjud in",
"lower_hand": "Sänk handen",
"no": "Nej",
"pick_reaction": "Välj reaktion",
"raise_hand": "Räck upp handen",
"register": "Registrera",
"remove": "Ta bort",
"show_less": "Visa mindre",
"show_more": "Visa mer",
"sign_in": "Logga in",
"sign_out": "Logga ut",
"submit": "Skicka",
"upload_file": "Ladda upp fil"
},
"analytics_notice": "Genom att delta i denna beta samtycker du till insamling av anonyma uppgifter, som vi använder för att förbättra produkten. Du kan hitta mer information om vilka data vi spårar i vår <2>integritetspolicy</2> och vår <5>cookiepolicy</5>.",
"app_selection_modal": {
"continue_in_browser": "Fortsätt i webbläsaren",
"open_in_app": "Öppna i appen",
"text": "Är du redo att gå med?",
"title": "Välj app"
},
"call_ended_view": {
"headline": "{{displayName}}, ditt samtal har avslutats."
"create_account_button": "Skapa konto",
"create_account_prompt": "<0>Varför inte avsluta genom att skapa ett lösenord för att behålla ditt konto?</0><1>Du kommer att kunna behålla ditt namn och ställa in en avatar för användning vid framtida samtal</1>",
"feedback_done": "<0>Tack för din feedback! </0>",
"feedback_prompt": "<0>Vi vill gärna höra din feedback så att vi kan förbättra din upplevelse. </0>",
"headline": "{{displayName}}, ditt samtal har avslutats.",
"not_now_button": "Inte nu, återgå till startskärmen",
"reconnect_button": "Återanslut",
"survey_prompt": "Hur gick det?"
},
"call_name": "Namn på samtal",
"common": {
"analytics": "Analysdata",
"audio": "Ljud",
"avatar": "Avatar",
"back": "Tillbaka",
"display_name": "Visningsnamn",
"encrypted": "Krypterad",
"home": "Hem",
"loading": "Laddar …",
"next": "Nästa",
"options": "Alternativ",
"password": "Lösenord",
"preferences": "Alternativ",
"profile": "Profil",
"reaction": "Reaktion",
"reactions": "Reaktioner",
"settings": "Inställningar",
"unencrypted": "Inte krypterad",
"username": "Användarnamn",
"video": "Video"
},
"developer_mode": {
"crypto_version": "Kryptoversion: {{version}}",
"debug_tile_layout_label": "Felsök panelarrangemang",
"device_id": "Enhets-ID: {{id}}",
"duplicate_tiles_label": "Antal ytterligare panelkopior per deltagare",
"environment_variables": "Miljövariabler",
"hostname": "Värdnamn: {{hostname}}",
"livekit_server_info": "LiveKit-serverinfo",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix-ID: {{id}}",
"show_connection_stats": "Visa anslutningsstatistik",
"show_non_member_tiles": "Visa paneler för media som inte är medlemmar",
"url_params": "URL-parametrar",
"use_new_membership_manager": "Använd den nya implementeringen av samtals-MembershipManager"
},
"disconnected_banner": "Anslutningen till servern har brutits.",
"error": {
"call_is_not_supported": "Call stöds inte",
"call_not_found": "Samtal hittades inte",
"call_not_found_description": "<0>Den länken verkar inte tillhöra något befintligt samtal. Kontrollera att du har rätt länk, eller <1>skapa en ny</1>.</0>",
"connection_lost": "Anslutning förlorad",
"connection_lost_description": "Du kopplades bort från samtalet.",
"e2ee_unsupported": "Inkompatibel webbläsare",
"e2ee_unsupported_description": "Din webbläsare stöder inte krypterade samtal. Webbläsare som stöds inkluderar Chrome, Safari och Firefox 117+.",
"generic": "Något gick fel",
"generic_description": "Att skicka felsökningsloggar hjälper oss att spåra problemet.",
"insufficient_capacity": "Otillräcklig kapacitet",
"insufficient_capacity_description": "Servern har nått sin maximala kapacitet och du kan inte gå med i samtalet just nu. Försök igen senare, eller kontakta serveradministratören om problemet kvarstår.",
"matrix_rtc_focus_missing": "Servern är inte konfigurerad för att fungera med {{brand}}. Vänligen kontakta serveradministratören (Domän: {{domain}}, Felkod: {{ errorCode }}).",
"open_elsewhere": "Öppnades i en annan flik",
"open_elsewhere_description": "{{brand}} har öppnats i en annan flik. Om det inte låter rätt, pröva att ladda om sidan.",
"unexpected_ec_error": "Ett oväntat fel inträffade (<0>Felkod:</0> <1>{{ errorCode }}</1>). Kontakta din serveradministratör."
},
"group_call_loader": {
"banned_body": "Du har bannats från rummet.",
"banned_heading": "Bannad",
"call_ended_body": "Du har har tagits bort från samtalet.",
"call_ended_heading": "Samtal avslutat",
"knock_reject_body": "Rumsmedlemmarna avslog din begäran om att gå med.",
"knock_reject_heading": "Inte tillåten att gå med",
"reason": "Anledning"
},
"hangup_button_label": "Avsluta samtal",
"header_label": "Element Call Hem",
"header_participants_label": "Deltagare",
"invite_modal": {
"link_copied_toast": "Länk kopierad till klippbordet",
"title": "Bjud in till det här samtalet"
},
"join_existing_call_modal": {
"join_button": "Ja, gå med i samtal",
"text": "Det här samtalet finns redan, vill du gå med?",
"title": "Gå med i befintligt samtal?"
},
"layout_grid_label": "Rutnät",
"layout_spotlight_label": "Spotlight",
"lobby": {
"ask_to_join": "Be om att delta i samtalet",
"join_as_guest": "Gå med som gäst",
"join_button": "Anslut till samtal",
"leave_button": "Tillbaka till senaste",
"waiting_for_invite": "Begäran skickad"
},
"log_in": "Logga in",
"logging_in": "Loggar in …",
"login_auth_links": "<0>Skapa ett konto</0> eller <2>Kom åt som gäst</2>",
"login_auth_links_prompt": "Inte registrerad än?",
"login_subheading": "För att fortsätta till Element",
"login_title": "Logga in",
"microphone_off": "Mikrofon av",
"microphone_on": "Mikrofon på",
"mute_microphone_button_label": "Tysta mikrofonen",
"participant_count_one": "{{count, number}}",
"participant_count_other": "{{count, number}}",
"qr_code": "QR-kod",
"rageshake_button_error_caption": "Försök att skicka loggar igen",
"rageshake_request_modal": {
"body": "En annan användare i det här samtalet har ett problem. För att bättre kunna diagnostisera dessa problem vill vi samla in en felsökningslogg.",
"title": "Begäran om felsökningslogg"
},
"rageshake_send_logs": "Skicka felsökningsloggar",
"rageshake_sending": "Skickar …",
"rageshake_sending_logs": "Skickar felsökningsloggar …",
"rageshake_sent": "Tack!",
"recaptcha_dismissed": "Recaptcha avvisad",
"recaptcha_not_loaded": "Recaptcha laddades inte",
"recaptcha_ssla_caption": "Denna webbplats skyddas av ReCAPTCHA och Googles <2>sekretesspolicy</2> och <6>användarvillkor</6> gäller.<9></9>Genom att klicka på ”Registrera” godkänner du vårt <12>licensavtal för programvara och tjänster</12>",
"register": {
"passwords_must_match": "Lösenorden måste överensstämma",
"registering": "Registrerar …"
},
"register_auth_links": "<0>Har du redan ett konto?</0><1><0>Logga in</0> eller <2>kom åt som en gäst</2></1>",
"register_confirm_password_label": "Bekräfta lösenord",
"register_heading": "Skapa ditt konto",
"return_home_button": "Återgå till startskärmen",
"room_auth_view_continue_button": "Fortsätt",
"room_auth_view_ssla_caption": "Genom att klicka på ”Anslut till samtal nu” godkänner du vårt <2>licensavtal för programvara och tjänster</2>",
"screenshare_button_label": "Dela skärm",
"settings": {
"audio_tab": {
"effect_volume_description": "Justera volymen vid vilken reaktioner och handuppräckningseffekter spelas",
"effect_volume_label": "Ljudeffektsvolym"
},
"developer_tab_title": "Utvecklare",
"devices": {
"camera": "Kamera",
"camera_numbered": "Kamera {{n}}",
"default": "Förval",
"default_named": "Förval <2>({{name}})</2>",
"microphone": "Mikrofon",
"microphone_numbered": "Mikrofon {{n}}",
"speaker": "Högtalare",
"speaker_numbered": "Högtalare {{n}}"
},
"feedback_tab_body": "Om du har problem eller bara vill ge lite återkoppling, skicka oss en kort beskrivning nedan.",
"feedback_tab_description_label": "Din återkoppling",
"feedback_tab_h4": "Skicka återkoppling",
"feedback_tab_send_logs_label": "Inkludera felsökningsloggar",
"feedback_tab_thank_you": "Tack, vi har tagit emot din återkoppling!",
"feedback_tab_title": "Återkoppling",
"opt_in_description": "<0></0><1></1>Du kan återkalla ditt samtycke genom att avmarkera den här rutan. Om du för närvarande är i ett samtal träder den här inställningen i kraft vid slutet av samtalet.",
"preferences_tab": {
"developer_mode_label": "Utvecklarläge",
"developer_mode_label_description": "Aktivera utvecklarläger och visa fliken utvecklarinställningar.",
"introduction": "Här kan du konfigurera extra alternativ för en förbättrad upplevelse.",
"reactions_play_sound_description": "Spela en ljudeffekt när någon skickar in en reaktion i ett samtal.",
"reactions_play_sound_label": "Spela reaktionsljud",
"reactions_show_description": "Visa en animering när någon skickar en reaktion.",
"reactions_show_label": "Visa reaktioner",
"show_hand_raised_timer_description": "Visa en timer när en deltagare räcker upp handen",
"show_hand_raised_timer_label": "Visa varaktighet för handuppräckning"
}
},
"star_rating_input_label_one": "{{count}} stjärna",
"star_rating_input_label_other": "{{count}} stjärnor"
"star_rating_input_label_other": "{{count}} stjärnor",
"start_new_call": "Starta ett nytt samtal",
"start_video_button_label": "Starta video",
"stop_screenshare_button_label": "Delar skärm",
"stop_video_button_label": "Stoppa video",
"submitting": "Skickar …",
"switch_camera": "Byt kamera",
"unauthenticated_view_body": "Inte registrerad än? <2>Skapa ett konto</2>",
"unauthenticated_view_login_button": "Logga in på ditt konto",
"unauthenticated_view_ssla_caption": "Genom att klicka på ”Kör” godkänner du vårt <2>licensavtal för programvara och tjänster</2>",
"unmute_microphone_button_label": "Sluta tysta mikrofonen",
"version": "Version: {{version}}",
"video_tile": {
"always_show": "Visa alltid",
"camera_starting": "Video laddar …",
"change_fit_contain": "Anpassa till ram",
"collapse": "Kollapsa",
"expand": "Expandera",
"mute_for_me": "Tysta för mig",
"muted_for_me": "Tystad för mig",
"volume": "Volym",
"waiting_for_media": "Väntar på media …"
}
}

View File

@@ -1,42 +1,141 @@
{
"a11y": {
"user_menu": "Kullanıcı menüsü"
},
"action": {
"close": "Kapat",
"copy_link": "Bağlantıyı kopyala",
"edit": "Düzenle",
"go": "Git",
"invite": "Davet et",
"lower_hand": "Elini indir",
"no": "Hayır",
"pick_reaction": "Tepki seç",
"raise_hand": "Elini kaldır",
"register": "Kaydol",
"remove": ıkar",
"show_less": "Daha az göster",
"show_more": "Daha fazla göster",
"sign_in": "Gir",
"sign_out": ık"
"sign_out": ık",
"submit": "Gönder",
"upload_file": "Dosya Yükle"
},
"analytics_notice": "Bu beta sürümüne katılarak, ürünü geliştirmek için kullandığımız anonim verilerin toplanmasına izin vermiş olursunuz. Hangi verileri izlediğimiz hakkında daha fazla bilgiyi <2>Gizlilik Politikamızda</2> ve <6>Çerez Politikamızda bulabilirsiniz</6>..",
"app_selection_modal": {
"continue_in_browser": "Tarayıcıda devam et",
"open_in_app": "Uygulamada aç",
"text": "Katılmaya hazır mısınız?",
"title": "Uygulama seçin"
},
"call_ended_view": {
"create_account_button": "Hesap aç",
"create_account_prompt": "<0>Hesabınızı tutmak için niye bir parola açmıyorsunuz?</0><1>Böylece ileriki aramalarda adınızı ve avatarınızı kullanabileceksiniz</1>",
"not_now_button": "Şimdi değil, ev ekranına dön"
"feedback_done": "<0>Geri bildiriminiz için teşekkürler!</0>",
"feedback_prompt": "<0>Deneyiminizi geliştirebilmemiz için geri bildirimlerinizi duymak isteriz.</0>",
"headline": "{{displayName}}, çağrınız sona erdi.",
"not_now_button": "Şimdi değil, ev ekranına dön",
"reconnect_button": "Yeniden bağlan",
"survey_prompt": "Nasıl geçti?"
},
"call_name": "Aramanın adı",
"common": {
"analytics": "Analiz",
"audio": "Ses",
"avatar": "Avatar",
"back": "Geri",
"display_name": "Ekran adı",
"encrypted": "Şifrelenmiş",
"home": "Ev",
"loading": "Yükleniyor…",
"next": "İleri",
"options": "Seçenekler",
"password": "Parola",
"settings": "Ayarlar"
"preferences": "Tercihler",
"profile": "Profil",
"reaction": "Tepki",
"reactions": "Tepkiler",
"settings": "Ayarlar",
"unencrypted": "Şifrelenmemiş",
"username": "Kullanıcı adı",
"video": "Video"
},
"developer_mode": {
"crypto_version": "Şifreleme sürümü: {{version}}",
"debug_tile_layout_label": "Hata ayıklama döşeme düzeni",
"device_id": "Cihaz Kimliği: {{id}}",
"duplicate_tiles_label": "Katılımcı başına ek döşeme sayısı",
"hostname": "Sunucu adı: {{hostname}}",
"livekit_server_info": "LiveKit Sunucu Bilgisi",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix Kimliği: {{id}}",
"show_connection_stats": "Bağlantı istatistiklerini göster",
"show_non_member_tiles": "Üye olmayan kullanıcılar için ortam döşemelerini göster"
},
"disconnected_banner": "Sunucuyla bağlantı kesildi.",
"error": {
"call_not_found": "Çağrı bulunamadı",
"call_not_found_description": "<0>Bu bağlantı mevcut herhangi bir çağrıya ait görünmüyor. Doğru bağlantıya sahip olduğunuzu kontrol edin veya <1> yeni bir bağlantı oluşturun</1>. </0>",
"connection_lost": "Bağlantı kesildi",
"connection_lost_description": "Çağrıdan bağlantınız kesildi.",
"e2ee_unsupported": "Uyumsuz Tarayıcı",
"e2ee_unsupported_description": "İnternet tarayıcınız şifreli aramaları desteklemiyor. Desteklenen tarayıcılar arasında Chrome, Safari ve Firefox 117+ bulunur.",
"generic": "Bir şeyler ters gitti",
"generic_description": "Hata ayıklama günlüklerini göndermeniz sorunu tespit etmemizde yardımcı olacaktır.",
"open_elsewhere": "Başka bir sekmede açıldı",
"open_elsewhere_description": "{{brand}} başka bir sekmede açıldı. Bu doğru değilse, sayfayı yeniden yüklemeyi deneyin."
},
"group_call_loader": {
"banned_body": "Odaya girmeniz yasaklandı.",
"banned_heading": "Yasaklandı",
"call_ended_body": "Aramadan çıkarıldınız.",
"call_ended_heading": "Arama sonlandırıldı",
"knock_reject_body": "Katılma isteğiniz reddedildi.",
"knock_reject_heading": "Erişim reddedildi",
"reason": "Neden: {{reason}}"
},
"hangup_button_label": "Aramayı sonlandır",
"header_label": "Element Call Ana Sayfa",
"header_participants_label": "Katılımcılar",
"invite_modal": {
"link_copied_toast": "Bağlantı panoya kopyalandı",
"title": "Bu görüşmeye davet edin"
},
"join_existing_call_modal": {
"join_button": "Evet, aramaya katıl",
"text": "Bu arama zaten var, katılmak ister misiniz?",
"title": "Mevcut aramaya katıl?"
},
"layout_grid_label": "Izgara",
"layout_spotlight_label": "İlgi Odağı",
"lobby": {
"join_button": "Aramaya katıl"
"ask_to_join": "Aramaya katılma isteği gönder",
"join_as_guest": "Misafir olarak katıl",
"join_button": "Aramaya katıl",
"leave_button": "Son aramalara dön",
"waiting_for_invite": "İstek gönderildi! Katılmak için izin verilmesi bekleniyor…"
},
"log_in": "Giriş yap",
"logging_in": "Giriliyor…",
"login_auth_links": "<0>Hesap oluştur</0> yahut <2>Konuk olarak gir</2>",
"login_auth_links_prompt": "Henüz kaydolmadınız mı?",
"login_subheading": "Element'e devam etmek için",
"login_title": "Gir",
"microphone_off": "Mikrofon kapalı",
"microphone_on": "Mikrofon açık",
"mute_microphone_button_label": "Mikrofonu sessize al",
"participant_count_one": "{{count, number}}",
"participant_count_other": "{{count, number}}",
"qr_code": "QR Kodu",
"rageshake_button_error_caption": "Günlükleri göndermeyi yeniden dene",
"rageshake_request_modal": {
"body": "Bu aramadaki başka bir kullanıcı sorun yaşıyor. Sorunu daha iyi çözebilmemiz için hata ayıklama kütüğünü almak isteriz.",
"title": "Hata ayıklama kütük istemi"
},
"rageshake_send_logs": "Hata ayıklama kütüğünü gönder",
"rageshake_sending": "Gönderiliyor…",
"rageshake_sending_logs": "Hata ayıklama günlükleri gönderiliyor...",
"rageshake_sent": "Teşekkürler!",
"recaptcha_dismissed": "reCAPTCHA atlandı",
"recaptcha_not_loaded": "reCAPTCHA yüklenmedi",
"register": {
@@ -45,13 +144,66 @@
},
"register_auth_links": "<0>Mevcut hesabınız mı var?</0><1><0>Gir</0> yahut <2>Konuk girişi</2></1>",
"register_confirm_password_label": "Parolayı tekrar edin",
"register_heading": "Hesabınızı Oluşturun",
"return_home_button": "Ev ekranına geri dön",
"room_auth_view_continue_button": "Devam et",
"screenshare_button_label": "Ekran paylaş",
"settings": {
"audio_tab": {
"effect_volume_description": "Tepkilerin ve el kaldırmaların çaldığı ses düzeyini ayarlayın.",
"effect_volume_label": "Ses efekti sesi"
},
"developer_tab_title": "Geliştirici",
"devices": {
"camera": "Kamera",
"camera_numbered": "Kamera {{n}}",
"default": "Varsayılan",
"default_named": "Varsayılan <2>({{name}})</2>",
"microphone": "Mikrofon",
"microphone_numbered": "Mikrofon {{n}}",
"speaker": "Hoparlör",
"speaker_numbered": "Hoparlör {{n}}"
},
"feedback_tab_body": "Sorun yaşıyorsanız veya yalnızca geri bildirimde bulunmak istiyorsanız, lütfen bize aşağıdan kısa bir açıklama gönderin.",
"feedback_tab_description_label": "Görüşleriniz",
"feedback_tab_h4": "Geri bildirim ver",
"feedback_tab_send_logs_label": "Hata ayıklama kütüğünü dahil et"
"feedback_tab_send_logs_label": "Hata ayıklama kütüğünü dahil et",
"feedback_tab_thank_you": "Teşekkürler, geri bildiriminizi aldık!",
"feedback_tab_title": "Geri Bildirim",
"opt_in_description": "<0></0><1></1>Bu kutunun işaretini kaldırarak onayınızı geri çekebilirsiniz. Şu anda bir aramadaysanız, bu ayar aramanın sonunda geçerli olacaktır.",
"preferences_tab": {
"developer_mode_label": "Geliştirici modu",
"developer_mode_label_description": "Geliştirici modunu etkinleştir ve geliştirici ayarları sekmesini göster.",
"introduction": "Burada daha iyi bir deneyim için ek seçenekleri yapılandırabilirsiniz.",
"reactions_play_sound_description": "Birisi aramada tepki gönderdiğinde ses efekti çal.",
"reactions_play_sound_label": "Tepki seslerini çal",
"reactions_show_description": "Biri tepki gönderdiğinde animasyon göster.",
"reactions_show_label": "Tepkileri göster",
"show_hand_raised_timer_description": "Bir katılımcı elini kaldırdığında bir zamanlayıcı göster",
"show_hand_raised_timer_label": "El kaldırma süresini göster"
}
},
"star_rating_input_label_one": "{{count}} yıldız",
"star_rating_input_label_other": "{{count}} yıldız",
"start_new_call": "Yeni arama başlat",
"start_video_button_label": "Videoy paylaşımı Başlat",
"stop_screenshare_button_label": "Ekran paylaşılıyor",
"stop_video_button_label": "Video paylaşımını durdur",
"submitting": "Gönderiliyor...",
"switch_camera": "Kamerayı değiştir",
"unauthenticated_view_body": "Kaydolmadınız mı? <2>Hesap açın</2>",
"unauthenticated_view_login_button": "Hesabınıza girin"
"unauthenticated_view_login_button": "Hesabınıza girin",
"unmute_microphone_button_label": "Mikrofonun sesini aç",
"version": "{{productName}} sürüm: {{version}}",
"video_tile": {
"always_show": "Her zaman göster",
"camera_starting": "Video paylaşımı başlatılıyor...",
"change_fit_contain": "Çerçeveye sığdır",
"collapse": "Daralt",
"expand": "Genişlet",
"mute_for_me": "Benim için sessize al",
"muted_for_me": "Benim için susturulanlar",
"volume": "Ses",
"waiting_for_media": "Ortam bekleniyor..."
}
}

View File

@@ -5,14 +5,21 @@
"action": {
"close": "Закрити",
"copy_link": "Скопіювати посилання",
"edit": "Редагувати",
"go": "Далі",
"invite": "Запросити",
"lower_hand": "Опустити руку",
"no": "Ні",
"pick_reaction": "Виберіть реакцію",
"raise_hand": "Підняти руку",
"register": "Зареєструватися",
"remove": "Вилучити",
"show_less": "Показувати менше",
"show_more": "Показати більше",
"sign_in": "Увійти",
"sign_out": "Вийти",
"submit": "Надіслати"
"submit": "Надіслати",
"upload_file": "Завантажити файл"
},
"analytics_notice": "Користуючись дочасним доступом, ви даєте згоду на збір анонімних даних, які ми використовуємо для вдосконалення продукту. Ви можете знайти більше інформації про те, які дані ми відстежуємо в нашій <2>Політиці Приватності</2> і нашій <5>Політиці про куки</5>.",
"app_selection_modal": {
@@ -33,20 +40,68 @@
},
"call_name": "Назва виклику",
"common": {
"analytics": "Аналітика",
"audio": "Звук",
"avatar": "Аватар",
"back": "Назад",
"display_name": "Псевдонім",
"encrypted": "Зашифровано",
"home": "Домівка",
"loading": "Завантаження…",
"next": "Далі",
"options": "Налаштування",
"password": "Пароль",
"preferences": "Уподобання",
"profile": "Профіль",
"reaction": "Реакція",
"reactions": "Реакції",
"settings": "Налаштування",
"unencrypted": "Не зашифровано",
"username": "Ім'я користувача",
"video": "Відео"
},
"developer_mode": {
"crypto_version": "Крипто-версія: {{version}}",
"debug_tile_layout_label": "Налагоджування макету плиток",
"device_id": "ID пристрою: {{id}}",
"duplicate_tiles_label": "Кількість додаткових копій плиток на одного учасника",
"environment_variables": "Змінні середовища",
"hostname": "Ім'я хоста: {{hostname}}",
"livekit_server_info": "Інформація про сервер LiveKit",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix ID: {{id}}",
"show_connection_stats": "Показувати статистику підключення",
"show_non_member_tiles": "Показувати плитки для медіа, які не є учасниками",
"url_params": "Параметри URL",
"use_new_membership_manager": "Використовуйте нову реалізацію виклику MembershipManager"
},
"disconnected_banner": "Втрачено зв'язок з сервером.",
"error": {
"call_is_not_supported": "Виклик не підтримується",
"call_not_found": "Виклик не знайдено",
"call_not_found_description": "<0>Схоже, що це посилання не належить до жодного існуючого дзвінка. Перевірте, чи посилання правильне, або <1> створіть нове</1>. </0>",
"connection_lost": "Зв'язок втрачено",
"connection_lost_description": "Вас було відключено від дзвінка.",
"e2ee_unsupported": "Несумісний браузер",
"e2ee_unsupported_description": "Ваш веб-браузер не підтримує зашифровані дзвінки. Підтримувані браузери включають Chrome, Safari та Firefox 117+.",
"generic": "Щось пішло не так",
"generic_description": "Надсилання журналів налагодження допоможе нам відстежити проблему.",
"insufficient_capacity": "Недостатньо обсягу",
"insufficient_capacity_description": "Сервер досяг максимального обсягу, і ви на разі не можете приєднатися до виклику. Спробуйте пізніше або зверніться до адміністратора сервера, якщо проблема не зникне.",
"matrix_rtc_focus_missing": "Сервер не налаштований щоб працювати з {{brand}}. Будь ласка, зв'яжіться з адміністратором сервера (Домен: {{domain}}, Код помилки: {{ errorCode }}).",
"open_elsewhere": "Відкрито в іншій вкладці",
"open_elsewhere_description": "{{brand}} було відкрито в іншій вкладці. Якщо це звучить неправильно, спробуйте перезавантажити сторінку.",
"unexpected_ec_error": "Сталася несподівана помилка (<0>Код помилки: </0> <1> {{ errorCode }}</1>). Будь ласка, зв'яжіться з адміністратором сервера."
},
"group_call_loader": {
"banned_body": "Вас було забанено в цій кімнаті.",
"banned_heading": "Забанено",
"call_ended_body": "Вас вилучено з виклику.",
"call_ended_heading": "Виклик завершено",
"knock_reject_body": "Ваш запит на приєднання було відхилено.",
"knock_reject_heading": "Доступ заборонено",
"reason": "Причина: {{reason}}"
},
"hangup_button_label": "Завершити виклик",
"header_label": "Домівка Element Call",
"header_participants_label": "Учасники",
@@ -62,15 +117,25 @@
"layout_grid_label": "Сітка",
"layout_spotlight_label": "У центрі уваги",
"lobby": {
"ask_to_join": "Запит на приєднання до виклику",
"join_as_guest": "Приєднатись як гість",
"join_button": "Приєднатися до виклику",
"leave_button": "Повернутися до недавніх"
"leave_button": "Повернутися до недавніх",
"waiting_for_invite": "Запит надіслано! Чекаємо дозволу на приєднання..."
},
"log_in": "Увійти",
"logging_in": "Вхід…",
"login_auth_links": "<0>Створити обліковий запис</0> або <2>Отримати доступ як гість</2>",
"login_auth_links_prompt": "Ще не зареєстровані?",
"login_subheading": "Продовжити в Element",
"login_title": "Увійти",
"microphone_off": "Мікрофон вимкнено",
"microphone_on": "Мікрофон увімкнено",
"mute_microphone_button_label": "Вимкнути мікрофон",
"participant_count_one": "{{count, number}}",
"participant_count_few": "{{count, number}}",
"participant_count_many": "{{count, number}}",
"qr_code": "QR-код",
"rageshake_button_error_caption": "Повторити надсилання журналів",
"rageshake_request_modal": {
"body": "Інший користувач у цьому виклику має проблему. Щоб краще визначити ці проблеми, ми хотіли б зібрати журнал налагодження.",
@@ -80,27 +145,54 @@
"rageshake_sending": "Надсилання…",
"rageshake_sending_logs": "Надсилання журналу налагодження…",
"rageshake_sent": "Дякуємо!",
"recaptcha_caption": "Цей сайт захищений ReCAPTCHA і до нього застосовується <2>Політика приватності</2> і <6>Умови надання послуг</6> Google.<9></9>Натискаючи \"Зареєструватися\", ви погоджуєтеся з нашою <12>Ліцензійною угодою з кінцевим користувачем (EULA)</12>",
"recaptcha_dismissed": "Recaptcha не пройдено",
"recaptcha_not_loaded": "Recaptcha не завантажено",
"recaptcha_ssla_caption": "Цей сайт захищений ReCAPTCHA та Google<2>Політикою конфіденційності</2> і <6>Умови обслуговування</6> застосовуються.<9></9> Натискаючи «Зареєструватися», ви погоджуєтеся з нашою<12> Ліцензійна угодою про програмне забезпечення та послуги (SSLA)</12>",
"register": {
"passwords_must_match": "Паролі відрізняються",
"registering": "Реєстрація…"
},
"register_auth_links": "<0>Уже маєте обліковий запис?</0><1><0>Увійти</0> Or <2>Отримати доступ як гість</2></1>",
"register_confirm_password_label": "Підтвердити пароль",
"register_heading": "Створити свій акаунт",
"return_home_button": "Повернутися на екран домівки",
"room_auth_view_eula_caption": "Натискаючи \"Приєднатися до виклику зараз\", ви погоджуєтеся з нашою <2>Ліцензійною угодою з кінцевим користувачем (EULA)</2>",
"room_auth_view_continue_button": "Продовжити",
"room_auth_view_ssla_caption": "Натиснувши «Приєднатися до виклику зараз», ви погоджуєтеся з нашою <2>Ліцензійною угодою на програмне забезпечення та послуги (SSLA) </2>",
"screenshare_button_label": "Поділитися екраном",
"settings": {
"audio_tab": {
"effect_volume_description": "Змінити гучність реакцій і ефекту підіймання руки.",
"effect_volume_label": "Гучність звукових ефектів"
},
"developer_tab_title": "Розробнику",
"devices": {
"camera": "Камера",
"camera_numbered": "Камера {{n}}",
"default": "За замовчуванням",
"default_named": "За замовчуванням <2> ({{name}}) </2>",
"microphone": "Мікрофон",
"microphone_numbered": "Мікрофон {{n}}",
"speaker": "Динамік",
"speaker_numbered": "Динамік {{n}}"
},
"feedback_tab_body": "Якщо у вас виникли проблеми або ви просто хочете залишити відгук, надішліть нам короткий опис нижче.",
"feedback_tab_description_label": "Ваш відгук",
"feedback_tab_h4": "Надіслати відгук",
"feedback_tab_send_logs_label": "Долучити журнали налагодження",
"feedback_tab_thank_you": "Дякуємо, ми отримали ваш відгук!",
"feedback_tab_title": "Відгук",
"opt_in_description": "<0></0><1></1>Ви можете відкликати згоду, прибравши цей прапорець. Якщо ви зараз розмовляєте, це налаштування застосується після завершення виклику."
"opt_in_description": "<0></0><1></1>Ви можете відкликати згоду, прибравши цей прапорець. Якщо ви зараз розмовляєте, це налаштування застосується після завершення виклику.",
"preferences_tab": {
"developer_mode_label": "Режим розробника",
"developer_mode_label_description": "Увімкнути режим розробника та показати вкладку налаштувань розробника.",
"introduction": "Тут ви можете налаштувати додаткові параметри для кращого досвіду.",
"reactions_play_sound_description": "Відтворювати звуковий ефект, коли хтось надсилає реакцію у виклик.",
"reactions_play_sound_label": "Відтворювати звуки реакції",
"reactions_show_description": "Показувати анімацію, коли хтось надсилає реакцію.",
"reactions_show_label": "Показувати реакції",
"show_hand_raised_timer_description": "Показувати таймер, коли учасник піднімає руку",
"show_hand_raised_timer_label": "Показувати тривалість підняття руки"
}
},
"star_rating_input_label_one": "{{count}} зірок",
"star_rating_input_label_other": "{{count}} зірок",
@@ -109,9 +201,21 @@
"stop_screenshare_button_label": "Презентація екрана",
"stop_video_button_label": "Зупинити відео",
"submitting": "Надсилання…",
"switch_camera": "Переключити камеру",
"unauthenticated_view_body": "Ще не зареєстровані? <2>Створіть обліковий запис</2>",
"unauthenticated_view_eula_caption": "Натискаючи \"Далі\", ви погоджуєтеся з нашою <2>Ліцензійною угодою з кінцевим користувачем (EULA)</2>",
"unauthenticated_view_login_button": "Увійдіть до свого облікового запису",
"unauthenticated_view_ssla_caption": "Натискаючи \"Перейти\", ви погоджуєтеся з нашою <2>Ліцензійною угодою на програмне забезпечення та послуги (SSLA) </2>",
"unmute_microphone_button_label": "Увімкнути мікрофон",
"version": "Версія: {{version}}"
"version": "Версія: {{version}}",
"video_tile": {
"always_show": "Показувати завжди",
"camera_starting": "Завантаження відео...",
"change_fit_contain": "Допасувати до рамки",
"collapse": "Згорнути",
"expand": "Розгорнути",
"mute_for_me": "Вимкнути звук для мене",
"muted_for_me": "Вимкнено звук для мене",
"volume": "Гучність",
"waiting_for_media": "Очікування медіа..."
}
}

View File

@@ -73,7 +73,6 @@
"rageshake_sending": "正在发送……",
"rageshake_sending_logs": "正在发送调试日志……",
"rageshake_sent": "谢谢!",
"recaptcha_caption": "该站点受 ReCAPTCHA 保护适用于Google的 <2>隐私政策</2>和 <6>服务条款</6>。 <9></9>点击 \"注册\",即表示您同意我们的 <12>最终用户许可协议 (EULA)</12>",
"recaptcha_dismissed": "人机验证失败",
"recaptcha_not_loaded": "recaptcha未加载",
"register": {
@@ -83,7 +82,6 @@
"register_auth_links": "<0>已有账户?</0><1><0>登录</0> Or <2>以访客身份继续</2></1>",
"register_confirm_password_label": "确认密码",
"return_home_button": "返回主页",
"room_auth_view_eula_caption": "点击 \"加入通话\",即表示您同意我们的<2>最终用户许可协议 (EULA)</2>",
"screenshare_button_label": "屏幕共享",
"settings": {
"developer_tab_title": "开发者",
@@ -103,7 +101,6 @@
"stop_video_button_label": "停止视频",
"submitting": "提交中…",
"unauthenticated_view_body": "还没有注册? <2>创建账户<2>",
"unauthenticated_view_eula_caption": "点击 \"开始\",即表示您同意我们的<2>最终用户许可协议 (EULA)</2>",
"unauthenticated_view_login_button": "登录你的账户",
"unmute_microphone_button_label": "取消麦克风静音",
"version": "版本:{{version}}"

View File

@@ -80,7 +80,6 @@
"rageshake_sending": "傳送中…",
"rageshake_sending_logs": "傳送除錯記錄檔中…",
"rageshake_sent": "感謝!",
"recaptcha_caption": "此網站被 ReCAPTCHA 保護,並適用 Google 的<2>隱私權政策</2>與<6>服務條款</6>。<9></9>點擊「註冊」即表示您同意我們的<12>終端使用者授權協議 (EULA)</12>",
"recaptcha_dismissed": "略過驗證碼",
"recaptcha_not_loaded": "驗證碼未載入",
"register": {
@@ -90,7 +89,6 @@
"register_auth_links": "<0>已經有帳號?</0><1><0>登入</0> 或<2>以訪客身份登入</2></1>",
"register_confirm_password_label": "確認密碼",
"return_home_button": "回到首頁",
"room_auth_view_eula_caption": "點擊「立刻加入通話」即表示您同意我們的<2>終端使用者授權協議 (EULA)</2>",
"screenshare_button_label": "分享畫面",
"settings": {
"developer_tab_title": "開發者",
@@ -110,7 +108,6 @@
"stop_video_button_label": "停止影片",
"submitting": "正在遞交……",
"unauthenticated_view_body": "還沒註冊嗎?<2>建立帳號</2>",
"unauthenticated_view_eula_caption": "點擊「前往」即表示您同意我們的<2>終端使用者授權協議 (EULA)</2>",
"unauthenticated_view_login_button": "登入您的帳號",
"unmute_microphone_button_label": "將麥克風取消靜音",
"version": "版本: {{version}}"

View File

@@ -23,7 +23,9 @@
"test:coverage": "vitest --coverage",
"backend": "docker-compose -f dev-backend-docker-compose.yml up",
"test:playwright": "playwright test",
"test:playwright:open": "yarn test:playwright --ui"
"test:playwright:open": "yarn test:playwright --ui",
"links:enable": "mv .links.disabled.yaml .links.yaml & touch .links.yaml",
"links:disable": "mv .links.yaml .links.disabled.yaml"
},
"devDependencies": {
"@babel/core": "^7.16.5",
@@ -95,10 +97,10 @@
"i18next-parser": "^9.1.0",
"jsdom": "^26.0.0",
"knip": "^5.27.2",
"livekit-client": "2.9.1",
"livekit-client": "^2.11.3",
"lodash-es": "^4.17.21",
"loglevel": "^1.9.1",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#8395919f0fd1af7cab1e793d736f2cdf18ef7686",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#19b1b901f575755d29d1fe03ca48cbf7c1cae05c",
"matrix-widget-api": "1.11.0",
"normalize.css": "^8.0.1",
"observable-hooks": "^4.2.3",
@@ -130,5 +132,6 @@
"resolutions": {
"@livekit/components-core/rxjs": "^7.8.1",
"matrix-widget-api": "1.11.0"
}
},
"packageManager": "yarn@4.7.0"
}

View File

@@ -51,6 +51,17 @@ services:
networks:
- ecbackend
element-web:
image: ghcr.io/element-hq/element-web:develop
volumes:
- ./backend/ew.test.config.json:/app/config.json
environment:
ELEMENT_WEB_PORT: 81
ports:
- "8081:81"
networks:
- ecbackend
synapse:
hostname: homeserver
image: docker.io/matrixdotorg/synapse:latest

View File

@@ -0,0 +1,185 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type Page, test, expect, type JSHandle } from "@playwright/test";
import type { MatrixClient } from "matrix-js-sdk";
export type UserBaseFixture = {
mxId: string;
page: Page;
clientHandle: JSHandle<MatrixClient>;
};
export type BaseWidgetSetup = {
brooks: UserBaseFixture;
whistler: UserBaseFixture;
};
export interface MyFixtures {
asWidget: BaseWidgetSetup;
}
const PASSWORD = "foobarbaz1!";
// Minimal config.json for the local element-web instance
const CONFIG_JSON = {
default_server_config: {
"m.homeserver": {
base_url: "http://synapse.localhost:8008",
server_name: "synapse.localhost",
},
},
element_call: {
participant_limit: 8,
brand: "Element Call",
},
// The default language is set here for test consistency
setting_defaults: {
language: "en-GB",
feature_group_calls: true,
},
// the location tests want a map style url.
map_style_url:
"https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx",
features: {
// We don't want to go through the feature announcement during the e2e test
feature_release_announcement: false,
feature_element_call_video_rooms: true,
feature_video_rooms: true,
feature_group_calls: true,
},
};
/**
* Set the Element Call URL in the dev tool settings using `window.mxSettingsStore` via `page.evaluate`.
* @param page
*/
async function setDevToolElementCallDevUrl(page: Page): Promise<void> {
await page.evaluate(() => {
window.mxSettingsStore.setValue(
"Developer.elementCallUrl",
null,
"device",
"https://localhost:3000/room",
);
});
}
export const widgetTest = test.extend<MyFixtures>({
asWidget: async ({ browser, context }, pUse) => {
await context.route(`http://localhost:8081/config.json*`, async (route) => {
await route.fulfill({ json: CONFIG_JSON });
});
const userA = `brooks_${Date.now()}`;
const userB = `whistler_${Date.now()}`;
const user1Context = await browser.newContext({
reducedMotion: "reduce",
});
const ewPage1 = await user1Context.newPage();
// Register the first user
await ewPage1.goto("http://localhost:8081/#/welcome");
await ewPage1.getByRole("link", { name: "Create Account" }).click();
await ewPage1.getByRole("textbox", { name: "Username" }).fill(userA);
await ewPage1
.getByRole("textbox", { name: "Password", exact: true })
.fill(PASSWORD);
await ewPage1.getByRole("textbox", { name: "Confirm password" }).click();
await ewPage1
.getByRole("textbox", { name: "Confirm password" })
.fill(PASSWORD);
await ewPage1.getByRole("button", { name: "Register" }).click();
await expect(
ewPage1.getByRole("heading", { name: `Welcome ${userA}` }),
).toBeVisible();
await setDevToolElementCallDevUrl(ewPage1);
const brooksClientHandle = await ewPage1.evaluateHandle(() =>
window.mxMatrixClientPeg.get(),
);
const brooksMxId = (await brooksClientHandle.evaluate((cli) => {
return cli.getUserId();
}, brooksClientHandle))!;
const user2Context = await browser.newContext({
reducedMotion: "reduce",
});
const ewPage2 = await user2Context.newPage();
// Register the second user
await ewPage2.goto("http://localhost:8081/#/welcome");
await ewPage2.getByRole("link", { name: "Create Account" }).click();
await ewPage2.getByRole("textbox", { name: "Username" }).fill(userB);
await ewPage2
.getByRole("textbox", { name: "Password", exact: true })
.fill(PASSWORD);
await ewPage2.getByRole("textbox", { name: "Confirm password" }).click();
await ewPage2
.getByRole("textbox", { name: "Confirm password" })
.fill(PASSWORD);
await ewPage2.getByRole("button", { name: "Register" }).click();
await expect(
ewPage2.getByRole("heading", { name: `Welcome ${userB}` }),
).toBeVisible();
await setDevToolElementCallDevUrl(ewPage2);
const whistlerClientHandle = await ewPage2.evaluateHandle(() =>
window.mxMatrixClientPeg.get(),
);
const whistlerMxId = (await whistlerClientHandle.evaluate((cli) => {
return cli.getUserId();
}, whistlerClientHandle))!;
// Invite the second user
await ewPage1.getByRole("button", { name: "Add room" }).click();
await ewPage1.getByText("New room").click();
await ewPage1.getByRole("textbox", { name: "Name" }).fill("Welcome Room");
await ewPage1.getByRole("button", { name: "Create room" }).click();
await expect(ewPage1.getByText("You created this room.")).toBeVisible();
await expect(ewPage1.getByText("Encryption enabled")).toBeVisible();
await ewPage1
.getByRole("button", { name: "Invite to this room", exact: true })
.click();
await expect(
ewPage1.getByRole("heading", { name: "Invite to Welcome Room" }),
).toBeVisible();
await ewPage1.getByRole("textbox").fill(whistlerMxId);
await ewPage1.getByRole("textbox").click();
await ewPage1.getByRole("button", { name: "Invite" }).click();
// Accept the invite
await expect(
ewPage2.getByRole("treeitem", { name: "Welcome Room" }),
).toBeVisible();
await ewPage2.getByRole("treeitem", { name: "Welcome Room" }).click();
await ewPage2.getByRole("button", { name: "Accept" }).click();
await expect(
ewPage2.getByRole("main").getByRole("heading", { name: "Welcome Room" }),
).toBeVisible();
// Renamed use to pUse, as a workaround for eslint error that was thinking this use was a react use.
await pUse({
brooks: {
mxId: brooksMxId,
page: ewPage1,
clientHandle: brooksClientHandle,
},
whistler: {
mxId: whistlerMxId,
page: ewPage2,
clientHandle: whistlerClientHandle,
},
});
},
});

24
playwright/global.d.ts vendored Normal file
View File

@@ -0,0 +1,24 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import type * as Matrix from "matrix-js-sdk";
declare global {
interface Window {
mxMatrixClientPeg: {
get(): Matrix.MatrixClient;
};
mxSettingsStore: {
setValue: (
settingKey: string,
room: string | null,
level: string,
setting: string,
) => void;
};
}
}

View File

@@ -0,0 +1,97 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { expect, test } from "@playwright/test";
import { widgetTest } from "../fixtures/widget-user.ts";
widgetTest("Start a new call as widget", async ({ asWidget, browserName }) => {
test.skip(
browserName === "firefox",
"This test is not working on firefox, after hangup brooks is locked in a strange state with a blank widget",
);
const { brooks, whistler } = asWidget;
await expect(
brooks.page.getByRole("button", { name: "Video call" }),
).toBeVisible();
await brooks.page.getByRole("button", { name: "Video call" }).click();
await expect(
brooks.page.getByRole("menuitem", { name: "Legacy Call" }),
).toBeVisible();
await expect(
brooks.page.getByRole("menuitem", { name: "Element Call" }),
).toBeVisible();
await brooks.page.getByRole("menuitem", { name: "Element Call" }).click();
await expect(
brooks.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("lobby_joinCall"),
).toBeVisible();
await brooks.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("lobby_joinCall")
.click();
// Check the join indicator on the room list
await expect(
brooks.page.locator("div").filter({ hasText: /^Joined • 1$/ }),
).toBeVisible();
// Join from the other side
await expect(whistler.page.getByText("Video call started")).toBeVisible();
await expect(
whistler.page.getByRole("button", { name: "Join" }),
).toBeVisible();
await whistler.page.getByRole("button", { name: "Join" }).click();
await expect(
whistler.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("lobby_joinCall"),
).toBeVisible();
await whistler.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("lobby_joinCall")
.click();
await expect(
whistler.page.locator("div").filter({ hasText: /^Joined • 2$/ }),
).toBeVisible();
await expect(
brooks.page.locator("div").filter({ hasText: /^Joined • 2$/ }),
).toBeVisible();
// Whistler leaves
await whistler.page.waitForTimeout(1000);
await whistler.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("incall_leave")
.click();
// Brooks leaves
await brooks.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("incall_leave")
.click();
await expect(whistler.page.locator(".mx_BasicMessageComposer")).toBeVisible();
await expect(brooks.page.locator(".mx_BasicMessageComposer")).toBeVisible();
});

View File

@@ -48,6 +48,20 @@
"groupName": "Vaul",
"matchDepNames": ["vaul"],
"prHeader": "Please review modals on mobile for visual regressions."
},
{
"groupName": "bundled element-call dependencies",
"matchPackageNames": [
"com.vanniktech.maven.publish",
"com.android.library",
"com.android.tools.build",
"gradle"
]
},
{
"groupName": "Yarn",
"matchPackageNames": ["yarn"],
"extends": ["schedule:weekly"]
}
],
"semanticCommits": "disabled",

View File

@@ -4,5 +4,6 @@ set -ex
export VITE_APP_VERSION=$(git describe --tags --abbrev=0)
corepack enable
yarn install
yarn run build

View File

@@ -5,7 +5,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import "matrix-js-sdk/src/@types/global";
import { type setLogLevel as setLKLogLevel } from "livekit-client";
import type { DurationFormat as PolyfillDurationFormat } from "@formatjs/intl-durationformat";

View File

@@ -11,7 +11,7 @@ import {
} from "../reactions";
// Extend Matrix JS SDK types via Typescript declaration merging to support unspecced event fields and types
declare module "matrix-js-sdk/src/types" {
declare module "matrix-js-sdk/lib/types" {
export interface TimelineEvents {
[ElementCallReactionEventType]: ECallReactionEventContent;
}

View File

@@ -9,7 +9,7 @@ import { type FC, type JSX, Suspense, useEffect, useState } from "react";
import { BrowserRouter, Route, useLocation, Routes } from "react-router-dom";
import * as Sentry from "@sentry/react";
import { TooltipProvider } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { HomePage } from "./home/HomePage";
import { LoginPage } from "./auth/LoginPage";

View File

@@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.
import { afterEach, expect, test, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type MatrixClient } from "matrix-js-sdk";
import { type FC, type PropsWithChildren } from "react";
import { ClientContextProvider } from "./ClientContext";

View File

@@ -13,7 +13,7 @@ import {
useEffect,
} from "react";
import { Avatar as CompoundAvatar } from "@vector-im/compound-web";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type MatrixClient } from "matrix-js-sdk";
import { useClientState } from "./ClientContext";

View File

@@ -17,9 +17,9 @@ import {
type JSX,
} from "react";
import { useNavigate } from "react-router-dom";
import { logger } from "matrix-js-sdk/src/logger";
import { type ISyncStateData, type SyncState } from "matrix-js-sdk/src/sync";
import { ClientEvent, type MatrixClient } from "matrix-js-sdk/src/client";
import { logger } from "matrix-js-sdk/lib/logger";
import { type ISyncStateData, type SyncState } from "matrix-js-sdk/lib/sync";
import { ClientEvent, type MatrixClient } from "matrix-js-sdk";
import type { WidgetApi } from "matrix-widget-api";
import { ErrorPage } from "./FullScreenView";
@@ -50,7 +50,7 @@ export type ValidClientState = {
reactions: boolean;
thumbnails: boolean;
};
setClient: (params?: SetClientParams) => void;
setClient: (client: MatrixClient, session: Session) => void;
};
export type AuthenticatedClient = {
@@ -65,11 +65,6 @@ export type ErrorState = {
error: Error;
};
export type SetClientParams = {
client: MatrixClient;
session: Session;
};
const ClientContext = createContext<ClientState | undefined>(undefined);
export const ClientContextProvider = ClientContext.Provider;
@@ -79,7 +74,7 @@ export const useClientState = (): ClientState | undefined =>
export function useClient(): {
client?: MatrixClient;
setClient?: (params?: SetClientParams) => void;
setClient?: (client: MatrixClient, session: Session) => void;
} {
let client;
let setClient;
@@ -96,7 +91,7 @@ export function useClient(): {
// Plain representation of the `ClientContext` as a helper for old components that expected an object with multiple fields.
export function useClientLegacy(): {
client?: MatrixClient;
setClient?: (params?: SetClientParams) => void;
setClient?: (client: MatrixClient, session: Session) => void;
passwordlessUser: boolean;
loading: boolean;
authenticated: boolean;
@@ -160,7 +155,11 @@ export const ClientProvider: FC<Props> = ({ children }) => {
initializing.current = true;
loadClient()
.then(setInitClientState)
.then((initResult) => {
setInitClientState(initResult);
if (PosthogAnalytics.instance.isEnabled())
PosthogAnalytics.instance.startListeningToSettingsChanges();
})
.catch((err) => logger.error(err))
.finally(() => (initializing.current = false));
}, []);
@@ -196,24 +195,20 @@ export const ClientProvider: FC<Props> = ({ children }) => {
);
const setClient = useCallback(
(clientParams?: SetClientParams) => {
(client: MatrixClient, session: Session) => {
const oldClient = initClientState?.client;
const newClient = clientParams?.client;
if (oldClient && oldClient !== newClient) {
if (oldClient && oldClient !== client) {
oldClient.stopClient();
}
if (clientParams) {
saveSession(clientParams.session);
setInitClientState({
widgetApi: null,
client: clientParams.client,
passwordlessUser: clientParams.session.passwordlessUser,
});
} else {
clearSession();
setInitClientState(null);
}
saveSession(session);
setInitClientState({
widgetApi: null,
client,
passwordlessUser: session.passwordlessUser,
});
if (PosthogAnalytics.instance.isEnabled())
PosthogAnalytics.instance.startListeningToSettingsChanges();
},
[initClientState?.client],
);
@@ -229,6 +224,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
clearSession();
setInitClientState(null);
await navigate("/");
PosthogAnalytics.instance.logout();
PosthogAnalytics.instance.setRegistrationType(RegistrationType.Guest);
}, [navigate, initClientState?.client]);

View File

@@ -15,7 +15,7 @@ import {
type ReactElement,
} from "react";
import { useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { RageshakeButton } from "./settings/RageshakeButton";
import styles from "./ErrorView.module.css";

View File

@@ -9,7 +9,7 @@ import { type FC, type ReactElement, type ReactNode, useEffect } from "react";
import classNames from "classnames";
import { useTranslation } from "react-i18next";
import * as Sentry from "@sentry/react";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { ErrorIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { Header, HeaderLogo, LeftNav, RightNav } from "./Header";

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { IndexedDBStoreWorker } from "matrix-js-sdk/src/indexeddb-worker";
import { IndexedDBStoreWorker } from "matrix-js-sdk/lib/indexeddb-worker";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const remoteWorker = new IndexedDBStoreWorker((self as any).postMessage);

View File

@@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.
import { useMemo } from "react";
import { useLocation } from "react-router-dom";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { Config } from "./config/Config";
import { type EncryptionSystem } from "./e2ee/sharedKeyManagement";

View File

@@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.
import { type FC, useCallback, useState } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { useClientLegacy } from "./ClientContext";
import { useProfile } from "./profile/useProfile";

View File

@@ -10,9 +10,9 @@ import posthog, {
type PostHog,
type Properties,
} from "posthog-js";
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import { Buffer } from "buffer";
import { logger } from "matrix-js-sdk/lib/logger";
import { type MatrixClient } from "matrix-js-sdk";
import { type Subscription } from "rxjs";
import { widget } from "../widget";
import {
@@ -96,6 +96,7 @@ export class PosthogAnalytics {
private anonymity = Anonymity.Disabled;
private platformSuperProperties = {};
private registrationType: RegistrationType = RegistrationType.Guest;
private optInListener: Subscription | null = null;
public static hasInstance(): boolean {
return Boolean(this.internalInstance);
@@ -144,7 +145,6 @@ export class PosthogAnalytics {
);
this.enabled = false;
}
this.startListeningToSettingsChanges(); // Triggers maybeIdentifyUser
}
private sanitizeProperties = (
@@ -295,7 +295,7 @@ export class PosthogAnalytics {
const posthogIdMaterial = "ec" + accountAnalyticsId + client.getUserId();
const bufferForPosthogId = await crypto.subtle.digest(
"sha-256",
Buffer.from(posthogIdMaterial, "utf-8"),
new TextEncoder().encode(posthogIdMaterial),
);
const view = new Int32Array(bufferForPosthogId);
return Array.from(view)
@@ -326,6 +326,8 @@ export class PosthogAnalytics {
if (this.enabled) {
this.posthog.reset();
}
this.optInListener?.unsubscribe();
this.optInListener = null;
this.setAnonymity(Anonymity.Disabled);
}
@@ -404,7 +406,7 @@ export class PosthogAnalytics {
}
}
private startListeningToSettingsChanges(): void {
public startListeningToSettingsChanges(): void {
// Listen to account data changes from sync so we can observe changes to relevant flags and update.
// This is called -
// * On page load, when the account data is first received by sync
@@ -413,7 +415,7 @@ export class PosthogAnalytics {
// * When the user changes their preferences on this device
// Note that for new accounts, pseudonymousAnalyticsOptIn won't be set, so updateAnonymityFromSettings
// won't be called (i.e. this.anonymity will be left as the default, until the setting changes)
optInAnalytics.value$.subscribe((optIn) => {
this.optInListener ??= optInAnalytics.value$.subscribe((optIn) => {
this.setAnonymity(optIn ? Anonymity.Pseudonymous : Anonymity.Disabled);
this.maybeIdentifyUser().catch(() =>
logger.log("Could not identify user"),

View File

@@ -6,8 +6,8 @@ Please see LICENSE in the repository root for full details.
*/
import { type DisconnectReason } from "livekit-client";
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc";
import { logger } from "matrix-js-sdk/lib/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import {
type IPosthogEvent,

View File

@@ -11,7 +11,7 @@ import {
type Span,
} from "@opentelemetry/sdk-trace-base";
import { hrTimeToMilliseconds } from "@opentelemetry/core";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { PosthogAnalytics } from "./PosthogAnalytics";

View File

@@ -53,7 +53,7 @@ export const LoginPage: FC = () => {
return;
}
setClient({ client, session });
setClient(client, session);
const locationState = location.state;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment

View File

@@ -16,9 +16,9 @@ import {
} from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { captureException } from "@sentry/react";
import { sleep } from "matrix-js-sdk/src/utils";
import { sleep } from "matrix-js-sdk/lib/utils";
import { Trans, useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { Button, Text } from "@vector-im/compound-web";
import { FieldRow, InputField, ErrorMessage } from "../input/Input";
@@ -95,7 +95,7 @@ export const RegisterPage: FC = () => {
}
}
setClient?.({ client: newClient, session });
setClient?.(newClient, session);
PosthogAnalytics.instance.eventSignup.cacheSignupEnd(new Date());
};
@@ -204,7 +204,7 @@ export const RegisterPage: FC = () => {
/>
</FieldRow>
<Text size="sm">
<Trans i18nKey="recaptcha_caption">
<Trans i18nKey="recaptcha_ssla_caption">
This site is protected by ReCAPTCHA and the Google{" "}
<ExternalLink href="https://www.google.com/policies/privacy/">
Privacy Policy
@@ -216,8 +216,8 @@ export const RegisterPage: FC = () => {
apply.
<br />
By clicking "Register", you agree to our{" "}
<ExternalLink href={Config.get().eula}>
End User Licensing Agreement (EULA)
<ExternalLink href={Config.get().ssla}>
Software and Services License Agreement (SSLA)
</ExternalLink>
</Trans>
</Text>

View File

@@ -6,12 +6,12 @@ Please see LICENSE in the repository root for full details.
*/
import { useCallback } from "react";
import { InteractiveAuth } from "matrix-js-sdk/src/interactive-auth";
import { InteractiveAuth } from "matrix-js-sdk";
import {
createClient,
type LoginResponse,
type MatrixClient,
} from "matrix-js-sdk/src/matrix";
} from "matrix-js-sdk";
import { initClient } from "../utils/matrix";
import { type Session } from "../ClientContext";

View File

@@ -6,13 +6,13 @@ Please see LICENSE in the repository root for full details.
*/
import { useState, useEffect, useCallback, useRef } from "react";
import { InteractiveAuth } from "matrix-js-sdk/src/interactive-auth";
import { InteractiveAuth } from "matrix-js-sdk";
import {
createClient,
type MatrixClient,
type RegisterResponse,
} from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
} from "matrix-js-sdk";
import { logger } from "matrix-js-sdk/lib/logger";
import { initClient } from "../utils/matrix";
import { type Session } from "../ClientContext";

View File

@@ -6,9 +6,9 @@ Please see LICENSE in the repository root for full details.
*/
import { useEffect, useCallback, useRef, useState } from "react";
import { secureRandomString } from "matrix-js-sdk/src/randomstring";
import { secureRandomString } from "matrix-js-sdk/lib/randomstring";
import { useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { translatedError } from "../TranslatedError";
declare global {

View File

@@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details.
*/
import { useCallback } from "react";
import { secureRandomString } from "matrix-js-sdk/src/randomstring";
import { secureRandomString } from "matrix-js-sdk/lib/randomstring";
import { useClient } from "../ClientContext";
import { useInteractiveRegistration } from "../auth/useInteractiveRegistration";
@@ -47,7 +47,7 @@ export function useRegisterPasswordlessUser(): UseRegisterPasswordlessUserType {
recaptchaResponse,
true,
);
setClient({ client, session });
setClient(client, session);
} catch (e) {
reset();
throw e;

View File

@@ -10,7 +10,7 @@ import { expect, test } from "vitest";
import { TooltipProvider } from "@vector-im/compound-web";
import { userEvent } from "@testing-library/user-event";
import { type ReactNode } from "react";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import { ReactionToggleButton } from "./ReactionToggleButton";
import { ElementCallReactionEventType } from "../reactions";

View File

@@ -22,7 +22,7 @@ import {
useState,
} from "react";
import { useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import classNames from "classnames";
import { useObservableState } from "observable-hooks";
import { map } from "rxjs";

View File

@@ -77,9 +77,9 @@ export interface ConfigOptions {
};
/**
* A link to the end-user license agreement (EULA)
* A link to the software and services license agreement (SSLA)
*/
eula?: string;
ssla?: string;
media_devices?: {
/**
@@ -134,7 +134,7 @@ export interface ResolvedConfigOptions extends ConfigOptions {
server_name: string;
};
};
eula: string;
ssla: string;
media_devices: {
enable_audio: boolean;
enable_video: boolean;
@@ -152,7 +152,7 @@ export const DEFAULT_CONFIG: ResolvedConfigOptions = {
features: {
feature_use_device_session_member_events: true,
},
eula: "https://static.element.io/legal/online-EULA.pdf",
ssla: "https://static.element.io/legal/element-software-and-services-license-agreement-uk-1.pdf",
media_devices: {
enable_audio: true,
enable_video: true,

View File

@@ -9,7 +9,7 @@ import { describe, expect, test, vi } from "vitest";
import {
type MatrixRTCSession,
MatrixRTCSessionEvent,
} from "matrix-js-sdk/src/matrixrtc";
} from "matrix-js-sdk/lib/matrixrtc";
import { KeyProviderEvent } from "livekit-client";
import { MatrixKeyProvider } from "./matrixKeyProvider";

View File

@@ -6,17 +6,17 @@ Please see LICENSE in the repository root for full details.
*/
import { BaseKeyProvider, createKeyMaterialFromBuffer } from "livekit-client";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import {
type MatrixRTCSession,
MatrixRTCSessionEvent,
} from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
} from "matrix-js-sdk/lib/matrixrtc";
export class MatrixKeyProvider extends BaseKeyProvider {
private rtcSession?: MatrixRTCSession;
public constructor() {
super({ ratchetWindowSize: 0, keyringSize: 256 });
super({ ratchetWindowSize: 10, keyringSize: 256 });
}
public setRTCSession(rtcSession: MatrixRTCSession): void {

View File

@@ -32,7 +32,7 @@ import {
} from "react";
import useMeasure from "react-use-measure";
import classNames from "classnames";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { useObservableEagerState } from "observable-hooks";
import { fromEvent, map, startWith } from "rxjs";

View File

@@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details.
*/
import { render, type RenderResult } from "@testing-library/react";
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import { type MatrixClient } from "matrix-js-sdk";
import { MemoryRouter } from "react-router-dom";
import { describe, expect, it } from "vitest";

View File

@@ -6,9 +6,7 @@ Please see LICENSE in the repository root for full details.
*/
import { Link } from "react-router-dom";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type RoomMember } from "matrix-js-sdk/src/models/room-member";
import { type Room } from "matrix-js-sdk/src/models/room";
import { type RoomMember, type Room, type MatrixClient } from "matrix-js-sdk";
import { type FC, useCallback, type MouseEvent, useState } from "react";
import { useTranslation } from "react-i18next";
import { IconButton, Text } from "@vector-im/compound-web";

View File

@@ -12,10 +12,10 @@ import {
type FormEventHandler,
type FC,
} from "react";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type MatrixClient } from "matrix-js-sdk";
import { useTranslation } from "react-i18next";
import { Heading, Text } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { Button } from "@vector-im/compound-web";
import { useNavigate } from "react-router-dom";

View File

@@ -6,10 +6,10 @@ Please see LICENSE in the repository root for full details.
*/
import { type FC, useCallback, useState, type FormEventHandler } from "react";
import { secureRandomString } from "matrix-js-sdk/src/randomstring";
import { secureRandomString } from "matrix-js-sdk/lib/randomstring";
import { Trans, useTranslation } from "react-i18next";
import { Button, Heading, Text } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { useNavigate } from "react-router-dom";
import { useClient } from "../ClientContext";
@@ -89,7 +89,7 @@ export const UnauthenticatedView: FC = () => {
// @ts-ignore
if (error.errcode === "M_ROOM_IN_USE") {
setOnFinished(() => {
setClient({ client, session });
setClient(client, session);
const aliasLocalpart = roomAliasLocalpartFromRoomName(roomName);
navigate(`/${aliasLocalpart}`)?.catch((error) => {
logger.error("Failed to navigate to alias localpart", error);
@@ -111,7 +111,7 @@ export const UnauthenticatedView: FC = () => {
if (!createRoomResult.password)
throw new Error("Failed to create room with shared secret");
setClient({ client, session });
setClient(client, session);
await navigate(
getRelativeRoomUrl(
createRoomResult.roomId,
@@ -185,10 +185,10 @@ export const UnauthenticatedView: FC = () => {
</Text>
)}
<Text size="sm" className={styles.notice}>
<Trans i18nKey="unauthenticated_view_eula_caption">
<Trans i18nKey="unauthenticated_view_ssla_caption">
By clicking "Go", you agree to our{" "}
<ExternalLink href={Config.get().eula}>
End User Licensing Agreement (EULA)
<ExternalLink href={Config.get().ssla}>
Software and Services License Agreement (SSLA)
</ExternalLink>
</Trans>
</Text>

View File

@@ -5,14 +5,21 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type Room, RoomEvent } from "matrix-js-sdk/src/models/room";
import { type RoomMember } from "matrix-js-sdk/src/models/room-member";
import {
type MatrixClient,
type RoomMember,
type Room,
RoomEvent,
EventTimeline,
EventType,
JoinRule,
KnownMembership,
} from "matrix-js-sdk";
import { useState, useEffect } from "react";
import { EventTimeline, EventType, JoinRule } from "matrix-js-sdk/src/matrix";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { MatrixRTCSessionManagerEvents } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSessionManager";
import { KnownMembership } from "matrix-js-sdk/src/types";
import {
MatrixRTCSessionManagerEvents,
type MatrixRTCSession,
} from "matrix-js-sdk/lib/matrixrtc";
import { getKeyForRoom } from "../e2ee/sharedKeyManagement";

View File

@@ -14,7 +14,7 @@ import i18n, {
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import * as Sentry from "@sentry/react";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { shouldPolyfill as shouldPolyfillSegmenter } from "@formatjs/intl-segmenter/should-polyfill";
import { shouldPolyfill as shouldPolyfillDurationFormat } from "@formatjs/intl-durationformat/should-polyfill";
import {

View File

@@ -19,7 +19,7 @@ import {
import { createMediaDeviceObserver } from "@livekit/components-core";
import { map, startWith } from "rxjs";
import { useObservableEagerState } from "observable-hooks";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import {
useSetting,

View File

@@ -5,16 +5,16 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type IOpenIDToken, type MatrixClient } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { type IOpenIDToken, type MatrixClient } from "matrix-js-sdk";
import { logger } from "matrix-js-sdk/lib/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import { useEffect, useState } from "react";
import { type LivekitFocus } from "matrix-js-sdk/src/matrixrtc/LivekitFocus";
import { type LivekitFocus } from "matrix-js-sdk/lib/matrixrtc";
import { useActiveLivekitFocus } from "../room/useActiveFocus";
import { useGroupCallErrorBoundary } from "../room/useCallErrorBoundary.ts";
import { FailToGetOpenIdToken } from "../utils/errors.ts";
import { doNetworkOperationWithRetry } from "../utils/matrix.ts";
import { useErrorBoundary } from "../useErrorBoundary";
import { FailToGetOpenIdToken } from "../utils/errors";
import { doNetworkOperationWithRetry } from "../utils/matrix";
export interface SFUConfig {
url: string;
@@ -41,7 +41,7 @@ export function useOpenIDSFU(
const [sfuConfig, setSFUConfig] = useState<SFUConfig | undefined>(undefined);
const activeFocus = useActiveLivekitFocus(rtcSession);
const { showGroupCallErrorBoundary } = useGroupCallErrorBoundary();
const { showErrorBoundary } = useErrorBoundary();
useEffect(() => {
if (activeFocus) {
@@ -50,14 +50,14 @@ export function useOpenIDSFU(
setSFUConfig(sfuConfig);
},
(e) => {
showGroupCallErrorBoundary(new FailToGetOpenIdToken(e));
showErrorBoundary(new FailToGetOpenIdToken(e));
logger.error("Failed to get SFU config", e);
},
);
} else {
setSFUConfig(undefined);
}
}, [client, activeFocus, showGroupCallErrorBoundary]);
}, [client, activeFocus, showErrorBoundary]);
return sfuConfig;
}

View File

@@ -15,7 +15,7 @@ import {
Track,
} from "livekit-client";
import { useCallback, useEffect, useRef, useState } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import * as Sentry from "@sentry/react";
import { type SFUConfig, sfuConfigEquals } from "./openIDSFU";

View File

@@ -15,8 +15,8 @@ import {
} from "livekit-client";
import { useEffect, useMemo, useRef } from "react";
import E2EEWorker from "livekit-client/e2ee-worker?worker";
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { logger } from "matrix-js-sdk/lib/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import { defaultLiveKitOptions } from "./options";
import { type SFUConfig } from "./openIDSFU";
@@ -49,11 +49,14 @@ export function useLiveKit(
if (e2eeSystem.kind === E2eeType.NONE) return undefined;
if (e2eeSystem.kind === E2eeType.PER_PARTICIPANT) {
logger.info("Created MatrixKeyProvider (per participant)");
return {
keyProvider: new MatrixKeyProvider(),
worker: new E2EEWorker(),
};
} else if (e2eeSystem.kind === E2eeType.SHARED_KEY && e2eeSystem.secret) {
logger.info("Created ExternalE2EEKeyProvider (shared key)");
return {
keyProvider: new ExternalE2EEKeyProvider(),
worker: new E2EEWorker(),

View File

@@ -9,12 +9,12 @@ Please see LICENSE in the repository root for full details.
// function gets set. It needs to be not in the same file as we use
// createClient, or the typescript transpiler gets confused about
// dependency references.
import "matrix-js-sdk/src/browser-index";
import "matrix-js-sdk/lib/browser-index";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import {
setLogExtension as setLKLogExtension,
setLogLevel as setLKLogLevel,

Some files were not shown because too many files have changed in this diff Show More