Compare commits
220 Commits
robin/post
...
robin/webc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f727b904b | ||
|
|
380880137e | ||
|
|
8828b705d9 | ||
|
|
b7e5b81dbf | ||
|
|
e12dfa9a9f | ||
|
|
48b4fd63fe | ||
|
|
f2b68e6dee | ||
|
|
128851263b | ||
|
|
679ff8c2af | ||
|
|
9dcaa60982 | ||
|
|
34a223f04b | ||
|
|
005402d8d1 | ||
|
|
76fb16dbfd | ||
|
|
1a3ac826b2 | ||
|
|
25afbf4303 | ||
|
|
9c65b40225 | ||
|
|
fb63e64eb4 | ||
|
|
8679b90bd7 | ||
|
|
14ff6dce93 | ||
|
|
08f034251c | ||
|
|
06e1a4eb1e | ||
|
|
aee30d8402 | ||
|
|
a4a6a16482 | ||
|
|
eeb3a1a991 | ||
|
|
c0c498aa04 | ||
|
|
9f5eae0ac1 | ||
|
|
f92c683bc1 | ||
|
|
dfb9eb4b1f | ||
|
|
fa0af6403e | ||
|
|
9df0f58117 | ||
|
|
0b82dcf701 | ||
|
|
8f1761442b | ||
|
|
7d0117903e | ||
|
|
cd9035b5fc | ||
|
|
02ce1f701a | ||
|
|
e88e0b1901 | ||
|
|
c91cc79162 | ||
|
|
edd8373649 | ||
|
|
31032994a5 | ||
|
|
984383b60d | ||
|
|
de4875ac7c | ||
|
|
9416c41d62 | ||
|
|
b61bed0197 | ||
|
|
8ad1d60975 | ||
|
|
1ae876de26 | ||
|
|
09177b90d3 | ||
|
|
dc5d1369bf | ||
|
|
a6696c2304 | ||
|
|
a1d6eef12a | ||
|
|
78a41c09de | ||
|
|
3fc4cc908e | ||
|
|
63ad4a3ad3 | ||
|
|
7142122a74 | ||
|
|
b7b3fde202 | ||
|
|
8fd99ed23e | ||
|
|
e751248fee | ||
|
|
3243afd061 | ||
|
|
733279f010 | ||
|
|
a5036ee291 | ||
|
|
2cf2e090f6 | ||
|
|
78a88a9e0b | ||
|
|
4694354f69 | ||
|
|
a839cde34f | ||
|
|
8b63813e51 | ||
|
|
e63aff3e9b | ||
|
|
d5407a4fde | ||
|
|
b813a3c95b | ||
|
|
0f69ace92a | ||
|
|
f5615f2e26 | ||
|
|
cb64c311c5 | ||
|
|
ee45e58903 | ||
|
|
4b247540ef | ||
|
|
fc281c516c | ||
|
|
8858e4003a | ||
|
|
58e542e15d | ||
|
|
770b94eb44 | ||
|
|
8c8a5e28a0 | ||
|
|
d0c76139a8 | ||
|
|
9c9d38cd95 | ||
|
|
13f12779dc | ||
|
|
c305fb8604 | ||
|
|
054d6a9e48 | ||
|
|
3c0d81844f | ||
|
|
1702b15abe | ||
|
|
e98b0ed1ed | ||
|
|
ba22be175d | ||
|
|
e166f36ab5 | ||
|
|
055f4d0193 | ||
|
|
7977101578 | ||
|
|
5267940a8a | ||
|
|
cb174aeaa6 | ||
|
|
d97332f47a | ||
|
|
6551ce8e18 | ||
|
|
3c5594b7e1 | ||
|
|
eb9593a4e5 | ||
|
|
078f36c14a | ||
|
|
7297dbcc00 | ||
|
|
ba382eef75 | ||
|
|
23b1a5fff5 | ||
|
|
95fed3fc2d | ||
|
|
6398fd2783 | ||
|
|
e8f0398f59 | ||
|
|
a7dc289b2d | ||
|
|
db10903ea0 | ||
|
|
ca1410bc85 | ||
|
|
c78360fce2 | ||
|
|
6884b19a73 | ||
|
|
75933a508c | ||
|
|
e5358e8609 | ||
|
|
bc0ea20343 | ||
|
|
ab8a86e451 | ||
|
|
45b0a5c2a6 | ||
|
|
c20aa5c1c8 | ||
|
|
d5481d8c20 | ||
|
|
bef57b677c | ||
|
|
ce1c5437fc | ||
|
|
46f059947b | ||
|
|
cf0cb2ebd2 | ||
|
|
2b35db3f39 | ||
|
|
a3f01a35c8 | ||
|
|
14b3e49de6 | ||
|
|
6ceaa073a9 | ||
|
|
deac07dd13 | ||
|
|
f0126f41fb | ||
|
|
8bd44344e7 | ||
|
|
9b945d00f7 | ||
|
|
e9e82ca3e1 | ||
|
|
c91d9e5790 | ||
|
|
7561e33e38 | ||
|
|
afced3eb73 | ||
|
|
70c97fa8be | ||
|
|
9acc1d1fe9 | ||
|
|
622d91d7cc | ||
|
|
e7086ff8fc | ||
|
|
5f0c3435fa | ||
|
|
18972c2fb9 | ||
|
|
d1753c33f5 | ||
|
|
e4c222a4e8 | ||
|
|
d12d616e28 | ||
|
|
2073cd3ac1 | ||
|
|
9f2f1d8641 | ||
|
|
fd2c1f6410 | ||
|
|
1be0733011 | ||
|
|
bfd4bb2ec1 | ||
|
|
f845397b87 | ||
|
|
aab4efe03a | ||
|
|
eb18cbef78 | ||
|
|
ae339ea5cc | ||
|
|
33700d1529 | ||
|
|
21140f6f2c | ||
|
|
6927a92ad3 | ||
|
|
f99eb3c88f | ||
|
|
a993d8cd26 | ||
|
|
53fa21b97a | ||
|
|
a4f86492f9 | ||
|
|
79404fcb18 | ||
|
|
defe880515 | ||
|
|
fa0365c409 | ||
|
|
6a5b79143e | ||
|
|
f868eca938 | ||
|
|
6fa218dd91 | ||
|
|
117b99d967 | ||
|
|
7003e1f7d2 | ||
|
|
ae7188cd65 | ||
|
|
7de7886453 | ||
|
|
efd08b4997 | ||
|
|
0fbde40359 | ||
|
|
3ce9d71983 | ||
|
|
238bdea2b0 | ||
|
|
fe382cfc0b | ||
|
|
ff6365cfed | ||
|
|
f820506184 | ||
|
|
9bf046b714 | ||
|
|
cb14b727ba | ||
|
|
d633ec5fcd | ||
|
|
0b26dc2f43 | ||
|
|
31fb916b9d | ||
|
|
95b37ea341 | ||
|
|
fee9841183 | ||
|
|
6f93a037cf | ||
|
|
f0545ced65 | ||
|
|
46f5c44db0 | ||
|
|
adb5934f0b | ||
|
|
00d724a3a9 | ||
|
|
4c4d01211c | ||
|
|
ba2e7a7462 | ||
|
|
38110749cd | ||
|
|
96ea920e98 | ||
|
|
bb0e1f38dc | ||
|
|
77ff3583b0 | ||
|
|
e0f4bf8eab | ||
|
|
7c985b0d9c | ||
|
|
7983adb98e | ||
|
|
6accf088bf | ||
|
|
3f48810034 | ||
|
|
843f081d78 | ||
|
|
f18ce5adf1 | ||
|
|
c860be73f6 | ||
|
|
5ead61d406 | ||
|
|
b6cc9c534b | ||
|
|
aa5cf2f591 | ||
|
|
18606462bb | ||
|
|
59bc73cedf | ||
|
|
b77c4afff2 | ||
|
|
574c89529a | ||
|
|
c6d48446f4 | ||
|
|
95c3ca8859 | ||
|
|
d179db1e8f | ||
|
|
9eae919050 | ||
|
|
7d8e9a7969 | ||
|
|
c2b6518027 | ||
|
|
a6745ef34a | ||
|
|
ae71c6e679 | ||
|
|
aade8f94a6 | ||
|
|
0be312a5e3 | ||
|
|
95bc7db28a | ||
|
|
d23beefb60 | ||
|
|
70ff435a8c | ||
|
|
140fe484d7 | ||
|
|
c798c79f41 |
11
.githooks/post-commit
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/sh
|
||||
|
||||
FILE=.links.temp-disabled.yaml
|
||||
if test -f "$FILE"; then
|
||||
# Only do the post-commit hook if the file was temp-disabled by the pre-commit hook.
|
||||
# Otherwise linking was actively (`yarn links:disable`) disabled and this hook should noop.
|
||||
mv .links.temp-disabled.yaml .links.yaml
|
||||
yarnLog=$(yarn)
|
||||
echo "[yarn-linker] The post-commit hook has re-enabled .links.yaml."
|
||||
exit 1
|
||||
fi
|
||||
11
.githooks/pre-commit
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/sh
|
||||
|
||||
FILE=".links.yaml"
|
||||
if test -f "$FILE"; then
|
||||
mv .links.yaml .links.temp-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/release.yml
vendored
Normal 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
|
||||
2
.github/workflows/blocked.yaml
vendored
@@ -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: |
|
||||
|
||||
@@ -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 }}
|
||||
@@ -46,6 +46,8 @@ jobs:
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: ${{ inputs.docker_tags}}
|
||||
labels: |
|
||||
org.opencontainers.image.licenses=AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
|
||||
|
||||
8
.github/workflows/build-element-call.yaml
vendored
@@ -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
|
||||
|
||||
8
.github/workflows/build.yaml
vendored
@@ -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
|
||||
|
||||
14
.github/workflows/changelog-label.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: PR changelog label
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [labeled, unlabeled, opened]
|
||||
jobs:
|
||||
pr-changelog-label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: yogevbd/enforce-label-action@2.1.0
|
||||
with:
|
||||
REQUIRED_LABELS_ANY: "PR-Bug-Fix,PR-Documentation,PR-Task,PR-Feature,PR-Improvement,PR-Developer-Experience,dependencies"
|
||||
REQUIRED_LABELS_ANY_DESCRIPTION: "Select at least one 'PR-' label"
|
||||
BANNED_LABELS: "banned"
|
||||
2
.github/workflows/deploy-to-netlify.yaml
vendored
@@ -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 }}
|
||||
|
||||
6
.github/workflows/lint.yaml
vendored
@@ -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
|
||||
|
||||
136
.github/workflows/publish-embedded-packages.yaml
vendored
@@ -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 }}")
|
||||
```
|
||||
|
||||
9
.github/workflows/publish.yaml
vendored
@@ -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 }}
|
||||
@@ -60,14 +60,13 @@ jobs:
|
||||
artifact_run_id: ${{ github.event.workflow_run.id || github.run_id }}
|
||||
docker_tags: |
|
||||
type=sha,format=short,event=branch
|
||||
type=semver,pattern=v{{version}}
|
||||
type=raw,value=${{ github.event.release.tag_name }}
|
||||
# Like before, using ${{ env.VERSION }} above doesn't work
|
||||
add_docker_release_note:
|
||||
needs: publish_docker
|
||||
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 +78,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 }}
|
||||
```
|
||||
|
||||
16
.github/workflows/test.yaml
vendored
@@ -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
|
||||
|
||||
9
.github/workflows/translations-download.yaml
vendored
@@ -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
|
||||
|
||||
14
.gitignore
vendored
@@ -9,10 +9,22 @@ 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
|
||||
/.links.temp-disabled.yaml
|
||||
|
||||
# Playwright
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
/playwright/.cache/
|
||||
91
.yarn/plugins/linker.cjs
vendored
Normal 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
@@ -0,0 +1,3 @@
|
||||
nodeLinker: node-modules
|
||||
plugins:
|
||||
- .yarn/plugins/linker.cjs
|
||||
147
README.md
@@ -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
|
||||
|
||||

|
||||
|
||||
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)
|
||||
|
||||

|
||||
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.
|
||||
|
||||

|
||||
<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.
|
||||

|
||||
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
|
||||
```
|
||||
|
||||
@@ -157,28 +192,35 @@ To use it, create a local config by, e.g.,
|
||||
The `config.devenv.json` config should work with the backend development
|
||||
environment as outlined in the next section out of box.
|
||||
|
||||
> [!NOTE]
|
||||
> Be aware, that this `config.devenv.json` is exposing a deprecated fallback
|
||||
> LiveKit config key. If the homeserver advertises SFU backend via
|
||||
> `.well-known/matrix/client` this has precedence.
|
||||
|
||||
You're now ready to launch the development server:
|
||||
|
||||
```sh
|
||||
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
|
||||
whole stack of components which is required for a local development environment:
|
||||
|
||||
- Minimum Synapse Setup (servername: `synapse.localhost`)
|
||||
- LiveKit JWT Service (Note requires Federation API and hence a TLS reverse proxy)
|
||||
- Minimum TLS reverse proxy (servername: `synapse.localhost`) Note certificates
|
||||
are valid for at least 10 years from now
|
||||
- Minimum Synapse Setup (servername: `synapse.m.localhost`)
|
||||
- LiveKit Authorization Service (Note requires Federation API and hence a TLS reverse proxy)
|
||||
- Minimum LiveKit SFU Setup using dev defaults for config
|
||||
- Redis db for completeness
|
||||
- Minimum `localhost` Certificate Authority (CA) for Transport Layer Security (TLS)
|
||||
- Hostnames: `m.localhost`, `*.m.localhost`
|
||||
- Add [./backend/dev_tls_local-ca.crt](./backend/dev_tls_local-ca.crt) to your web browsers trusted
|
||||
certificates
|
||||
- Minimum TLS reverse proxy for
|
||||
- Synapse homeserver: `synapse.m.localhost`
|
||||
- MatrixRTC backend: `matrix-rtc.m.localhost`
|
||||
- Local Element Call development `call.m.localhost` via `yarn dev --host `
|
||||
- Element Web `app.m.localhost`
|
||||
- Note certificates will expire on Thu, 03 May 2035 10:32:02 GMT
|
||||
|
||||
These use a test 'secret' published in this repository, so this must be used
|
||||
only for local development and **_never be exposed to the public Internet._**
|
||||
@@ -191,23 +233,35 @@ yarn backend
|
||||
# podman-compose -f dev-backend-docker-compose.yml up
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> To ensure your local development frontend functions properly, you’ll need to
|
||||
> add certificate exceptions in your browser for `https://localhost:3000`,
|
||||
> `https://matrix-rtc.m.localhost/livekit/jwt/healthz` and
|
||||
> `https://synapse.m.localhost/.well-known/matrix/client`. This can be either
|
||||
> done by adding the minimum localhost CA
|
||||
> ([./backend/dev_tls_local-ca.crt](./backend/dev_tls_local-ca.crt)) to your web
|
||||
> browsers trusted certificates or by simply copying and pasting each URL into
|
||||
> your browser’s address bar and follow the prompts to add the exception.
|
||||
|
||||
### 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 +281,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 +300,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
@@ -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.
|
||||
@@ -1,5 +1,5 @@
|
||||
server_name: "synapse.localhost"
|
||||
public_baseurl: http://synapse.localhost:8008/
|
||||
server_name: "synapse.m.localhost"
|
||||
public_baseurl: https://synapse.m.localhost/
|
||||
|
||||
pid_file: /data/homeserver.pid
|
||||
|
||||
|
||||
155
backend/dev_nginx.conf
Normal file
@@ -0,0 +1,155 @@
|
||||
# Synapse reverse proxy including .well-known/matrix/client
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
listen 443 ssl;
|
||||
listen 8448 ssl;
|
||||
listen [::]:443 ssl;
|
||||
listen [::]:8448 ssl;
|
||||
server_name synapse.m.localhost;
|
||||
ssl_certificate /root/ssl/cert.pem;
|
||||
ssl_certificate_key /root/ssl/key.pem;
|
||||
|
||||
# well-known config adding rtc_foci backend
|
||||
# Note well-known is currently not effective due to:
|
||||
# https://spec.matrix.org/v1.12/client-server-api/#well-known-uri the spec
|
||||
# says it must be at https://$server_name/... (implied port 443) Hence, we
|
||||
# currently rely for local development environment on deprecated config.json
|
||||
# setting for livekit_service_url
|
||||
location /.well-known/matrix/client {
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
return 200 '{"m.homeserver": {"base_url": "https://synapse.m.localhost"}, "org.matrix.msc4143.rtc_foci": [{"type": "livekit", "livekit_service_url": "https://matrix-rtc.m.localhost/livekit/jwt"}]}';
|
||||
default_type application/json;
|
||||
}
|
||||
|
||||
# Reverse proxy for Matrix Synapse Homeserver
|
||||
# This is also required for development environment.
|
||||
# Reason: the lk-jwt-service uses the federation API for the openid token
|
||||
# verification, which requires TLS
|
||||
location / {
|
||||
proxy_pass "http://homeserver:8008";
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
}
|
||||
|
||||
# MatrixRTC reverse proxy
|
||||
# - MatrixRTC Authorization Service
|
||||
# - LiveKit SFU websocket signaling connection
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
listen 8448 ssl;
|
||||
listen [::]:8448 ssl;
|
||||
server_name matrix-rtc.m.localhost;
|
||||
ssl_certificate /root/ssl/cert.pem;
|
||||
ssl_certificate_key /root/ssl/key.pem;
|
||||
|
||||
|
||||
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://auth-server: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://livekit-sfu:7880/;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
}
|
||||
|
||||
# Convenience reverse proxy for the call.m.localhost domain to yarn dev --host
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name call.m.localhost;
|
||||
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name call.m.localhost;
|
||||
ssl_certificate /root/ssl/cert.pem;
|
||||
ssl_certificate_key /root/ssl/key.pem;
|
||||
|
||||
|
||||
location ^~ / {
|
||||
|
||||
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_pass https://host.docker.internal:3000;
|
||||
proxy_ssl_verify off;
|
||||
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
}
|
||||
|
||||
# Convenience reverse proxy app.m.localhost for element web
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name app.m.localhost;
|
||||
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name app.m.localhost;
|
||||
ssl_certificate /root/ssl/cert.pem;
|
||||
ssl_certificate_key /root/ssl/key.pem;
|
||||
|
||||
|
||||
location ^~ / {
|
||||
|
||||
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_pass http://element-web:81;
|
||||
proxy_ssl_verify off;
|
||||
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
}
|
||||
19
backend/dev_tls_local-ca.crt
Normal file
@@ -0,0 +1,19 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDGjCCAgKgAwIBAgIUGdiFHhH4KL2pqBjMQHQ+PVIkSV8wDQYJKoZIhvcNAQEL
|
||||
BQAwHjEcMBoGA1UEAwwTRWxlbWVudCBDYWxsIERldiBDQTAeFw0yNTA1MDUxMDMy
|
||||
MDJaFw0zNTA1MDMxMDMyMDJaMB4xHDAaBgNVBAMME0VsZW1lbnQgQ2FsbCBEZXYg
|
||||
Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA2y0hjmNn1vRsVSdy
|
||||
8IOfo8N1q9UgkhQWpGKXzPh+D5d1fnuJEmHIVwtDEtS/PwQ43LTmegChPtKH9jdT
|
||||
tG0IihW9Ja5YNG+9xAwaoA/sB3CGCBYsz+2/XjVUpXoBJXIPoFBWsn+K0oeFw9fw
|
||||
eRO1z9abM4cl+LjKzMNM8CCyu9uI1MaGjYez2YIWvG854VucLxX7HSlMJxZNWnie
|
||||
Ui7fMakuJhB2+aiIQjdKxy4E5RHNhzYG/LXhvP+wBYBDPNRsP3rtzEaE9HAveL9K
|
||||
FGqd3R4cBia6r1WIXmpAzyu5RGP5Eou0TZlGkal96/bF0I7q/pKlL23Jt1BLPiQU
|
||||
KGKrAgMBAAGjUDBOMB0GA1UdDgQWBBQJqBjMu61c1p24txw/y+kv3D+V6DAfBgNV
|
||||
HSMEGDAWgBQJqBjMu61c1p24txw/y+kv3D+V6DAMBgNVHRMEBTADAQH/MA0GCSqG
|
||||
SIb3DQEBCwUAA4IBAQB8m2YfFGLugNt5vAAOvNxVqDA8c72yCVYr3CBCpmTIEY5Z
|
||||
d3qVGhG9//ux6+J8ntkSwd9nV5GJyYXHukCG1VavnAWolWdNF/WAllf0jhLuz7kD
|
||||
/cJnuI1By4tBsBmSz851i6HJ4t5k99Be+6GQVzi0e7zzfxTHZE4xP2J6Ox8QbPsP
|
||||
n0m76nIp/WbWaJqzvIIjJhmUUPPv+4wN+eOArgjiGLzptM2qTtGZtd0c9nS5gvep
|
||||
+mEbSUN9zkhAroZf80wf+hEvy+fJ94VbZ9QjTzTg7odZLrsXGIe8DaG63EYRQ25b
|
||||
W5iYBAreln5fGSt7qHsGfqwZibTEk/Lx3dydO1Kg
|
||||
-----END CERTIFICATE-----
|
||||
28
backend/dev_tls_local-ca.key
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDA2y0hjmNn1vRs
|
||||
VSdy8IOfo8N1q9UgkhQWpGKXzPh+D5d1fnuJEmHIVwtDEtS/PwQ43LTmegChPtKH
|
||||
9jdTtG0IihW9Ja5YNG+9xAwaoA/sB3CGCBYsz+2/XjVUpXoBJXIPoFBWsn+K0oeF
|
||||
w9fweRO1z9abM4cl+LjKzMNM8CCyu9uI1MaGjYez2YIWvG854VucLxX7HSlMJxZN
|
||||
WnieUi7fMakuJhB2+aiIQjdKxy4E5RHNhzYG/LXhvP+wBYBDPNRsP3rtzEaE9HAv
|
||||
eL9KFGqd3R4cBia6r1WIXmpAzyu5RGP5Eou0TZlGkal96/bF0I7q/pKlL23Jt1BL
|
||||
PiQUKGKrAgMBAAECggEAAPX2kxi5AQ7ul82SzT1KgpSXyDHLdYaUyAoYnaX9RO+B
|
||||
8ylmpyeqygs4+KQS4EMJm9jpo85Oy37bIKdG3kljU6wQcKlL5Y+ZUOo1nzpV6fid
|
||||
hGVs6ts8VXw8KshKQ9AyccZ8L/pirUfgOffgTwfjY7/90zceAL/s98GuZWc62nkX
|
||||
55joQv/OikqYfAGP/U6Bp2Zyf23DwJB09Z3B6NnZj/ZyAbDrDEHuA15LhCOcCczp
|
||||
IU/mFEywBPHT9Tg4w4Beq78PeAETvku2UalYRLhP3RLlXr2oEbwUtINRVt2QjZ85
|
||||
Esps4uCqL/mgQluIebtudD9HL/YMlNPXue1mDXFxJQKBgQDgZZY4yJBcf488T1V6
|
||||
HNm06b/LvVGj253pKgw14hpY1xQu3Ymgzv1GEqzhSYdzxhpmj0tMUNHxAp+YdGQu
|
||||
SZ0wcPKhw0aYVkIjDRYDC3Wn5GJhyIEYHGYMo/n4l49UzHRBPOTDzp49DkHTKBgh
|
||||
XgIIazYT3CkjTIMRrkUv+qfIPQKBgQDcBGu/mqbjxs4sN3zqPS4aB21o6t6W0sXs
|
||||
ZP9w6RlTPQi5U2oRbftjZtYc0bbEgkMUImB1HwYPQT5pJ+MyC414xDvSc2exBr5d
|
||||
To6yyPIy78Tf5PHM12fpKV92nSvoz/pSjYcGxxDtKfPqu+t8mOJfjCV1lLLA+xuB
|
||||
DDaE4p8dBwKBgQCdAne6A5v/HMH8UQZeCxHJpESvKiiVnnU/UEx651nID7XvlNNX
|
||||
0X0mKqsMd4ZvW43ddSYan/JF0LAa3FW8jYWO/3jF9vzOWoysOdvNBZetgf/Uq5ao
|
||||
aDZ/YbzmVCXWD7jIbPMkjs3pqrAkL0mzDzQc7+dGviWKrV6IYIfIqnn7gQKBgDCz
|
||||
vdIk/qpO+JZrFfiX4Fucp0hhLTJ/p5ZDaRPqVVPKn+K+Jy2ChfIj8mNgvK9VEloj
|
||||
nexvGJ1J2PHYBX+vdPp1nbRhHWPfVUY8PHQw7QP/dToGaMvqJrNDGEGeWvjnCMc7
|
||||
UtdaO1H0Rm0AegkTopB56lTTvJnhO95eALd7nrMDAoGAEPdzJtWoKafp49svhSj0
|
||||
hiXQv2SPBwVUN4LZ4SOWiXUcmYYm80aNpYKLkBxYjrfqFWhE7NUHLGp8YorQWKY2
|
||||
acD9AReHk/xku0ABy6jeYmSCmCxASxst5liKD+l12sk0gB0rk5MBxB4Uu1MIbQZ2
|
||||
aCASX3AVD2/XyC2MKkzc8Eg=
|
||||
-----END PRIVATE KEY-----
|
||||
21
backend/dev_tls_m.localhost.crt
Normal file
@@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDZzCCAk+gAwIBAgIUXizLjwkdqepX0bh0K3abeJxj68IwDQYJKoZIhvcNAQEL
|
||||
BQAwHjEcMBoGA1UEAwwTRWxlbWVudCBDYWxsIERldiBDQTAeFw0yNTA1MDUxMzU5
|
||||
MTFaFw0zNTA1MDMxMzU5MTFaMBgxFjAUBgNVBAMMDSoubS5sb2NhbGhvc3QwggEi
|
||||
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrzGSScSgaQuZdELGFYiLiYRwr
|
||||
LKyUdNr0rsPcOo0bvbeZ3zQMeUMRNlA69zGFdarumiDRXUoAmZI39WmH95aX3d+A
|
||||
U7EFnWev7xpWSVhSYj8T0d4rke8HjGk3LpaffJ93tbJuagBIH1ouuN6AOdzWs8hp
|
||||
RYIomWleEeeuVnnfaMwaXOdc+ihJJ6wzm2hwQSfdpjZPWBDd/DFft1ZXxIZOCjDs
|
||||
rEIiI7uU8iZPLB3QEM/tgxSSAOxrcKvQvxZokk+FD7aMJFP71IfieLCEzMTP1VXa
|
||||
tP7UTAKAqB2NyDJ8m3IHbOINiqcdFvFR3R1D9bXOYE4oRynNvYZrQUGnL2RtAgMB
|
||||
AAGjgaIwgZ8wHwYDVR0jBBgwFoAUCagYzLutXNaduLccP8vpL9w/legwCQYDVR0T
|
||||
BAIwADALBgNVHQ8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwMAYDVR0RBCkw
|
||||
J4IJbG9jYWxob3N0ggttLmxvY2FsaG9zdIINKi5tLmxvY2FsaG9zdDAdBgNVHQ4E
|
||||
FgQUfdh1p52ZgWyZcBgBXGwKi4EnUE0wDQYJKoZIhvcNAQELBQADggEBAKrHEuB6
|
||||
33j8+EwSHw3zrvt/DRXK2BDHI1Ir9JcztSunaKAjZXVvf/dvZp0Xs1dEdJIdnv6G
|
||||
iZYhBbOqDqpQZbf2h/h0kuu5yZSBUdnQXnYNxlhp2UaC/UEgw5iZT/p1rm7RjVie
|
||||
y4Dp2WytV5iZOLmLj6xDvd3DXazgJPWIRX8p8qJZbKTkwCjTr7nDIj8jjG1sVFf7
|
||||
1RJBO5/6WSnImrpDmlLUrvjiKvbxcdseDJyBOhTwdRdSk4S2M+s5tR5j2I1gXLOq
|
||||
J5ioN76+SCrTY0K0WKRy9oOXWO1/X3+VYcekp+0F3SGkd5w17jylCv1XIGHAdEsQ
|
||||
v2z2/aMI/7sAD2Q=
|
||||
-----END CERTIFICATE-----
|
||||
28
backend/dev_tls_m.localhost.key
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCrzGSScSgaQuZd
|
||||
ELGFYiLiYRwrLKyUdNr0rsPcOo0bvbeZ3zQMeUMRNlA69zGFdarumiDRXUoAmZI3
|
||||
9WmH95aX3d+AU7EFnWev7xpWSVhSYj8T0d4rke8HjGk3LpaffJ93tbJuagBIH1ou
|
||||
uN6AOdzWs8hpRYIomWleEeeuVnnfaMwaXOdc+ihJJ6wzm2hwQSfdpjZPWBDd/DFf
|
||||
t1ZXxIZOCjDsrEIiI7uU8iZPLB3QEM/tgxSSAOxrcKvQvxZokk+FD7aMJFP71Ifi
|
||||
eLCEzMTP1VXatP7UTAKAqB2NyDJ8m3IHbOINiqcdFvFR3R1D9bXOYE4oRynNvYZr
|
||||
QUGnL2RtAgMBAAECggEAJaFQii8U/KOYt9vXNoMnZvSkaeSQLLhn2V6Kciu1CtWE
|
||||
aMTWLsFE6nk+G5xXkYcTmM3T0GghtH3u5CjyI6EcsEkeEorCZJt0wbmayDmqiekR
|
||||
LfMzOdHuTHX5+edPgMGYYG1BFyRKyYFsjH1b5zRFZhXdGQnrl5760GsVlz9D1KZQ
|
||||
iHcT+q1S2tmZeoUukQnADENKXUMCyTGM5FCddgNtsWnGDsTDayh7hUdvDkB+mW4G
|
||||
lSp+BZuc3PCwpbD6qkXvfugWs6CUAAtXoV3ceWgxQ+TEnNlwxaG1AyugfgNUBolk
|
||||
8xgeZt4r5QId03jsHDf7hpBAofcaCd5EMIIQYFvWoQKBgQDlbAvAzEFPTZZn2nRV
|
||||
Xagw4xjqVc1LLEKLCWq0N5rEkwn0h90Dz5N7/3NuonP/sIDsDHCbyiOYBI1Ck6Xi
|
||||
0WuB+OyKDh+xeF2mekN9G9ywPahdK5lT/TVsxXFyZlwtVv1x/6KBO4yv5URizxqU
|
||||
gyAPDDxfD/KcNjkOBaodWEwQGQKBgQC/s2gPDBtQkjLwkHXchBomLww5eLlVrac1
|
||||
WK4UX6uSdOgrjJ375OOgMTxe8NVZdOuAKytGXRWDwgH3nVWvuZhe7dGlX3JMuSer
|
||||
e9VwDpBESrvqcR4ruL6wm8wej6BXyjH0wD3FHb0S5HfuBDxTn+4bDwrbRzOUMNgy
|
||||
lSppuflxdQKBgQDiZcIfazFT8evn5nMAvuC4BZNTxIJHmZC9JfjPiUPIkpWzYtOe
|
||||
7BvNtKOT3Op9uw8uYYRKqKqBXJSNy6ha8XCXHS9HeXKbLn20SFkLQBCDNwVLlDfF
|
||||
40zyXtF6JDr4XyzSb4NM5pgKCER5AYloXxGm59s3sEQpFXUuOjbKqJS/GQKBgAoI
|
||||
c7vF4HAZFr1sch62cz/oWnVvkhOf4Q5zs7ixQSOLJtOQqnwSgK9TpFs7s47ZBbJR
|
||||
kBRAru2Ua9Hv1Bo8VnMxczV6h1roneDlvEf/GyHX33nnrbKQGrrXjJlU3wl5NaAf
|
||||
p5v3cHvapUQ5yIZ/6lBUOzc6xMJOxCHxmKSr7Rg5AoGAbEE4lt6Xh2dnBPJ81eNI
|
||||
IDrw/3ITY53qAY4Bx88CByIFuu8CEUdUZprh98jSl6ic1tMinZfUhRMwABLrUD51
|
||||
DGst8iGLPD9u83iMcUHI/L+p7AbxrKLvWXZrF5UZm440c9mSWqfhPaTBosPtNDsG
|
||||
LfETwH1flKXMTXd2xA9RTE4=
|
||||
-----END PRIVATE KEY-----
|
||||
38
backend/dev_tls_setup
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Step 1: Create a Root CA key and cert
|
||||
openssl genrsa -out dev_tls_local-ca.key 2048
|
||||
openssl req -x509 -new -nodes \
|
||||
-days 3650 \
|
||||
-subj "/CN=Element Call Dev CA" \
|
||||
-key dev_tls_local-ca.key \
|
||||
-out dev_tls_local-ca.crt \
|
||||
-sha256 -addext "basicConstraints=CA:TRUE"
|
||||
|
||||
# Step 2: Create a private key and CSR for *.m.localhost
|
||||
openssl req -new -nodes -newkey rsa:2048 \
|
||||
-keyout dev_tls_m.localhost.key \
|
||||
-out dev_tls_m.localhost.csr \
|
||||
-subj "/CN=*.m.localhost"
|
||||
|
||||
# Step 3: Sign the CSR with your CA
|
||||
openssl x509 \
|
||||
-req -in dev_tls_m.localhost.csr \
|
||||
-CA dev_tls_local-ca.crt -CAkey dev_tls_local-ca.key \
|
||||
-CAcreateserial \
|
||||
-out dev_tls_m.localhost.crt \
|
||||
-days 3650 \
|
||||
-sha256 \
|
||||
-extfile <( cat <<EOF
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = serverAuth
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
DNS.1 = localhost
|
||||
DNS.2 = m.localhost
|
||||
DNS.3 = *.m.localhost
|
||||
EOF
|
||||
)
|
||||
53
backend/ew.test.config.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"default_server_config": {
|
||||
"m.homeserver": {
|
||||
"base_url": "https://synapse.m.localhost",
|
||||
"server_name": "synapse.m.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"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
server_name: "synapse.localhost"
|
||||
public_baseurl: http://synapse.localhost:8008/
|
||||
server_name: "synapse.m.localhost"
|
||||
public_baseurl: https://synapse.m.localhost/
|
||||
|
||||
pid_file: /data/homeserver.pid
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDtzCCAp+gAwIBAgIUCmJjl3HAeLmrPwRg+/OzikW6peQwDQYJKoZIhvcNAQEL
|
||||
BQAwazELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkxvbmRvbjEPMA0GA1UEBwwGTG9u
|
||||
ZG9uMQ4wDAYDVQQKDAVBbHJvczEWMBQGA1UECwwNSVQgRGVwYXJ0bWVudDESMBAG
|
||||
A1UEAwwJbG9jYWxob3N0MB4XDTI0MTEwNDIxNDcwMFoXDTM0MTEwMjIxNDcwMFow
|
||||
azELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkxvbmRvbjEPMA0GA1UEBwwGTG9uZG9u
|
||||
MQ4wDAYDVQQKDAVBbHJvczEWMBQGA1UECwwNSVQgRGVwYXJ0bWVudDESMBAGA1UE
|
||||
AwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs368
|
||||
ExLSudP8luNoY5UfaPqBSVJUPYBi+JGyd36tyN75p5OI7xSfHTttQxuD4KrExBFP
|
||||
C8mAhE1eoZPBVBOZJ4FYWBJfMaQnCjeqU+laP36td65kSJYbUYlKYH1WpxEpCdgx
|
||||
wWOKkP/kPX5YXbYqODx9aBJXgoT3yAJW7AniIoL+eLFnS9Xo86TPqCDBTJU9ocwK
|
||||
gPIDLhDv60724rhZT1kbGp7ECqRovndoDTQjuws2D3yNMfQ+4rrQGPXHGmP5PcaR
|
||||
0R7uueB+6APyC7MJbuhbxxg/+DFHrRi3lJsgwxuh2hi/+vWw8zgKlgYIwHFA9X0l
|
||||
cX0UlQdENMH3bgcGIwIDAQABo1MwUTAdBgNVHQ4EFgQUUFGxw7zoiHXGwRqtagjZ
|
||||
RPYc85cwHwYDVR0jBBgwFoAUUFGxw7zoiHXGwRqtagjZRPYc85cwDwYDVR0TAQH/
|
||||
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEALokb1z2lu3qW141b2wm14ilZQKCZ
|
||||
reNNuUR95Uom96FXPH4QVEH+mYTXXJ5UrfNhQYKQFpdE+5S4HL/UqEOxtWvbAHpK
|
||||
nsLQ62J8m+0+uwiJGqeQpWr03KJgXDAVE9X3XwMlp/+buxSLhc+GIHWuXW56itV2
|
||||
jiZJYjhO5SnhhgTWNoVZk93qXuuWEN0yacw7c3Fr1IvFYYYWufbXTk70dbZihPDK
|
||||
VD141o8tpp6FerSKHNYDqkVFDyTz3DVOhQQJ59zfMre7bFr+PpTTl4vIuGzXEY+E
|
||||
HPjUSlOzwkCoh5fu7Fs3qG55rJt8akhTEoKpiBTaLucgAjVWNHeci1+Yxg==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,28 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCzfrwTEtK50/yW
|
||||
42hjlR9o+oFJUlQ9gGL4kbJ3fq3I3vmnk4jvFJ8dO21DG4PgqsTEEU8LyYCETV6h
|
||||
k8FUE5kngVhYEl8xpCcKN6pT6Vo/fq13rmRIlhtRiUpgfVanESkJ2DHBY4qQ/+Q9
|
||||
flhdtio4PH1oEleChPfIAlbsCeIigv54sWdL1ejzpM+oIMFMlT2hzAqA8gMuEO/r
|
||||
TvbiuFlPWRsansQKpGi+d2gNNCO7CzYPfI0x9D7iutAY9ccaY/k9xpHRHu654H7o
|
||||
A/ILswlu6FvHGD/4MUetGLeUmyDDG6HaGL/69bDzOAqWBgjAcUD1fSVxfRSVB0Q0
|
||||
wfduBwYjAgMBAAECggEACTqdSExxzJ+LX5ARFaWyOBSWly2GKqSyR14+aInOklhx
|
||||
9QgkmfOxJrCf3TvJ8RWhXloW0Aqr8qGDxG0Ixgjn7rG7gskXCey1xn8MNppLS0kj
|
||||
ztaG+NB3AR89ABm8XdoHsSY45geh3/Ni9I0i1VardGQafUJhgNLTZqjwIodzkBtJ
|
||||
S/bi4uFk1lGNfuvWQvWqzGXUvd1l1YupV6iA4GfhXlUvrSBZwftLBD6xEvQaSqsA
|
||||
pHvBxTfMXG4RMAkNPDIElkuQ8++CGi1gIRkJfmrv4OgbbitteMnxqqqGYV0zSNCg
|
||||
R/5FG6umIV7lDLBHZCSCk7wmfmq2UUvzhHThHy4yMQKBgQDu4TwFJCIcVIj7Wj4r
|
||||
DUBFvz6Lgbltqb+YAMUBtpiDcAQxDJWmedh6dK04ts5CFAFRlRjjuz2uFn7qlVBm
|
||||
uye9R7tL+tOv5viqDXU78a4snFywoXub6yzpbxrW8B4W1pdIUvQmhwCcDwvO1V24
|
||||
7Vj2vxcM5I9dsk1aCQSi3VY5yQKBgQDAW/VoTRwhU6OUc6sji5Z5dnkMjkP6NZK9
|
||||
CSrTWLAMGaLPY+g6fFS7JMNSvfWm/okypD6rcN7p0cxMK3mfFKmMiyPRde0wdrci
|
||||
sGFjGxM/2d2D7KTMC9iMYwA0K17UIna+UiYPfhR/muIg/dCyjlkKDFs9Z4jk//r1
|
||||
91bmznt2iwKBgFdiYXhn/Wprqih4nKFXGZnqGdEixVhObl4GegrkZuo+AeqHdf8O
|
||||
N5ikMfG7PbyCYPEdH5u/FRMn+4mI0X6jHChroyJqQSHp1jEu9yHUiSicknOyvusM
|
||||
nsNN932FHRyxp2m3nsSxQhHUlzc0ajKJ8K9iu+XlfmSCIzW6cs25Nh+xAoGBAJro
|
||||
M0wIdPPdsCj3sUVRvx8XqknTM6kGhaIYBNXoYPWNm5BaC4U15OJEq8sxUOdnqcMP
|
||||
g6x6m/k+S8C3bh0O/a9Bydl/l0BlCfw0gGjYP/s2ju4Tn272xy/e9iYNGzPIgUmp
|
||||
TB9D0GwmpZ4d6HgyrD+sTbm4bATGpCp6QhBjDggbAoGBAJVMMtZ4pF8D6mLMRZGR
|
||||
pQjNPy+MH13XYmDRc/BSF8KJ4yKk3tohr9LSXzxR0SEB43NoL1bHkucZrNjGyL8x
|
||||
jktnwkoIs96kO2mPrl1TqWkXs5RjGkkSTbAJovIcvkRU31SWap/WzN2kHpmRVcQc
|
||||
KEFKXT5fUYZCLLWxhgZFlGPp
|
||||
-----END PRIVATE KEY-----
|
||||
@@ -1,40 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
listen 443 ssl;
|
||||
listen 8448 ssl;
|
||||
listen [::]:443 ssl;
|
||||
listen [::]:8448 ssl;
|
||||
server_name synapse.localhost;
|
||||
ssl_certificate /root/ssl/cert.pem;
|
||||
ssl_certificate_key /root/ssl/key.pem;
|
||||
|
||||
# well-known config adding rtc_foci backend
|
||||
# Note well-known is currently not effective due to:
|
||||
# https://spec.matrix.org/v1.12/client-server-api/#well-known-uri the spec
|
||||
# says it must be at https://$server_name/... (implied port 443) Hence, we
|
||||
# currently rely for local development environment on deprecated config.json
|
||||
# setting for livekit_service_url
|
||||
location /.well-known/matrix/client {
|
||||
return 200 '{"m.homeserver": {"base_url": "http://synapse.localhost:8008"}, "org.matrix.msc4143.rtc_foci": [{"type": "livekit", "livekit_service_url": "http://localhost:8080"}]}';
|
||||
default_type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
}
|
||||
|
||||
# Reverse proxy for Matrix Synapse Homeserver
|
||||
# This is also required for development environment.
|
||||
# Reason: the lk-jwt-service uses the federation API for the openid token
|
||||
# verification, which requires TLS
|
||||
location / {
|
||||
proxy_pass "http://homeserver:8008";
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
{
|
||||
"default_server_config": {
|
||||
"m.homeserver": {
|
||||
"base_url": "http://synapse.localhost:8008",
|
||||
"server_name": "synapse.localhost"
|
||||
"base_url": "https://synapse.m.localhost",
|
||||
"server_name": "synapse.m.localhost"
|
||||
}
|
||||
},
|
||||
"livekit": {
|
||||
"livekit_service_url": "http://localhost:8009"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ services:
|
||||
hostname: auth-server
|
||||
environment:
|
||||
- LK_JWT_PORT=8080
|
||||
- LIVEKIT_URL=ws://localhost:7880
|
||||
- LIVEKIT_URL=wss://matrix-rtc.m.localhost/livekit/sfu
|
||||
- LIVEKIT_KEY=devkey
|
||||
- LIVEKIT_SECRET=secret
|
||||
# If the configured homeserver runs on localhost, it'll probably be using
|
||||
@@ -18,12 +18,13 @@ services:
|
||||
condition: on-failure
|
||||
ports:
|
||||
# HOST_PORT:CONTAINER_PORT
|
||||
- 8009:8080
|
||||
- 8080:8080
|
||||
networks:
|
||||
- ecbackend
|
||||
|
||||
livekit:
|
||||
image: livekit/livekit-server:latest
|
||||
hostname: livekit-sfu
|
||||
command: --dev --config /etc/livekit.yaml
|
||||
restart: unless-stopped
|
||||
# The SFU seems to work far more reliably when we let it share the host
|
||||
@@ -68,18 +69,35 @@ 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
|
||||
# see backend/dev_tls_setup for how to generate the tls certs
|
||||
hostname: synapse.m.localhost
|
||||
image: nginx:latest
|
||||
volumes:
|
||||
- ./backend/tls_localhost_nginx.conf:/etc/nginx/conf.d/default.conf:Z
|
||||
- ./backend/tls_localhost_key.pem:/root/ssl/key.pem:Z
|
||||
- ./backend/tls_localhost_cert.pem:/root/ssl/cert.pem:Z
|
||||
- ./backend/dev_nginx.conf:/etc/nginx/conf.d/default.conf:Z
|
||||
- ./backend/dev_tls_m.localhost.key:/root/ssl/key.pem:Z
|
||||
- ./backend/dev_tls_m.localhost.crt:/root/ssl/cert.pem:Z
|
||||
ports:
|
||||
# HOST_PORT:CONTAINER_PORT
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8008:80"
|
||||
- "4443:443"
|
||||
- "8448:8448"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
depends_on:
|
||||
- synapse
|
||||
networks:
|
||||
|
||||
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 67 KiB |
@@ -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)
|
||||
|
||||
|
Before Width: | Height: | Size: 909 KiB After Width: | Height: | Size: 929 KiB |
|
Before Width: | Height: | Size: 868 KiB After Width: | Height: | Size: 886 KiB |
@@ -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
|
||||
|
||||
|
||||
BIN
docs/embedded_package.drawio.png
Normal file
|
After Width: | Height: | Size: 302 KiB |
BIN
docs/full_package.drawio.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
39
docs/linking.md
Normal 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/
|
||||
```
|
||||
@@ -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,13 +55,19 @@ 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
|
||||
```
|
||||
|
||||
As a prerequisite for the
|
||||
[Matrix LiveKit JWT auth service](https://github.com/element-hq/lk-jwt-service)
|
||||
make sure that your Synapse server has either a `federation` or `openid`
|
||||
[listener configured](https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#listeners).
|
||||
|
||||
### MatrixRTC Backend
|
||||
|
||||
In order to **guarantee smooth operation** of Element Call MatrixRTC backend is
|
||||
@@ -64,35 +75,99 @@ required for each site deployment.
|
||||
|
||||

|
||||
|
||||
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:
|
||||
|
||||
```nginx configuration file
|
||||
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 +180,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
|
||||
```
|
||||
@@ -127,7 +203,7 @@ Because Element Call uses client-side routing, your server must be able to route
|
||||
any requests to non-existing paths back to `/index.html`. For example, in Nginx
|
||||
you can achieve this with the `try_files` directive:
|
||||
|
||||
```jsonc
|
||||
```nginx configuration file
|
||||
server {
|
||||
...
|
||||
location / {
|
||||
@@ -164,3 +240,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.
|
||||
|
||||
@@ -27,7 +27,7 @@ android {
|
||||
}
|
||||
|
||||
mavenPublishing {
|
||||
publishToMavenCentral(SonatypeHost.S01)
|
||||
publishToMavenCentral(SonatypeHost.S01, automaticRelease = true)
|
||||
|
||||
signAllPublications()
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -5,7 +5,7 @@ import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "EmbeddedElementCall",
|
||||
platforms: [.iOS(.v17_6)],
|
||||
platforms: [.iOS(.v17)],
|
||||
products: [
|
||||
.library(
|
||||
name: "EmbeddedElementCall",
|
||||
|
||||
@@ -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"
|
||||
|
||||
4
knip.ts
@@ -27,6 +27,10 @@ export default {
|
||||
// then Knip will flag it as a false positive
|
||||
// https://github.com/webpro-nl/knip/issues/766
|
||||
"@vector-im/compound-web",
|
||||
// We need this so that TypeScript is happy with @livekit/track-processors.
|
||||
// This might be a bug in the LiveKit repo but for now we fix it on the
|
||||
// Element Call side.
|
||||
"@types/dom-mediacapture-transform",
|
||||
"matrix-widget-api",
|
||||
],
|
||||
ignoreExportsUsedInFile: true,
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
},
|
||||
"action": {
|
||||
"close": "Затвори",
|
||||
"copy_link": "Копиране на връзката",
|
||||
"go": "Напред",
|
||||
"invite": "Покана",
|
||||
"no": "Не",
|
||||
"register": "Регистрация",
|
||||
"remove": "Премахни",
|
||||
|
||||
@@ -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..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 geht’s“ 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": {
|
||||
|
||||
@@ -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,13 +157,16 @@
|
||||
"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": {
|
||||
"effect_volume_description": "Adjust the volume at which reactions and hand raised effects play.",
|
||||
"effect_volume_label": "Sound effect volume"
|
||||
},
|
||||
"background_blur_header": "Background",
|
||||
"background_blur_label": "Blur the background of the video",
|
||||
"blur_not_supported_by_browser": "(Background blur is not supported by this device.)",
|
||||
"developer_tab_title": "Developer",
|
||||
"devices": {
|
||||
"camera": "Camera",
|
||||
@@ -200,8 +206,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": {
|
||||
|
||||
@@ -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}}"
|
||||
}
|
||||
|
||||
@@ -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..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 d’utilisation</6> de Google s’appliquent.<9></9>En cliquant sur « S’enregistrer » 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 à l’accueil",
|
||||
"room_auth_view_eula_caption": "En cliquant sur « Rejoindre l’appel 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}}"
|
||||
|
||||
@@ -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}}"
|
||||
|
||||
@@ -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..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "ボリューム"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}}"
|
||||
}
|
||||
|
||||
@@ -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..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}}",
|
||||
|
||||
@@ -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": "В ожидании медиа..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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á..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 …"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "Очікування медіа..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}}"
|
||||
|
||||
@@ -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}}"
|
||||
|
||||
24
package.json
@@ -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",
|
||||
@@ -38,6 +40,8 @@
|
||||
"@livekit/components-core": "^0.12.0",
|
||||
"@livekit/components-react": "^2.0.0",
|
||||
"@livekit/protocol": "^1.33.0",
|
||||
"@livekit/track-processors": "^0.5.5",
|
||||
"@mediapipe/tasks-vision": "^0.10.18",
|
||||
"@opentelemetry/api": "^1.4.0",
|
||||
"@opentelemetry/core": "^1.25.1",
|
||||
"@opentelemetry/exporter-trace-otlp-http": "^0.57.0",
|
||||
@@ -45,7 +49,7 @@
|
||||
"@opentelemetry/sdk-trace-base": "^1.25.1",
|
||||
"@opentelemetry/sdk-trace-web": "^1.9.1",
|
||||
"@opentelemetry/semantic-conventions": "^1.25.1",
|
||||
"@playwright/test": "^1.51.0",
|
||||
"@playwright/test": "^1.52.0",
|
||||
"@radix-ui/react-dialog": "^1.0.4",
|
||||
"@radix-ui/react-slider": "^1.1.2",
|
||||
"@radix-ui/react-visually-hidden": "^1.0.3",
|
||||
@@ -58,6 +62,7 @@
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@testing-library/user-event": "^14.5.1",
|
||||
"@types/content-type": "^1.1.5",
|
||||
"@types/dom-mediacapture-transform": "^0.1.11",
|
||||
"@types/grecaptcha": "^3.0.9",
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
@@ -68,12 +73,11 @@
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/sdp-transform": "^2.4.5",
|
||||
"@types/uuid": "10",
|
||||
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
||||
"@typescript-eslint/parser": "^8.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.31.0",
|
||||
"@typescript-eslint/parser": "^8.31.0",
|
||||
"@use-gesture/react": "^10.2.11",
|
||||
"@vector-im/compound-design-tokens": "^3.0.0",
|
||||
"@vector-im/compound-web": "^7.2.0",
|
||||
"@vitejs/plugin-basic-ssl": "^1.0.1",
|
||||
"@vitejs/plugin-react": "^4.0.1",
|
||||
"@vitest/coverage-v8": "^3.0.0",
|
||||
"babel-plugin-transform-vite-meta-env": "^1.0.3",
|
||||
@@ -95,10 +99,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",
|
||||
@@ -116,7 +120,7 @@
|
||||
"react-use-measure": "^2.1.1",
|
||||
"rxjs": "^7.8.1",
|
||||
"sass": "^1.42.1",
|
||||
"typescript": "^5.1.6",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint-language-service": "^5.0.5",
|
||||
"unique-names-generator": "^4.6.0",
|
||||
"vaul": "^1.0.0",
|
||||
@@ -129,6 +133,8 @@
|
||||
},
|
||||
"resolutions": {
|
||||
"@livekit/components-core/rxjs": "^7.8.1",
|
||||
"@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18",
|
||||
"matrix-widget-api": "1.11.0"
|
||||
}
|
||||
},
|
||||
"packageManager": "yarn@4.7.0"
|
||||
}
|
||||
|
||||
4
playwright-backend-docker-compose.override.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
services:
|
||||
synapse:
|
||||
volumes:
|
||||
- ./backend/playwright_homeserver.yaml:/data/cfg/homeserver.yaml:Z
|
||||
@@ -1,86 +1,2 @@
|
||||
networks:
|
||||
ecbackend:
|
||||
|
||||
services:
|
||||
auth-service:
|
||||
image: ghcr.io/element-hq/lk-jwt-service:latest-ci
|
||||
hostname: auth-server
|
||||
environment:
|
||||
- LK_JWT_PORT=8080
|
||||
- LIVEKIT_URL=ws://localhost:7880
|
||||
- LIVEKIT_KEY=devkey
|
||||
- LIVEKIT_SECRET=secret
|
||||
# If the configured homeserver runs on localhost, it'll probably be using
|
||||
# a self-signed certificate
|
||||
- LIVEKIT_INSECURE_SKIP_VERIFY_TLS=YES_I_KNOW_WHAT_I_AM_DOING
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
ports:
|
||||
# HOST_PORT:CONTAINER_PORT
|
||||
- 8009:8080
|
||||
networks:
|
||||
- ecbackend
|
||||
|
||||
livekit:
|
||||
image: livekit/livekit-server:latest
|
||||
command: --dev --config /etc/livekit.yaml
|
||||
restart: unless-stopped
|
||||
# The SFU seems to work far more reliably when we let it share the host
|
||||
# network rather than opening specific ports (but why?? we're not missing
|
||||
# any…)
|
||||
ports:
|
||||
# HOST_PORT:CONTAINER_PORT
|
||||
- 7880:7880/tcp
|
||||
- 7881:7881/tcp
|
||||
- 7882:7882/tcp
|
||||
- 50100-50200:50100-50200/udp
|
||||
volumes:
|
||||
- ./backend/dev_livekit.yaml:/etc/livekit.yaml:Z
|
||||
networks:
|
||||
- ecbackend
|
||||
|
||||
redis:
|
||||
image: redis:6-alpine
|
||||
command: redis-server /etc/redis.conf
|
||||
ports:
|
||||
# HOST_PORT:CONTAINER_PORT
|
||||
- 6379:6379
|
||||
volumes:
|
||||
- ./backend/redis.conf:/etc/redis.conf:Z
|
||||
networks:
|
||||
- ecbackend
|
||||
|
||||
synapse:
|
||||
hostname: homeserver
|
||||
image: docker.io/matrixdotorg/synapse:latest
|
||||
environment:
|
||||
- SYNAPSE_CONFIG_PATH=/data/cfg/homeserver.yaml
|
||||
# Needed for rootless podman-compose such that the uid/gid mapping does
|
||||
# fit local user uid. If the container runs as root (uid 0) it is fine as
|
||||
# it actually maps to your non-root user on the host (e.g. 1000).
|
||||
# Otherwise uid mapping will not match your non-root user.
|
||||
- UID=0
|
||||
- GID=0
|
||||
volumes:
|
||||
- ./backend/synapse_tmp:/data:Z
|
||||
- ./backend/playwright_homeserver.yaml:/data/cfg/homeserver.yaml:Z
|
||||
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
|
||||
image: nginx:latest
|
||||
volumes:
|
||||
- ./backend/tls_localhost_nginx.conf:/etc/nginx/conf.d/default.conf:Z
|
||||
- ./backend/tls_localhost_key.pem:/root/ssl/key.pem:Z
|
||||
- ./backend/tls_localhost_cert.pem:/root/ssl/cert.pem:Z
|
||||
ports:
|
||||
# HOST_PORT:CONTAINER_PORT
|
||||
- "8008:80"
|
||||
- "4443:443"
|
||||
depends_on:
|
||||
- synapse
|
||||
networks:
|
||||
- ecbackend
|
||||
include:
|
||||
- dev-backend-docker-compose.yml
|
||||
|
||||
190
playwright/fixtures/widget-user.ts
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
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();
|
||||
|
||||
// To get the invite textbox we need to specifically select within the
|
||||
// dialog, since there is another textbox in the background (the message
|
||||
// composer). In theory the composer shouldn't be visible to Playwright at
|
||||
// all because the invite dialog has trapped focus, but the focus trap
|
||||
// doesn't quite work right on Firefox.
|
||||
await ewPage1.getByRole("dialog").getByRole("textbox").fill(whistlerMxId);
|
||||
await ewPage1.getByRole("dialog").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
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
97
playwright/widget/simple-create.spec.ts
Normal 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();
|
||||
});
|
||||
@@ -48,6 +48,14 @@
|
||||
"groupName": "Vaul",
|
||||
"matchDepNames": ["vaul"],
|
||||
"prHeader": "Please review modals on mobile for visual regressions."
|
||||
},
|
||||
{
|
||||
"groupName": "embedded package dependencies",
|
||||
"matchFileNames": ["embedded/**/*"]
|
||||
},
|
||||
{
|
||||
"groupName": "Yarn",
|
||||
"matchDepNames": ["yarn"]
|
||||
}
|
||||
],
|
||||
"semanticCommits": "disabled",
|
||||
|
||||
@@ -4,5 +4,6 @@ set -ex
|
||||
|
||||
export VITE_APP_VERSION=$(git describe --tags --abbrev=0)
|
||||
|
||||
corepack enable
|
||||
yarn install
|
||||
yarn run build
|
||||
|
||||
1
src/@types/global.d.ts
vendored
@@ -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";
|
||||
|
||||
2
src/@types/matrix-js-sdk.d.ts
vendored
@@ -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;
|
||||
}
|
||||
|
||||
37
src/App.tsx
@@ -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";
|
||||
@@ -22,6 +22,7 @@ import { Initializer } from "./initializer";
|
||||
import { MediaDevicesProvider } from "./livekit/MediaDevicesContext";
|
||||
import { widget } from "./widget";
|
||||
import { useTheme } from "./useTheme";
|
||||
import { ProcessorProvider } from "./livekit/TrackProcessorContext";
|
||||
|
||||
const SentryRoute = Sentry.withSentryReactRouterV7Routing(Route);
|
||||
|
||||
@@ -72,22 +73,24 @@ export const App: FC = () => {
|
||||
<Suspense fallback={null}>
|
||||
<ClientProvider>
|
||||
<MediaDevicesProvider>
|
||||
<Sentry.ErrorBoundary
|
||||
fallback={(error) => (
|
||||
<ErrorPage error={error} widget={widget} />
|
||||
)}
|
||||
>
|
||||
<DisconnectedBanner />
|
||||
<Routes>
|
||||
<SentryRoute path="/" element={<HomePage />} />
|
||||
<SentryRoute path="/login" element={<LoginPage />} />
|
||||
<SentryRoute
|
||||
path="/register"
|
||||
element={<RegisterPage />}
|
||||
/>
|
||||
<SentryRoute path="*" element={<RoomPage />} />
|
||||
</Routes>
|
||||
</Sentry.ErrorBoundary>
|
||||
<ProcessorProvider>
|
||||
<Sentry.ErrorBoundary
|
||||
fallback={(error) => (
|
||||
<ErrorPage error={error} widget={widget} />
|
||||
)}
|
||||
>
|
||||
<DisconnectedBanner />
|
||||
<Routes>
|
||||
<SentryRoute path="/" element={<HomePage />} />
|
||||
<SentryRoute path="/login" element={<LoginPage />} />
|
||||
<SentryRoute
|
||||
path="/register"
|
||||
element={<RegisterPage />}
|
||||
/>
|
||||
<SentryRoute path="*" element={<RoomPage />} />
|
||||
</Routes>
|
||||
</Sentry.ErrorBoundary>
|
||||
</ProcessorProvider>
|
||||
</MediaDevicesProvider>
|
||||
</ClientProvider>
|
||||
</Suspense>
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -10,9 +10,8 @@ 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";
|
||||
@@ -296,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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
@@ -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>
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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 {
|
||||
|
||||