diff --git a/.eslintrc.json b/.eslintrc.json index 404abef39a7..3a1c197326d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -64,6 +64,7 @@ "message": "Calling `svgIcon` directly is not allowed", "selector": "CallExpression[callee.name='svgIcon']" } - ] + ], + "curly": ["error", "all"] } } diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index 6c0f000bad8..35d6bf8b2f0 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -386,6 +386,7 @@ jobs: - name: Log out of Docker run: docker logout + crowdin-push: name: Crowdin Push if: github.ref == 'refs/heads/master' diff --git a/.github/workflows/release-web.yml b/.github/workflows/release-web.yml index aae053c35c9..23f99c8f9b3 100644 --- a/.github/workflows/release-web.yml +++ b/.github/workflows/release-web.yml @@ -74,7 +74,7 @@ jobs: azure-creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} azure-keyvault-name: "bitwarden-prod-kv" - - name: Pull latest selfhost image + - name: Pull branch image run: | if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then docker pull bitwarden/web:latest @@ -82,7 +82,7 @@ jobs: docker pull bitwarden/web:$_BRANCH_NAME fi - - name: Docker Tag version and latest image + - name: Docker Tag version run: | if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then docker tag bitwarden/web:latest bitwarden/web:$_RELEASE_VERSION @@ -90,7 +90,7 @@ jobs: docker tag bitwarden/web:$_BRANCH_NAME bitwarden/web:$_RELEASE_VERSION fi - - name: Docker Push version and latest image + - name: Docker Push version if: ${{ github.event.inputs.release_type != 'Dry Run' }} env: DOCKER_CONTENT_TRUST: 1 @@ -112,7 +112,7 @@ jobs: - name: Login to Azure ACR run: az acr login -n bitwardenqa - - name: Tag version and latest + - name: Tag version env: REGISTRY: bitwardenqa.azurecr.io run: | @@ -126,7 +126,7 @@ jobs: docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web-sh:$_RELEASE_VERSION fi - - name: Push version and latest image + - name: Push version if: ${{ github.event.inputs.release_type != 'Dry Run' }} env: REGISTRY: bitwardenqa.azurecr.io diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 36e4157f05b..bb0b4453dfa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,7 +42,16 @@ jobs: - name: Install Node dependencies run: npm ci + # We use isolatedModules: true which disables typechecking in tests + # Tests in apps/ are typechecked when their app is built, so we just do it here for libs/ + # See https://bitwarden.atlassian.net/browse/EC-497 + - name: Run typechecking + run: | + for p in libs/**/tsconfig.spec.json; do + echo "Typechecking $p" + npx tsc --noEmit --project $p + done + - name: Run tests run: | - export NODE_OPTIONS=--max_old_space_size=6144 npm run test diff --git a/apps/browser/gulpfile.js b/apps/browser/gulpfile.js index 29bca0f8954..d54a4826fa6 100644 --- a/apps/browser/gulpfile.js +++ b/apps/browser/gulpfile.js @@ -61,7 +61,6 @@ function distFirefox() { return dist("firefox", (manifest) => { delete manifest.content_security_policy; delete manifest.storage; - removeShortcuts(manifest); return manifest; }); } @@ -70,7 +69,6 @@ function distOpera() { return dist("opera", (manifest) => { delete manifest.applications; delete manifest.content_security_policy; - removeShortcuts(manifest); return manifest; }); } @@ -95,15 +93,6 @@ function distEdge() { }); } -function removeShortcuts(manifest) { - if (manifest.content_scripts && manifest.content_scripts.length > 1) { - const shortcutsScript = manifest.content_scripts[1]; - if (shortcutsScript.js.indexOf("content/shortcuts.js") > -1) { - manifest.content_scripts.splice(1, 1); - } - } -} - function distSafariMas(cb) { return distSafariApp(cb, "mas"); } @@ -212,6 +201,8 @@ function safariCopyBuild(source, dest) { gulpif( "manifest.json", jeditor((manifest) => { + delete manifest.sidebar_action; + delete manifest.commands._execute_sidebar_action; delete manifest.optional_permissions; manifest.permissions.push("nativeMessaging"); return manifest; diff --git a/apps/browser/package.json b/apps/browser/package.json index 1be11430684..0bc496a190a 100644 --- a/apps/browser/package.json +++ b/apps/browser/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/browser", - "version": "2022.8.0", + "version": "2022.9.0", "scripts": { "build": "webpack", "build:mv3": "cross-env MANIFEST_VERSION=3 webpack", diff --git a/apps/browser/src/_locales/ar/messages.json b/apps/browser/src/_locales/ar/messages.json index 600a596cd01..bbcdf2e2b26 100644 --- a/apps/browser/src/_locales/ar/messages.json +++ b/apps/browser/src/_locales/ar/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "لإعادة تعيين الإعدادات المُعدة مسبقاً" + }, + "serverVersion": { + "message": "إصدار الخادم" + }, + "selfHosted": { + "message": "استضافة ذاتية" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/az/messages.json b/apps/browser/src/_locales/az/messages.json index b6c8b93db04..ad0bd40da11 100644 --- a/apps/browser/src/_locales/az/messages.json +++ b/apps/browser/src/_locales/az/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "ön konfiqurasiyalı tənzimləmələri sıfırlamaq üçün" + }, + "serverVersion": { + "message": "Server Versiyası" + }, + "selfHosted": { + "message": "Öz-özünə sahiblik edən" + }, + "thirdParty": { + "message": "Üçüncü tərəf" + }, + "thirdPartyServerMessage": { + "message": "Üçüncü tərəf server tətbiqetməsi ilə bağlantı quruldu, $SERVERNAME$. Zəhmət olmasa rəsmi serveri istifadə edərək xətaları təsdiqləyin və ya onları üçüncü tərəf serverə bildirin.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "son görünmə $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/be/messages.json b/apps/browser/src/_locales/be/messages.json index 8c2d1907aac..b132e0c464a 100644 --- a/apps/browser/src/_locales/be/messages.json +++ b/apps/browser/src/_locales/be/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "для скіду да прадвызначаных наладаў" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/bg/messages.json b/apps/browser/src/_locales/bg/messages.json index f7723538001..7c3f497daba 100644 --- a/apps/browser/src/_locales/bg/messages.json +++ b/apps/browser/src/_locales/bg/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "за да върнете предварително зададените настройки" + }, + "serverVersion": { + "message": "Версия на сървъра" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/bn/messages.json b/apps/browser/src/_locales/bn/messages.json index 7e702fcf3e8..bcfcd5060ce 100644 --- a/apps/browser/src/_locales/bn/messages.json +++ b/apps/browser/src/_locales/bn/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/bs/messages.json b/apps/browser/src/_locales/bs/messages.json index 0bbea26f561..9085037f549 100644 --- a/apps/browser/src/_locales/bs/messages.json +++ b/apps/browser/src/_locales/bs/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/ca/messages.json b/apps/browser/src/_locales/ca/messages.json index 9170b3978f0..f4574ce9c6d 100644 --- a/apps/browser/src/_locales/ca/messages.json +++ b/apps/browser/src/_locales/ca/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "per restablir els paràmetres preconfigurats" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/cs/messages.json b/apps/browser/src/_locales/cs/messages.json index a1d5706e642..8c3df17fe2b 100644 --- a/apps/browser/src/_locales/cs/messages.json +++ b/apps/browser/src/_locales/cs/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/da/messages.json b/apps/browser/src/_locales/da/messages.json index 1476952e07e..7bade191dd1 100644 --- a/apps/browser/src/_locales/da/messages.json +++ b/apps/browser/src/_locales/da/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "for at nulstille til forudkonfigurerede indstillinger" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/de/messages.json b/apps/browser/src/_locales/de/messages.json index fb5c9a6abdc..859b6523592 100644 --- a/apps/browser/src/_locales/de/messages.json +++ b/apps/browser/src/_locales/de/messages.json @@ -38,10 +38,10 @@ "message": "Master-Passwort" }, "masterPassDesc": { - "message": "Das Master-Passwort wird verwendet, um den Tresor zu öffnen. Es ist sehr wichtig, dass du das Passwort nicht vergisst, da es keine Möglichkeit gibt es zurückzusetzen." + "message": "Das Master-Passwort wird verwendet, um den Tresor zu öffnen. Es ist sehr wichtig, dass du das Passwort nicht vergisst, da es keine Möglichkeit gibt dieses zurückzusetzen." }, "masterPassHintDesc": { - "message": "Ein Master-Passwort-Hinweis kann dir helfen, dich an das Passwort zu erinnern, solltest du es vergessen." + "message": "Ein Master-Passwort-Hinweis kann dir helfen, dich an das Passwort zu erinnern, sofern du es vergessen hast." }, "reTypeMasterPass": { "message": "Master-Passwort wiederholen" @@ -146,7 +146,7 @@ "message": "Konto" }, "changeMasterPassword": { - "message": "Masterpasswort ändern" + "message": "Master-Passwort ändern" }, "fingerprintPhrase": { "message": "Prüfschlüssel", @@ -954,7 +954,7 @@ "message": "Die URLs der Umgebung wurden gespeichert." }, "enableAutoFillOnPageLoad": { - "message": "Auto-Ausfüllen beim Seitenladen aktivieren" + "message": "Auto-Ausfüllen beim Laden einer Seite aktivieren" }, "enableAutoFillOnPageLoadDesc": { "message": "Wenn eine Zugangsmaske erkannt wird, füge automatisch die Zugangsdaten ein während die Webseite lädt." @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "um auf vorkonfigurierte Einstellungen zurückzusetzen" + }, + "serverVersion": { + "message": "Server-Version" + }, + "selfHosted": { + "message": "Selbstverwaltet" + }, + "thirdParty": { + "message": "Drittanbieter" + }, + "thirdPartyServerMessage": { + "message": "Verbunden mit Server-Implementierung eines Drittanbieters, $SERVERNAME$. Bitte verifiziere Fehler mit dem offiziellen Server oder melde diese an den Drittanbieter-Server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "zuletzt am $DATE$ gesehen", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/el/messages.json b/apps/browser/src/_locales/el/messages.json index 653988ec120..378c6c28167 100644 --- a/apps/browser/src/_locales/el/messages.json +++ b/apps/browser/src/_locales/el/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "επαναφορά στις προ-ρυθμισμένες ρυθμίσεις" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index f5b3e798aff..a23bfa56501 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/en_GB/messages.json b/apps/browser/src/_locales/en_GB/messages.json index 91e65e5e317..e94a67345ff 100644 --- a/apps/browser/src/_locales/en_GB/messages.json +++ b/apps/browser/src/_locales/en_GB/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/en_IN/messages.json b/apps/browser/src/_locales/en_IN/messages.json index acdde9117c4..ad541380547 100644 --- a/apps/browser/src/_locales/en_IN/messages.json +++ b/apps/browser/src/_locales/en_IN/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/es/messages.json b/apps/browser/src/_locales/es/messages.json index 65183ac1655..b85c00492f2 100644 --- a/apps/browser/src/_locales/es/messages.json +++ b/apps/browser/src/_locales/es/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "para restablecer a los ajustes por defecto" + }, + "serverVersion": { + "message": "Versión del servidor" + }, + "selfHosted": { + "message": "Autoalojado" + }, + "thirdParty": { + "message": "Aplicaciones de terceros" + }, + "thirdPartyServerMessage": { + "message": "Conectado al servidor de terceros, $SERVERNAME$. Por favor, verifica los errores usando el servidor oficial o informe al servidor de terceros.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "visto por última vez el $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/et/messages.json b/apps/browser/src/_locales/et/messages.json index 4b99f7da66b..c4c50d07d69 100644 --- a/apps/browser/src/_locales/et/messages.json +++ b/apps/browser/src/_locales/et/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "et taastada eelseadistatud seaded" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/eu/messages.json b/apps/browser/src/_locales/eu/messages.json index 83677b7140e..619efc76b98 100644 --- a/apps/browser/src/_locales/eu/messages.json +++ b/apps/browser/src/_locales/eu/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "ezarpen lehenetsiak ezartzeko" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/fa/messages.json b/apps/browser/src/_locales/fa/messages.json index cc60dac223d..29cd75ad3f3 100644 --- a/apps/browser/src/_locales/fa/messages.json +++ b/apps/browser/src/_locales/fa/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "برای بازنشانی به تنظیمات از پیش پیکربندی شده" + }, + "serverVersion": { + "message": "نسخه سرور" + }, + "selfHosted": { + "message": "میزبانی خود" + }, + "thirdParty": { + "message": "شخص ثالث" + }, + "thirdPartyServerMessage": { + "message": "به اجرای سرور شخص ثالث، $SERVERNAME$ متصل شد. لطفاً اشکالات را با استفاده از سرور رسمی تأیید کنید یا آنها را به سرور شخص ثالث گزارش دهید.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "آخرین بار در $DATE$ دیده شده است", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/fi/messages.json b/apps/browser/src/_locales/fi/messages.json index b1e0361e082..9235a490046 100644 --- a/apps/browser/src/_locales/fi/messages.json +++ b/apps/browser/src/_locales/fi/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "palauttaaksesi oletusasetukset" + }, + "serverVersion": { + "message": "Palvelimen versio" + }, + "selfHosted": { + "message": "Itse ylläpidetty" + }, + "thirdParty": { + "message": "Ulkopuolinen taho" + }, + "thirdPartyServerMessage": { + "message": "Yhdistetty ulkopuoliseen palvelinympäristöön, $SERVERNAME$. Tarkista virheet virallisella palvelimella tai ilmoita niistä ulkopuolisen palvelimen ylläpidolle.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "nähty viimeksi $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/fil/messages.json b/apps/browser/src/_locales/fil/messages.json index ccf34655e19..acad55e4dc8 100644 --- a/apps/browser/src/_locales/fil/messages.json +++ b/apps/browser/src/_locales/fil/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/fr/messages.json b/apps/browser/src/_locales/fr/messages.json index a04d893f3fb..68b3ca0bb11 100644 --- a/apps/browser/src/_locales/fr/messages.json +++ b/apps/browser/src/_locales/fr/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/he/messages.json b/apps/browser/src/_locales/he/messages.json index b053866ea04..2f368b4fc36 100644 --- a/apps/browser/src/_locales/he/messages.json +++ b/apps/browser/src/_locales/he/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/hi/messages.json b/apps/browser/src/_locales/hi/messages.json index d0b03617407..69e737c73b4 100644 --- a/apps/browser/src/_locales/hi/messages.json +++ b/apps/browser/src/_locales/hi/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/hr/messages.json b/apps/browser/src/_locales/hr/messages.json index 8c73b4c13eb..767b60e70db 100644 --- a/apps/browser/src/_locales/hr/messages.json +++ b/apps/browser/src/_locales/hr/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/hu/messages.json b/apps/browser/src/_locales/hu/messages.json index 6069fcdcb65..78a4bc43e0d 100644 --- a/apps/browser/src/_locales/hu/messages.json +++ b/apps/browser/src/_locales/hu/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "az előre konfigurált beállítások visszaállításához." + }, + "serverVersion": { + "message": "Szerver verzió" + }, + "selfHosted": { + "message": "Saját kiszolgáló" + }, + "thirdParty": { + "message": "Harmadik fél" + }, + "thirdPartyServerMessage": { + "message": "Csatlakozva harmadik féltől származó kiszolgáló implementációhoz: $SERVERNAME$. Ellenőrizzük a hibákat a hivatalos szerver segítségével vagy jelentsük azokat a harmadik fél szerverének.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "utolsó megtekintés: $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/id/messages.json b/apps/browser/src/_locales/id/messages.json index f067df0dc78..af77247d8f3 100644 --- a/apps/browser/src/_locales/id/messages.json +++ b/apps/browser/src/_locales/id/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/it/messages.json b/apps/browser/src/_locales/it/messages.json index d01b13ec3f8..347de759123 100644 --- a/apps/browser/src/_locales/it/messages.json +++ b/apps/browser/src/_locales/it/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "per ritornare alle impostazioni preconfigurate" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/ja/messages.json b/apps/browser/src/_locales/ja/messages.json index 81da03b0904..31e2ec70665 100644 --- a/apps/browser/src/_locales/ja/messages.json +++ b/apps/browser/src/_locales/ja/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "すると初期設定に戻します" + }, + "serverVersion": { + "message": "サーバーのバージョン" + }, + "selfHosted": { + "message": "セルフホスト" + }, + "thirdParty": { + "message": "サードパーティー" + }, + "thirdPartyServerMessage": { + "message": "サードパーティーサーバーの実装である $SERVERNAME$に接続しました。公式サーバーを使用してバグを確認するか、サードパーティサーバーに報告してください。", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "$DATE$ で最後に確認", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/ka/messages.json b/apps/browser/src/_locales/ka/messages.json index 15acccb2591..4352e3cb8ce 100644 --- a/apps/browser/src/_locales/ka/messages.json +++ b/apps/browser/src/_locales/ka/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/km/messages.json b/apps/browser/src/_locales/km/messages.json index 3fd3fe8875d..d329d72a777 100644 --- a/apps/browser/src/_locales/km/messages.json +++ b/apps/browser/src/_locales/km/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/kn/messages.json b/apps/browser/src/_locales/kn/messages.json index 7751a99cb3e..0efa7fbdb3f 100644 --- a/apps/browser/src/_locales/kn/messages.json +++ b/apps/browser/src/_locales/kn/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/ko/messages.json b/apps/browser/src/_locales/ko/messages.json index 597484c5a28..ea449c6cc97 100644 --- a/apps/browser/src/_locales/ko/messages.json +++ b/apps/browser/src/_locales/ko/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/lt/messages.json b/apps/browser/src/_locales/lt/messages.json index 5c154c2489b..9718609b743 100644 --- a/apps/browser/src/_locales/lt/messages.json +++ b/apps/browser/src/_locales/lt/messages.json @@ -53,13 +53,13 @@ "message": "Skirtukas" }, "vault": { - "message": "Vault" + "message": "Saugykla" }, "myVault": { "message": "Saugykla" }, "allVaults": { - "message": "All Vaults" + "message": "Visos saugyklos" }, "tools": { "message": "Įrankiai" @@ -101,10 +101,10 @@ "message": "Nėra atitinkančių prisijungimų." }, "unlockVaultMenu": { - "message": "Unlock your vault" + "message": "Atrakinti saugyklą" }, "loginToVaultMenu": { - "message": "Log in to your vault" + "message": "Prisijungti prie saugyklos" }, "autoFillInfo": { "message": "Nėra galimų prisijungimų prie dabartinio naršyklės skirtuko." @@ -236,16 +236,16 @@ "message": "Ilgis" }, "uppercase": { - "message": "Uppercase (A-Z)" + "message": "Didžiosiomis (A-Z)" }, "lowercase": { - "message": "Lowercase (a-z)" + "message": "Mažosiomis (a-z)" }, "numbers": { - "message": "Numbers (0-9)" + "message": "Skaitmuo (0-9)" }, "specialCharacters": { - "message": "Special Characters (!@#$%^&*)" + "message": "Specialieji simboliai (!@#$%^&*)" }, "numWords": { "message": "Žodžių skaičius" @@ -339,7 +339,7 @@ "message": "Jūsų žiniatinklio naršyklė nepalaiko automatinio kopijavimo. Vietoj to nukopijuokite rankiniu būdu." }, "verifyIdentity": { - "message": "Verify Identity" + "message": "Patvirtinti tapatybę" }, "yourVaultIsLocked": { "message": "Jūsų saugykla užrakinta. Norėdami tęsti, patikrinkite pagrindinį slaptažodį." @@ -424,13 +424,13 @@ "message": "Klaidingas el. pašto adresas." }, "masterPasswordRequired": { - "message": "Master password is required." + "message": "Būtinas pagrindinis slaptažodis." }, "confirmMasterPasswordRequired": { - "message": "Master password retype is required." + "message": "Būtinas prisijungimo slaptažodžio patvirtinimas." }, "masterPasswordMinlength": { - "message": "Master password must be at least 8 characters long." + "message": "Pagrindinis slaptažodis turi būti bent 8 simbolių ilgio." }, "masterPassDoesntMatch": { "message": "Pagrindinio slaptažodžio patvirtinimas nesutampa." @@ -571,7 +571,7 @@ "description": "This is the folder for uncategorized items" }, "enableAddLoginNotification": { - "message": "Ask to add login" + "message": "Prašyti pridėti prisijungimą" }, "addLoginNotificationDesc": { "message": "Prisijungimo pridėjimo pranešimas automatiškai Jūs paragina išsaugoti naujus prisijungimus Jūsų saugykloje, kuomet prisijungiate pirmą kartą." @@ -668,7 +668,7 @@ "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." }, "exportMasterPassword": { - "message": "Enter your master password to export your vault data." + "message": "Įveskite pagrindinį slaptažodį norint išsinešti saugyklos duomenis." }, "shared": { "message": "Pasidalinti" @@ -702,67 +702,67 @@ "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." }, "learnMore": { - "message": "Learn more" + "message": "Sužinoti daugiau" }, "authenticatorKeyTotp": { - "message": "Authenticator Key (TOTP)" + "message": "Vienkartinio autentifikavimo raktas (TOTP)" }, "verificationCodeTotp": { - "message": "Verification Code (TOTP)" + "message": "Patvirtinimo kodas (TOTP)" }, "copyVerificationCode": { - "message": "Copy Verification Code" + "message": "Kopijuoti patvirtinimo kodą" }, "attachments": { - "message": "Attachments" + "message": "Priedai" }, "deleteAttachment": { - "message": "Delete attachment" + "message": "Ištrinti priedą" }, "deleteAttachmentConfirmation": { - "message": "Are you sure you want to delete this attachment?" + "message": "Ar esate tikri, kad norite ištrinti šį priedą?" }, "deletedAttachment": { - "message": "Deleted attachment" + "message": "Ištrintas priedas" }, "newAttachment": { - "message": "Add New Attachment" + "message": "Pridėti naują priedą" }, "noAttachments": { - "message": "No attachments." + "message": "Priedų nėra." }, "attachmentSaved": { - "message": "The attachment has been saved." + "message": "Priedas buvo išsaugotas." }, "file": { - "message": "File" + "message": "Failas" }, "selectFile": { - "message": "Select a file." + "message": "Pasirinkite failą." }, "maxFileSize": { - "message": "Maximum file size is 500 MB." + "message": "Failai negali būti didesni už 500 MB." }, "featureUnavailable": { - "message": "Feature Unavailable" + "message": "Funkcija neprieinama" }, "updateKey": { - "message": "You cannot use this feature until you update your encryption key." + "message": "Negalite naudoti šios funkcijos, kol neatnaujinsite šifravimo raktą." }, "premiumMembership": { - "message": "Premium membership" + "message": "Premium narystė" }, "premiumManage": { - "message": "Manage Membership" + "message": "Tvarkyti narystę" }, "premiumManageAlert": { - "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + "message": "Galite tvarkyti savo narystę internete per bitwarden.com. Ar norite aplankyti šį puslapį dabar?" }, "premiumRefresh": { - "message": "Refresh Membership" + "message": "Atnaujinti narystę" }, "premiumNotCurrentMember": { - "message": "You are not currently a premium member." + "message": "Neturite Premium narystės." }, "premiumSignUpAndGet": { "message": "Sign up for a premium membership and get:" @@ -795,10 +795,10 @@ "message": "You are a premium member!" }, "premiumCurrentMemberThanks": { - "message": "Thank you for supporting Bitwarden." + "message": "Dėkojame, kad remiate Bitwarden." }, "premiumPrice": { - "message": "All for just $PRICE$ /year!", + "message": "Visa tai tik už $PRICE$ / metus!", "placeholders": { "price": { "content": "$1", @@ -810,7 +810,7 @@ "message": "Atnaujinimas įvykdytas" }, "enableAutoTotpCopy": { - "message": "Copy TOTP automatically" + "message": "Kopijuoti vienkartinį kodą (TOTP) automatiškai" }, "disableAutoTotpCopyDesc": { "message": "If a login has an authenticator key, copy the TOTP verification code to your clip-board when you auto-fill the login." @@ -819,10 +819,10 @@ "message": "Ask for biometrics on launch" }, "premiumRequired": { - "message": "Premium Required" + "message": "Tik su Premium naryste" }, "premiumRequiredDesc": { - "message": "A premium membership is required to use this feature." + "message": "Premium narystė reikalinga šiai funkcijai naudoti." }, "enterVerificationCodeApp": { "message": "Enter the 6 digit verification code from your authenticator app." @@ -888,7 +888,7 @@ "message": "Recovery Code" }, "authenticatorAppTitle": { - "message": "Authenticator App" + "message": "Autentifikavimo programa" }, "authenticatorAppDesc": { "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", @@ -936,7 +936,7 @@ "message": "Serverio URL" }, "apiUrl": { - "message": "API Server URL" + "message": "API serverio nuoroda" }, "webVaultUrl": { "message": "Web Vault Server URL" @@ -954,7 +954,7 @@ "message": "The environment URLs have been saved." }, "enableAutoFillOnPageLoad": { - "message": "Auto-fill on page load" + "message": "Automatiškai užpildyti užsikrovus puslapiui" }, "enableAutoFillOnPageLoadDesc": { "message": "If a login form is detected, auto-fill when the web page loads." @@ -993,7 +993,7 @@ "message": "Generate and copy a new random password to the clipboard" }, "commandLockVaultDesc": { - "message": "Lock the vault" + "message": "Užrakinti saugyklą" }, "privateModeWarning": { "message": "Private mode support is experimental and some features are limited." @@ -1008,22 +1008,22 @@ "message": "Value" }, "newCustomField": { - "message": "New Custom Field" + "message": "Naujas pasirinktis laukelis" }, "dragToSort": { "message": "Drag to sort" }, "cfTypeText": { - "message": "Text" + "message": "Tekstas" }, "cfTypeHidden": { - "message": "Hidden" + "message": "Paslėpta" }, "cfTypeBoolean": { - "message": "Boolean" + "message": "Taip/Ne" }, "cfTypeLinked": { - "message": "Linked", + "message": "Susieta", "description": "This describes a field that is 'linked' (tied) to another field." }, "linkedValue": { @@ -1037,7 +1037,7 @@ "message": "This browser cannot process U2F requests in this popup window. Do you want to open this popup in a new window so that you can log in using U2F?" }, "enableFavicon": { - "message": "Show website icons" + "message": "Rodyti tinklalapių ikonėles" }, "faviconDesc": { "message": "Show a recognizable image next to each login." @@ -1049,7 +1049,7 @@ "message": "Indicate how many logins you have for the current web page." }, "cardholderName": { - "message": "Cardholder Name" + "message": "Mokėjimo kortelės savininko vardas" }, "number": { "message": "Number" @@ -1073,43 +1073,43 @@ "message": "February" }, "march": { - "message": "March" + "message": "Kovas" }, "april": { - "message": "April" + "message": "Balandis" }, "may": { - "message": "May" + "message": "Gegužė" }, "june": { - "message": "June" + "message": "Birželis" }, "july": { - "message": "July" + "message": "Liepa" }, "august": { - "message": "August" + "message": "Rugpjūtis" }, "september": { - "message": "September" + "message": "Rugsėjis" }, "october": { - "message": "October" + "message": "Spalis" }, "november": { - "message": "November" + "message": "Lapkritis" }, "december": { - "message": "December" + "message": "Gruodis" }, "securityCode": { - "message": "Security Code" + "message": "Apsaugos kodas" }, "ex": { - "message": "ex." + "message": "pvz." }, "title": { - "message": "Title" + "message": "Pavadinimas" }, "mr": { "message": "Mr" @@ -1124,103 +1124,103 @@ "message": "Dr" }, "firstName": { - "message": "First Name" + "message": "Vardas" }, "middleName": { - "message": "Middle Name" + "message": "Antras vardas" }, "lastName": { - "message": "Last Name" + "message": "Pavardė" }, "fullName": { - "message": "Full Name" + "message": "Vardas ir pavardė" }, "identityName": { - "message": "Identity Name" + "message": "Tapatybės vardas" }, "company": { - "message": "Company" + "message": "Įmonė" }, "ssn": { - "message": "Social Security Number" + "message": "ID kortelės numeris" }, "passportNumber": { - "message": "Passport Number" + "message": "Paso numeris" }, "licenseNumber": { - "message": "License Number" + "message": "Licencijos numeris" }, "email": { - "message": "Email" + "message": "El. paštas" }, "phone": { - "message": "Phone" + "message": "Telefonas" }, "address": { - "message": "Address" + "message": "Adresas" }, "address1": { - "message": "Address 1" + "message": "Adresas 1" }, "address2": { - "message": "Address 2" + "message": "Adresas 2" }, "address3": { - "message": "Address 3" + "message": "Adresas 3" }, "cityTown": { - "message": "City / Town" + "message": "Miestas" }, "stateProvince": { - "message": "State / Province" + "message": "Rajonas/apskritis" }, "zipPostalCode": { - "message": "Zip / Postal Code" + "message": "Pašto kodas" }, "country": { - "message": "Country" + "message": "Šalis" }, "type": { - "message": "Type" + "message": "Tipas" }, "typeLogin": { - "message": "Login" + "message": "Prisijungimas" }, "typeLogins": { - "message": "Logins" + "message": "Prisijungimai" }, "typeSecureNote": { - "message": "Secure Note" + "message": "Saugus įrašas" }, "typeCard": { - "message": "Card" + "message": "Kortelė" }, "typeIdentity": { - "message": "Identity" + "message": "Tapatybė" }, "passwordHistory": { - "message": "Password History" + "message": "Slaptažodžio istorija" }, "back": { - "message": "Back" + "message": "Atgal" }, "collections": { - "message": "Collections" + "message": "Kolekcijos" }, "favorites": { - "message": "Favorites" + "message": "Mėgstamiausi" }, "popOutNewWindow": { - "message": "Pop out to a new window" + "message": "Atverti naujame lange" }, "refresh": { - "message": "Refresh" + "message": "Atnaujinti" }, "cards": { - "message": "Cards" + "message": "Kortelės" }, "identities": { - "message": "Identities" + "message": "Tapatybės" }, "logins": { "message": "Logins" @@ -1343,7 +1343,7 @@ "description": "ex. A weak password. Scale: Weak -> Good -> Strong" }, "weakMasterPassword": { - "message": "Weak Master Password" + "message": "Silpnas pagrindinis slaptažodis" }, "weakMasterPasswordDesc": { "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" @@ -1392,24 +1392,24 @@ "message": "Vault timeout action" }, "lock": { - "message": "Lock", + "message": "Užrakinti", "description": "Verb form: to make secure or inaccesible by" }, "trash": { - "message": "Trash", + "message": "Šiukšliadėžė", "description": "Noun: a special folder to hold deleted items" }, "searchTrash": { - "message": "Search trash" + "message": "Ieškoti šiukšliadėžėje" }, "permanentlyDeleteItem": { - "message": "Permanently Delete Item" + "message": "Ištrinti visam laikui" }, "permanentlyDeleteItemConfirmation": { - "message": "Are you sure you want to permanently delete this item?" + "message": "Ar tai tikrai norite visam laikui ištrinti?" }, "permanentlyDeletedItem": { - "message": "Permanently Deleted item" + "message": "Ištrintas visam laikui" }, "restoreItem": { "message": "Restore Item" @@ -1427,7 +1427,7 @@ "message": "Timeout Action Confirmation" }, "autoFillAndSave": { - "message": "Auto-fill and Save" + "message": "Automatiškai užpildyti ir išsaugoti" }, "autoFillSuccessAndSavedUri": { "message": "Auto-filled Item and Saved URI" @@ -1436,7 +1436,7 @@ "message": "Auto-filled Item" }, "setMasterPassword": { - "message": "Set Master Password" + "message": "Pagrindinio slaptažodžio nustatymas" }, "masterPasswordPolicyInEffect": { "message": "One or more organization policies require your master password to meet the following requirements:" @@ -1487,16 +1487,16 @@ "message": "Terms of Service and Privacy Policy have not been acknowledged." }, "termsOfService": { - "message": "Terms of Service" + "message": "Paslaugų teikimo paslaugos" }, "privacyPolicy": { - "message": "Privacy Policy" + "message": "Privatumo politika" }, "hintEqualsPassword": { "message": "Your password hint cannot be the same as your password." }, "ok": { - "message": "Ok" + "message": "Gerai" }, "desktopSyncVerificationTitle": { "message": "Desktop sync verification" @@ -1541,13 +1541,13 @@ "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." }, "biometricsNotSupportedTitle": { - "message": "Biometrics not supported" + "message": "Biometrika negali būti naudojama" }, "biometricsNotSupportedDesc": { - "message": "Browser biometrics is not supported on this device." + "message": "Šiame įrenginyje biometrikos negalima naudoti." }, "nativeMessaginPermissionErrorTitle": { - "message": "Permission not provided" + "message": "Nesuteiktos teisės" }, "nativeMessaginPermissionErrorDesc": { "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." @@ -1795,13 +1795,13 @@ "message": "One or more organization policies are affecting your Send options." }, "passwordPrompt": { - "message": "Master password re-prompt" + "message": "Iš naujo prašoma pagrindinio slaptažodžio" }, "passwordConfirmation": { - "message": "Master password confirmation" + "message": "Pagrindinio slaptažodžio patvirtinimas" }, "passwordConfirmationDesc": { - "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + "message": "Negalite šio veiksmo padaryti neįvedus savo pagrindinio slaptažodžio ir patvirtinę tapatybę." }, "emailVerificationRequired": { "message": "Email Verification Required" @@ -1810,7 +1810,7 @@ "message": "You must verify your email to use this feature. You can verify your email in the web vault." }, "updatedMasterPassword": { - "message": "Updated Master Password" + "message": "Naujasis pagrindinis slaptažodis" }, "updateMasterPassword": { "message": "Update Master Password" @@ -1877,7 +1877,7 @@ "message": "Leave Organization" }, "removeMasterPassword": { - "message": "Remove Master Password" + "message": "Ištrinti pagrindinį slaptažodį" }, "removedMasterPassword": { "message": "Master password removed." @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/lv/messages.json b/apps/browser/src/_locales/lv/messages.json index 7bc2f416ad3..63a46fb97dd 100644 --- a/apps/browser/src/_locales/lv/messages.json +++ b/apps/browser/src/_locales/lv/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "lai atiestatītu pirmsuzstādītos iestatījumus" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/ml/messages.json b/apps/browser/src/_locales/ml/messages.json index 76447ecbd36..c22e6b62c5f 100644 --- a/apps/browser/src/_locales/ml/messages.json +++ b/apps/browser/src/_locales/ml/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/nb/messages.json b/apps/browser/src/_locales/nb/messages.json index 52385e651b6..bd1c5022a2f 100644 --- a/apps/browser/src/_locales/nb/messages.json +++ b/apps/browser/src/_locales/nb/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/nl/messages.json b/apps/browser/src/_locales/nl/messages.json index b51c3ea81ca..48082e1ded5 100644 --- a/apps/browser/src/_locales/nl/messages.json +++ b/apps/browser/src/_locales/nl/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "om terug te gaan naar vooraf geconfigureerde instellingen" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/nn/messages.json b/apps/browser/src/_locales/nn/messages.json index 3fd3fe8875d..d329d72a777 100644 --- a/apps/browser/src/_locales/nn/messages.json +++ b/apps/browser/src/_locales/nn/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/pl/messages.json b/apps/browser/src/_locales/pl/messages.json index dff14b6fbb1..e6a0203e424 100644 --- a/apps/browser/src/_locales/pl/messages.json +++ b/apps/browser/src/_locales/pl/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "aby zresetować do wstępnie skonfigurowanych ustawień" + }, + "serverVersion": { + "message": "Wersja serwera" + }, + "selfHosted": { + "message": "Samodzielnie hostowany" + }, + "thirdParty": { + "message": "Innego dostawcy" + }, + "thirdPartyServerMessage": { + "message": "Połączono z implementacją serwera innego dostawcy, $SERVERNAME$. Zweryfikuj błędy za pomocą oficjalnego serwera lub zgłoś je serwerowi innego dostawcy.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "ostatnio widziano $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/pt_BR/messages.json b/apps/browser/src/_locales/pt_BR/messages.json index c26f8e59f79..a81faf65245 100644 --- a/apps/browser/src/_locales/pt_BR/messages.json +++ b/apps/browser/src/_locales/pt_BR/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/pt_PT/messages.json b/apps/browser/src/_locales/pt_PT/messages.json index 98385fcbeaf..d803ba85428 100644 --- a/apps/browser/src/_locales/pt_PT/messages.json +++ b/apps/browser/src/_locales/pt_PT/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "para voltar às definições predefinidas" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/ro/messages.json b/apps/browser/src/_locales/ro/messages.json index f467a240202..60b2d1adf85 100644 --- a/apps/browser/src/_locales/ro/messages.json +++ b/apps/browser/src/_locales/ro/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "pentru a restabili setările preconfigurate" + }, + "serverVersion": { + "message": "Versiune server" + }, + "selfHosted": { + "message": "Auto-găzduit" + }, + "thirdParty": { + "message": "Parte terță" + }, + "thirdPartyServerMessage": { + "message": "Conectat la implementarea serverului terță parte, $SERVERNAME$. Verificați erorile folosind serverul oficial sau raportați-le serverului terț.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "văzut ultima dată la $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/ru/messages.json b/apps/browser/src/_locales/ru/messages.json index 9178bc577dc..53814e19891 100644 --- a/apps/browser/src/_locales/ru/messages.json +++ b/apps/browser/src/_locales/ru/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "для сброса к предварительно настроенным параметрам" + }, + "serverVersion": { + "message": "Версия сервера" + }, + "selfHosted": { + "message": "Собственный хостинг" + }, + "thirdParty": { + "message": "Сторонний" + }, + "thirdPartyServerMessage": { + "message": "Подключено к стороннему серверу, $SERVERNAME$. Пожалуйста, проверяйте ошибки, используя официальный сервер, или сообщайте о них на сторонний сервер.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "был $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/si/messages.json b/apps/browser/src/_locales/si/messages.json index 5b5ae9544e0..a6d371bdc4f 100644 --- a/apps/browser/src/_locales/si/messages.json +++ b/apps/browser/src/_locales/si/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/sk/messages.json b/apps/browser/src/_locales/sk/messages.json index 5601fb90a4f..e699eaf3ffd 100644 --- a/apps/browser/src/_locales/sk/messages.json +++ b/apps/browser/src/_locales/sk/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "na obnovenie predvolených nastavení" + }, + "serverVersion": { + "message": "Verzia servera" + }, + "selfHosted": { + "message": "Vlastný hosting" + }, + "thirdParty": { + "message": "Tretia strana" + }, + "thirdPartyServerMessage": { + "message": "Pripojené na server $SERVERNAME$ implementovaný treťou stranou. Prosím overte chyby použitím oficiálneho servera, alebo nahláste problém tretej strane.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "naposledy videné $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/sl/messages.json b/apps/browser/src/_locales/sl/messages.json index 36b52f9dc4f..e781475dd90 100644 --- a/apps/browser/src/_locales/sl/messages.json +++ b/apps/browser/src/_locales/sl/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/sr/messages.json b/apps/browser/src/_locales/sr/messages.json index 183c5503ef2..b2b6ca8c7aa 100644 --- a/apps/browser/src/_locales/sr/messages.json +++ b/apps/browser/src/_locales/sr/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "за рисетовање на подразумевана подешавања" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/sv/messages.json b/apps/browser/src/_locales/sv/messages.json index 69a32d73d7f..a2a23c4a761 100644 --- a/apps/browser/src/_locales/sv/messages.json +++ b/apps/browser/src/_locales/sv/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "för att återställa till förkonfigurerade inställningar" + }, + "serverVersion": { + "message": "Serverversion" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Tredje part" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "sågs senast den $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/th/messages.json b/apps/browser/src/_locales/th/messages.json index 26c07d9168b..28d94140a26 100644 --- a/apps/browser/src/_locales/th/messages.json +++ b/apps/browser/src/_locales/th/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "to reset to pre-configured settings" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/tr/messages.json b/apps/browser/src/_locales/tr/messages.json index eaf967c9c5c..be7bbefb8dd 100644 --- a/apps/browser/src/_locales/tr/messages.json +++ b/apps/browser/src/_locales/tr/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "ön tanımlı ayarları sıfırlayabilirsiniz" + }, + "serverVersion": { + "message": "Sunucu Sürümü" + }, + "selfHosted": { + "message": "Barındırılan" + }, + "thirdParty": { + "message": "Üçüncü Taraf" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "son görüldüğü tarih: $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/uk/messages.json b/apps/browser/src/_locales/uk/messages.json index 5048d64028c..ce1660dd759 100644 --- a/apps/browser/src/_locales/uk/messages.json +++ b/apps/browser/src/_locales/uk/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "щоб скинути налаштування" + }, + "serverVersion": { + "message": "Версія сервера" + }, + "selfHosted": { + "message": "Власне розміщення" + }, + "thirdParty": { + "message": "Сторонній" + }, + "thirdPartyServerMessage": { + "message": "Під'єднано до стороннього сервера $SERVERNAME$. Будь ласка, перевірте помилки з використанням офіційного сервера, або повідомте про них сторонньому серверу.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "востаннє відвідано $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/vi/messages.json b/apps/browser/src/_locales/vi/messages.json index 9a96d69fcd3..dc471e9c7fe 100644 --- a/apps/browser/src/_locales/vi/messages.json +++ b/apps/browser/src/_locales/vi/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "để đặt lại cài đặt đã thiết đặt từ trước" + }, + "serverVersion": { + "message": "Server Version" + }, + "selfHosted": { + "message": "Self-Hosted" + }, + "thirdParty": { + "message": "Third-Party" + }, + "thirdPartyServerMessage": { + "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "last seen on $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/zh_CN/messages.json b/apps/browser/src/_locales/zh_CN/messages.json index 7590de95e87..40731c89ccb 100644 --- a/apps/browser/src/_locales/zh_CN/messages.json +++ b/apps/browser/src/_locales/zh_CN/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "重置为预设设置" + }, + "serverVersion": { + "message": "服务器版本" + }, + "selfHosted": { + "message": "自托管" + }, + "thirdParty": { + "message": "第三方" + }, + "thirdPartyServerMessage": { + "message": "已连接到第三方服务器,$SERVERNAME$。请使用官方服务器验证错误,或将其报告给第三方服务器。", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "最后上线于 $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/_locales/zh_TW/messages.json b/apps/browser/src/_locales/zh_TW/messages.json index 053d38cd58e..0f78713b417 100644 --- a/apps/browser/src/_locales/zh_TW/messages.json +++ b/apps/browser/src/_locales/zh_TW/messages.json @@ -1997,5 +1997,32 @@ }, "environmentEditedReset": { "message": "重設為預設設定" + }, + "serverVersion": { + "message": "伺服器版本" + }, + "selfHosted": { + "message": "自我裝載" + }, + "thirdParty": { + "message": "第三方" + }, + "thirdPartyServerMessage": { + "message": "已連線至第三方伺服器實作,$SERVERNAME$。 請使用官方伺服器驗證錯誤,或將其報告給第三方伺服器。", + "placeholders": { + "servername": { + "content": "$1", + "example": "ThirdPartyServerName" + } + } + }, + "lastSeenOn": { + "message": "最後上線於 $DATE$", + "placeholders": { + "date": { + "content": "$1", + "example": "Jun 15, 2015" + } + } } } diff --git a/apps/browser/src/background/commands.background.ts b/apps/browser/src/background/commands.background.ts index 05a83c8eb54..7303d790ec9 100644 --- a/apps/browser/src/background/commands.background.ts +++ b/apps/browser/src/background/commands.background.ts @@ -34,14 +34,10 @@ export default class CommandsBackground { msg.data.commandToRetry.sender ); } - - if (this.isVivaldi && msg.command === "keyboardShortcutTriggered" && msg.shortcut) { - await this.processCommand(msg.shortcut, sender); - } } ); - if (!this.isVivaldi && chrome && chrome.commands) { + if (chrome && chrome.commands) { chrome.commands.onCommand.addListener(async (command: string) => { await this.processCommand(command); }); diff --git a/apps/browser/src/content/message_handler.ts b/apps/browser/src/content/message_handler.ts index 2e90038673f..0f690bd4f79 100644 --- a/apps/browser/src/content/message_handler.ts +++ b/apps/browser/src/content/message_handler.ts @@ -1,7 +1,9 @@ window.addEventListener( "message", (event) => { - if (event.source !== window) return; + if (event.source !== window) { + return; + } if (event.data.command && event.data.command === "authResult") { chrome.runtime.sendMessage({ diff --git a/apps/browser/src/content/shortcuts.ts b/apps/browser/src/content/shortcuts.ts deleted file mode 100644 index 48326440826..00000000000 --- a/apps/browser/src/content/shortcuts.ts +++ /dev/null @@ -1,52 +0,0 @@ -import * as Mousetrap from "mousetrap"; - -document.addEventListener("DOMContentLoaded", (event) => { - const isSafari = - typeof safari !== "undefined" && - navigator.userAgent.indexOf(" Safari/") !== -1 && - navigator.userAgent.indexOf("Chrome") === -1; - const isVivaldi = !isSafari && navigator.userAgent.indexOf(" Vivaldi/") !== -1; - - if (!isSafari && !isVivaldi) { - return; - } - - if (isSafari && (window as any).__bitwardenFrameId == null) { - (window as any).__bitwardenFrameId = Math.floor(Math.random() * Math.floor(99999999)); - } - - Mousetrap.prototype.stopCallback = () => { - return false; - }; - - let autofillCommand = ["mod+shift+l"]; - if (isSafari) { - autofillCommand = ["mod+\\", "mod+8", "mod+shift+p"]; - } - Mousetrap.bind(autofillCommand, () => { - sendMessage("autofill_login"); - }); - - if (isSafari) { - Mousetrap.bind("mod+shift+y", () => { - sendMessage("open_popup"); - }); - - Mousetrap.bind("mod+shift+s", () => { - sendMessage("lock_vault"); - }); - } else { - Mousetrap.bind("mod+shift+9", () => { - sendMessage("generate_password"); - }); - } - - function sendMessage(shortcut: string) { - const msg: any = { - command: "keyboardShortcutTriggered", - shortcut: shortcut, - }; - - chrome.runtime.sendMessage(msg); - } -}); diff --git a/apps/browser/src/listeners/onCommandListener.ts b/apps/browser/src/listeners/onCommandListener.ts index 3abcd69e807..2a33e91e578 100644 --- a/apps/browser/src/listeners/onCommandListener.ts +++ b/apps/browser/src/listeners/onCommandListener.ts @@ -5,7 +5,7 @@ import { AuthService } from "@bitwarden/common/services/auth.service"; import { CipherService } from "@bitwarden/common/services/cipher.service"; import { ConsoleLogService } from "@bitwarden/common/services/consoleLog.service"; import { EncryptService } from "@bitwarden/common/services/encrypt.service"; -import NoOpEventService from "@bitwarden/common/services/noOpEvent.service"; +import { NoopEventService } from "@bitwarden/common/services/noopEvent.service"; import { SearchService } from "@bitwarden/common/services/search.service"; import { SettingsService } from "@bitwarden/common/services/settings.service"; import { StateMigrationService } from "@bitwarden/common/services/stateMigration.service"; @@ -102,7 +102,7 @@ const doAutoFillLogin = async (tab: chrome.tabs.Tab): Promise => { searchService = new SearchService(cipherService, logService, i18nService); // TODO: Remove this before we encourage anyone to start using this - const eventService = new NoOpEventService(); + const eventService = new NoopEventService(); const autofillService = new AutofillService( cipherService, diff --git a/apps/browser/src/manifest.json b/apps/browser/src/manifest.json index 5bad5737fce..9d0b491481c 100644 --- a/apps/browser/src/manifest.json +++ b/apps/browser/src/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "__MSG_extName__", "short_name": "__MSG_appName__", - "version": "2022.8.0", + "version": "2022.9.0", "description": "__MSG_extDesc__", "default_locale": "en", "author": "Bitwarden Inc.", @@ -26,12 +26,6 @@ "matches": ["http://*/*", "https://*/*", "file:///*"], "run_at": "document_start" }, - { - "all_frames": false, - "js": ["content/shortcuts.js"], - "matches": ["http://*/*", "https://*/*", "file:///*"], - "run_at": "document_start" - }, { "all_frames": false, "js": ["content/message_handler.js"], diff --git a/apps/browser/src/manifest.v3.json b/apps/browser/src/manifest.v3.json index 8004f199791..509fe467c65 100644 --- a/apps/browser/src/manifest.v3.json +++ b/apps/browser/src/manifest.v3.json @@ -3,7 +3,7 @@ "minimum_chrome_version": "102.0", "name": "__MSG_extName__", "short_name": "__MSG_appName__", - "version": "2022.8.0", + "version": "2022.9.0", "description": "__MSG_extDesc__", "default_locale": "en", "author": "Bitwarden Inc.", @@ -27,12 +27,6 @@ "matches": ["http://*/*", "https://*/*", "file:///*"], "run_at": "document_start" }, - { - "all_frames": false, - "js": ["content/shortcuts.js"], - "matches": ["http://*/*", "https://*/*", "file:///*"], - "run_at": "document_start" - }, { "all_frames": false, "js": ["content/message_handler.js"], diff --git a/apps/browser/src/popup/app.module.ts b/apps/browser/src/popup/app.module.ts index af1e78fc59e..473ffb33a98 100644 --- a/apps/browser/src/popup/app.module.ts +++ b/apps/browser/src/popup/app.module.ts @@ -94,6 +94,7 @@ import { SendAddEditComponent } from "./send/send-add-edit.component"; import { SendGroupingsComponent } from "./send/send-groupings.component"; import { SendTypeComponent } from "./send/send-type.component"; import { ServicesModule } from "./services/services.module"; +import { AboutComponent } from "./settings/about.component"; import { ExcludedDomainsComponent } from "./settings/excluded-domains.component"; import { ExportComponent } from "./settings/export.component"; import { FolderAddEditComponent } from "./settings/folder-add-edit.component"; @@ -242,6 +243,7 @@ registerLocaleData(localeZhTw, "zh-TW"); ViewCustomFieldsComponent, RemovePasswordComponent, VaultSelectComponent, + AboutComponent, ], providers: [CurrencyPipe, DatePipe], bootstrap: [AppComponent], diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index c070db6087a..87c1dd17e93 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -2,11 +2,8 @@ import { APP_INITIALIZER, LOCALE_ID, NgModule } from "@angular/core"; import { LockGuard as BaseLockGuardService } from "@bitwarden/angular/guards/lock.guard"; import { UnauthGuard as BaseUnauthGuardService } from "@bitwarden/angular/guards/unauth.guard"; -import { - JslibServicesModule, - MEMORY_STORAGE, - SECURE_STORAGE, -} from "@bitwarden/angular/services/jslib-services.module"; +import { MEMORY_STORAGE, SECURE_STORAGE } from "@bitwarden/angular/services/injection-tokens"; +import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module"; import { ThemingService } from "@bitwarden/angular/services/theming/theming.service"; import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; diff --git a/apps/browser/src/popup/settings/about.component.html b/apps/browser/src/popup/settings/about.component.html new file mode 100644 index 00000000000..ed2ceb40bec --- /dev/null +++ b/apps/browser/src/popup/settings/about.component.html @@ -0,0 +1,52 @@ + diff --git a/apps/browser/src/popup/settings/about.component.ts b/apps/browser/src/popup/settings/about.component.ts new file mode 100644 index 00000000000..338a00e2685 --- /dev/null +++ b/apps/browser/src/popup/settings/about.component.ts @@ -0,0 +1,25 @@ +import { Component } from "@angular/core"; +import { Observable } from "rxjs"; + +import { ConfigServiceAbstraction } from "@bitwarden/common/abstractions/config/config.service.abstraction"; +import { ServerConfig } from "@bitwarden/common/abstractions/config/server-config"; +import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; + +import { BrowserApi } from "../../browser/browserApi"; + +@Component({ + selector: "app-about", + templateUrl: "about.component.html", +}) +export class AboutComponent { + serverConfig$: Observable; + + year = new Date().getFullYear(); + version = BrowserApi.getApplicationVersion(); + isCloud: boolean; + + constructor(configService: ConfigServiceAbstraction, environmentService: EnvironmentService) { + this.serverConfig$ = configService.serverConfig$; + this.isCloud = environmentService.isCloud(); + } +} diff --git a/apps/browser/src/popup/settings/settings.component.ts b/apps/browser/src/popup/settings/settings.component.ts index 029812ba49b..9728ff2a5de 100644 --- a/apps/browser/src/popup/settings/settings.component.ts +++ b/apps/browser/src/popup/settings/settings.component.ts @@ -20,6 +20,8 @@ import { BiometricErrors, BiometricErrorTypes } from "../../models/biometricErro import { SetPinComponent } from "../components/set-pin.component"; import { PopupUtilsService } from "../services/popup-utils.service"; +import { AboutComponent } from "./about.component"; + const RateUrls = { [DeviceType.ChromeExtension]: "https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews", @@ -377,26 +379,7 @@ export class SettingsComponent implements OnInit { } about() { - const year = new Date().getFullYear(); - const versionText = document.createTextNode( - this.i18nService.t("version") + ": " + BrowserApi.getApplicationVersion() - ); - const div = document.createElement("div"); - div.innerHTML = - `

-

Bitwarden
© Bitwarden Inc. 2015-` + - year + - `

`; - div.appendChild(versionText); - - Swal.fire({ - heightAuto: false, - buttonsStyling: false, - html: div, - showConfirmButton: false, - showCancelButton: true, - cancelButtonText: this.i18nService.t("close"), - }); + this.modalService.open(AboutComponent); } async fingerprint() { diff --git a/apps/browser/store/locales/bs/copy.resx b/apps/browser/store/locales/bs/copy.resx index cfb4c5df101..191198691d4 100644 --- a/apps/browser/store/locales/bs/copy.resx +++ b/apps/browser/store/locales/bs/copy.resx @@ -139,7 +139,7 @@ Bitwarden offers Teams and Enterprise plans for companies so you can securely sh Why Choose Bitwarden: World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashing, and PBKDF2 SHA-256) so your data stays secure and private. Built-in Password Generator Generate strong, unique, and random passwords based on security requirements for every website you frequent. diff --git a/apps/browser/store/locales/en_IN/copy.resx b/apps/browser/store/locales/en_IN/copy.resx index cfb4c5df101..191198691d4 100644 --- a/apps/browser/store/locales/en_IN/copy.resx +++ b/apps/browser/store/locales/en_IN/copy.resx @@ -139,7 +139,7 @@ Bitwarden offers Teams and Enterprise plans for companies so you can securely sh Why Choose Bitwarden: World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashing, and PBKDF2 SHA-256) so your data stays secure and private. Built-in Password Generator Generate strong, unique, and random passwords based on security requirements for every website you frequent. diff --git a/apps/browser/store/locales/fi/copy.resx b/apps/browser/store/locales/fi/copy.resx index a27f806bb76..5a85be3b48a 100644 --- a/apps/browser/store/locales/fi/copy.resx +++ b/apps/browser/store/locales/fi/copy.resx @@ -124,22 +124,22 @@ Turvallinen ja ilmainen salasanojen hallinta kaikille laitteillesi - Bitwarden, inc. on 8bit Solutions LLC:n emoyhtiö. + Bitwarden, Inc. on 8bit Solutions LLC:n emoyhtiö. NIMENNYT PARHAAKSI SALASANOJEN HALLINNAKSI MM. THE VERGE, U.S. NEWS & WORLD REPORT JA CNET. -Hallinnoi, säilytä, suojaa ja jaa rajattomasti salasanoja missä tahansa ja miltä tahansa laitteelta. Bitwarden tarjoaa avoimeen lähdekoodin perustuvan salasanojen hallintaratkaisun kaikille, olitpa sitten kotona, töissä tai liikkeellä. +Hallinnoi, säilytä, suojaa ja jaa salasanoja rajattomalta laitemäärältä mistä tahansa. Bitwarden tarjoaa avoimeen lähdekoodin perustuvan salasanojen hallintaratkaisun kaikille, olitpa sitten kotona, töissä tai liikkeellä. Luo usein käyttämillesi sivustoille automaattisesti vahvoja, yksilöllisiä ja satunnaisia salasanoja. Bitwarden Send -ominaisuudella lähetät tietoa nopeasti salattuna — tiedostoja ja tekstiä — suoraan kenelle tahansa. -Yrityksille Bitwarden tarjoaa Teams ja Enterprise -tilaukset, jotta voit jakaa salasanoja kollegoiden kesken turvallisesti. +Yrityksille Bitwarden tarjoaa Teams- ja Enterprise-tilaukset, jotka mahdollistavat turvallisen salasanojen jaon kollegoiden kesken. Miksi Bitwarden?: Maailmanluokan salaus -Salasanat on suojattu tehokkaalla päästä päähän salauksella (AES-256 Bit, suolattu hajautus ja PBKDF2 SHA-256), joten tietosi pysyvät turvassa ja yksityisinä. +Salasanat on suojattu tehokkaalla päästä päähän salauksella (AES-256 bit, suolattu hajautus ja PBKDF2 SHA-256), joten tietosi pysyvät turvassa ja yksityisinä. Sisäänrakennettu salasanageneraattori Luo usein käyttämillesi sivustoille vahvoja, yksilöllisiä ja satunnaisia salasanoja. @@ -148,7 +148,8 @@ Monikielinen Bitwardenin sovelluksia on käännetty yli 40 kielelle ja määrä kasvaa jatkuvasti, kiitos kansainvälisen yhteisömme. Alustariippumattomaton -Suojaa, käytä ja jaa Bitwarden-holvisi arkaluontoisia tietoja kaikilla selaimilla, mobiililaitteilla, pöytätietokoneilla ja muissa järjestelmissä. +Suojaa, käytä ja jaa Bitwarden-holvisi arkaluontoisia tietoja kaikilla selaimilla, mobiililaitteilla, pöytätietokoneilla ja muissa järjestelmissä. + Turvallinen ja ilmainen salasanojen hallinta kaikille laitteillesi diff --git a/apps/browser/store/locales/fil/copy.resx b/apps/browser/store/locales/fil/copy.resx index b91560b285a..dcc7455e52c 100644 --- a/apps/browser/store/locales/fil/copy.resx +++ b/apps/browser/store/locales/fil/copy.resx @@ -139,7 +139,7 @@ Bitwarden offers Teams and Enterprise plans for companies so you can securely sh Why Choose Bitwarden: World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashing, and PBKDF2 SHA-256) so your data stays secure and private. Built-in Password Generator Generate strong, unique, and random passwords based on security requirements for every website you frequent. diff --git a/apps/browser/store/locales/ka/copy.resx b/apps/browser/store/locales/ka/copy.resx index cfb4c5df101..191198691d4 100644 --- a/apps/browser/store/locales/ka/copy.resx +++ b/apps/browser/store/locales/ka/copy.resx @@ -139,7 +139,7 @@ Bitwarden offers Teams and Enterprise plans for companies so you can securely sh Why Choose Bitwarden: World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashing, and PBKDF2 SHA-256) so your data stays secure and private. Built-in Password Generator Generate strong, unique, and random passwords based on security requirements for every website you frequent. diff --git a/apps/browser/store/locales/km/copy.resx b/apps/browser/store/locales/km/copy.resx index cfb4c5df101..191198691d4 100644 --- a/apps/browser/store/locales/km/copy.resx +++ b/apps/browser/store/locales/km/copy.resx @@ -139,7 +139,7 @@ Bitwarden offers Teams and Enterprise plans for companies so you can securely sh Why Choose Bitwarden: World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashing, and PBKDF2 SHA-256) so your data stays secure and private. Built-in Password Generator Generate strong, unique, and random passwords based on security requirements for every website you frequent. diff --git a/apps/browser/store/locales/nn/copy.resx b/apps/browser/store/locales/nn/copy.resx index cfb4c5df101..191198691d4 100644 --- a/apps/browser/store/locales/nn/copy.resx +++ b/apps/browser/store/locales/nn/copy.resx @@ -139,7 +139,7 @@ Bitwarden offers Teams and Enterprise plans for companies so you can securely sh Why Choose Bitwarden: World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashing, and PBKDF2 SHA-256) so your data stays secure and private. Built-in Password Generator Generate strong, unique, and random passwords based on security requirements for every website you frequent. diff --git a/apps/browser/store/locales/ro/copy.resx b/apps/browser/store/locales/ro/copy.resx index d8beda8c80a..0e12b289af3 100644 --- a/apps/browser/store/locales/ro/copy.resx +++ b/apps/browser/store/locales/ro/copy.resx @@ -126,29 +126,30 @@ Bitwarden, Inc. este compania mamă a 8bit Solutions LLC. -NUMIT CEL MAI BUN MANAGER DE PAROLE DE CĂTRE THE VERGE, U.S. NEWS & WORLD REPORT, CNET, ȘI MULȚI ALȚII. +NUMIT CEL MAI BUN MANAGER DE PAROLE DE CĂTRE THE VERGE, U.S. NEWS & WORLD REPORT, CNET ȘI MULȚI ALȚII. -Gestionează, stochează, securizează și partajează parole nelimitate, pe dispozitive nelimitate, de oriunde. Bitwarden oferă soluții de gestionare a parolelor open source pentru toată lumea, fie acasă, la serviciu sau în deplasare. +Gestionați, stocați, securizați și partajați un număr nelimitat de parole pe un număr nelimitat de dispozitive, de oriunde. Bitwarden oferă soluții open source de gestionare a parolelor pentru toată lumea, fie că se află acasă, la serviciu sau în mișcare. -Generează parole puternice, unice și aleatorii pe baza cerințelor de securitate a fiecărui site web pe care îl frecventați. +Generați parole puternice, unice și aleatorii, bazate pe cerințe de securitate pentru fiecare site web pe care îl frecventați. -Bitwarden Send transmite rapid informații criptate --- fișiere și text simplu -- direct către oricine. +Bitwarden Send transmite rapid informații criptate --- fișiere și text simple -- direct către oricine. -Bitwarden oferă planurile Echipe și Organizație pentru companii, astfel încât să puteți partaja în siguranță parolele cu colegii. +Bitwarden oferă planuri Teams și Enterprise pentru companii, astfel încât să puteți partaja în siguranță parolele cu colegii. De ce să alegeți Bitwarden: Criptare de clasă mondială -Parolele sunt protejate cu criptare avansată completă (AES-256 bit, hashtag experimentat și PBKDF2 SHA-256), astfel încât datele dvs. să rămână sigure și private. +Parolele sunt protejate cu criptare avansată end-to-end (AES-256 bit, salted hashing și PBKDF2 SHA-256), astfel încât datele dvs. să rămână sigure și private. Generator de parole încorporat -Generează parole puternice, unice și aleatorii pe baza cerințelor de securitate a fiecărui site web pe care îl frecventați. +Generați parole puternice, unice și aleatorii, bazate pe cerințele de securitate pentru fiecare site web pe care îl frecventați. -Traducere în mai multe limbi +Traduceri la nivel mondial Bitwarden este deja tradus în 40 de limbi și numărul lor crește, datorită comunității noastre mondiale. -Aplicații multi-platformă -Asigură și partajează date sensibile din seiful Bitwarden de pe orice browser, dispozitiv mobil sau sistem de operare desktop și multe altele. +Aplicații multi-platformă +Protejați și partajați date sensibile în seiful Bitwarden de pe orice browser, dispozitiv mobil sau sistem de operare desktop și multe altele. + Un manager de parole sigur și gratuit, pentru toate dispozitivele dvs. diff --git a/apps/browser/store/locales/si/copy.resx b/apps/browser/store/locales/si/copy.resx index cfb4c5df101..191198691d4 100644 --- a/apps/browser/store/locales/si/copy.resx +++ b/apps/browser/store/locales/si/copy.resx @@ -139,7 +139,7 @@ Bitwarden offers Teams and Enterprise plans for companies so you can securely sh Why Choose Bitwarden: World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashing, and PBKDF2 SHA-256) so your data stays secure and private. Built-in Password Generator Generate strong, unique, and random passwords based on security requirements for every website you frequent. diff --git a/apps/browser/store/locales/sk/copy.resx b/apps/browser/store/locales/sk/copy.resx index a548d10a607..ba2a2a5a071 100644 --- a/apps/browser/store/locales/sk/copy.resx +++ b/apps/browser/store/locales/sk/copy.resx @@ -139,7 +139,7 @@ Bitwarden ponúka Teams a Enterprise paušály pre firmy, aby ste mohli bezpečn Prečo si vybrať Bitwarden: Svetová trieda v šifrovaní -Heslá sú chránené pokročilým end-to-end šifrovaním (AES-256 bit, salted hashtag a PBKDF2 SHA-256), takže Vaše dáta zostanú bezpečné a súkromné. +Heslá sú chránené pokročilým end-to-end šifrovaním (AES-256 bit, salted hash a PBKDF2 SHA-256), takže Vaše dáta zostanú bezpečné a súkromné. Vstavaný generátor hesiel Vygenerujte si silné, unikátne a náhodné heslá podľa bezpečnostných požiadaviek na každej stránke, ktorú navštevujete. diff --git a/apps/browser/store/locales/sl/copy.resx b/apps/browser/store/locales/sl/copy.resx index cfb4c5df101..191198691d4 100644 --- a/apps/browser/store/locales/sl/copy.resx +++ b/apps/browser/store/locales/sl/copy.resx @@ -139,7 +139,7 @@ Bitwarden offers Teams and Enterprise plans for companies so you can securely sh Why Choose Bitwarden: World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashing, and PBKDF2 SHA-256) so your data stays secure and private. Built-in Password Generator Generate strong, unique, and random passwords based on security requirements for every website you frequent. diff --git a/apps/browser/store/locales/uk/copy.resx b/apps/browser/store/locales/uk/copy.resx index 77f9820d598..471d5806918 100644 --- a/apps/browser/store/locales/uk/copy.resx +++ b/apps/browser/store/locales/uk/copy.resx @@ -139,7 +139,7 @@ Bitwarden пропонує командні та корпоративні тар Чому варто обрати Bitwarden: Шифрування світового рівня -Паролі захищаються з використанням розширеного наскрізного шифрування (AES-256 bit, salted hashtag, та PBKDF2 SHA-256), тому ваші дані завжди захищені та приватні. +Паролі захищаються з використанням розширеного наскрізного шифрування (AES-256 bit, хешування з сіллю та PBKDF2 SHA-256), тому ваші дані завжди захищені та приватні. Вбудований генератор паролів Генеруйте випадкові, надійні та унікальні паролі, які задовольняють вимоги безпеки, для кожного вебсайту та сервісу. @@ -148,7 +148,8 @@ Bitwarden пропонує командні та корпоративні тар Завдяки нашій глобальній спільноті, Bitwarden перекладено 40 мовами, і їх кількість продовжує зростати. Програми для різних платформ -Зберігайте і діліться важливими даними, а також користуйтеся іншими можливостями у вашому сховищі Bitwarden в будь-якому браузері, мобільному пристрої, чи комп'ютерній операційній системі. +Зберігайте і діліться важливими даними, а також користуйтеся іншими можливостями у вашому сховищі Bitwarden в будь-якому браузері, мобільному пристрої, чи комп'ютерній операційній системі. + Захищений і безкоштовний менеджер паролів для всіх ваших пристроїв diff --git a/apps/browser/store/locales/zh_CN/copy.resx b/apps/browser/store/locales/zh_CN/copy.resx index 055a736e2a3..4c36c3fc31f 100644 --- a/apps/browser/store/locales/zh_CN/copy.resx +++ b/apps/browser/store/locales/zh_CN/copy.resx @@ -126,15 +126,15 @@ Bitwarden, Inc. 是 8bit Solutions LLC 的母公司。 -被 the verge、U.S. news & world report、cnet 等评为最佳密码管理器。 +被 THE VERGE、U.S. NEWS & WORLD REPORT、CNET 等评为最佳的密码管理器。 从任何地方,不限制设备,管理、存储、保护和共享无限的密码。Bitwarden 为每个人提供开源的密码管理解决方案,无论是在家里,在工作中,还是在旅途中。 -基于安全要求,为你经常访问的每个网站生成强大、唯一和随机的密码。 +基于安全要求,为您经常访问的每个网站生成强大、唯一和随机的密码。 Bitwarden Send 快速传输加密的信息---文件和文本---直接给任何人。 -Bitwarden 为公司提供团队和企业计划,因此你可以安全地与同事共享密码。 +Bitwarden 为公司提供团队和企业计划,因此您可以安全地与同事共享密码。 为何选择 Bitwarden: @@ -142,12 +142,12 @@ Bitwarden 为公司提供团队和企业计划,因此你可以安全地与同 密码受到先进的端到端加密(AES-256 位、盐化标签和 PBKDF2 SHA-256)的保护,为您的数据保持安全和隐密。 内置密码生成器 -基于安全要求,为你经常访问的每个网站生成强大、唯一和随机的密码。 +基于安全要求,为您经常访问的每个网站生成强大、唯一和随机的密码。 -全球翻译 +全球翻译 Bitwarden 的翻译有 40 种语言,而且还在不断增加,感谢我们的全球社区。 -跨平台的应用程序 +跨平台应用程序 从任何浏览器、移动设备或桌面操作系统,以及更多的地方,在您的 Bitwarden 密码库中保护和分享敏感数据。 diff --git a/apps/browser/store/locales/zh_TW/copy.resx b/apps/browser/store/locales/zh_TW/copy.resx index 96b4f92f179..e9aa7acac6d 100644 --- a/apps/browser/store/locales/zh_TW/copy.resx +++ b/apps/browser/store/locales/zh_TW/copy.resx @@ -126,29 +126,29 @@ Bitwarden, Inc. 是 8bit Solutions LLC 的母公司。 -被 THE VERGE、U.S. NEWS & WORLD REPORT、CNET 等評為最佳密碼管理器。 +被 THE VERGE、U.S. NEWS & WORLD REPORT、CNET 等評為最佳的密碼管理器。 從任何地方,不限制設備,管理、存儲、保護和共享無限的密碼。Bitwarden 為每個人提供開源的密碼管理解決方案,無論是在家裡,在工作中,還是在旅途中。 -基於安全要求,為你經常訪問的每個網站生成強大、唯一和隨機的密碼。 +基於安全要求,為您經常訪問的每個網站生成強大、唯一和隨機的密碼。 Bitwarden Send 快速傳輸加密的信息---文檔和文本---直接給任何人。 -Bitwarden 為公司提供團隊和企業計劃,因此你可以安全地與同事共享密碼。 +Bitwarden 為公司提供團隊和企業計劃,因此您可以安全地與同事共享密碼。 為何選擇 Bitwarden: 世界級的加密技術 -密碼受到先進的端到端加密(AES-256 位、鹽化標籤和 PBKDF2 SHA-256)的保護,為您的數據保持安全和隱密。 +密碼受到先進的端到端加密(AES-256 位、鹽化標籤和 PBKDF2 SHA-256)的保護,為您的資料保持安全和隱密。 內置密碼生成器 -基於安全要求,為你經常訪問的每個網站生成強大、唯一和隨機的密碼。 +基於安全要求,為您經常訪問的每個網站生成強大、唯一和隨機的密碼。 -全球翻譯 +全球翻譯 Bitwarden 的翻譯有 40 種語言,而且還在不斷增加,感謝我們的全球社區。 -跨平台的應用程式 -從任何瀏覽器、行動裝置或桌面作業系統,以及更多的地方,在您的 Bitwarden 密碼庫中保護和分享敏感數據。 +跨平台應用程式 +從任何瀏覽器、行動裝置或桌面作業系統,以及更多的地方,在您的 Bitwarden 密碼庫中保護和分享敏感資料。 安全、免費、跨平台的密碼管理工具 diff --git a/apps/browser/webpack.config.js b/apps/browser/webpack.config.js index 301e20a2c26..116ed19bd2e 100644 --- a/apps/browser/webpack.config.js +++ b/apps/browser/webpack.config.js @@ -136,7 +136,6 @@ const config = { "content/autofiller": "./src/content/autofiller.ts", "content/notificationBar": "./src/content/notificationBar.ts", "content/contextMenuHandler": "./src/content/contextMenuHandler.ts", - "content/shortcuts": "./src/content/shortcuts.ts", "content/message_handler": "./src/content/message_handler.ts", "notification/bar": "./src/notification/bar.js", }, diff --git a/apps/cli/package-lock.json b/apps/cli/package-lock.json index 51dd94fc888..8a66d813d65 100644 --- a/apps/cli/package-lock.json +++ b/apps/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "@bitwarden/cli", - "version": "2022.8.0", + "version": "2022.9.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@bitwarden/cli", - "version": "2022.8.0", + "version": "2022.9.0", "license": "GPL-3.0-only", "dependencies": { "@koa/multer": "^3.0.0", diff --git a/apps/cli/package.json b/apps/cli/package.json index b09a593d640..b833fe5b072 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,7 +1,7 @@ { "name": "@bitwarden/cli", "description": "A secure and free password manager for all of your devices.", - "version": "2022.8.0", + "version": "2022.9.0", "keywords": [ "bitwarden", "password", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index a283b68e519..58b31e7dbfd 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@bitwarden/desktop", "description": "A secure and free password manager for all of your devices.", - "version": "2022.8.2", + "version": "2022.9.1", "keywords": [ "bitwarden", "password", diff --git a/apps/desktop/src/app/accounts/settings.component.html b/apps/desktop/src/app/accounts/settings.component.html index 33abdc934c6..420ee20a39e 100644 --- a/apps/desktop/src/app/accounts/settings.component.html +++ b/apps/desktop/src/app/accounts/settings.component.html @@ -108,14 +108,6 @@ - -
- - - {{ "deleteAccountDesc" | i18n }} - {{ "deleteAccount" | i18n }} - -
diff --git a/apps/desktop/src/app/accounts/settings.component.ts b/apps/desktop/src/app/accounts/settings.component.ts index 24c1ba576f6..ec9744f654b 100644 --- a/apps/desktop/src/app/accounts/settings.component.ts +++ b/apps/desktop/src/app/accounts/settings.component.ts @@ -18,8 +18,6 @@ import { isWindowsStore } from "@bitwarden/electron/utils"; import { SetPinComponent } from "../components/set-pin.component"; -import { DeleteAccountComponent } from "./delete-account.component"; - @Component({ selector: "app-settings", templateUrl: "settings.component.html", @@ -439,8 +437,4 @@ export class SettingsComponent implements OnInit { this.enableBrowserIntegrationFingerprint ); } - - async openDeleteAccount() { - this.modalService.open(DeleteAccountComponent, { replaceTopModal: true }); - } } diff --git a/apps/desktop/src/app/services/init.service.ts b/apps/desktop/src/app/services/init.service.ts index 722ae013fc1..7e250a1ee5e 100644 --- a/apps/desktop/src/app/services/init.service.ts +++ b/apps/desktop/src/app/services/init.service.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from "@angular/core"; -import { WINDOW } from "@bitwarden/angular/services/jslib-services.module"; +import { WINDOW } from "@bitwarden/angular/services/injection-tokens"; import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction"; import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service"; import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service"; diff --git a/apps/desktop/src/app/services/services.module.ts b/apps/desktop/src/app/services/services.module.ts index df32a71839f..d49872987cb 100644 --- a/apps/desktop/src/app/services/services.module.ts +++ b/apps/desktop/src/app/services/services.module.ts @@ -1,7 +1,6 @@ import { APP_INITIALIZER, InjectionToken, NgModule } from "@angular/core"; import { - JslibServicesModule, SECURE_STORAGE, STATE_FACTORY, STATE_SERVICE_USE_CACHE, @@ -9,7 +8,8 @@ import { LOCALES_DIRECTORY, SYSTEM_LANGUAGE, MEMORY_STORAGE, -} from "@bitwarden/angular/services/jslib-services.module"; +} from "@bitwarden/angular/services/injection-tokens"; +import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module"; import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction"; import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service"; import { BroadcasterService as BroadcasterServiceAbstraction } from "@bitwarden/common/abstractions/broadcaster.service"; diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json index e399281c061..860dd9302b4 100644 --- a/apps/desktop/src/locales/en/messages.json +++ b/apps/desktop/src/locales/en/messages.json @@ -1577,7 +1577,7 @@ "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." }, "browserIntegrationWindowsStoreDesc": { - "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + "message": "Unfortunately browser integration is currently not supported in the Microsoft Store version." }, "browserIntegrationLinuxDesc": { "message": "Unfortunately browser integration is currently not supported in the linux version." diff --git a/apps/desktop/src/locales/nl/messages.json b/apps/desktop/src/locales/nl/messages.json index e66d5644ac4..d4737d3430f 100644 --- a/apps/desktop/src/locales/nl/messages.json +++ b/apps/desktop/src/locales/nl/messages.json @@ -1299,10 +1299,10 @@ "description": "hCaptcha is the name of a website, should not be translated" }, "invalidUrl": { - "message": "Invalid Url" + "message": "Ongeldige URL" }, "done": { - "message": "Done" + "message": "Klaar" }, "accessibilityCookieSaved": { "message": "Accessibility cookie saved!" @@ -1970,14 +1970,14 @@ "message": "Generate an email alias with an external forwarding service." }, "hostname": { - "message": "Hostname", + "message": "Hostnaam", "description": "Part of a URL." }, "apiAccessToken": { "message": "API Access Token" }, "apiKey": { - "message": "API Key" + "message": "API-sleutel" }, "premiumSubcriptionRequired": { "message": "Premium-abonnement vereist" diff --git a/apps/desktop/src/package-lock.json b/apps/desktop/src/package-lock.json index cc99cdb53e2..69a5370b6e5 100644 --- a/apps/desktop/src/package-lock.json +++ b/apps/desktop/src/package-lock.json @@ -1,12 +1,12 @@ { "name": "@bitwarden/desktop", - "version": "2022.8.2", + "version": "2022.9.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@bitwarden/desktop", - "version": "2022.8.2", + "version": "2022.9.1", "license": "GPL-3.0", "dependencies": { "@bitwarden/desktop-native": "file:../desktop_native" diff --git a/apps/desktop/src/package.json b/apps/desktop/src/package.json index aa912f42231..705c6dc9be6 100644 --- a/apps/desktop/src/package.json +++ b/apps/desktop/src/package.json @@ -2,7 +2,7 @@ "name": "@bitwarden/desktop", "productName": "Bitwarden", "description": "A secure and free password manager for all of your devices.", - "version": "2022.8.2", + "version": "2022.9.1", "author": "Bitwarden Inc. (https://bitwarden.com)", "homepage": "https://bitwarden.com", "license": "GPL-3.0", diff --git a/apps/web/src/app/accounts/register-form/register-form.component.html b/apps/web/src/app/accounts/register-form/register-form.component.html index e147f463cb6..56364086ff9 100644 --- a/apps/web/src/app/accounts/register-form/register-form.component.html +++ b/apps/web/src/app/accounts/register-form/register-form.component.html @@ -113,16 +113,21 @@
- {{ "createAccount" | i18n }} - - - {{ "logIn" | i18n }} - + + {{ "createAccount" | i18n }} + + + {{ "logIn" | i18n }} + + + + {{ "logIn" | i18n }} +
diff --git a/apps/web/src/app/accounts/trial-initiation/content/abm-enterprise-content.component.html b/apps/web/src/app/accounts/trial-initiation/content/abm-enterprise-content.component.html new file mode 100644 index 00000000000..46e1fae80df --- /dev/null +++ b/apps/web/src/app/accounts/trial-initiation/content/abm-enterprise-content.component.html @@ -0,0 +1,17 @@ +

The Bitwarden Password Manager

+
+

+ Trusted by millions of individuals, teams, and organizations worldwide for secure password + storage and sharing. +

+
+
    +
  • Store logins, secure notes, and more
  • +
  • Collaborate and share securely
  • +
  • Access anywhere on any device
  • +
  • Create your account to get started
  • +
+
+ + +
diff --git a/apps/web/src/app/accounts/trial-initiation/content/abm-enterprise-content.component.ts b/apps/web/src/app/accounts/trial-initiation/content/abm-enterprise-content.component.ts new file mode 100644 index 00000000000..0f9db7b4405 --- /dev/null +++ b/apps/web/src/app/accounts/trial-initiation/content/abm-enterprise-content.component.ts @@ -0,0 +1,7 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "app-abm-enterprise-content", + templateUrl: "abm-enterprise-content.component.html", +}) +export class AbmEnterpriseContentComponent {} diff --git a/apps/web/src/app/accounts/trial-initiation/content/abm-teams-content.component.html b/apps/web/src/app/accounts/trial-initiation/content/abm-teams-content.component.html new file mode 100644 index 00000000000..46e1fae80df --- /dev/null +++ b/apps/web/src/app/accounts/trial-initiation/content/abm-teams-content.component.html @@ -0,0 +1,17 @@ +

The Bitwarden Password Manager

+
+

+ Trusted by millions of individuals, teams, and organizations worldwide for secure password + storage and sharing. +

+
+
    +
  • Store logins, secure notes, and more
  • +
  • Collaborate and share securely
  • +
  • Access anywhere on any device
  • +
  • Create your account to get started
  • +
+
+ + +
diff --git a/apps/web/src/app/accounts/trial-initiation/content/abm-teams-content.component.ts b/apps/web/src/app/accounts/trial-initiation/content/abm-teams-content.component.ts new file mode 100644 index 00000000000..7765555f5cc --- /dev/null +++ b/apps/web/src/app/accounts/trial-initiation/content/abm-teams-content.component.ts @@ -0,0 +1,7 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "app-abm-teams-content", + templateUrl: "abm-teams-content.component.html", +}) +export class AbmTeamsContentComponent {} diff --git a/apps/web/src/app/accounts/trial-initiation/trial-initiation.component.html b/apps/web/src/app/accounts/trial-initiation/trial-initiation.component.html index b78468133d5..2b7f07254b6 100644 --- a/apps/web/src/app/accounts/trial-initiation/trial-initiation.component.html +++ b/apps/web/src/app/accounts/trial-initiation/trial-initiation.component.html @@ -37,6 +37,8 @@ *ngIf="layout === 'cnetcmpgnind'" > + +
diff --git a/apps/web/src/app/accounts/trial-initiation/trial-initiation.module.ts b/apps/web/src/app/accounts/trial-initiation/trial-initiation.module.ts index fb02824222f..fd188002229 100644 --- a/apps/web/src/app/accounts/trial-initiation/trial-initiation.module.ts +++ b/apps/web/src/app/accounts/trial-initiation/trial-initiation.module.ts @@ -10,6 +10,8 @@ import { RegisterFormModule } from "../register-form/register-form.module"; import { BillingComponent } from "./billing.component"; import { ConfirmationDetailsComponent } from "./confirmation-details.component"; +import { AbmEnterpriseContentComponent } from "./content/abm-enterprise-content.component"; +import { AbmTeamsContentComponent } from "./content/abm-teams-content.component"; import { CnetEnterpriseContentComponent } from "./content/cnet-enterprise-content.component"; import { CnetIndividualContentComponent } from "./content/cnet-individual-content.component"; import { CnetTeamsContentComponent } from "./content/cnet-teams-content.component"; @@ -52,6 +54,8 @@ import { VerticalStepperModule } from "./vertical-stepper/vertical-stepper.modul CnetEnterpriseContentComponent, CnetIndividualContentComponent, CnetTeamsContentComponent, + AbmEnterpriseContentComponent, + AbmTeamsContentComponent, LogoCnetComponent, LogoForbesComponent, LogoUSNewsComponent, diff --git a/apps/web/src/app/core/core.module.ts b/apps/web/src/app/core/core.module.ts index 95e5a766066..ba22f4422c4 100644 --- a/apps/web/src/app/core/core.module.ts +++ b/apps/web/src/app/core/core.module.ts @@ -2,14 +2,14 @@ import { CommonModule } from "@angular/common"; import { APP_INITIALIZER, NgModule, Optional, SkipSelf } from "@angular/core"; import { - JslibServicesModule, SECURE_STORAGE, STATE_FACTORY, STATE_SERVICE_USE_CACHE, LOCALES_DIRECTORY, SYSTEM_LANGUAGE, MEMORY_STORAGE, -} from "@bitwarden/angular/services/jslib-services.module"; +} from "@bitwarden/angular/services/injection-tokens"; +import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module"; import { ModalService as ModalServiceAbstraction } from "@bitwarden/angular/services/modal.service"; import { FileDownloadService } from "@bitwarden/common/abstractions/fileDownload/fileDownload.service"; import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/abstractions/i18n.service"; diff --git a/apps/web/src/app/core/init.service.ts b/apps/web/src/app/core/init.service.ts index 03f4d99f3ad..0f61efb6738 100644 --- a/apps/web/src/app/core/init.service.ts +++ b/apps/web/src/app/core/init.service.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from "@angular/core"; -import { WINDOW } from "@bitwarden/angular/services/jslib-services.module"; +import { WINDOW } from "@bitwarden/angular/services/injection-tokens"; import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction"; import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service"; import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service"; diff --git a/apps/web/src/app/core/state/state.service.ts b/apps/web/src/app/core/state/state.service.ts index 074ffa44538..7284ad87fed 100644 --- a/apps/web/src/app/core/state/state.service.ts +++ b/apps/web/src/app/core/state/state.service.ts @@ -5,7 +5,7 @@ import { SECURE_STORAGE, STATE_FACTORY, STATE_SERVICE_USE_CACHE, -} from "@bitwarden/angular/services/jslib-services.module"; +} from "@bitwarden/angular/services/injection-tokens"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { StateMigrationService } from "@bitwarden/common/abstractions/stateMigration.service"; import { AbstractStorageService } from "@bitwarden/common/abstractions/storage.service"; diff --git a/apps/web/src/locales/be/messages.json b/apps/web/src/locales/be/messages.json index 3d40976b187..252e101dace 100644 --- a/apps/web/src/locales/be/messages.json +++ b/apps/web/src/locales/be/messages.json @@ -306,7 +306,7 @@ "message": "Абароненая нататка" }, "typeLoginPlural": { - "message": "Logins" + "message": "Лагіны" }, "typeCardPlural": { "message": "Карткі" @@ -679,7 +679,7 @@ "message": "Памылковы асноўны пароль" }, "invalidFilePassword": { - "message": "Invalid file password, please use the password you entered when you created the export file." + "message": "Памылковы пароль файла. Скарыстайцеся паролем, які вы ўводзілі пры стварэнні файла экспартавання." }, "lockNow": { "message": "Заблакіраваць" @@ -894,46 +894,46 @@ "message": "Фармат файла" }, "fileEncryptedExportWarningDesc": { - "message": "This file export will be password protected and require the file password to decrypt." + "message": "Гэты экспартаваны файл будзе абаронены паролем, які неабходна будзе ўвесці для яго расшыфроўкі." }, "exportPasswordDescription": { - "message": "This password will be used to export and import this file" + "message": "Гэты пароль будзе выкарыстоўвацца для экспартавання і імпартавання гэтага файла" }, "confirmMasterPassword": { - "message": "Confirm Master Password" + "message": "Пацвердзіць асноўны пароль" }, "confirmFormat": { - "message": "Confirm Format" + "message": "Пацвердзіць фармат" }, "filePassword": { - "message": "File Password" + "message": "Пароль файла" }, "confirmFilePassword": { - "message": "Confirm File Password" + "message": "Пацвердзіць пароль файла" }, "accountBackupOptionDescription": { - "message": "Use your account encryption key to encrypt the export and restrict import to only the current Bitwarden account." + "message": "Выкарыстоўвайце ключ шыфравання вашага ўліковага запісу, каб зашыфраваць экспартаванне і абмежаваць імпартаванне толькі бягучага ўліковага запісу Bitwarden." }, "passwordProtectedOptionDescription": { - "message": "Set a password to encrypt the export and import it to any Bitwarden account using the password for decryption." + "message": "Прызначце пароль, каб зашыфраваць экспартаванне і імпартуйце яго ў любы ўліковы запіс Bitwarden з выкарыстаннем пароля для расшыфроўкі." }, "fileTypeHeading": { - "message": "File Type" + "message": "Тып файла" }, "accountBackup": { - "message": "Account Backup" + "message": "Рэзервовая копія ўліковага запісу" }, "passwordProtected": { - "message": "Password Protected" + "message": "Абаронена паролем" }, "filePasswordAndConfirmFilePasswordDoNotMatch": { - "message": "“File password” and “Confirm File Password“ do not match." + "message": "“Пароль файла” і “Пацвярджэнне пароля файла“ не супадаюць." }, "confirmVaultImport": { - "message": "Confirm Vault Import" + "message": "Пацвердзіць імпартаванне сімвала" }, "confirmVaultImportDesc": { - "message": "This file is password-protected. Please enter the file password to import data." + "message": "Гэты файл абаронены паролем. Калі ласка, увядзіце пароль для імпартавання даных." }, "exportSuccess": { "message": "Даныя вашага сховішча былі экспартаваныя." @@ -1212,7 +1212,7 @@ "message": "Паказваць значкі вэб-сайтаў" }, "faviconDesc": { - "message": "Show a recognizable image next to each login." + "message": "Паказваць распазнавальны відарыс побач з кожным з кожным лагінам." }, "enableGravatars": { "message": "Паказваць Gravatars", @@ -1596,7 +1596,7 @@ "message": "Праверка скампраметаваных пароляў" }, "exposedXTimes": { - "message": "Exposed $COUNT$ time(s)", + "message": "Скампраметаваны $COUNT$ раз(-ы; -оў)", "placeholders": { "count": { "content": "$1", @@ -1614,7 +1614,7 @@ "message": "Знойдзены слабыя паролі" }, "weakPasswordsFoundDesc": { - "message": "We found $COUNT$ items in your vault with passwords that are not strong. You should update them to use stronger passwords.", + "message": "У сховішчы ёсць элементы ($COUNT$ шт.) з ненадзейнымі паролямі. Вам неабходна змяніць іх на больш складаныя.", "placeholders": { "count": { "content": "$1", @@ -1623,19 +1623,19 @@ } }, "noWeakPasswords": { - "message": "No items in your vault have weak passwords." + "message": "У вашым сховішчы адсутнічаюць ненадзейныя паролі." }, "reusedPasswordsReport": { "message": "Паўторна выкарыстаныя паролі" }, "reusedPasswordsReportDesc": { - "message": "Reusing passwords makes it easier for attackers to break into multiple accounts. Change these passwords so that each is unique." + "message": "Паўторныя паролі дазваляюць зламысніку атрымаць несанкцыянаваны доступ да некалькіх уліковых запісаў адразу. Змяніце гэтыя паролі і зрабіце кожны з іх унікальным." }, "reusedPasswordsFound": { - "message": "Reused Passwords Found" + "message": "Знойдзены паўторныя паролі" }, "reusedPasswordsFoundDesc": { - "message": "We found $COUNT$ passwords that are being reused in your vault. You should change them to a unique value.", + "message": "У сховішчы знойдзены паўторныя паролі ($COUNT$ шт.). Змяніце іх на ўнікальныя.", "placeholders": { "count": { "content": "$1", @@ -1644,7 +1644,7 @@ } }, "noReusedPasswords": { - "message": "No logins in your vault have passwords that are being reused." + "message": "У вашым сховішчы адсутнічаюць паўторныя паролі." }, "reusedXTimes": { "message": "Паўторна выкарыстаны разоў: $COUNT$", @@ -1659,16 +1659,16 @@ "message": "Уцечка даных" }, "breachDesc": { - "message": "Breached accounts can expose your personal information. Secure breached accounts by enabling 2FA or creating a stronger password." + "message": "Узламаныя ўліковы запісы могуць скампраметаваць вашу асабістую інфармацыю. Абараніце іх з дапамогай 2ФА або стварыце больш надзейны пароль." }, "breachCheckUsernameEmail": { - "message": "Check any usernames or email addresses that you use." + "message": "Праверце імёны карыстальнікаў або адрасы электроннай пошты, якія вы выкарыстоўваеце." }, "checkBreaches": { "message": "Праверыць па базах уцечак" }, "breachUsernameNotFound": { - "message": "$USERNAME$ was not found in any known data breaches.", + "message": "$USERNAME$ не знойдзены ў вядомых базах уцечак.", "placeholders": { "username": { "content": "$1", @@ -1681,7 +1681,7 @@ "description": "ex. Good News, No Breached Accounts Found!" }, "breachUsernameFound": { - "message": "$USERNAME$ was found in $COUNT$ different data breaches online.", + "message": "$USERNAME$ быў знойдзены ў $COUNT$ разнастайных базах уцечак у інтэрнэце.", "placeholders": { "username": { "content": "$1", @@ -1694,7 +1694,7 @@ } }, "breachFound": { - "message": "Breached Accounts Found" + "message": "Выяўлена ўцечка ўліковых запісаў" }, "compromisedData": { "message": "Скампраметаваныя даныя" @@ -1712,7 +1712,7 @@ "message": "Паведамлена пра ўцечку" }, "reportError": { - "message": "An error occurred trying to load the report. Try again" + "message": "Адбылася памылка пры спробе загрузіць справаздачу. Паспрабуйце яшчэ раз" }, "billing": { "message": "Аплата" @@ -1724,7 +1724,7 @@ "message": "Тып аплаты" }, "accountCredit": { - "message": "Account Credit", + "message": "Крэдыт рахунку", "description": "Financial term. In the case of Bitwarden, a positive balance means that you owe money, while a negative balance means that you have a credit (Bitwarden owes you money)." }, "accountBalance": { @@ -1740,13 +1740,13 @@ "description": "Dollar amount, or quantity." }, "creditDelayed": { - "message": "Added credit will appear on your account after the payment has been fully processed. Some payment methods are delayed and can take longer to process than others." + "message": "Дададзеныя крэдыты з'явяцца на вашым рахунку пасля поўнай апрацоўкі плацяжу. Некаторыя спосабы аплаты адбываюцца з затрымкай і могуць заняць больш часу, чым астатнія." }, "makeSureEnoughCredit": { "message": "Пераканайцеся, што на вашым рахунку дастаткова крэдытаў для ажыццяўлення гэтай пакупкі. Калі сродкаў на вашым рахунку не хапае, то для кампенсацыі нястачы будзе выкарыстаны ваш прадвызначаны метад аплаты. Вы можаце дадаць крэдыты на свой рахунак на старонцы аплаты." }, "creditAppliedDesc": { - "message": "Your account's credit can be used to make purchases. Any available credit will be automatically applied towards invoices generated for this account." + "message": "Крэдыт вашага рахунку можа выкарыстоўвацца для здзяйснення купляў. Любыя даступныя крэдыты будуць аўтаматычна ўжыты для рахункаў, якія згенерыраваны для гэтага ўліковага запісу." }, "goPremium": { "message": "Перайсці на прэміум", @@ -1756,7 +1756,7 @@ "message": "Вы абнавіліся да прэміяльнага статусу." }, "premiumUpgradeUnlockFeatures": { - "message": "Upgrade your account to a premium membership and unlock some great additional features." + "message": "Абнавіце свой уліковы запіс да платнай версіі і разблакіруйце некаторыя цудоўныя дадатковыя функцыі." }, "premiumSignUpStorage": { "message": "1 ГБ зашыфраванага сховішча для далучаных файлаў." @@ -1795,7 +1795,7 @@ "message": "Прэміяльны доступ" }, "premiumAccessDesc": { - "message": "You can add premium access to all members of your organization for $PRICE$ /$INTERVAL$.", + "message": "Вы можаце дадаць прэміяльны доступ да ўсіх удзельнікаў вашай арганізацыі за $PRICE$ у $INTERVAL$.", "placeholders": { "price": { "content": "$1", @@ -1808,13 +1808,13 @@ } }, "additionalStorageGb": { - "message": "Additional Storage (GB)" + "message": "Дадатковая сховішча (ГБ)" }, "additionalStorageGbDesc": { "message": "# дадатковых ГБ" }, "additionalStorageIntervalDesc": { - "message": "Your plan comes with $SIZE$ of encrypted file storage. You can add additional storage for $PRICE$ per GB /$INTERVAL$.", + "message": "У ваш тарыфны план уключана $SIZE$ зашыфраванага сховішча. Вы можаце дадаць дадатковае сховішча, якое будзе каштаваць $PRICE$ за кожны ГБ у $INTERVAL$.", "placeholders": { "size": { "content": "$1", @@ -1850,10 +1850,10 @@ "description": "Short abbreviation for 'month'" }, "paymentChargedAnnually": { - "message": "Your payment method will be charged immediately and then on a recurring basis each year. You may cancel at any time." + "message": "У вас адразу будзе спагнана плата згодна з абраным спосабам плацяжу, а інтэрвал такіх плацяжоў будзе ажыццяўляцца штогод. Вы можаце скасаваць іх у любы момант." }, "paymentCharged": { - "message": "Your payment method will be charged immediately and then on a recurring basis each $INTERVAL$. You may cancel at any time.", + "message": "У вас адразу будзе спагнана плата згодна з абраным спосабам плацяжу, а інтэрвал такіх плацяжоў будзе ажыццяўляцца $INTERVAL$. Вы можаце скасаваць яго ў любы момант.", "placeholders": { "interval": { "content": "$1", @@ -1862,7 +1862,7 @@ } }, "paymentChargedWithTrial": { - "message": "Your plan comes with a free 7 day trial. Your payment method will not be charged until the trial has ended. You may cancel at any time." + "message": "У ваш тарыфны план уключаны выпрабавальны перыяд на 7 дзён. У вас не будзе спагнана плата згодна з абраным спосабам плацяжу пакуль выпрабавальны перыяд не скончыцца. Вы можаце скасаваць яго ў любы момант." }, "paymentInformation": { "message": "Плацежная інфармацыя" @@ -1871,40 +1871,40 @@ "message": "Плацежная інфармацыя" }, "billingTrialSubLabel": { - "message": "Your payment method will not be charged during the 7 day free trial." + "message": "У вас не будзе спаганяцца плата абраным метадам плацяжу на працягу 7 дзён выпрабавальнага перыяду." }, "creditCard": { "message": "Крэдытная картка" }, "paypalClickSubmit": { - "message": "Click the PayPal button to log into your PayPal account, then click the Submit button below to continue." + "message": "Націсніце кнопку PayPal, каб увайсці ва ўліковы запіс PayPal, а потым націсніце кнопку \"Пацвердзіць\" ніжэй для працягу." }, "cancelSubscription": { "message": "Скасаваць падпіску" }, "subscriptionCanceled": { - "message": "The subscription has been canceled." + "message": "Падпіска была скасавана." }, "pendingCancellation": { "message": "Чаканне скасавання" }, "subscriptionPendingCanceled": { - "message": "The subscription has been marked for cancellation at the end of the current billing period." + "message": "Падпіска была пазначана для скасавання ў канцы бягучага плацежнага перыяду." }, "reinstateSubscription": { - "message": "Reinstate Subscription" + "message": "Аднавіць падпіску" }, "reinstateConfirmation": { - "message": "Are you sure you want to remove the pending cancellation request and reinstate your subscription?" + "message": "Вы ўпэўнены, што хочаце выдаліць запыт, які чакае скасавання і аднавіць сваю падпіску?" }, "reinstated": { - "message": "The subscription has been reinstated." + "message": "Падпіска была адноўлена." }, "cancelConfirmation": { - "message": "Are you sure you want to cancel? You will lose access to all of this subscription's features at the end of this billing cycle." + "message": "Вы ўпэўнены, што хочаце скасаваць? Вы страціце доступ да ўсіх функцый падпіскі ў канцы гэтага плацежнага перыяду." }, "canceledSubscription": { - "message": "The subscription has been canceled." + "message": "Падпіска была скасавана." }, "neverExpires": { "message": "Неабмежаваны тэрмін дзеяння" @@ -1940,7 +1940,7 @@ "message": "Выдаліць сховішча" }, "subscriptionStorage": { - "message": "Your subscription has a total of $MAX_STORAGE$ GB of encrypted file storage. You are currently using $USED_STORAGE$.", + "message": "Ваша падпіска ўключае ўсяго $MAX_STORAGE$ ГБ зашыфраванага сховішча. Зараз вы выкарыстоўваеце $USED_STORAGE$.", "placeholders": { "max_storage": { "content": "$1", @@ -1956,7 +1956,7 @@ "message": "Спосаб аплаты" }, "noPaymentMethod": { - "message": "No payment method on file." + "message": "Файл не змяшчае метаду аплаты." }, "addPaymentMethod": { "message": "Дадаць спосаб аплаты" @@ -1994,7 +1994,7 @@ "description": "Noun. A refunded payment that was charged." }, "chargesStatement": { - "message": "Any charges will appear on your statement as $STATEMENT_NAME$.", + "message": "Плацяжы будуць адлюстроўвацца ў вашай выпісцы як $STATEMENT_NAME$.", "placeholders": { "statement_name": { "content": "$1", @@ -2003,10 +2003,10 @@ } }, "gbStorageAdd": { - "message": "GB of Storage To Add" + "message": "ГБ сховішча для дадавання" }, "gbStorageRemove": { - "message": "GB of Storage To Remove" + "message": "ГБ сховішча для выдалення" }, "storageAddNote": { "message": "Дадаванне сховішча прывядзе да карэкціроўкі ў вашым выніковым рахунку і адразу будзе спагнана аплата згодна з азначаным метадам. Першы плацеж будзе прапарцыйны астачы бягучага плацежнага перыяду." @@ -2015,7 +2015,7 @@ "message": "Выдаленне сховішча прывядзе да карэкціроўкі вашага выніковага рахунку, які будзе прапарцыйна раздзелены ў выглядзе крэдытаў за наступны плацежны перыяд." }, "adjustedStorage": { - "message": "Adjusted $AMOUNT$ GB of storage.", + "message": "Скарэктавана $AMOUNT$ ГБ сховішча.", "placeholders": { "amount": { "content": "$1", @@ -2024,10 +2024,10 @@ } }, "contactSupport": { - "message": "Contact Customer Support" + "message": "Звязацца са службай падтрымкі" }, "updatedPaymentMethod": { - "message": "Updated payment method." + "message": "Спосаб аплаты абноўлены." }, "purchasePremium": { "message": "Купіць прэміяльны статус" @@ -2036,7 +2036,7 @@ "message": "Файл ліцэнзіі" }, "licenseFileDesc": { - "message": "Your license file will be named something like $FILE_NAME$", + "message": "Ваш файл з ліцэнзіяй будзе мець назву $FILE_NAME$", "placeholders": { "file_name": { "content": "$1", @@ -2045,16 +2045,16 @@ } }, "uploadLicenseFilePremium": { - "message": "To upgrade your account to a premium membership you need to upload a valid license file." + "message": "Для паляпшэння вашага ўліковага запісу да прэміяльнага ўдзельніка вам неабходна запампаваць сапраўдны файл з ліцэнзіяй." }, "uploadLicenseFileOrg": { - "message": "To create an on-premises hosted organization you need to upload a valid license file." + "message": "Для стварэння арганізацыі, якая будзе размешчана на лакальным хостынгу, вам неабходна запампаваць сапраўдны файл з ліцэнзіяй." }, "accountEmailMustBeVerified": { - "message": "Your account's email address must be verified." + "message": "Электронная пошта вашага ўліковага запісу павінна быць пацверджана." }, "newOrganizationDesc": { - "message": "Organizations allow you to share parts of your vault with others as well as manage related users for a specific entity such as a family, small team, or large company." + "message": "Арганізацыі дазваляюць дзяліцца элементамі вашага сховішча з іншымі, а таксама кіраваць звязанымі карыстальнікамі для вызначанага аб'екта. Гэта можа быць сям'я, невялікая каманда або вялікая кампанія." }, "generalInformation": { "message": "Агульная інфармацыя" @@ -2063,7 +2063,7 @@ "message": "Назва арганізацыі" }, "accountOwnedBusiness": { - "message": "This account is owned by a business." + "message": "Гэты ўліковы запіс належыць кампаніі." }, "billingEmail": { "message": "Адрас пошты для разлікаў" @@ -2107,7 +2107,7 @@ "description": "Free as in 'free beer'." }, "planDescFree": { - "message": "For testing or personal users to share with $COUNT$ other user.", + "message": "Для тэсціравання або асабістага выкарыстання з магчымасцю абагульнення з яшчэ $COUNT$ карыстальнікам.", "placeholders": { "count": { "content": "$1", @@ -2119,25 +2119,25 @@ "message": "Сямейны" }, "planDescFamilies": { - "message": "For personal use, to share with family & friends." + "message": "Для асабістага выкарыстання, каб мець магчымасць абагуліць з сям'ёй і сябрамі." }, "planNameTeams": { "message": "Каманды" }, "planDescTeams": { - "message": "For businesses and other team organizations." + "message": "Для кампаній і іншых камандных арганізацый." }, "planNameEnterprise": { "message": "Прадпрыемства" }, "planDescEnterprise": { - "message": "For businesses and other large organizations." + "message": "Для кампаній і іншых вялікіх арганізацый." }, "freeForever": { "message": "Бясплатна назаўсёды" }, "includesXUsers": { - "message": "includes $COUNT$ users", + "message": "уключае $COUNT$ карыстальнікаў", "placeholders": { "count": { "content": "$1", @@ -2158,7 +2158,7 @@ } }, "limitedUsers": { - "message": "Limited to $COUNT$ users (including you)", + "message": "Абмежаванне да $COUNT$ карыстальнікаў (разам з вамі)", "placeholders": { "count": { "content": "$1", @@ -2167,7 +2167,7 @@ } }, "limitedCollections": { - "message": "Limited to $COUNT$ collections", + "message": "Абмежаванне да $COUNT$ калекцый", "placeholders": { "count": { "content": "$1", @@ -2176,7 +2176,7 @@ } }, "addShareLimitedUsers": { - "message": "Add and share with up to $COUNT$ users", + "message": "Дабаўленне і абагульненне з $COUNT$ карыстальнікамі", "placeholders": { "count": { "content": "$1", @@ -2185,13 +2185,13 @@ } }, "addShareUnlimitedUsers": { - "message": "Add and share with unlimited users" + "message": "Дабаўленне і абагуленне з неабмежаванай колькасцю карыстальнікаў" }, "createUnlimitedCollections": { - "message": "Create unlimited Collections" + "message": "Стварэнне неабмежаваных калекцый" }, "gbEncryptedFileStorage": { - "message": "$SIZE$ encrypted file storage", + "message": "$SIZE$ зашыфраванага файлавага сховішча", "placeholders": { "size": { "content": "$1", @@ -2200,28 +2200,28 @@ } }, "onPremHostingOptional": { - "message": "On-premise hosting (optional)" + "message": "Лакальны хостынг (неабавязкова)" }, "usersGetPremium": { - "message": "Users get access to Premium Features" + "message": "Карыстальнікі атрымліваюць доступ да прэміяльных функцый" }, "controlAccessWithGroups": { - "message": "Control user access with Groups" + "message": "Кантроль доступу карыстальнікаў з дапамогай груп" }, "syncUsersFromDirectory": { - "message": "Sync your users and Groups from a directory" + "message": "Сінхранізацыя карыстальнікаў і груп з каталогу" }, "trackAuditLogs": { - "message": "Track user actions with audit logs" + "message": "Адсочванне дзеянняў карыстальнікаў з журнала аўдыту" }, "enforce2faDuo": { - "message": "Enforce 2FA with Duo" + "message": "Прымусовая 2ФА з Duo" }, "priorityCustomerSupport": { - "message": "Priority customer support" + "message": "Прыярытэтная падтрымка" }, "xDayFreeTrial": { - "message": "$COUNT$ day free trial, cancel anytime", + "message": "$COUNT$ дзён бясплатнага выпрабавальнага перыяду. Можна скасаваць у любы час", "placeholders": { "count": { "content": "$1", @@ -2230,7 +2230,7 @@ } }, "trialThankYou": { - "message": "Thanks for signing up for Bitwarden for $PLAN$!", + "message": "Дзякуй за падпіску на тарыфны план Bitwarden $PLAN$!", "placeholders": { "plan": { "content": "$1", @@ -2239,7 +2239,7 @@ } }, "trialPaidInfoMessage": { - "message": "Your $PLAN$ 7 day free trial will be converted to a paid subscription after 7 days.", + "message": "Ваш тарыфны план $PLAN$ праз 7 дзён выпрабавальнага перыяду будзе пераведзены на платную падпіску.", "placeholders": { "plan": { "content": "$1", @@ -2248,7 +2248,7 @@ } }, "trialConfirmationEmail": { - "message": "We've sent a confirmation email to your team's billing email at " + "message": "Мы адправілі ліст з пацвярджэннем на электронную пошту выстаўлення рахункаў для вашай каманды " }, "monthly": { "message": "Штомесяц" @@ -2263,22 +2263,22 @@ "message": "Базавы кошт" }, "organizationCreated": { - "message": "Organization Created" + "message": "Арганізацыя створана" }, "organizationReadyToGo": { - "message": "Your new organization is ready to go!" + "message": "Ваша новая арганізацыя гатова да выкарыстання!" }, "organizationUpgraded": { - "message": "Your organization has been upgraded." + "message": "Ваша арганізацыя была абноўлена." }, "leave": { "message": "Пакінуць" }, "leaveOrganizationConfirmation": { - "message": "Are you sure you want to leave this organization?" + "message": "Вы ўпэўнены, што хочаце пакінуць гэту арганізацыю?" }, "leftOrganization": { - "message": "You have left the organization." + "message": "Вы пакінулі арганізацыю." }, "defaultCollection": { "message": "Прадвызначаная калекцыя" @@ -2320,34 +2320,34 @@ "message": "Рэдагаваць групу" }, "deleteGroupConfirmation": { - "message": "Are you sure you want to delete this group?" + "message": "Вы ўпэўнены, што хочаце выдаліць гэту групу?" }, "removeUserConfirmation": { - "message": "Are you sure you want to remove this user?" + "message": "Вы ўпэўнены, што хочаце выдаліць гэтага карыстальніка?" }, "removeOrgUserConfirmation": { - "message": "When a member is removed, they no longer have access to organization data and this action is irreversible. To add the member back to the organization, they must be invited and onboarded again." + "message": "Пры выдаленні ўдзельніка, ён больш не зможа атрымаць доступ да даных арганізацыі і гэта дзеянне з'яўляецца незваротным. Для таго, каб зноў дадаць удзельніка ў арганізацыю, яго неабходна будзе запрасіць паўторна." }, "revokeUserConfirmation": { - "message": "When a member is revoked, they no longer have access to organization data. To quickly restore member access, go to the Revoked tab." + "message": "Пасля таго, як удзельнік адкліканы, ён больш не зможа атрымаць доступ да даных арганізацыі. Для хуткага аднаўлення доступу ўдзельніка, перайдзіце ва ўкладку \"Адкліканыя\"." }, "removeUserConfirmationKeyConnector": { - "message": "Warning! This user requires Key Connector to manage their encryption. Removing this user from your organization will permanently disable their account. This action cannot be undone. Do you want to proceed?" + "message": "Увага! Гэтаму карыстальніку патрабуецца Key Connector для таго, каб кіраваць шыфраваннем. Выдаленне гэтага карыстальніка з вашай арганізацыі канчаткова адключыць яго ўліковы запіс. Гэта дзеянне нельга будзе адрабіць. Вы сапраўды хочаце працягнуць?" }, "externalId": { "message": "Знешні ідэнтыфікатар" }, "externalIdDesc": { - "message": "The external id can be used as a reference or to link this resource to an external system such as a user directory." + "message": "Знешні ідэнтыфікатара можа быць выкарыстаны ў якасці спасылкі для сувязі гэтага рэсурсу са знешняй сістэмай, такой як каталог карыстальніка." }, "accessControl": { "message": "Кантроль доступу" }, "groupAccessAllItems": { - "message": "This group can access and modify all items." + "message": "Гэта група можа мець доступ і змяняць усе элементы." }, "groupAccessSelectedCollections": { - "message": "This group can access only the selected collections." + "message": "Гэта група можа мець доступ толькі да выбраных калекцый." }, "readOnly": { "message": "Толькі чытанне" @@ -2371,10 +2371,10 @@ "message": "Запрасіць карыстальніка" }, "inviteUserDesc": { - "message": "Invite a new user to your organization by entering their Bitwarden account email address below. If they do not have a Bitwarden account already, they will be prompted to create a new account." + "message": "Запрасіце новага карыстальніка ў вашу арганізацыю ўвёўшы яго электронную пошту ўліковага запісу Bitwarden. Калі ў яго пакуль няма ўліковага запісу Bitwarden, яму будзе прапанавана стварыць яго." }, "inviteMultipleEmailDesc": { - "message": "You can invite up to $COUNT$ users at a time by comma separating a list of email addresses.", + "message": "Вы можаце запрасіць да $COUNT$ карыстальнікаў за раз, падзяляючы адрасы электроннай пошты ў спісе коскамі.", "placeholders": { "count": { "content": "$1", @@ -2383,13 +2383,13 @@ } }, "userUsingTwoStep": { - "message": "This user is using two-step login to protect their account." + "message": "Гэты карыстальнік выкарыстоўвае двухэтапны ўваход для абароны свайго ўліковага запісу." }, "userAccessAllItems": { - "message": "This user can access and modify all items." + "message": "Гэты карыстальнік можа атрымліваць доступ і змяняць усе элементы." }, "userAccessSelectedCollections": { - "message": "This user can access only the selected collections." + "message": "Гэта карыстальнік можа мець доступ толькі да выбраных калекцый." }, "search": { "message": "Пошук" @@ -2410,7 +2410,7 @@ "message": "Уладальнік" }, "ownerDesc": { - "message": "The highest access user that can manage all aspects of your organization." + "message": "Карыстальнік з самым высокім узроўнем доступу, які можа кіраваць усімі аспектамі вашай арганізацыі." }, "clientOwnerDesc": { "message": "Гэты карыстальнік павінен быць незалежным ад пастаўшчыка. Калі пастаўшчык не звязаны з арганізацыяй, то гэты карыстальнік будзе падтрымліваць права ўласнасці арганізацыі." @@ -2419,19 +2419,19 @@ "message": "Адміністратар" }, "adminDesc": { - "message": "Admins can access and manage all items, collections and users in your organization." + "message": "Адміністратары могуць атрымліваць доступ і кіраваць усімі элементамі, калекцыямі і карыстальнікамі ў вашай арганізацыі." }, "user": { "message": "Карыстальнік" }, "userDesc": { - "message": "A regular user with access to assigned collections in your organization." + "message": "Звычайныя карыстальнікі з доступам да прызначаных калекцый у вашай арганізацыі." }, "manager": { "message": "Менеджар" }, "managerDesc": { - "message": "Managers can access and manage assigned collections in your organization." + "message": "Менеджары могуць атрымліваць доступ і кіраваць прызначанымі калекцыямі ў вашай арганізацыі." }, "all": { "message": "Усе" @@ -2470,31 +2470,31 @@ "message": "Выкананы ўваход." }, "changedPassword": { - "message": "Changed account password." + "message": "Пароль уліковага запісу зменены." }, "enabledUpdated2fa": { - "message": "Enabled/updated two-step login." + "message": "Двухэтапны ўваход уключаны/абноўлены." }, "disabled2fa": { - "message": "Disabled two-step login." + "message": "Двухэтапны ўваход адключаны." }, "recovered2fa": { - "message": "Recovered account from two-step login." + "message": "Уліковы запіс адноўлены пасля двухэтапнага ўваходу." }, "failedLogin": { - "message": "Login attempt failed with incorrect password." + "message": "Не атрымалася выканаць уваход з-за няправільнага пароля." }, "failedLogin2fa": { - "message": "Login attempt failed with incorrect two-step login." + "message": "Не атрымалася выканаць уваход з-за няправільнага двухэтапнага ўваходу." }, "exportedVault": { - "message": "Exported vault." + "message": "Сховішча экспартавана." }, "exportedOrganizationVault": { - "message": "Exported organization vault." + "message": "Сховішча арганізацыі экспартавана." }, "editedOrgSettings": { - "message": "Edited organization settings." + "message": "Налады арганізацыі адрэдагаваны." }, "createdItemId": { "message": "Створаны элемент $ID$.", @@ -2515,7 +2515,7 @@ } }, "deletedItemId": { - "message": "Sent item $ID$ to trash.", + "message": "Элемент $ID$ адпраўлены ў сметніцу.", "placeholders": { "id": { "content": "$1", @@ -2524,7 +2524,7 @@ } }, "movedItemIdToOrg": { - "message": "Moved item $ID$ to an organization.", + "message": "Элемент $ID$ перамешчаны ў арганізацыю.", "placeholders": { "id": { "content": "$1", @@ -2542,7 +2542,7 @@ } }, "viewedPasswordItemId": { - "message": "Viewed password for item $ID$.", + "message": "Прагледжаны пароль для элемента $ID$.", "placeholders": { "id": { "content": "$1", @@ -2551,7 +2551,7 @@ } }, "viewedHiddenFieldItemId": { - "message": "Viewed hidden field for item $ID$.", + "message": "Прагледжана схаванае поле для элемента $ID$.", "placeholders": { "id": { "content": "$1", @@ -2560,7 +2560,7 @@ } }, "viewedSecurityCodeItemId": { - "message": "Viewed security code for item $ID$.", + "message": "Прагледжаны код бяспекі для элемента $ID$.", "placeholders": { "id": { "content": "$1", @@ -2569,7 +2569,7 @@ } }, "copiedPasswordItemId": { - "message": "Copied password for item $ID$.", + "message": "Скапіяваны пароль для элемента $ID$.", "placeholders": { "id": { "content": "$1", @@ -2578,7 +2578,7 @@ } }, "copiedHiddenFieldItemId": { - "message": "Copied hidden field for item $ID$.", + "message": "Скапіявана схаванае поле для элемента $ID$.", "placeholders": { "id": { "content": "$1", @@ -2587,7 +2587,7 @@ } }, "copiedSecurityCodeItemId": { - "message": "Copied security code for item $ID$.", + "message": "Скапіяваны код бяспекі для элемента $ID$.", "placeholders": { "id": { "content": "$1", @@ -2596,7 +2596,7 @@ } }, "autofilledItemId": { - "message": "Auto-filled item $ID$.", + "message": "Аўтаматычна запоўнены элемент $ID$.", "placeholders": { "id": { "content": "$1", @@ -2605,7 +2605,7 @@ } }, "createdCollectionId": { - "message": "Created collection $ID$.", + "message": "Створана калекцыя $ID$.", "placeholders": { "id": { "content": "$1", @@ -2614,7 +2614,7 @@ } }, "editedCollectionId": { - "message": "Edited collection $ID$.", + "message": "Адрэдагавана калекцыя $ID$.", "placeholders": { "id": { "content": "$1", @@ -2623,7 +2623,7 @@ } }, "deletedCollectionId": { - "message": "Deleted collection $ID$.", + "message": "Выдалена калекцыя $ID$.", "placeholders": { "id": { "content": "$1", @@ -2686,7 +2686,7 @@ } }, "revokedUserId": { - "message": "Revoked organization access for $ID$.", + "message": "Адкліканы доступ арганізацыі для $ID$.", "placeholders": { "id": { "content": "$1", @@ -2695,7 +2695,7 @@ } }, "restoredUserId": { - "message": "Restored organization access for $ID$.", + "message": "Адноўлены доступ арганізацыі для $ID$.", "placeholders": { "id": { "content": "$1", @@ -2713,7 +2713,7 @@ } }, "createdAttachmentForItem": { - "message": "Created attachment for item $ID$.", + "message": "Створана далучэнне для элемента $ID$.", "placeholders": { "id": { "content": "$1", @@ -2722,7 +2722,7 @@ } }, "deletedAttachmentForItem": { - "message": "Deleted attachment for item $ID$.", + "message": "Выдалена далучэнне для элемента $ID$.", "placeholders": { "id": { "content": "$1", @@ -2731,7 +2731,7 @@ } }, "editedCollectionsForItem": { - "message": "Edited collections for item $ID$.", + "message": "Адрэдагаваныя калекцыі для элемента $ID$.", "placeholders": { "id": { "content": "$1", @@ -2767,7 +2767,7 @@ } }, "editedGroupsForUser": { - "message": "Edited groups for user $ID$.", + "message": "Адрэдагаваныя групы для карыстальніка $ID$.", "placeholders": { "id": { "content": "$1", @@ -2776,7 +2776,7 @@ } }, "unlinkedSsoUser": { - "message": "Unlinked SSO for user $ID$.", + "message": "Нязвязныя SSO для карыстальніка $ID$.", "placeholders": { "id": { "content": "$1", @@ -2785,7 +2785,7 @@ } }, "createdOrganizationId": { - "message": "Created organization $ID$.", + "message": "Створана арганізацыя $ID$.", "placeholders": { "id": { "content": "$1", @@ -2794,7 +2794,7 @@ } }, "addedOrganizationId": { - "message": "Added organization $ID$.", + "message": "Дададзена арганізацыя $ID$.", "placeholders": { "id": { "content": "$1", @@ -2803,7 +2803,7 @@ } }, "removedOrganizationId": { - "message": "Removed organization $ID$.", + "message": "Выдалена арганізацыя $ID$.", "placeholders": { "id": { "content": "$1", @@ -2812,7 +2812,7 @@ } }, "accessedClientVault": { - "message": "Accessed $ID$ organization vault.", + "message": "Доступ да сховішча арганізацыі $ID$.", "placeholders": { "id": { "content": "$1", @@ -2830,7 +2830,7 @@ "message": "Памылковы дыяпазон даты." }, "errorOccurred": { - "message": "An error has occurred." + "message": "Адбылася памылка." }, "userAccess": { "message": "Доступ карыстальніка" @@ -2842,7 +2842,7 @@ "message": "Доступ да групы" }, "groupAccessUserDesc": { - "message": "Edit the groups that this user belongs to." + "message": "Рэдагуйце групы да якіх належыць гэты карыстальнік." }, "invitedUsers": { "message": "Запрошаныя карыстальнікі." @@ -2854,7 +2854,7 @@ "message": "Адправіць ліст паўторна" }, "hasBeenReinvited": { - "message": "$USER$ has been reinvited.", + "message": "$USER$ быў запрошаны паўторна.", "placeholders": { "user": { "content": "$1", @@ -2869,7 +2869,7 @@ "message": "Пацвердзіць карыстальніка" }, "hasBeenConfirmed": { - "message": "$USER$ has been confirmed.", + "message": "$USER$ быў пацверджаны.", "placeholders": { "user": { "content": "$1", @@ -2881,7 +2881,7 @@ "message": "Пацвердзіць карыстальнікаў" }, "usersNeedConfirmed": { - "message": "You have users that have accepted their invitation, but still need to be confirmed. Users will not have access to the organization until they are confirmed." + "message": "У вас ёсць карыстальнікі, які прынялі запрашэнне, але патрабуюць пацвярджэння. Гэтыя карыстальнікі не будуць мець доступу да арганізацыі, пакуль не будуць пацверджаны." }, "startDate": { "message": "Дата пачатку" @@ -2893,49 +2893,49 @@ "message": "Праверыць пошту" }, "verifyEmailDesc": { - "message": "Verify your account's email address to unlock access to all features." + "message": "Параверце ваш адрас электроннай пошты для разблакіроўкі доступу да ўсіх функцый." }, "verifyEmailFirst": { - "message": "Your account's email address first must be verified." + "message": "Спачатку неабходна праверыць адрас электроннай пошты вашага ўліковага запісу." }, "checkInboxForVerification": { - "message": "Check your email inbox for a verification link." + "message": "У папцы ўваходныя павінен быць праверачны код." }, "emailVerified": { - "message": "Your email has been verified." + "message": "Ваша пошта была праверана." }, "emailVerifiedFailed": { - "message": "Unable to verify your email. Try sending a new verification email." + "message": "Немагчыма праверыць вашу пошту. Паспрабуйце адправіць новы праверачны ліст." }, "emailVerificationRequired": { - "message": "Email Verification Required" + "message": "Патрабуецца праверка электроннай пошты" }, "emailVerificationRequiredDesc": { - "message": "You must verify your email to use this feature." + "message": "Для выкарыстання гэтай функцыі патрабуецца праверыць электронную пошту." }, "updateBrowser": { "message": "Абнавіць браўзер" }, "updateBrowserDesc": { - "message": "You are using an unsupported web browser. The web vault may not function properly." + "message": "Ваш браўзер не падтрымліваецца. Вэб-сховішча можа працаваць няправільна." }, "joinOrganization": { "message": "Далучыцца да арганізацыі" }, "joinOrganizationDesc": { - "message": "You've been invited to join the organization listed above. To accept the invitation, you need to log in or create a new Bitwarden account." + "message": "Вас запрасілі далучыцца да арганізацыі, якая азначана вышэй. Для таго, каб прыняць запрашэнне, вам неабходна ўвайсці або стварыць новы ўліковы запіс Bitwarden." }, "inviteAccepted": { "message": "Запрашэнне прынята" }, "inviteAcceptedDesc": { - "message": "You can access this organization once an administrator confirms your membership. We'll send you an email when that happens." + "message": "Вы можаце атрымаць доступ да гэтага арганізацыі адразу пасля таго, як будзе пацверджаны ваш удзел. Мы апавясцім вас, калі гэта адбудзецца." }, "inviteAcceptFailed": { - "message": "Unable to accept invitation. Ask an organization admin to send a new invitation." + "message": "Немагчыма прыняць запрашэнне. Папрасіце адміністратара арганізацыі адправіць яго яшчэ раз." }, "inviteAcceptFailedShort": { - "message": "Unable to accept invitation. $DESCRIPTION$", + "message": "Немагчыма прыняць запрашэнне. $DESCRIPTION$", "placeholders": { "description": { "content": "$1", @@ -2950,22 +2950,22 @@ "message": "Калі вы не можаце атрымаць доступ да свайго ўліковага запісу з дапамогай двухэтапнага ўваходу, то вы можаце скарыстацца кодам аднаўлення, каб адключыць усіх пастаўшчыкоў двухэтапнага ўваходу для вашага ўліковага запісу." }, "recoverAccountTwoStep": { - "message": "Recover Account Two-Step Login" + "message": "Аднавіць двухэтапны ўваход уліковага запісу" }, "twoStepRecoverDisabled": { - "message": "Two-step login has been disabled on your account." + "message": "Двухэтапны ўваход быў адключаны для вашага ўліковага запісу." }, "learnMore": { "message": "Даведацца больш" }, "deleteRecoverDesc": { - "message": "Enter your email address below to recover and delete your account." + "message": "Увядзіце адрас сваёй электроннай ніжэй, каб аднавіць і выдаліць ваш уліковы запіс." }, "deleteRecoverEmailSent": { - "message": "If your account exists, we've sent you an email with further instructions." + "message": "Калі ваш уліковы запіс існуе, мы адправім вам ліст з далейшымі інструкцыямі." }, "deleteRecoverConfirmDesc": { - "message": "You have requested to delete your Bitwarden account. Click the button below to confirm." + "message": "Вы запыталі выдаленне вашага ўліковага запісу Bitwarden. Націсніце на кнопку ніжэй для пацвярджэння." }, "myOrganization": { "message": "Мая арганізацыя" @@ -2974,7 +2974,7 @@ "message": "Выдаліць арганізацыю" }, "deletingOrganizationContentWarning": { - "message": "Enter the master password to confirm deletion of $ORGANIZATION$ and all associated data. Vault data in $ORGANIZATION$ includes:", + "message": "Увядзіце галоўны пароль для пацвярджэння выдалення $ORGANIZATION$ і ўсіх звязаных даных. Даныя сховішча $ORGANIZATION$ уключаюць:", "placeholders": { "organization": { "content": "$1", @@ -2983,10 +2983,10 @@ } }, "deletingOrganizationActiveUserAccountsWarning": { - "message": "User accounts will remain active after deletion but will no longer be associated to this organization." + "message": "Уліковыя запісы карыстальнікаў застануцца актыўнымі пасля выдалення, але больш не будуць звязаны з гэтай арганізацыяй." }, "deletingOrganizationIsPermanentWarning": { - "message": "Deleting $ORGANIZATION$ is permanent and irreversible.", + "message": "Выдаленне $ORGANIZATION$ будзе канчатковым і незваротным.", "placeholders": { "organization": { "content": "$1", @@ -2998,7 +2998,7 @@ "message": "Арганізацыя выдалена" }, "organizationDeletedDesc": { - "message": "The organization and all associated data has been deleted." + "message": "Арганізацыя і ўсе звязаныя даныя былі выдалены." }, "organizationUpdated": { "message": "Арганізацыя абноўлена" @@ -3007,7 +3007,7 @@ "message": "Інфармацыя пра падаткі" }, "taxInformationDesc": { - "message": "For customers within the US, ZIP code is required to satisfy sales tax requirements, for other countries you may optionally provide a tax identification number (VAT/GST) and/or address to appear on your invoices." + "message": "Для кліентаў з ЗША, паштовы індэкс патрабуецца для выканання патрабаванняў падатковых органаў ад продажу праграмы. Для астатніх краін ідэнтыфікацыйны нумар падаткаплацельшчыка (VAT/GST) і/або адрас, які будзе азначаны ў рахунках указваць не абавязкова." }, "billingPlan": { "message": "Тарыфны план", @@ -3018,7 +3018,7 @@ "description": "A billing plan/package. For example: families, teams, enterprise, etc." }, "changeBillingPlanUpgrade": { - "message": "Upgrade your account to another plan by providing the information below. Please ensure that you have an active payment method added to the account.", + "message": "Палепшыце свой уліковы запіс да іншага тарыфнага плана, указаўшы інфармацыю ўнізе. Пераканайцеся, што ў вашым уліковым запісе ўжо ёсць актуальны спосаб аплаты.", "description": "A billing plan/package. For example: families, teams, enterprise, etc." }, "invoiceNumber": { @@ -3041,16 +3041,16 @@ "message": "Праверыць банкаўскі рахунак" }, "verifyBankAccountDesc": { - "message": "We have made two micro-deposits to your bank account (it may take 1-2 business days to show up). Enter these amounts to verify the bank account." + "message": "Мы зрабілі два сімвалічныя ўклады на ваш банкаўскі рахунак (ён адлюструецца ў спісе на працягу 1-2 працоўных дзён). Увядзіце гэту суму для праверкі банкаўскага рахунку." }, "verifyBankAccountInitialDesc": { "message": "Плацеж праз банкаўскі рахунак даступны толькі кліентам, якія пражываюць у ЗША. Вам неабходна будзе пацвердзіць свой банкаўскі рахунак. Мы зробім два сімвалічныя ўклады на працягу наступных 1-2 дзён. Увядзіце гэтыя сумы на старонцы аплаты арганізацыі для праверкі банкаўскага рахунку." }, "verifyBankAccountFailureWarning": { - "message": "Failure to verify the bank account will result in a missed payment and your subscription being disabled." + "message": "Невыкананне праверкі банкаўскага рахунку прывядзе да збою аплаты і адключэння падпіскі." }, "verifiedBankAccount": { - "message": "Bank account has been verified." + "message": "Банкаўскі рахунак быў правераны." }, "bankAccount": { "message": "Банкаўскі рахунак" @@ -3085,10 +3085,10 @@ "message": "Індывідуальны (персанальны)" }, "enterInstallationId": { - "message": "Enter your installation id" + "message": "Увядзіце ваш ідэнтыфікатар усталявання" }, "limitSubscriptionDesc": { - "message": "Set a seat limit for your subscription. Once this limit is reached, you will not be able to invite new users." + "message": "Прызначыць абмежаванне месцаў для вашай падпіскі. Пасля дасягнення гэтага абмежавання, вы не зможаце запрашаць новых карыстальнікаў." }, "maxSeatLimit": { "message": "Максімальная колькасць ліцэнзій (неабавязкова)", @@ -3109,7 +3109,7 @@ "message": "Карэкціроўка вашай падпіскі прывядзе да прапарцыйнага змянення ў вашым выніковым рахунку. Калі колькасць карыстальнікаў перавысіць колькасць ліцэнзій у вашай падпісцы, вы адразу атрымаеце прапарцыйную плату за дадатковых карыстальнікаў." }, "subscriptionUserSeats": { - "message": "Your subscription allows for a total of $COUNT$ users.", + "message": "Колькасць карыстальнікаў для вашай падпіскі: $COUNT$.", "placeholders": { "count": { "content": "$1", @@ -3118,7 +3118,7 @@ } }, "limitSubscription": { - "message": "Limit Subscription (Optional)" + "message": "Абмежаваць падпіску (неабавязкова)" }, "subscriptionSeats": { "message": "Месцы для падпіскі" @@ -3130,7 +3130,7 @@ "message": "Дадатковыя параметры" }, "additionalOptionsDesc": { - "message": "For additional help in managing your subscription, please contact Customer Support." + "message": "Для атрымання дадатковай дапамогі ў кіраванні вашай падпіскай, калі ласка, звярніцеся ў службу падтрымкі." }, "subscriptionUserSeatsUnlimitedAutoscale": { "message": "Карэкціроўка вашай падпіскі прывядзе да прапарцыйнага змянення ў вашым выніковым рахунку. Калі колькасць карыстальнікаў перавысіць колькасць ліцэнзій у вашай падпісцы, вы адразу атрымаеце прапарцыйную плату за дадатковых карыстальнікаў." @@ -3145,7 +3145,7 @@ } }, "subscriptionFreePlan": { - "message": "You cannot invite more than $COUNT$ users without upgrading your plan.", + "message": "Вы не можаце запрасіць больш чым $COUNT$ карыстальнікаў без паляпшэння тарыфнага плана.", "placeholders": { "count": { "content": "$1", @@ -3154,7 +3154,7 @@ } }, "subscriptionFamiliesPlan": { - "message": "You cannot invite more than $COUNT$ users without upgrading your plan. Please contact Customer Support to upgrade.", + "message": "Вы не можаце запрасіць больш чым $COUNT$ карыстальнікаў без паляпшэння тарыфнага плана. Звярніцеся з нашай службай падтрымкі для паляпшэння.", "placeholders": { "count": { "content": "$1", @@ -3163,7 +3163,7 @@ } }, "subscriptionSponsoredFamiliesPlan": { - "message": "Your subscription allows for a total of $COUNT$ users. Your plan is sponsored and billed to an external organization.", + "message": "Колькасць карыстальнікаў для вашай падпіскі: $COUNT$. Ваш тарыфны план мае спонсарскую падтрымку і аплачваецца знешняй арганізацыяй.", "placeholders": { "count": { "content": "$1", @@ -3193,7 +3193,7 @@ "message": "Выдаленне карыстальніцкіх ліцэнзій прывядзе да змен у вашым выніковым рахунку, які будзе прапарцыйна раздзелены ў выглядзе крэдытаў за наступны плацежны перыяд." }, "adjustedSeats": { - "message": "Adjusted $AMOUNT$ user seats.", + "message": "Скарэктавана месцаў карыстальніка: $AMOUNT$.", "placeholders": { "amount": { "content": "$1", @@ -3211,16 +3211,16 @@ "message": "Абнавіць ключ шыфравання" }, "updateEncryptionKeyShortDesc": { - "message": "You are currently using an outdated encryption scheme." + "message": "Зараз вы выкарыстоўваеце састарэлую схему шыфравання." }, "updateEncryptionKeyDesc": { - "message": "We've moved to larger encryption keys that provide better security and access to newer features. Updating your encryption key is quick and easy. Just type your master password below. This update will eventually become mandatory." + "message": "Мы перайшлі на больш складаныя ключы шыфравання, якія забяспечваюць лепшую бяспеку і доступ да самых новых функцый. Абнаўленне вашы ключоў шыфравання адбываецца хутка і лёгка. Проста ўвядзіце свой галоўны пароль знізу. Гэта абнаўленне ўрэшце стане абавязковым." }, "updateEncryptionKeyWarning": { "message": "Пасля абнаўлення вашага ключа шыфравання вам неабходна выйсці з сістэмы, а потым выканаць паўторны ўваход ва ўсе праграмы Bitwarden, якія вы зараз выкарыстоўваеце (напрыклад, мабільныя праграмы або пашырэнні для браўзераў). Збой пры выхадзе і паўторным уваходзе (пры гэтым спампоўваецца ваш новы ключ шыфравання) можа стаць прычынай пашкоджання даных. Мы паспрабуем аўтаматычна ажыццявіць завяршэнне ўсіх вашых сеансаў, але гэта можа адбывацца з затрымкай." }, "updateEncryptionKeyExportWarning": { - "message": "Any encrypted exports that you have saved will also become invalid." + "message": "Любыя зашыфраваныя экспартаванні, якія вы захавалі, таксама стануць памылковымі." }, "subscription": { "message": "Падпіска" @@ -3235,25 +3235,25 @@ "message": "Палепшыць арганізацыю" }, "upgradeOrganizationDesc": { - "message": "This feature is not available for free organizations. Switch to a paid plan to unlock more features." + "message": "Гэта функцыя недаступна для бясплатных арганізацый. Перайдзіце на платны тарыфны план, каб разблакіраваць дадатковыя функцыі." }, "createOrganizationStep1": { - "message": "Create Organization: Step 1" + "message": "Стварэнне арганізацыі: Крок 1" }, "createOrganizationCreatePersonalAccount": { - "message": "Before creating your organization, you first need to create a free personal account." + "message": "Спачатку вы павінны стварыць бясплатны ўліковы запіс, а потым перайсці да стварэння арганізацыі." }, "refunded": { "message": "Вернута" }, "nothingSelected": { - "message": "You have not selected anything." + "message": "Вы нічога не выбралі." }, "acceptPolicies": { - "message": "By checking this box you agree to the following:" + "message": "Ставячы гэты сцяжок вы пагаджаецеся з наступным:" }, "acceptPoliciesRequired": { - "message": "Terms of Service and Privacy Policy have not been acknowledged." + "message": "Умовы выкарыстання і Палітыка прыватнасці не былі пацверджаны." }, "termsOfService": { "message": "Умовы выкарыстання" @@ -3268,7 +3268,7 @@ "message": "Час чакання сховішча" }, "vaultTimeoutDesc": { - "message": "Choose when your vault will take the vault timeout action." + "message": "Выберыце дзеянне, якое неабходна выканаць пасля завяршэння часу чакання сховішча." }, "oneMinute": { "message": "1 хвіліна" @@ -3300,10 +3300,10 @@ "description": "ex. Date this password was updated" }, "organizationIsDisabled": { - "message": "Organization is disabled." + "message": "Арганізацыя адключана." }, "disabledOrganizationFilterError": { - "message": "Items in disabled Organizations cannot be accessed. Contact your Organization owner for assistance." + "message": "Доступ да элементаў у адключаных арганізацыях немагчымы. Звяжыце з уладальнікам арганізацыі для атрымання дапамогі." }, "licenseIsExpired": { "message": "Ліцэнзія пратэрмінавана." @@ -3343,37 +3343,37 @@ "message": "Асноўны пароль, які вы выбралі з'яўляецца ненадзейным. Для належнай абароны ўліковага запісу Bitwarden, вы павінны выкарыстоўваць надзейны асноўны пароль (або парольную фразу). Вы ўпэўнены, што хочаце выкарыстоўваць гэты асноўны пароль?" }, "rotateAccountEncKey": { - "message": "Also rotate my account's encryption key" + "message": "Таксама змяніць ключ шыфравання майго ўліковага запісу" }, "rotateEncKeyTitle": { "message": "Змяніць ключ шыфравання" }, "rotateEncKeyConfirmation": { - "message": "Are you sure you want to rotate your account's encryption key?" + "message": "Вы ўпэўнены, што хочаце змяніць ключ шыфравання свайго ўліковага запісу?" }, "attachmentsNeedFix": { - "message": "This item has old file attachments that need to be fixed." + "message": "Гэты элемент мае старыя далучаныя файлы, якія неабходна выправіць." }, "attachmentFixDesc": { - "message": "This is an old file attachment the needs to be fixed. Click to learn more." + "message": "Гэта стары далучаны файл, які неабходна выправіць. Націсніце, каб даведацца больш." }, "fix": { "message": "Выправіць", "description": "This is a verb. ex. 'Fix The Car'" }, "oldAttachmentsNeedFixDesc": { - "message": "There are old file attachments in your vault that need to be fixed before you can rotate your account's encryption key." + "message": "У вашым сховішчы ёсць старыя далучаныя файлы, якія неабходна выправіць перад тым, як змяніць ключ шыфравання ўліковага запісу." }, "yourAccountsFingerprint": { - "message": "Your account's fingerprint phrase", + "message": "Фраза адбітку вашага ўліковага запісу", "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." }, "fingerprintEnsureIntegrityVerify": { - "message": "To ensure the integrity of your encryption keys, please verify the user's fingerprint phrase before continuing.", + "message": "Для забеспячэння цэласнасці вашых ключоў шыфравання, калі ласка, праверце фразу адбітка пальца карыстальніка.", "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." }, "dontAskFingerprintAgain": { - "message": "Never prompt to verify fingerprint phrases for invited users (Not recommended)", + "message": "Ніколі не пытаць пра праверку фразы адбітку пальца для запрошаных карыстальнікаў (не рэкамендуецца)", "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." }, "free": { @@ -3384,22 +3384,22 @@ "message": "Ключ API" }, "apiKeyDesc": { - "message": "Your API key can be used to authenticate to the Bitwarden public API." + "message": "Ваш ключ API можа быць выкарыстаны для аўтэнтыфікацыі публічнага API праграмы." }, "apiKeyRotateDesc": { - "message": "Rotating the API key will invalidate the previous key. You can rotate your API key if you believe that the current key is no longer safe to use." + "message": "Змяненне ключа API анулюе папярэдні ключ. Вы можаце змяніць ваш ключ API, калі ёсць любыя сумневы адносна бяспекі бягучага ключа." }, "apiKeyWarning": { - "message": "Your API key has full access to the organization. It should be kept secret." + "message": "Ваш ключ API мае поўны доступ да арганізацыі. Яго неабходна захоўваць у надзейным месцы." }, "userApiKeyDesc": { - "message": "Your API key can be used to authenticate in the Bitwarden CLI." + "message": "Ваш ключ API можа быць выкарыстаны для аўтэнтыфікацыі ў Bitwarden CLI." }, "userApiKeyWarning": { - "message": "Your API key is an alternative authentication mechanism. It should be kept secret." + "message": "Ваш ключ API з'яўляецца альтэрнатыўным механізмам аўтэнтыфікацыі. Яго неабходна захоўваць у надзейным месцы." }, "oauth2ClientCredentials": { - "message": "OAuth 2.0 Client Credentials", + "message": "Уліковыя даныя кліента OAuth 2.0", "description": "'OAuth 2.0' is a programming protocol. It should probably not be translated." }, "viewApiKey": { @@ -3409,19 +3409,19 @@ "message": "Змяніць ключ API" }, "selectOneCollection": { - "message": "You must select at least one collection." + "message": "Вы павінны выбраць прынамсі адну калекцыю." }, "couldNotChargeCardPayInvoice": { - "message": "We were not able to charge your card. Please view and pay the unpaid invoice listed below." + "message": "Мы не можам змяніць вашу картку. Калі ласка, паглядзіце і заплаціце за ўсе пратэрмінаваныя рахункі, якія азначаны ніжэй." }, "inAppPurchase": { - "message": "In-app Purchase" + "message": "Купля ў праграме" }, "cannotPerformInAppPurchase": { - "message": "You cannot perform this action while using an in-app purchase payment method." + "message": "Вы не можаце выканаць гэта дзеянне падчас выкарыстання аплаты ў праграме." }, "manageSubscriptionFromStore": { - "message": "You must manage your subscription from the store where your in-app purchase was made." + "message": "Вы павінны кіраваць сваёй падпіскай з той крамы, у якой вы ажыццяўлялі куплю праграмы." }, "minLength": { "message": "Мінімальная даўжыня" @@ -3430,34 +3430,34 @@ "message": "Кланіраваць" }, "masterPassPolicyTitle": { - "message": "Master password requirements" + "message": "Патрабуецца асноўны пароль" }, "masterPassPolicyDesc": { "message": "Задайце мінімальныя патрабаванні для надзейнасці асноўнага пароля." }, "twoStepLoginPolicyTitle": { - "message": "Require two-step login" + "message": "Патрабуецца двухэтапны ўваход" }, "twoStepLoginPolicyDesc": { - "message": "Require members to set up two-step login." + "message": "Патрабаваць удзельнікаў наладу двуэтапнага ўваходу." }, "twoStepLoginPolicyWarning": { - "message": "Organization members who are not Owners or Administrators and do not have two-step login turned on for their account will be removed from the organization and will receive an email notifying them about the change." + "message": "Удзельнікі арганізацыі, якія не з'яўляюцца ўладальнікамі або адміністратарамі і якія не ўключылі двухэтапны ўваход у сваіх уліковых запісаць будуць выдалены з арганізацыі і атрымаюць адпаведнае апавяшчэнне па электроннай пошце." }, "twoStepLoginPolicyUserWarning": { "message": "Вы з'яўляецеся ўдзельнікам арганізацыі, якая патрабуе выкарыстанне двухэтапнага ўваходу для вашага ўліковага запісу. Калі вы адключыце ўсіх пастаўшчыкоў двухэтапнага ўваходу, то вы будзеце аўтаматычна выдалены з гэтай арганізацыі." }, "passwordGeneratorPolicyDesc": { - "message": "Set requirements for password generator." + "message": "Прызначыць патрабаванні для генератара пароляў." }, "passwordGeneratorPolicyInEffect": { - "message": "One or more organization policies are affecting your generator settings." + "message": "На налады генератара ўплываюць адна або некалькі палітык арганізацый." }, "masterPasswordPolicyInEffect": { "message": "Згодна з адной або некалькімі палітыкамі арганізацыі асноўны пароль павінен адпавядаць наступным патрабаванням:" }, "policyInEffectMinComplexity": { - "message": "Minimum complexity score of $SCORE$", + "message": "Мінімальны ўзровень складанасці $SCORE$", "placeholders": { "score": { "content": "$1", @@ -3466,7 +3466,7 @@ } }, "policyInEffectMinLength": { - "message": "Minimum length of $LENGTH$", + "message": "Мінімальная даўжыня $LENGTH$", "placeholders": { "length": { "content": "$1", @@ -3475,16 +3475,16 @@ } }, "policyInEffectUppercase": { - "message": "Contain one or more uppercase characters" + "message": "Уключыць адну ці больш вялікіх літар" }, "policyInEffectLowercase": { - "message": "Contain one or more lowercase characters" + "message": "Уключыць адну ці больш малых літар" }, "policyInEffectNumbers": { - "message": "Contain one or more numbers" + "message": "Уключыць адну або больш лічбаў" }, "policyInEffectSpecial": { - "message": "Contain one or more of the following special characters $CHARS$", + "message": "Уключаць хаця б адзін з наступных спецыяльных сімвалаў $CHARS$", "placeholders": { "chars": { "content": "$1", @@ -3496,22 +3496,22 @@ "message": "Ваш новы асноўны пароль не адпавядае патрабаванням палітыцы." }, "minimumNumberOfWords": { - "message": "Minimum Number of Words" + "message": "Мінімум лічбаў або слоў" }, "defaultType": { "message": "Прадвызначаны тып" }, "userPreference": { - "message": "User Preference" + "message": "Параметры карыстальніка" }, "vaultTimeoutAction": { "message": "Дзеянне пасля заканчэння часу сховішча" }, "vaultTimeoutActionLockDesc": { - "message": "Master password or other unlock method is required to access your vault again." + "message": "Для таго, каб атрымаць доступ да заблакіраванага сховішча, вам неабходна ўвесці галоўны пароль або скарыстацца іншым метадам разблакіроўкі." }, "vaultTimeoutActionLogOutDesc": { - "message": "Re-authentication is required to access your vault again." + "message": "Для таго, каб аднавіць доступ да сховішча, патрабуецца паўторная аўтарызацыя." }, "lock": { "message": "Заблакіраваць", @@ -3528,22 +3528,22 @@ "message": "Выдаліць канчаткова" }, "permanentlyDeleteSelected": { - "message": "Permanently Delete Selected" + "message": "Назаўсёды выдаліць выбраныя" }, "permanentlyDeleteItem": { - "message": "Permanently Delete Item" + "message": "Назаўсёды выдаліць элементы" }, "permanentlyDeleteItemConfirmation": { - "message": "Are you sure you want to permanently delete this item?" + "message": "Вы ўпэўнены, што хочаце назаўсёды выдаліць гэтыя элементы?" }, "permanentlyDeletedItem": { - "message": "Permanently Deleted item" + "message": "Элемент выдалены назаўсёды" }, "permanentlyDeletedItems": { - "message": "Permanently Deleted items" + "message": "Элементы выдалены назаўсёды" }, "permanentlyDeleteSelectedItemsDesc": { - "message": "You have selected $COUNT$ item(s) to permanently delete. Are you sure you want to permanently delete all of these items?", + "message": "Вы выбралі наступную колькасць запісаў для выдалення: $COUNT$ шт. Вы ўпэўнены, што хочаце назаўсёды выдаліць гэтыя элементы?", "placeholders": { "count": { "content": "$1", @@ -3552,7 +3552,7 @@ } }, "permanentlyDeletedItemId": { - "message": "Permanently Deleted item $ID$.", + "message": "Элемент $ID$ выдалены назаўсёды.", "placeholders": { "id": { "content": "$1", @@ -3576,13 +3576,13 @@ "message": "Адноўленыя элементы" }, "restoreItemConfirmation": { - "message": "Are you sure you want to restore this item?" + "message": "Вы ўпэўнены, што хочаце аднавіць гэты элемент?" }, "restoreItems": { "message": "Аднавіць элементы" }, "restoreSelectedItemsDesc": { - "message": "You have selected $COUNT$ item(s) to restore. Are you sure you want to restore all of these items?", + "message": "Вы выбралі наступную колькасць запісаў для аднаўлення: $COUNT$. Вы ўпэўнены, што хочаце аднавіць гэтыя элементы?", "placeholders": { "count": { "content": "$1", @@ -3600,52 +3600,52 @@ } }, "vaultTimeoutLogOutConfirmation": { - "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + "message": "Выхад з сістэмы скасуе ўсе магчымасці доступу да сховішча і запатрабуе аўтэнтыфікацыі праз інтэрнэт пасля завяршэння часу чакання. Вы ўпэўнены, што хочаце выкарыстоўваць гэты параметр?" }, "vaultTimeoutLogOutConfirmationTitle": { - "message": "Timeout Action Confirmation" + "message": "Пацвярджэнне дзеяння часу чакання" }, "hidePasswords": { "message": "Схаваць паролі" }, "countryPostalCodeRequiredDesc": { - "message": "We require this information for calculating sales tax and financial reporting only." + "message": "Нам неабходна гэта інфармацыя толькі для падліку падатку ад продажу і фінансавай справаздачы." }, "includeVAT": { - "message": "Include VAT/GST Information (optional)" + "message": "Уключыць інфармацыю пра VAT/GST (неабавязкова)" }, "taxIdNumber": { - "message": "VAT/GST Tax ID" + "message": "Ідэнтыфікатар падатку VAT/GST" }, "taxInfoUpdated": { - "message": "Tax information updated." + "message": "Падатковая інфармацыя абноўлена." }, "setMasterPassword": { "message": "Задаць асноўны пароль" }, "ssoCompleteRegistration": { - "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + "message": "Для завяршэння працэсу ўваходу з дапамогай SSO, прызначце галоўны пароль для доступу да вашага сховішча і яго абароны." }, "identifier": { "message": "Ідэнтыфікатар" }, "organizationIdentifier": { - "message": "Organization Identifier" + "message": "Ідэнтыфікатар арганізацыі" }, "ssoLogInWithOrgIdentifier": { - "message": "Log in using your organization's single sign-on portal. Please enter your organization's identifier to begin." + "message": "Уваходзьце з выкарыстаннем партала адзінага ўваходу вашай арганізацыі. Калі ласка, увядзіце ідэнтыфікатар вашай арганізацыі для пачатку працы." }, "enterpriseSingleSignOn": { - "message": "Enterprise Single Sign-On" + "message": "Адзіны карпаратыўны ўваход (SSO)" }, "ssoHandOff": { - "message": "You may now close this tab and continue in the extension." + "message": "Цяпер вы можаце закрыць гэту ўкладку і працягнуць у пашырэнні." }, "includeAllTeamsFeatures": { - "message": "All Teams features, plus:" + "message": "Усе функцыі каманд, плюс:" }, "includeSsoAuthentication": { - "message": "SSO Authentication via SAML2.0 and OpenID Connect" + "message": "Аўтэнтыфікацыя SSO праз SAML2.0 і OpenID Connect" }, "includeEnterprisePolicies": { "message": "Палітыкі прадпрыемства" @@ -3654,13 +3654,13 @@ "message": "Збой праверкі SSO" }, "ssoIdentifierRequired": { - "message": "Organization Identifier is required." + "message": "Неабходны ідэнтыфікатар арганізацыі." }, "unlinkSso": { "message": "Адлучыць SSO" }, "unlinkSsoConfirmation": { - "message": "Are you sure you want to unlink SSO for this organization?" + "message": "Вы ўпэўнены, што хочаце адлучыць SSO для гэтай арганізацыі?" }, "linkSso": { "message": "Падлучыць SSO" @@ -3669,31 +3669,31 @@ "message": "Адна арганізацыя" }, "singleOrgDesc": { - "message": "Restrict members from joining other organizations." + "message": "Забараніць удзельнікам далучацца да іншых арганізацый." }, "singleOrgBlockCreateMessage": { - "message": "Your current organization has a policy that does not allow you to join more than one organization. Please contact your organization admins or sign up from a different Bitwarden account." + "message": "Ваша бягучая арганізацыя мае палітыку, якая не дазваляе вам далучацца да больш чым да адной арганізацыі. Калі ласка, звяжыцеся з адміністратарам вашай арганізацыі або ўвайдзіце пад іншым уліковым запісам Bitwarden." }, "singleOrgPolicyWarning": { - "message": "Organization members who are not Owners or Administrators and are already a member of another organization will be removed from your organization." + "message": "Удзельнікі арганізацыі, якія не з'яўляюцца ўладальнікамі або адміністратарамі і ўжо ўваходзяць у іншую арганізацыю будуць выдалены з вашай арганізацыі." }, "requireSso": { - "message": "Require single sign-on authentication" + "message": "Патрабаваць аўтэнтыфікацыю праз адзіны ўваход (SSO)" }, "requireSsoPolicyDesc": { - "message": "Require members to log in with the Enterprise Single Sign-On method." + "message": "Патрабаваць ад удзельнікаў уваходзіць праз адзіны карпаратыўны ўваход (SSO)." }, "prerequisite": { "message": "Перадумова" }, "requireSsoPolicyReq": { - "message": "The Single Organization enterprise policy must be turned on before activating this policy." + "message": "Перад актывацыяй гэтай палітыкі неабходна ўключыць палітыку адзінага ўваходу (SSO)." }, "requireSsoPolicyReqError": { - "message": "Single Organization policy not enabled." + "message": "Палітыка адзінай арганізацыі не ўключана." }, "requireSsoExemption": { - "message": "Organization Owners and Administrators are exempt from this policy's enforcement." + "message": "На ўладальнікаў арганізацыі і адміністратараў гэта палітыка не аказвае ўплыву." }, "sendTypeFile": { "message": "Файл" @@ -3702,7 +3702,7 @@ "message": "Тэкст" }, "createSend": { - "message": "Create New Send", + "message": "Стварыць новы Send", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "editSend": { @@ -3726,43 +3726,43 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "deleteSendConfirmation": { - "message": "Are you sure you want to delete this Send?", + "message": "Вы ўпэўнены, што хочаце выдаліць гэты Send?", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "whatTypeOfSend": { - "message": "What type of Send is this?", + "message": "Які гэта тып Send?", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "deletionDate": { "message": "Дата выдалення" }, "deletionDateDesc": { - "message": "The Send will be permanently deleted on the specified date and time.", + "message": "Send будзе незваротна выдалены ў азначаныя дату і час.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "expirationDate": { - "message": "Expiration Date" + "message": "Дата завяршэння" }, "expirationDateDesc": { - "message": "If set, access to this Send will expire on the specified date and time.", + "message": "Калі зададзена, то доступ да гэтага Send міне ў азначаную дату і час.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "maxAccessCount": { "message": "Максімальная колькасць доступаў" }, "maxAccessCountDesc": { - "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "message": "Калі зададзена, то карыстальнікі больш не змогуць атрымаць доступ да гэтага Send пасля таго, як будзе дасягнута максімальная колькасць зваротаў.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "currentAccessCount": { "message": "Бягучая колькасць доступаў" }, "sendPasswordDesc": { - "message": "Optionally require a password for users to access this Send.", + "message": "Па магчымасці запытваць у карыстальнікаў пароль для доступу да гэтага Send.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendNotesDesc": { - "message": "Private notes about this Send.", + "message": "Прыватныя нататкі пра гэты Send.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "disabled": { @@ -3780,26 +3780,26 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "removePassword": { - "message": "Remove Password" + "message": "Выдаліць пароль" }, "removedPassword": { "message": "Пароль выдалены" }, "removePasswordConfirmation": { - "message": "Are you sure you want to remove the password?" + "message": "Вы ўпэўнены, што хочаце выдаліць пароль?" }, "hideEmail": { - "message": "Hide my email address from recipients." + "message": "Схаваць мой адрас электроннай пошты ад атрымальнікаў." }, "disableThisSend": { - "message": "Disable this Send so that no one can access it.", + "message": "Адключыць гэты Send, каб ніхто не змог атрымаць да яго доступ.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "allSends": { "message": "Усе адпраўленні" }, "maxAccessCountReached": { - "message": "Max access count reached", + "message": "Дасягнута максімальная колькасць доступаў", "description": "This text will be displayed after a Send has been accessed the maximum amount of times." }, "pendingDeletion": { @@ -3813,30 +3813,30 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendProtectedPassword": { - "message": "This Send is protected with a password. Please type the password below to continue.", + "message": "Гэты Send абаронены паролем. Увядзіце пароль ніжэй, каб працягнуць.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendProtectedPasswordDontKnow": { - "message": "Don't know the password? Ask the Sender for the password needed to access this Send.", + "message": "Не ведаеце пароль? Спытайце ў адпраўніка пароль, які неабходны для доступу да гэтага Send.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendHiddenByDefault": { - "message": "This send is hidden by default. You can toggle its visibility using the button below.", + "message": "Прадвызначана гэты Send схаваны. Вы можаце змяніць яго бачнасць выкарыстоўваючы кнопку ніжэй.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "downloadFile": { "message": "Спампаваць файл" }, "sendAccessUnavailable": { - "message": "The Send you are trying to access does not exist or is no longer available.", + "message": "Send да якога вы спрабуеце атрымаць доступ не існуе або больш недаступны.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "missingSendFile": { - "message": "The file associated with this Send could not be found.", + "message": "Не атрымалася знайсці файл, якія звязаны з гэтым Send.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "noSendsInList": { - "message": "There are no Sends to list.", + "message": "У спісе адсутнічае Send.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "emergencyAccess": { @@ -3846,52 +3846,52 @@ "message": "Забяспечце экстранны доступ давераным кантактам. Давераныя кантакты могуць атрымаць доступ для прагляду або перадачы валодання вашым уліковы запісам у экстранных сітуацыях. Наведайце нашу старонку дапамогі для падрабязнага азнаямлення, як працуе супольны доступ нулявога ўзроўню." }, "emergencyAccessOwnerWarning": { - "message": "You are an Owner of one or more organizations. If you give takeover access to an emergency contact, they will be able to use all your permissions as Owner after a takeover." + "message": "Вы ўладальнік адной або некалькіх арганізацый. Калі перадаць доступ валодання экстранным кантактам, то ён будзе мець усе дазволы ўладальніка пасля перадачы." }, "trustedEmergencyContacts": { - "message": "Trusted emergency contacts" + "message": "Давераныя экстранныя кантакты" }, "noTrustedContacts": { - "message": "You have not added any emergency contacts yet, invite a trusted contact to get started." + "message": "Пакуль вы не дадалі ніводнага экстраннага кантакту. Запрасіце давераны кантакт, каб зрабіць гэта." }, "addEmergencyContact": { "message": "Дадаць экстранны кантакт" }, "designatedEmergencyContacts": { - "message": "Designated as emergency contact" + "message": "Прызначаны ў якасці экстраннага кантакту" }, "noGrantedAccess": { - "message": "You have not been designated as an emergency contact for anyone yet." + "message": "Вы нікога пакуль не прызначылі ў якасці экстраннага кантакту." }, "inviteEmergencyContact": { - "message": "Invite emergency contact" + "message": "Запрасіць экстранны кантакт" }, "editEmergencyContact": { - "message": "Edit emergency contact" + "message": "Рэдагаваць экстранны кантакт" }, "inviteEmergencyContactDesc": { - "message": "Invite a new emergency contact by entering their Bitwarden account email address below. If they do not have a Bitwarden account already, they will be prompted to create a new account." + "message": "Запрасіць новы экстранны кантакт, увёўшы электронную пошту яго ўліковага запісу Bitwarden ніжэй. Калі ён не мае ўліковага запісу, то ён атрымае запыт на яго стварэнне." }, "emergencyAccessRecoveryInitiated": { - "message": "Emergency Access Initiated" + "message": "Ініцыялізаваны экстранны доступ" }, "emergencyAccessRecoveryApproved": { - "message": "Emergency Access Approved" + "message": "Экстранны доступ ухвалены" }, "viewDesc": { - "message": "Can view all items in your own vault." + "message": "Можа праглядаць усе запісы ў вашым сховішчы." }, "takeover": { "message": "Перадача ўласнасці" }, "takeoverDesc": { - "message": "Can reset your account with a new master password." + "message": "Можа скідаць пароль вашага ўліковага запісу." }, "waitTime": { "message": "Час чакання" }, "waitTimeDesc": { - "message": "Time required before automatically granting access." + "message": "Час, пасля якога доступ будзе дазволены аўтаматычна." }, "oneDay": { "message": "1 дзень" @@ -3909,13 +3909,13 @@ "message": "Запрошаны карыстальнік." }, "acceptEmergencyAccess": { - "message": "You've been invited to become an emergency contact for the user listed above. To accept the invitation, you need to log in or create a new Bitwarden account." + "message": "Вас запрасілі стаць экстранным кантактам для карыстальніка, які пазначаны вышэй. Для таго, каб прыняць запрашэнне, вам неабходна ўвайсці або стварыць новы ўліковы запіс Bitwarden." }, "emergencyInviteAcceptFailed": { - "message": "Unable to accept invitation. Ask the user to send a new invitation." + "message": "Немагчыма прыняць запрашэнне. Папрасіце карыстальніка адправіць новае запрашэнне." }, "emergencyInviteAcceptFailedShort": { - "message": "Unable to accept invitation. $DESCRIPTION$", + "message": "Немагчыма прыняць запрашэнне. $DESCRIPTION$", "placeholders": { "description": { "content": "$1", @@ -3924,13 +3924,13 @@ } }, "emergencyInviteAcceptedDesc": { - "message": "You can access the emergency options for this user after your identity has been confirmed. We'll send you an email when that happens." + "message": "Вы зможаце атрымаць доступ да экстранных параметраў для гэтага карыстальніка пасля пацвярджэння сваёй асобы. Мы адправім вам ліст, калі гэта адбудзецца." }, "requestAccess": { "message": "Запытаць доступ" }, "requestAccessConfirmation": { - "message": "Are you sure you want to request emergency access? You will be provided access after $WAITTIME$ day(s) or whenever the user manually approves the request.", + "message": "Вы ўпэўнены, што хочаце запытаць экстранны доступ? Вам будзе забяспечаны доступ праз $WAITTIME$ дзён або калі карыстальнік уручную ўхваліць вас.", "placeholders": { "waittime": { "content": "$1", @@ -3939,7 +3939,7 @@ } }, "requestSent": { - "message": "Emergency access requested for $USER$. We'll notify you by email when it's possible to continue.", + "message": "Экстранны доступ запрошаны для $USER$. Вы апавясцім вас па электроннай пошце, калі можна будзе працягнуць.", "placeholders": { "user": { "content": "$1", @@ -3954,7 +3954,7 @@ "message": "Адхіліць" }, "approveAccessConfirmation": { - "message": "Are you sure you want to approve emergency access? This will allow $USER$ to $ACTION$ your account.", + "message": "Вы ўпэўнены, што хочаце ўхваліць экстранны доступ? Гэта дазволіць карыстальніку $USER$ $ACTION$ ваш уліковы запіс.", "placeholders": { "user": { "content": "$1", @@ -3967,13 +3967,13 @@ } }, "emergencyApproved": { - "message": "Emergency access approved." + "message": "Экстранны доступ ухвалены." }, "emergencyRejected": { - "message": "Emergency access rejected" + "message": "Экстранны доступ адхілены" }, "passwordResetFor": { - "message": "Password reset for $USER$. You can now login using the new password.", + "message": "Пароль скінуты для $USER$. Цяпер вы ўвайсці з дапамогай новага пароля.", "placeholders": { "user": { "content": "$1", @@ -3982,33 +3982,33 @@ } }, "personalOwnership": { - "message": "Remove individual vault" + "message": "Выдаліць асабістае сховішча" }, "personalOwnershipPolicyDesc": { - "message": "Require members to save items to an organization by removing the individual vault option." + "message": "Патрабаваць ад удзельнікаў захавання элементаў у арганізацыі, выдаліўшы параметр асабістага сховішча." }, "personalOwnershipExemption": { - "message": "Organization Owners and Administrators are exempt from this policy's enforcement." + "message": "На ўладальнікаў арганізацыі і адміністратараў гэта палітыка не аказвае ўплыву." }, "personalOwnershipSubmitError": { - "message": "Due to an enterprise policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + "message": "У адпаведнасці з карпаратыўнай палітыкай вам забаронена захоўваць элементы ў асабістым сховішчы. Змяніце параметры ўласнасці на арганізацыю і выберыце з даступных калекцый." }, "disableSend": { "message": "Выдаліць Send" }, "disableSendPolicyDesc": { - "message": "Do not allow members to create or edit sends.", + "message": "Не дазваляць удзельнікам ствараць або рэдагаваць Send'ы.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "disableSendExemption": { - "message": "Organization users that can manage the organization's policies are exempt from this policy's enforcement." + "message": "Карыстальнікі арганізацыі, якія могуць кіраваць палітыкамі арганізацыі гэта палітыка не аказвае ўплыву." }, "sendDisabled": { - "message": "Send disabled", + "message": "Send адключаны", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendDisabledWarning": { - "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "message": "У адпаведнасці з карпаратыўнай палітыкай, вы можаце выдаліць толькі бягучы Send.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendOptions": { @@ -4016,21 +4016,21 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendOptionsPolicyDesc": { - "message": "Set options for creating and editing Sends.", + "message": "Прызначце параметр для стварэння і рэдагавання Send'a.", "description": "'Sends' is a plural noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendOptionsExemption": { - "message": "Organization users that can manage the organization's policies are exempt from this policy's enforcement." + "message": "Карыстальнікі арганізацыі, якія могуць кіраваць палітыкамі арганізацыі гэта палітыка не аказвае ўплыву." }, "disableHideEmail": { - "message": "Always show member’s email address with recipients when creating or editing a send.", + "message": "Заўсёды паказваць атрымальнікам адрас электроннай пошты ўдзельніка пры стварэнні або рэдагаванні Send'a.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendOptionsPolicyInEffect": { - "message": "The following organization policies are currently in effect:" + "message": "Зараз дзейнічаюць наступныя палітыкі арганізацыі:" }, "sendDisableHideEmailInEffect": { - "message": "Users are not allowed to hide their email address from recipients when creating or editing a Send.", + "message": "Карыстальнікам не дазваляецца хаваць свой адрас электроннай пошты ад атрымальнікаў пры стварэнні або рэдагаванні Send'a.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "modifiedPolicyId": { @@ -4052,7 +4052,7 @@ "message": "Карыстальніцкі" }, "customDesc": { - "message": "Allows more granular control of user permissions for advanced configurations." + "message": "Дазваляе больш паглыблена кантраляваць дазволы карыстальніка для дадатковых канфігурацый." }, "permissions": { "message": "Дазволы" @@ -4067,13 +4067,13 @@ "message": "Доступ да справаздач" }, "missingPermissions": { - "message": "You lack the necessary permissions to perform this action." + "message": "У вас недастаткова правоў для выканання гэтага дзеяння." }, "manageAllCollections": { - "message": "Manage All Collections" + "message": "Кіраваць усімі калекцыямі" }, "createNewCollections": { - "message": "Create New Collections" + "message": "Старыць новыя калекцыі" }, "editAnyCollection": { "message": "Рэдагаваць любую калекцыю" @@ -4082,19 +4082,19 @@ "message": "Выдаліць любую калекцыю" }, "manageAssignedCollections": { - "message": "Manage Assigned Collections" + "message": "Кіраваць прызначанымі калекцыямі" }, "editAssignedCollections": { - "message": "Edit Assigned Collections" + "message": "Рэдагаваць прызначаныя калекцыі" }, "deleteAssignedCollections": { - "message": "Delete Assigned Collections" + "message": "Выдаліць прызначаныя калекцыі" }, "manageGroups": { "message": "Кіраванне групамі" }, "managePolicies": { - "message": "Manage Policies" + "message": "Кіраванне палітыкамі" }, "manageSso": { "message": "Кіраванне SSO" @@ -4106,7 +4106,7 @@ "message": "Кіраванне скіданнем пароля" }, "disableRequiredError": { - "message": "You must manually disable the $POLICYNAME$ policy before this policy can be disabled.", + "message": "Перад адключэннем гэтай палітыкі, вам спачатку неабходна ўручную адключыць палітыку $POLICYNAME$.", "placeholders": { "policyName": { "content": "$1", @@ -4115,30 +4115,30 @@ } }, "personalOwnershipPolicyInEffect": { - "message": "An organization policy is affecting your ownership options." + "message": "Палітыка арганізацыі ўплывае на вашы параметры ўласнасці." }, "personalOwnershipPolicyInEffectImports": { - "message": "An organization policy has disabled importing items into your personal vault." + "message": "Імпартаванне элементаў у вашым асабістым сховішчы адключаны палітыкай арганізацыі." }, "personalOwnershipCheckboxDesc": { - "message": "Disable personal ownership for organization users" + "message": "Адключыць асабістую ўласная для карыстальнікаў арганізацыі" }, "textHiddenByDefault": { - "message": "When accessing the Send, hide the text by default", + "message": "Пры доступе да Send прадвызначана хаваць тэкст", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendNameDesc": { - "message": "A friendly name to describe this Send.", + "message": "Зразумелая назва для апісання гэтага Send'a.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendTextDesc": { - "message": "The text you want to send." + "message": "Тэкст, які вы хочаце адправіць." }, "sendFileDesc": { - "message": "The file you want to send." + "message": "Файл, які вы хочаце адправіць." }, "copySendLinkOnSave": { - "message": "Copy the link to share this Send to my clipboard upon save." + "message": "Скапіяваць спасылку ў буфер абмену пасля захавання, каб абагуліць гэты Send." }, "sendLinkLabel": { "message": "Адправіць спасылку", @@ -4149,7 +4149,7 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendAccessTaglineProductDesc": { - "message": "Bitwarden Send transmits sensitive, temporary information to others easily and securely.", + "message": "Bitwarden Send лёгка і надзейна перадае канфідэнцыяльную, часовую інфармацыю іншым.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendAccessTaglineLearnMore": { @@ -4157,7 +4157,7 @@ "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**Learn more about** Bitwarden Send or sign up to try it today.'" }, "sendVaultCardProductDesc": { - "message": "Share text or files directly with anyone." + "message": "Дзяліцеся тэкстам або файламі наўпрост з любым карыстальнікам." }, "sendVaultCardLearnMore": { "message": "Даведацца больш", @@ -4192,7 +4192,7 @@ "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Learn more about Bitwarden Send or sign up to **try it today.**'" }, "sendCreatorIdentifier": { - "message": "Bitwarden user $USER_IDENTIFIER$ shared the following with you", + "message": "Карыстальнік Bitwarden $USER_IDENTIFIER$ абагуліў з вамі", "placeholders": { "user_identifier": { "content": "$1", @@ -4201,56 +4201,56 @@ } }, "viewSendHiddenEmailWarning": { - "message": "The Bitwarden user who created this Send has chosen to hide their email address. You should ensure you trust the source of this link before using or downloading its content.", + "message": "Карыстальнік Bitwarden, які стварыў гэты Send, вырашыў схаваць сваю электронную пошту. Пераканайцеся, што гэта спасылка атрымана з надзейных крыніц і толькі пасля гэтага выкарыстоўвайце або пампуйце дадзенае змесціва.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "expirationDateIsInvalid": { - "message": "The expiration date provided is not valid." + "message": "Азначаная дата завяршэння тэрміну дзеяння з'яўляецца няправільнай." }, "deletionDateIsInvalid": { - "message": "The deletion date provided is not valid." + "message": "Азначаная дата выдалення з'яўляецца няправільнай." }, "expirationDateAndTimeRequired": { - "message": "An expiration date and time are required." + "message": "Неабходна азначыць дату і час завяршэння тэрміну дзеяння." }, "deletionDateAndTimeRequired": { - "message": "A deletion date and time are required." + "message": "Патрабуюцца дата і час выдалення." }, "dateParsingError": { - "message": "There was an error saving your deletion and expiration dates." + "message": "Адбылася памылка пры захаванні дат выдалення і завяршэння тэрміну дзеяння." }, "webAuthnFallbackMsg": { - "message": "To verify your 2FA please click the button below." + "message": "Для праверкі вашага 2ФА, націсніце кнопку ніжэй." }, "webAuthnAuthenticate": { "message": "Аўтэнтыфікатар WebAuthn" }, "webAuthnNotSupported": { - "message": "WebAuthn is not supported in this browser." + "message": "WebAuthn не падтрымліваецца ў гэтым браўзеры." }, "webAuthnSuccess": { - "message": "WebAuthn verified successfully! You may close this tab." + "message": "WebAuthn паспяхова правераны! Вы можаце закрыць гэту ўкладку." }, "hintEqualsPassword": { - "message": "Your password hint cannot be the same as your password." + "message": "Падказка для пароля не можа супадаць з паролем." }, "enrollPasswordReset": { - "message": "Enroll in Password Reset" + "message": "Зарэгістравацца на скіданне пароля" }, "enrolledPasswordReset": { - "message": "Enrolled in Password Reset" + "message": "Зарэгістраваны на скіданне пароля" }, "withdrawPasswordReset": { - "message": "Withdraw from Password Reset" + "message": "Адмова ад скідання пароля" }, "enrollPasswordResetSuccess": { "message": "Паспяховая рэгістрацыя!" }, "withdrawPasswordResetSuccess": { - "message": "Withdrawal success!" + "message": "Адмова паспяхова ўжыта!" }, "eventEnrollPasswordReset": { - "message": "User $ID$ enrolled in password reset assistance.", + "message": "Карыстальнік $ID$ зарэгістраваўся, каб атрымаць дапамогу ў скіданні пароля.", "placeholders": { "id": { "content": "$1", @@ -4259,7 +4259,7 @@ } }, "eventWithdrawPasswordReset": { - "message": "User $ID$ withdrew from password reset assistance.", + "message": "Карыстальнік $ID$ адмовіўся ад дапамогі ў скіданні пароля.", "placeholders": { "id": { "content": "$1", @@ -4268,7 +4268,7 @@ } }, "eventAdminPasswordReset": { - "message": "Master password reset for user $ID$.", + "message": "Галоўны пароль скінуты карыстальнікам $ID$.", "placeholders": { "id": { "content": "$1", @@ -4277,7 +4277,7 @@ } }, "eventResetSsoLink": { - "message": "Reset Sso link for user $ID$", + "message": "Скінуць спасылку SSO для карыстальніка $ID$", "placeholders": { "id": { "content": "$1", @@ -4286,7 +4286,7 @@ } }, "firstSsoLogin": { - "message": "$ID$ logged in using Sso for the first time", + "message": "$ID$ упершыню ўваходзіць з выкарыстаннем SSO", "placeholders": { "id": { "content": "$1", @@ -4310,19 +4310,19 @@ "message": "гэты карыстальнік" }, "resetPasswordMasterPasswordPolicyInEffect": { - "message": "One or more organization policies require the master password to meet the following requirements:" + "message": "Згодна з адной або некалькімі палітыкамі арганізацыі асноўны пароль павінен адпавядаць наступным патрабаванням:" }, "resetPasswordSuccess": { - "message": "Password reset success!" + "message": "Пароль паспяхова скінуты!" }, "resetPasswordEnrollmentWarning": { - "message": "Enrollment will allow organization administrators to change your master password" + "message": "Рэгістрацыя дазволіць адміністратарам арганізацыі змяць ваш галоўны пароль" }, "resetPasswordPolicy": { "message": "Скіданне асноўнага пароля" }, "resetPasswordPolicyDescription": { - "message": "Allow admins to reset master passwords for members." + "message": "Дазволіць адміністратарам скідаць галоўны пароль для ўдзельнікаў." }, "resetPasswordPolicyWarning": { "message": "Users in the organization will need to self-enroll or be auto-enrolled before administrators can reset their master password." @@ -4487,13 +4487,13 @@ "message": "Пастаўшчык" }, "newClientOrganization": { - "message": "New Client Organization" + "message": "Новая арганізацыя кліента" }, "newClientOrganizationDesc": { "message": "Стварыць новую арганізацыю кліента, які будзе звязаны з вамі, як з пастаўшчыком. У вас будзе магчымасць атрымаць доступ і кіраваць гэтай арганізацыяй." }, "addExistingOrganization": { - "message": "Add Existing Organization" + "message": "Дадаць існуючую арганізацыю" }, "myProvider": { "message": "Мой пастаўшчык" @@ -4554,10 +4554,10 @@ "message": "Дадаць" }, "updatedMasterPassword": { - "message": "Updated Master Password" + "message": "Галоўны пароль абноўлены" }, "updateMasterPassword": { - "message": "Update Master Password" + "message": "Абнавіць галоўны пароль" }, "updateMasterPasswordWarning": { "message": "Ваш галоўны пароль быў нядаўна зменены адміністратарам вашай арганізацыі. Для атрымання доступу да сховішча, вы павінны абнавіць галоўны пароль. Працягваючы, вы выйдзіце з бягучага сеанса і вам неабходна будзе ўвайсці паўторна. Сеансы на іншых прыладах могуць заставацца актыўнымі на працягу адной гадзіны." @@ -4569,13 +4569,13 @@ "message": "Час чакання сховішча" }, "maximumVaultTimeoutDesc": { - "message": "Set a maximum vault timeout for members." + "message": "Прызначыць час чакання сховішча для ўдзельнікаў." }, "maximumVaultTimeoutLabel": { "message": "Максімальны час чакання сховішча" }, "invalidMaximumVaultTimeout": { - "message": "Invalid Maximum Vault Timeout." + "message": "Памылковы максімальны час чакання сховішча." }, "hours": { "message": "Гадзіны" @@ -4672,7 +4672,7 @@ "message": "Custom Name Claim Types" }, "acrValues": { - "message": "Requested Authentication Context Class Reference values" + "message": "Запытаныя значэнні спасылак класа кантэксту аўтэнтыфікацыі" }, "expectedReturnAcrValue": { "message": "Expected \"acr\" Claim Value In Response" @@ -4723,13 +4723,13 @@ "message": "Outbound Signing Algorithm" }, "idpAllowUnsolicitedAuthnResponse": { - "message": "Allow unsolicited authentication response" + "message": "Дазваляць непажаданы адказ аўтэнтыфікацыі" }, "idpAllowOutboundLogoutRequests": { "message": "Allow outbound logout requests" }, "idpSignAuthenticationRequests": { - "message": "Sign authentication requests" + "message": "Падпісваць запыты аўтэнтыфікацыі" }, "ssoSettingsSaved": { "message": "Single Sign-On configuration was saved." @@ -4894,7 +4894,7 @@ "message": "Master password removed." }, "allowSso": { - "message": "Allow SSO authentication" + "message": "Дазволіць аўтэнтыфікацыю SSO" }, "allowSsoDesc": { "message": "Пасля наладжвання ваша канфігурацыя будзе захавана і ўдзельнікі змогуць праходзіць аўтэнтыфікацыю выкарыстоўваючы свае ўліковыя даныя пасведчанняў пастаўшчыка." @@ -4904,15 +4904,15 @@ "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Use the require single-sign-on authentication policy to require all members to log in with SSO.'" }, "ssoPolicyHelpLink": { - "message": "require single-sign-on authentication policy", + "message": "абавязковую палітыку аўтэнтыфікацыі адзінага ўваходу (SSO)", "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Use the require single-sign-on authentication policy to require all members to log in with SSO.'" }, "ssoPolicyHelpEnd": { - "message": "to require all members to log in with SSO.", + "message": "для таго, каб патрабаваць ва ўсіх удзельнікаў выконваць уваход з SSO.", "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Use the require single-sign-on authentication policy to require all members to log in with SSO.'" }, "ssoPolicyHelpKeyConnector": { - "message": "The require SSO authentication and single organization policies are required to set up Key Connector decryption." + "message": "Для наладжвання расшыфроўкі Key Connector неабходна палітыка аўтэнтыфікацыі SSO і адзінай арганізацыі." }, "memberDecryptionOption": { "message": "Member Decryption Options" @@ -5056,10 +5056,10 @@ } }, "formErrorSummarySingle": { - "message": "1 field above needs your attention." + "message": "1 поле вышэй патрабуе вашай увагі." }, "fieldRequiredError": { - "message": "$FIELDNAME$ is required.", + "message": "$FIELDNAME$ абавязкова.", "placeholders": { "fieldname": { "content": "$1", @@ -5071,10 +5071,10 @@ "message": "абавязкова" }, "idpSingleSignOnServiceUrlRequired": { - "message": "Required if Entity ID is not a URL." + "message": "Патрабуецца, калі ідэнтыфікатар аб'екта не з'яўляецца URL-адрасам." }, "openIdOptionalCustomizations": { - "message": "Optional Customizations" + "message": "Дадатковыя дапасаванні" }, "openIdAuthorityRequired": { "message": "Required if Authority is not valid." @@ -5232,10 +5232,10 @@ "description": "This text is displayed if an organization's billing is managed by a Provider. It tells the user to contact the Provider for assistance." }, "forwardedEmail": { - "message": "Forwarded Email Alias" + "message": "Псеўданім электроннай пошты для перасылкі" }, "forwardedEmailDesc": { - "message": "Generate an email alias with an external forwarding service." + "message": "Генерыраваць псеўданім электроннай пошты са знешнім сэрвісам перасылкі." }, "hostname": { "message": "Назва вузла", @@ -5248,13 +5248,13 @@ "message": "Праверка прылады" }, "enableDeviceVerification": { - "message": "Enable Device Verification" + "message": "Уключыць праверку прылады" }, "deviceVerificationDesc": { "message": "Калі ўключана, то пры ўваходзе з нераспазнанай прылады на ваш адрас электроннай пошты будуць адпраўляцца праверачныя коды" }, "updatedDeviceVerification": { - "message": "Updated Device Verification" + "message": "Праверка прылады абноўлена" }, "areYouSureYouWantToEnableDeviceVerificationTheVerificationCodeEmailsWillArriveAtX": { "message": "Вы ўпэўнены, што хочаце ўключыць праверку прылады? Ліст з праверачным кодам будзе адпраўлены на: $EMAIL$", @@ -5266,7 +5266,7 @@ } }, "premiumSubcriptionRequired": { - "message": "Premium subscription required" + "message": "Патрабуецца прэміяльная падпіска" }, "scim": { "message": "Забеспячэнне SCIM", diff --git a/apps/web/src/locales/eu/messages.json b/apps/web/src/locales/eu/messages.json index 03fe2d2e010..d9eca7116d4 100644 --- a/apps/web/src/locales/eu/messages.json +++ b/apps/web/src/locales/eu/messages.json @@ -679,7 +679,7 @@ "message": "Master pasahitz baliogabea" }, "invalidFilePassword": { - "message": "Invalid file password, please use the password you entered when you created the export file." + "message": "Fitxategi pasahitzak ez du balio; mesedez, erabili esportazio fitxategia sortzean sartutako pasahitza." }, "lockNow": { "message": "Blokeatu orain" @@ -894,46 +894,46 @@ "message": "Fitxategiaren formatua" }, "fileEncryptedExportWarningDesc": { - "message": "This file export will be password protected and require the file password to decrypt." + "message": "Fitxategien esportazio hori pasahitzaren bidez babestuta egongo da eta deszifratzeko fitxategi pasahitza beharko da." }, "exportPasswordDescription": { - "message": "This password will be used to export and import this file" + "message": "Fitxategi hau esportatu eta inportatzeko erabiliko da pasahitz hau" }, "confirmMasterPassword": { - "message": "Confirm Master Password" + "message": "Pasahitz nagusia baieztatu" }, "confirmFormat": { - "message": "Confirm Format" + "message": "Formatua baieztatu" }, "filePassword": { - "message": "File Password" + "message": "Fitxategi pasahitza" }, "confirmFilePassword": { - "message": "Confirm File Password" + "message": "Fitxategi pasahitza berretsi" }, "accountBackupOptionDescription": { - "message": "Use your account encryption key to encrypt the export and restrict import to only the current Bitwarden account." + "message": "Erabili zure kontuaren zifratze-gakoa esportazioa zifratzeko eta inportazioa egungo Bitwarden kontura bakarrik mugatzeko." }, "passwordProtectedOptionDescription": { - "message": "Set a password to encrypt the export and import it to any Bitwarden account using the password for decryption." + "message": "Erabili pasahitza esportazioa zifratzeko eta Bitwardeneko edozein kontutara inportatzean deszifratzeko." }, "fileTypeHeading": { "message": "Fitxategi mota" }, "accountBackup": { - "message": "Account Backup" + "message": "Kontuaren segurtasun kopia" }, "passwordProtected": { - "message": "Password Protected" + "message": "Pasahitz babestua" }, "filePasswordAndConfirmFilePasswordDoNotMatch": { - "message": "“File password” and “Confirm File Password“ do not match." + "message": "“Fitxategi pasahitza” eta “Fitxategi pasahitza berretsi” ez datoz bat." }, "confirmVaultImport": { - "message": "Confirm Vault Import" + "message": "Berretsi kutxa gotorra inportatzea" }, "confirmVaultImportDesc": { - "message": "This file is password-protected. Please enter the file password to import data." + "message": "Fitxategi hau pasahitzez babestuta dago. Sartu fitxategiaren pasahitza datuak inportatzeko." }, "exportSuccess": { "message": "Zure kutxa gotorra esportatu da." diff --git a/apps/web/src/locales/fi/messages.json b/apps/web/src/locales/fi/messages.json index 9b2b92289c4..370a51952ab 100644 --- a/apps/web/src/locales/fi/messages.json +++ b/apps/web/src/locales/fi/messages.json @@ -679,7 +679,7 @@ "message": "Virheellinen pääsalasana" }, "invalidFilePassword": { - "message": "Tiedoston salasana on virheellinen. Käytä vientitiedoston luonnin yhteydessä käytettyä salasanaa." + "message": "Tiedoston salasana on virheellinen. Käytä vientitiedoston luonnin yhteydessä syötettyä salasanaa." }, "lockNow": { "message": "Lukitse nyt" @@ -912,10 +912,10 @@ "message": "Vahvista tiedoston salasana" }, "accountBackupOptionDescription": { - "message": "Hyödyntää viennin suojauksessa Bitwarden-tilisi salausta sen pääsalasanan sijaan. Tällainen vienti voidaan tuoda vain nykyiselle käyttäjätilille. Tämän avulla voidaan luoda varmuuskopio, jota ei ole mahdollista käyttää muilla tileillä." + "message": "Salaa vienti tilisi salausavaimella, joka rajoittaa sen tuonnin vain tälle Bitwarden-tilille." }, "passwordProtectedOptionDescription": { - "message": "Suojaa vienti omavalintaisella salasanalla. Tämän avulla voidaan luoda vienti, jota on mahdollista käyttää myös muilla käyttäjätileillä." + "message": "Salaa vienti salasanalla, joka mahdollistaa sen tuonnin mille tahansa Bitwarden-tilille." }, "fileTypeHeading": { "message": "Tiedostotyyppi" diff --git a/apps/web/src/locales/it/messages.json b/apps/web/src/locales/it/messages.json index 95d88164705..3c095b31c7a 100644 --- a/apps/web/src/locales/it/messages.json +++ b/apps/web/src/locales/it/messages.json @@ -679,7 +679,7 @@ "message": "Password principale errata" }, "invalidFilePassword": { - "message": "Invalid file password, please use the password you entered when you created the export file." + "message": "Password errata, usa la password che hai inserito quando hai creato il file di esportazione." }, "lockNow": { "message": "Blocca" diff --git a/apps/web/src/locales/zh_CN/messages.json b/apps/web/src/locales/zh_CN/messages.json index 0e7c56669d3..ac34e62c36c 100644 --- a/apps/web/src/locales/zh_CN/messages.json +++ b/apps/web/src/locales/zh_CN/messages.json @@ -645,7 +645,7 @@ "message": "您的新账户已创建!您现在可以登录了。" }, "trialAccountCreated": { - "message": "帐户创建成功。" + "message": "账户创建成功。" }, "masterPassSent": { "message": "我们已经为您发送了包含主密码提示的邮件。" @@ -915,13 +915,13 @@ "message": "使用您的账户加密密钥来加密导出的数据,并且限制只能导入到当前的 Bitwarden 账户。" }, "passwordProtectedOptionDescription": { - "message": "设置一个密码来加密导出的数据,并使用密码解密以导入到任何 Bitwarden 账户。" + "message": "设置一个密码用来加密导出的数据,并使用此密码解密以导入到任何 Bitwarden 账户。" }, "fileTypeHeading": { "message": "文件类型" }, "accountBackup": { - "message": "帐户备份" + "message": "账户备份" }, "passwordProtected": { "message": "密码保护" @@ -3687,7 +3687,7 @@ "message": "先决条件" }, "requireSsoPolicyReq": { - "message": "激活此策略前,需先启用「单一组织」企业策略。" + "message": "激活此策略前,需先开启「单一组织」企业策略。" }, "requireSsoPolicyReqError": { "message": "单一组织策略未启用。" @@ -5347,7 +5347,7 @@ } }, "turnOn": { - "message": "打开" + "message": "开启" }, "on": { "message": "开启" diff --git a/apps/web/src/locales/zh_TW/messages.json b/apps/web/src/locales/zh_TW/messages.json index 943adfc0918..a083d86e490 100644 --- a/apps/web/src/locales/zh_TW/messages.json +++ b/apps/web/src/locales/zh_TW/messages.json @@ -915,7 +915,7 @@ "message": "使用您的帳戶加密金鑰來加密匯出的資料,並限制只能匯入到目前的 Bitwarden 帳戶。" }, "passwordProtectedOptionDescription": { - "message": "設定一个密碼來加密匯出的資料,並使用密碼解密以匯入到任何 Bitwarden 帳戶。" + "message": "設定一个密碼來加密匯出的資料,並使用此密碼解密以匯入到任何 Bitwarden 帳戶。" }, "fileTypeHeading": { "message": "檔案類型" @@ -2302,7 +2302,7 @@ "message": "原則" }, "singleSignOn": { - "message": "單一登入 (SSO)" + "message": "單一登入" }, "editPolicy": { "message": "編輯原則" @@ -5347,7 +5347,7 @@ } }, "turnOn": { - "message": "打開" + "message": "開啟" }, "on": { "message": "開啟" diff --git a/apps/web/webpack.config.js b/apps/web/webpack.config.js index a7f60904f58..6ddff6edd5a 100644 --- a/apps/web/webpack.config.js +++ b/apps/web/webpack.config.js @@ -209,6 +209,12 @@ const devServer = secure: false, changeOrigin: true, }, + "/icons": { + target: envConfig.dev?.proxyIcons, + pathRewrite: { "^/icons": "" }, + secure: false, + changeOrigin: true, + }, }, headers: (req) => { if (!req.originalUrl.includes("connector.html")) { diff --git a/jest.config.js b/jest.config.js index e8f4ce151d4..7a747974f53 100644 --- a/jest.config.js +++ b/jest.config.js @@ -26,4 +26,13 @@ module.exports = { // https://github.com/facebook/jest/issues/9430#issuecomment-1149882002 // Also anecdotally improves performance when run locally maxWorkers: 3, + globals: { + "ts-jest": { + // Further workaround for memory leak, recommended here: + // https://github.com/kulshekhar/ts-jest/issues/1967#issuecomment-697494014 + // Makes tests run faster and reduces size/rate of leak, but loses typechecking on test code + // See https://bitwarden.atlassian.net/browse/EC-497 for more info + isolatedModules: true, + }, + }, }; diff --git a/libs/angular/src/components/register.component.ts b/libs/angular/src/components/register.component.ts index 1dd1b779312..5abf4d9fdb2 100644 --- a/libs/angular/src/components/register.component.ts +++ b/libs/angular/src/components/register.component.ts @@ -68,6 +68,8 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn protected successRoute = "login"; + protected accountCreated = false; + constructor( protected formValidationErrorService: FormValidationErrorsService, protected formBuilder: UntypedFormBuilder, @@ -92,100 +94,33 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn async submit(showToast = true) { let email = this.formGroup.get("email")?.value; - let name = this.formGroup.get("name")?.value; - const masterPassword = this.formGroup.get("masterPassword")?.value; - const hint = this.formGroup.get("hint")?.value; - - this.formGroup.markAllAsTouched(); - this.showErrorSummary = true; - - if (this.formGroup.get("acceptPolicies").hasError("required")) { - this.platformUtilsService.showToast( - "error", - this.i18nService.t("errorOccurred"), - this.i18nService.t("acceptPoliciesRequired") - ); - return; - } - - //web - if (this.formGroup.invalid && !showToast) { - return; - } - - //desktop, browser - if (this.formGroup.invalid && showToast) { - const errorText = this.getErrorToastMessage(); - this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), errorText); - return; - } - - if (this.passwordStrengthResult != null && this.passwordStrengthResult.score < 3) { - const result = await this.platformUtilsService.showDialog( - this.i18nService.t("weakMasterPasswordDesc"), - this.i18nService.t("weakMasterPassword"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); - if (!result) { - return; - } - } - - name = name === "" ? null : name; email = email.trim().toLowerCase(); - const kdf = DEFAULT_KDF_TYPE; - const kdfIterations = DEFAULT_KDF_ITERATIONS; - const key = await this.cryptoService.makeKey(masterPassword, email, kdf, kdfIterations); - const encKey = await this.cryptoService.makeEncKey(key); - const hashedPassword = await this.cryptoService.hashPassword(masterPassword, key); - const keys = await this.cryptoService.makeKeyPair(encKey[0]); - const request = new RegisterRequest( - email, - name, - hashedPassword, - hint, - encKey[1].encryptedString, - kdf, - kdfIterations, - this.referenceData, - this.captchaToken - ); - request.keys = new KeysRequest(keys[0], keys[1].encryptedString); - const orgInvite = await this.stateService.getOrganizationInvitation(); - if (orgInvite != null && orgInvite.token != null && orgInvite.organizationUserId != null) { - request.token = orgInvite.token; - request.organizationUserId = orgInvite.organizationUserId; - } - + let name = this.formGroup.get("name")?.value; + name = name === "" ? null : name; // Why do we do this? + const masterPassword = this.formGroup.get("masterPassword")?.value; try { - this.formPromise = this.apiService.postRegister(request); - try { - await this.formPromise; - } catch (e) { - if (this.handleCaptchaRequired(e)) { + if (!this.accountCreated) { + const registerResponse = await this.registerAccount( + await this.buildRegisterRequest(email, masterPassword, name), + showToast + ); + if (!registerResponse.successful) { return; - } else { - throw e; } + this.accountCreated = true; } - if (this.isInTrialFlow) { - this.platformUtilsService.showToast( - "success", - null, - this.i18nService.t("trialAccountCreated") - ); - //login user here - const credentials = new PasswordLogInCredentials( - email, - masterPassword, - this.captchaToken, - null - ); - await this.authService.logIn(credentials); - + if (!this.accountCreated) { + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("trialAccountCreated") + ); + } + const loginResponse = await this.logIn(email, masterPassword, this.captchaToken); + if (loginResponse.captchaRequired) { + return; + } this.createdAccount.emit(this.formGroup.get("email")?.value); } else { this.platformUtilsService.showToast( @@ -247,4 +182,114 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn return !ctrlValue && this.showTerms ? { required: true } : null; }; } + + private async validateRegistration(showToast: boolean): Promise<{ isValid: boolean }> { + this.formGroup.markAllAsTouched(); + this.showErrorSummary = true; + + if (this.formGroup.get("acceptPolicies").hasError("required")) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("acceptPoliciesRequired") + ); + return { isValid: false }; + } + + //web + if (this.formGroup.invalid && !showToast) { + return { isValid: false }; + } + + //desktop, browser + if (this.formGroup.invalid && showToast) { + const errorText = this.getErrorToastMessage(); + this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), errorText); + return { isValid: false }; + } + + if (this.passwordStrengthResult != null && this.passwordStrengthResult.score < 3) { + const result = await this.platformUtilsService.showDialog( + this.i18nService.t("weakMasterPasswordDesc"), + this.i18nService.t("weakMasterPassword"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!result) { + return { isValid: false }; + } + } + return { isValid: true }; + } + + private async buildRegisterRequest( + email: string, + masterPassword: string, + name: string + ): Promise { + const hint = this.formGroup.get("hint")?.value; + const kdf = DEFAULT_KDF_TYPE; + const kdfIterations = DEFAULT_KDF_ITERATIONS; + const key = await this.cryptoService.makeKey(masterPassword, email, kdf, kdfIterations); + const encKey = await this.cryptoService.makeEncKey(key); + const hashedPassword = await this.cryptoService.hashPassword(masterPassword, key); + const keys = await this.cryptoService.makeKeyPair(encKey[0]); + const request = new RegisterRequest( + email, + name, + hashedPassword, + hint, + encKey[1].encryptedString, + kdf, + kdfIterations, + this.referenceData, + this.captchaToken + ); + request.keys = new KeysRequest(keys[0], keys[1].encryptedString); + const orgInvite = await this.stateService.getOrganizationInvitation(); + if (orgInvite != null && orgInvite.token != null && orgInvite.organizationUserId != null) { + request.token = orgInvite.token; + request.organizationUserId = orgInvite.organizationUserId; + } + return request; + } + + private async registerAccount( + request: RegisterRequest, + showToast: boolean + ): Promise<{ successful: boolean }> { + if (!(await this.validateRegistration(showToast)).isValid) { + return { successful: false }; + } + this.formPromise = this.apiService.postRegister(request); + try { + await this.formPromise; + return { successful: true }; + } catch (e) { + if (this.handleCaptchaRequired(e)) { + return { successful: false }; + } else { + throw e; + } + } + } + + private async logIn( + email: string, + masterPassword: string, + captchaBypassToken: string + ): Promise<{ captchaRequired: boolean }> { + const credentials = new PasswordLogInCredentials( + email, + masterPassword, + captchaBypassToken, + null + ); + const loginResponse = await this.authService.logIn(credentials); + if (this.handleCaptchaRequired(loginResponse)) { + return { captchaRequired: true }; + } + return { captchaRequired: false }; + } } diff --git a/libs/angular/src/services/injection-tokens.ts b/libs/angular/src/services/injection-tokens.ts new file mode 100644 index 00000000000..7e1b9124b1a --- /dev/null +++ b/libs/angular/src/services/injection-tokens.ts @@ -0,0 +1,18 @@ +import { InjectionToken } from "@angular/core"; + +import { AbstractStorageService } from "@bitwarden/common/abstractions/storage.service"; +import { StateFactory } from "@bitwarden/common/factories/stateFactory"; + +export const WINDOW = new InjectionToken("WINDOW"); +export const MEMORY_STORAGE = new InjectionToken("MEMORY_STORAGE"); +export const SECURE_STORAGE = new InjectionToken("SECURE_STORAGE"); +export const STATE_FACTORY = new InjectionToken("STATE_FACTORY"); +export const STATE_SERVICE_USE_CACHE = new InjectionToken("STATE_SERVICE_USE_CACHE"); +export const LOGOUT_CALLBACK = new InjectionToken<(expired: boolean, userId?: string) => void>( + "LOGOUT_CALLBACK" +); +export const LOCKED_CALLBACK = new InjectionToken<() => void>("LOCKED_CALLBACK"); +export const CLIENT_TYPE = new InjectionToken("CLIENT_TYPE"); +export const LOCALES_DIRECTORY = new InjectionToken("LOCALES_DIRECTORY"); +export const SYSTEM_LANGUAGE = new InjectionToken("SYSTEM_LANGUAGE"); +export const LOG_MAC_FAILURES = new InjectionToken("LOG_MAC_FAILURES"); diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index ab51488ffe5..b76ad9a5903 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -1,4 +1,4 @@ -import { InjectionToken, Injector, LOCALE_ID, NgModule } from "@angular/core"; +import { Injector, LOCALE_ID, NgModule } from "@angular/core"; import { ThemingService } from "@bitwarden/angular/services/theming/theming.service"; import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction"; @@ -12,6 +12,8 @@ import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/abstrac import { BroadcasterService as BroadcasterServiceAbstraction } from "@bitwarden/common/abstractions/broadcaster.service"; import { CipherService as CipherServiceAbstraction } from "@bitwarden/common/abstractions/cipher.service"; import { CollectionService as CollectionServiceAbstraction } from "@bitwarden/common/abstractions/collection.service"; +import { ConfigApiServiceAbstraction } from "@bitwarden/common/abstractions/config/config-api.service.abstraction"; +import { ConfigServiceAbstraction } from "@bitwarden/common/abstractions/config/config.service.abstraction"; import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service"; import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/abstractions/cryptoFunction.service"; import { EnvironmentService as EnvironmentServiceAbstraction } from "@bitwarden/common/abstractions/environment.service"; @@ -66,6 +68,8 @@ import { AuditService } from "@bitwarden/common/services/audit.service"; import { AuthService } from "@bitwarden/common/services/auth.service"; import { CipherService } from "@bitwarden/common/services/cipher.service"; import { CollectionService } from "@bitwarden/common/services/collection.service"; +import { ConfigApiService } from "@bitwarden/common/services/config/config-api.service"; +import { ConfigService } from "@bitwarden/common/services/config/config.service"; import { ConsoleLogService } from "@bitwarden/common/services/consoleLog.service"; import { CryptoService } from "@bitwarden/common/services/crypto.service"; import { EncryptService } from "@bitwarden/common/services/encrypt.service"; @@ -105,24 +109,22 @@ import { LockGuard } from "../guards/lock.guard"; import { UnauthGuard } from "../guards/unauth.guard"; import { BroadcasterService } from "./broadcaster.service"; +import { + WINDOW, + MEMORY_STORAGE, + SECURE_STORAGE, + STATE_FACTORY, + STATE_SERVICE_USE_CACHE, + LOGOUT_CALLBACK, + LOCKED_CALLBACK, + LOCALES_DIRECTORY, + SYSTEM_LANGUAGE, + LOG_MAC_FAILURES, +} from "./injection-tokens"; import { ModalService } from "./modal.service"; import { PasswordRepromptService } from "./passwordReprompt.service"; import { ValidationService } from "./validation.service"; -export const WINDOW = new InjectionToken("WINDOW"); -export const MEMORY_STORAGE = new InjectionToken("MEMORY_STORAGE"); -export const SECURE_STORAGE = new InjectionToken("SECURE_STORAGE"); -export const STATE_FACTORY = new InjectionToken("STATE_FACTORY"); -export const STATE_SERVICE_USE_CACHE = new InjectionToken("STATE_SERVICE_USE_CACHE"); -export const LOGOUT_CALLBACK = new InjectionToken<(expired: boolean, userId?: string) => void>( - "LOGOUT_CALLBACK" -); -export const LOCKED_CALLBACK = new InjectionToken<() => void>("LOCKED_CALLBACK"); -export const CLIENT_TYPE = new InjectionToken("CLIENT_TYPE"); -export const LOCALES_DIRECTORY = new InjectionToken("LOCALES_DIRECTORY"); -export const SYSTEM_LANGUAGE = new InjectionToken("SYSTEM_LANGUAGE"); -export const LOG_MAC_FAILURES = new InjectionToken("LOG_MAC_FAILURES"); - @NgModule({ declarations: [], providers: [ @@ -532,6 +534,16 @@ export const LOG_MAC_FAILURES = new InjectionToken("LOG_MAC_FAILURES"); useClass: OrganizationApiService, deps: [ApiServiceAbstraction], }, + { + provide: ConfigServiceAbstraction, + useClass: ConfigService, + deps: [StateServiceAbstraction, ConfigApiServiceAbstraction], + }, + { + provide: ConfigApiServiceAbstraction, + useClass: ConfigApiService, + deps: [ApiServiceAbstraction], + }, ], }) export class JslibServicesModule {} diff --git a/libs/angular/src/services/theming/theming.service.ts b/libs/angular/src/services/theming/theming.service.ts index 38eb574a725..7da6565e6d9 100644 --- a/libs/angular/src/services/theming/theming.service.ts +++ b/libs/angular/src/services/theming/theming.service.ts @@ -5,7 +5,7 @@ import { BehaviorSubject, filter, fromEvent, Observable } from "rxjs"; import { StateService } from "@bitwarden/common/abstractions/state.service"; import { ThemeType } from "@bitwarden/common/enums/themeType"; -import { WINDOW } from "../jslib-services.module"; +import { WINDOW } from "../injection-tokens"; import { Theme } from "./theme"; import { ThemeBuilder } from "./themeBuilder"; diff --git a/libs/common/spec/services/consoleLog.service.spec.ts b/libs/common/spec/services/consoleLog.service.spec.ts index 5f8e9ead013..3c961487f31 100644 --- a/libs/common/spec/services/consoleLog.service.spec.ts +++ b/libs/common/spec/services/consoleLog.service.spec.ts @@ -1,32 +1,9 @@ import { ConsoleLogService } from "@bitwarden/common/services/consoleLog.service"; -const originalConsole = console; +import { interceptConsole, restoreConsole } from "../shared/interceptConsole"; + let caughtMessage: any; -declare let console: any; - -export function interceptConsole(interceptions: any): object { - console = { - log: function () { - // eslint-disable-next-line - interceptions.log = arguments; - }, - warn: function () { - // eslint-disable-next-line - interceptions.warn = arguments; - }, - error: function () { - // eslint-disable-next-line - interceptions.error = arguments; - }, - }; - return interceptions; -} - -export function restoreConsole() { - console = originalConsole; -} - describe("ConsoleLogService", () => { let logService: ConsoleLogService; beforeEach(() => { diff --git a/libs/common/spec/shared/interceptConsole.ts b/libs/common/spec/shared/interceptConsole.ts new file mode 100644 index 00000000000..01c4063e7aa --- /dev/null +++ b/libs/common/spec/shared/interceptConsole.ts @@ -0,0 +1,25 @@ +const originalConsole = console; + +declare let console: any; + +export function interceptConsole(interceptions: any): object { + console = { + log: function () { + // eslint-disable-next-line + interceptions.log = arguments; + }, + warn: function () { + // eslint-disable-next-line + interceptions.warn = arguments; + }, + error: function () { + // eslint-disable-next-line + interceptions.error = arguments; + }, + }; + return interceptions; +} + +export function restoreConsole() { + console = originalConsole; +} diff --git a/libs/common/src/abstractions/config/config-api.service.abstraction.ts b/libs/common/src/abstractions/config/config-api.service.abstraction.ts new file mode 100644 index 00000000000..3ebd79e4fc1 --- /dev/null +++ b/libs/common/src/abstractions/config/config-api.service.abstraction.ts @@ -0,0 +1,5 @@ +import { ServerConfigResponse } from "@bitwarden/common/models/response/server-config-response"; + +export abstract class ConfigApiServiceAbstraction { + get: () => Promise; +} diff --git a/libs/common/src/abstractions/config/config.service.abstraction.ts b/libs/common/src/abstractions/config/config.service.abstraction.ts new file mode 100644 index 00000000000..ee9f946c7f3 --- /dev/null +++ b/libs/common/src/abstractions/config/config.service.abstraction.ts @@ -0,0 +1,7 @@ +import { Observable } from "rxjs"; + +import { ServerConfig } from "./server-config"; + +export abstract class ConfigServiceAbstraction { + serverConfig$: Observable; +} diff --git a/libs/common/src/abstractions/config/server-config.ts b/libs/common/src/abstractions/config/server-config.ts new file mode 100644 index 00000000000..c6c008a8cc1 --- /dev/null +++ b/libs/common/src/abstractions/config/server-config.ts @@ -0,0 +1,40 @@ +import { + ServerConfigData, + ThirdPartyServerConfigData, + EnvironmentServerConfigData, +} from "@bitwarden/common/models/data/server-config.data"; + +const dayInMilliseconds = 24 * 3600 * 1000; +const eighteenHoursInMilliseconds = 18 * 3600 * 1000; + +export class ServerConfig { + version: string; + gitHash: string; + server?: ThirdPartyServerConfigData; + environment?: EnvironmentServerConfigData; + utcDate: Date; + + constructor(serverConfigData: ServerConfigData) { + this.version = serverConfigData.version; + this.gitHash = serverConfigData.gitHash; + this.server = serverConfigData.server; + this.utcDate = new Date(serverConfigData.utcDate); + this.environment = serverConfigData.environment; + + if (this.server?.name == null && this.server?.url == null) { + this.server = null; + } + } + + private getAgeInMilliseconds(): number { + return new Date().getTime() - this.utcDate?.getTime(); + } + + isValid(): boolean { + return this.getAgeInMilliseconds() <= dayInMilliseconds; + } + + expiresSoon(): boolean { + return this.getAgeInMilliseconds() >= eighteenHoursInMilliseconds; + } +} diff --git a/libs/common/src/abstractions/environment.service.ts b/libs/common/src/abstractions/environment.service.ts index 84bceaa1972..1d608ed02c4 100644 --- a/libs/common/src/abstractions/environment.service.ts +++ b/libs/common/src/abstractions/environment.service.ts @@ -33,4 +33,5 @@ export abstract class EnvironmentService { setUrlsFromStorage: () => Promise; setUrls: (urls: Urls) => Promise; getUrls: () => Urls; + isCloud: () => boolean; } diff --git a/libs/common/src/abstractions/state.service.ts b/libs/common/src/abstractions/state.service.ts index b976a6195a0..238dfe199dd 100644 --- a/libs/common/src/abstractions/state.service.ts +++ b/libs/common/src/abstractions/state.service.ts @@ -13,6 +13,7 @@ import { OrganizationData } from "../models/data/organizationData"; import { PolicyData } from "../models/data/policyData"; import { ProviderData } from "../models/data/providerData"; import { SendData } from "../models/data/sendData"; +import { ServerConfigData } from "../models/data/server-config.data"; import { Account, AccountSettingsSettings } from "../models/domain/account"; import { EncString } from "../models/domain/encString"; import { EnvironmentUrls } from "../models/domain/environmentUrls"; @@ -319,4 +320,12 @@ export abstract class StateService { setStateVersion: (value: number) => Promise; getWindow: () => Promise; setWindow: (value: WindowState) => Promise; + /** + * @deprecated Do not call this directly, use ConfigService + */ + getServerConfig: (options?: StorageOptions) => Promise; + /** + * @deprecated Do not call this directly, use ConfigService + */ + setServerConfig: (value: ServerConfigData, options?: StorageOptions) => Promise; } diff --git a/libs/common/src/models/data/server-config.data.ts b/libs/common/src/models/data/server-config.data.ts new file mode 100644 index 00000000000..62744ecb621 --- /dev/null +++ b/libs/common/src/models/data/server-config.data.ts @@ -0,0 +1,51 @@ +import { + ServerConfigResponse, + ThirdPartyServerConfigResponse, + EnvironmentServerConfigResponse, +} from "../response/server-config-response"; + +export class ServerConfigData { + version: string; + gitHash: string; + server?: ThirdPartyServerConfigData; + environment?: EnvironmentServerConfigData; + utcDate: string; + + constructor(serverConfigReponse: ServerConfigResponse) { + this.version = serverConfigReponse?.version; + this.gitHash = serverConfigReponse?.gitHash; + this.server = serverConfigReponse?.server + ? new ThirdPartyServerConfigData(serverConfigReponse.server) + : null; + this.utcDate = new Date().toISOString(); + this.environment = serverConfigReponse?.environment + ? new EnvironmentServerConfigData(serverConfigReponse.environment) + : null; + } +} + +export class ThirdPartyServerConfigData { + name: string; + url: string; + + constructor(response: ThirdPartyServerConfigResponse) { + this.name = response.name; + this.url = response.url; + } +} + +export class EnvironmentServerConfigData { + vault: string; + api: string; + identity: string; + notifications: string; + sso: string; + + constructor(response: EnvironmentServerConfigResponse) { + this.vault = response.vault; + this.api = response.api; + this.identity = response.identity; + this.notifications = response.notifications; + this.sso = response.sso; + } +} diff --git a/libs/common/src/models/domain/account.ts b/libs/common/src/models/domain/account.ts index dfeacce1207..b7bbcb431c9 100644 --- a/libs/common/src/models/domain/account.ts +++ b/libs/common/src/models/domain/account.ts @@ -10,6 +10,7 @@ import { OrganizationData } from "../data/organizationData"; import { PolicyData } from "../data/policyData"; import { ProviderData } from "../data/providerData"; import { SendData } from "../data/sendData"; +import { ServerConfigData } from "../data/server-config.data"; import { CipherView } from "../view/cipherView"; import { CollectionView } from "../view/collectionView"; import { SendView } from "../view/sendView"; @@ -140,6 +141,7 @@ export class AccountSettings { settings?: AccountSettingsSettings; // TODO: Merge whatever is going on here into the AccountSettings model properly vaultTimeout?: number; vaultTimeoutAction?: string = "lock"; + serverConfig?: ServerConfigData; } export type AccountSettingsSettings = { diff --git a/libs/common/src/models/response/server-config-response.ts b/libs/common/src/models/response/server-config-response.ts new file mode 100644 index 00000000000..c296292f306 --- /dev/null +++ b/libs/common/src/models/response/server-config-response.ts @@ -0,0 +1,59 @@ +import { BaseResponse } from "./baseResponse"; + +export class ServerConfigResponse extends BaseResponse { + version: string; + gitHash: string; + server: ThirdPartyServerConfigResponse; + environment: EnvironmentServerConfigResponse; + + constructor(response: any) { + super(response); + + if (response == null) { + return; + } + + this.version = this.getResponseProperty("Version"); + this.gitHash = this.getResponseProperty("GitHash"); + this.server = new ThirdPartyServerConfigResponse(this.getResponseProperty("Server")); + this.environment = new EnvironmentServerConfigResponse(this.getResponseProperty("Environment")); + } +} + +export class EnvironmentServerConfigResponse extends BaseResponse { + vault: string; + api: string; + identity: string; + notifications: string; + sso: string; + + constructor(data: any = null) { + super(data); + + if (data == null) { + return; + } + + this.vault = this.getResponseProperty("Vault"); + this.api = this.getResponseProperty("Api"); + this.identity = this.getResponseProperty("Identity"); + this.notifications = this.getResponseProperty("Notifications"); + this.sso = this.getResponseProperty("Sso"); + } +} + +export class ThirdPartyServerConfigResponse extends BaseResponse { + name: string; + url: string; + + constructor(data: any = null) { + super(data); + + if (data == null) { + return; + } + + this.name = this.getResponseProperty("Name"); + this.url = this.getResponseProperty("Url"); + } +} diff --git a/libs/common/src/services/config/config-api.service.ts b/libs/common/src/services/config/config-api.service.ts new file mode 100644 index 00000000000..6b92ae0dc6e --- /dev/null +++ b/libs/common/src/services/config/config-api.service.ts @@ -0,0 +1,12 @@ +import { ApiService } from "@bitwarden/common/abstractions/api.service"; +import { ConfigApiServiceAbstraction as ConfigApiServiceAbstraction } from "@bitwarden/common/abstractions/config/config-api.service.abstraction"; +import { ServerConfigResponse } from "@bitwarden/common/models/response/server-config-response"; + +export class ConfigApiService implements ConfigApiServiceAbstraction { + constructor(private apiService: ApiService) {} + + async get(): Promise { + const r = await this.apiService.send("GET", "/config", null, true, true); + return new ServerConfigResponse(r); + } +} diff --git a/libs/common/src/services/config/config.service.ts b/libs/common/src/services/config/config.service.ts new file mode 100644 index 00000000000..9f9e0938b5a --- /dev/null +++ b/libs/common/src/services/config/config.service.ts @@ -0,0 +1,61 @@ +import { BehaviorSubject, concatMap, map, switchMap, timer, EMPTY } from "rxjs"; + +import { ServerConfigData } from "@bitwarden/common/models/data/server-config.data"; + +import { ConfigApiServiceAbstraction } from "../../abstractions/config/config-api.service.abstraction"; +import { ConfigServiceAbstraction } from "../../abstractions/config/config.service.abstraction"; +import { ServerConfig } from "../../abstractions/config/server-config"; +import { StateService } from "../../abstractions/state.service"; + +export class ConfigService implements ConfigServiceAbstraction { + private _serverConfig = new BehaviorSubject(null); + serverConfig$ = this._serverConfig.asObservable(); + + constructor( + private stateService: StateService, + private configApiService: ConfigApiServiceAbstraction + ) { + this.stateService.activeAccountUnlocked$ + .pipe( + switchMap((unlocked) => { + if (!unlocked) { + this._serverConfig.next(null); + return EMPTY; + } + + // Re-fetch the server config every hour + return timer(0, 3600 * 1000).pipe(map(() => unlocked)); + }), + concatMap(async (unlocked) => { + return unlocked ? await this.buildServerConfig() : null; + }) + ) + .subscribe((serverConfig) => { + this._serverConfig.next(serverConfig); + }); + } + + private async buildServerConfig(): Promise { + const data = await this.stateService.getServerConfig(); + const domain = data ? new ServerConfig(data) : null; + + if (domain == null || !domain.isValid() || domain.expiresSoon()) { + const value = await this.fetchServerConfig(); + return value ?? domain; + } + + return domain; + } + + private async fetchServerConfig(): Promise { + const response = await this.configApiService.get(); + const data = new ServerConfigData(response); + + if (data != null) { + await this.stateService.setServerConfig(data); + return new ServerConfig(data); + } + + return null; + } +} diff --git a/libs/common/src/services/environment.service.ts b/libs/common/src/services/environment.service.ts index d79b2b189da..48561a99092 100644 --- a/libs/common/src/services/environment.service.ts +++ b/libs/common/src/services/environment.service.ts @@ -207,4 +207,10 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { return url.trim(); } + + isCloud(): boolean { + return ["https://api.bitwarden.com", "https://vault.bitwarden.com/api"].includes( + this.getApiUrl() + ); + } } diff --git a/libs/common/src/services/noopEvent.service.ts b/libs/common/src/services/noopEvent.service.ts index 63d045524ec..4504ceb29f5 100644 --- a/libs/common/src/services/noopEvent.service.ts +++ b/libs/common/src/services/noopEvent.service.ts @@ -5,7 +5,7 @@ import { EventType } from "@bitwarden/common/enums/eventType"; * If you want to use this, don't. * If you think you should use that after the warning, don't. */ -export default class NoOpEventService implements EventService { +export class NoopEventService implements EventService { constructor() { if (chrome.runtime.getManifest().manifest_version !== 3) { throw new Error("You are not allowed to use this when not in manifest_version 3"); diff --git a/libs/common/src/services/state.service.ts b/libs/common/src/services/state.service.ts index 6dd6187cc97..d5aabb3490a 100644 --- a/libs/common/src/services/state.service.ts +++ b/libs/common/src/services/state.service.ts @@ -21,6 +21,7 @@ import { OrganizationData } from "../models/data/organizationData"; import { PolicyData } from "../models/data/policyData"; import { ProviderData } from "../models/data/providerData"; import { SendData } from "../models/data/sendData"; +import { ServerConfigData } from "../models/data/server-config.data"; import { Account, AccountData, @@ -2277,6 +2278,23 @@ export class StateService< ); } + async setServerConfig(value: ServerConfigData, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + account.settings.serverConfig = value; + return await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getServerConfig(options: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.settings?.serverConfig; + } + protected async getGlobals(options: StorageOptions): Promise { let globals: TGlobalState; if (this.useMemory(options.storageLocation)) { diff --git a/libs/components/src/dialog/dialog.module.ts b/libs/components/src/dialog/dialog.module.ts index 828ae368adf..535972417c1 100644 --- a/libs/components/src/dialog/dialog.module.ts +++ b/libs/components/src/dialog/dialog.module.ts @@ -1,15 +1,22 @@ import { DialogModule as CdkDialogModule } from "@angular/cdk/dialog"; -import { CommonModule } from "@angular/common"; import { NgModule } from "@angular/core"; -import { DialogCloseDirective } from "./dialog-close.directive"; +import { SharedModule } from "../shared"; + import { DialogService } from "./dialog.service"; import { DialogComponent } from "./dialog/dialog.component"; +import { DialogCloseDirective } from "./directives/dialog-close.directive"; +import { DialogTitleContainerDirective } from "./directives/dialog-title-container.directive"; import { SimpleDialogComponent } from "./simple-dialog/simple-dialog.component"; @NgModule({ - imports: [CommonModule, CdkDialogModule], - declarations: [DialogCloseDirective, DialogComponent, SimpleDialogComponent], + imports: [SharedModule, CdkDialogModule], + declarations: [ + DialogCloseDirective, + DialogComponent, + DialogTitleContainerDirective, + SimpleDialogComponent, + ], exports: [CdkDialogModule, DialogComponent, SimpleDialogComponent], providers: [DialogService], }) diff --git a/libs/components/src/dialog/dialog.service.stories.ts b/libs/components/src/dialog/dialog.service.stories.ts new file mode 100644 index 00000000000..942891ba061 --- /dev/null +++ b/libs/components/src/dialog/dialog.service.stories.ts @@ -0,0 +1,97 @@ +import { DialogModule, DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; +import { Component, Inject } from "@angular/core"; +import { Meta, moduleMetadata, Story } from "@storybook/angular"; + +import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; + +import { ButtonModule } from "../button"; +import { I18nMockService } from "../utils/i18n-mock.service"; + +import { DialogService } from "./dialog.service"; +import { DialogComponent } from "./dialog/dialog.component"; +import { DialogCloseDirective } from "./directives/dialog-close.directive"; +import { DialogTitleContainerDirective } from "./directives/dialog-title-container.directive"; + +interface Animal { + animal: string; +} + +@Component({ + selector: "app-story-dialog", + template: ``, +}) +class StoryDialogComponent { + constructor(public dialogService: DialogService) {} + + openDialog() { + this.dialogService.open(StoryDialogContentComponent, { + data: { + animal: "panda", + }, + }); + } +} + +@Component({ + selector: "story-dialog-content", + template: ` + + Dialog Title + + Dialog body text goes here. +
+ Animal: {{ animal }} +
+
+ + +
+
+ `, +}) +class StoryDialogContentComponent { + constructor(public dialogRef: DialogRef, @Inject(DIALOG_DATA) private data: Animal) {} + + get animal() { + return this.data?.animal; + } +} + +export default { + title: "Component Library/Dialogs/Service", + component: StoryDialogComponent, + decorators: [ + moduleMetadata({ + declarations: [ + DialogCloseDirective, + DialogComponent, + DialogTitleContainerDirective, + StoryDialogContentComponent, + ], + imports: [ButtonModule, DialogModule], + providers: [ + DialogService, + { + provide: I18nService, + useFactory: () => { + return new I18nMockService({ + close: "Close", + }); + }, + }, + ], + }), + ], + parameters: { + design: { + type: "figma", + url: "https://www.figma.com/file/Zt3YSeb6E6lebAffrNLa0h/Tailwind-Component-Library", + }, + }, +} as Meta; + +const Template: Story = (args: StoryDialogComponent) => ({ + props: args, +}); + +export const Default = Template.bind({}); diff --git a/libs/components/src/dialog/dialog/dialog.component.html b/libs/components/src/dialog/dialog/dialog.component.html index c71e38120b9..1bc95d5208d 100644 --- a/libs/components/src/dialog/dialog/dialog.component.html +++ b/libs/components/src/dialog/dialog/dialog.component.html @@ -5,21 +5,26 @@
-

- -

-
- +
- +
diff --git a/libs/components/src/dialog/dialog/dialog.stories.ts b/libs/components/src/dialog/dialog/dialog.stories.ts index 3f2220d49fb..3bf8457d128 100644 --- a/libs/components/src/dialog/dialog/dialog.stories.ts +++ b/libs/components/src/dialog/dialog/dialog.stories.ts @@ -1,6 +1,12 @@ import { Meta, moduleMetadata, Story } from "@storybook/angular"; +import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; + import { ButtonModule } from "../../button"; +import { SharedModule } from "../../shared"; +import { I18nMockService } from "../../utils/i18n-mock.service"; +import { DialogCloseDirective } from "../directives/dialog-close.directive"; +import { DialogTitleContainerDirective } from "../directives/dialog-title-container.directive"; import { DialogComponent } from "./dialog.component"; @@ -9,7 +15,18 @@ export default { component: DialogComponent, decorators: [ moduleMetadata({ - imports: [ButtonModule], + imports: [SharedModule, ButtonModule], + declarations: [DialogTitleContainerDirective, DialogCloseDirective], + providers: [ + { + provide: I18nService, + useFactory: () => { + return new I18nMockService({ + close: "Close", + }); + }, + }, + ], }), ], args: { @@ -27,9 +44,9 @@ const Template: Story = (args: DialogComponent) => ({ props: args, template: ` - {{title}} - Dialog body text goes here. -
+ {{title}} + Dialog body text goes here. +
@@ -59,15 +76,15 @@ const TemplateScrolling: Story = (args: DialogComponent) => ({ props: args, template: ` - Scrolling Example - + Scrolling Example + Dialog body text goes here.
repeating lines of characters
end of sequence!
-
+
diff --git a/libs/components/src/dialog/dialog-close.directive.ts b/libs/components/src/dialog/directives/dialog-close.directive.ts similarity index 72% rename from libs/components/src/dialog/dialog-close.directive.ts rename to libs/components/src/dialog/directives/dialog-close.directive.ts index 11f894e04dc..a45991bb5e6 100644 --- a/libs/components/src/dialog/dialog-close.directive.ts +++ b/libs/components/src/dialog/directives/dialog-close.directive.ts @@ -1,18 +1,15 @@ import { DialogRef } from "@angular/cdk/dialog"; -import { Directive, Input, Optional } from "@angular/core"; +import { Directive, HostListener, Input, Optional } from "@angular/core"; @Directive({ selector: "[bitDialogClose]", - host: { - "(click)": "close()", - }, }) export class DialogCloseDirective { @Input("bit-dialog-close") dialogResult: any; constructor(@Optional() public dialogRef: DialogRef) {} - close() { + @HostListener("click") close(): void { this.dialogRef.close(this.dialogResult); } } diff --git a/libs/components/src/dialog/directives/dialog-title-container.directive.ts b/libs/components/src/dialog/directives/dialog-title-container.directive.ts new file mode 100644 index 00000000000..96664a5f94b --- /dev/null +++ b/libs/components/src/dialog/directives/dialog-title-container.directive.ts @@ -0,0 +1,30 @@ +import { CdkDialogContainer, DialogRef } from "@angular/cdk/dialog"; +import { Directive, HostBinding, Input, OnInit, Optional } from "@angular/core"; + +// Increments for each instance of this component +let nextId = 0; + +@Directive({ + selector: "[bitDialogTitleContainer]", +}) +export class DialogTitleContainerDirective implements OnInit { + @HostBinding("id") id = `bit-dialog-title-${nextId++}`; + + @Input() simple = false; + + constructor(@Optional() private dialogRef: DialogRef) {} + + ngOnInit(): void { + // Based on angular/components, licensed under MIT + // https://github.com/angular/components/blob/14.2.0/src/material/dialog/dialog-content-directives.ts#L121-L128 + if (this.dialogRef) { + Promise.resolve().then(() => { + const container = this.dialogRef.containerInstance as CdkDialogContainer; + + if (container && !container._ariaLabelledBy) { + container._ariaLabelledBy = this.id; + } + }); + } + } +} diff --git a/libs/components/src/dialog/dialog-service.stories.ts b/libs/components/src/dialog/simple-dialog.service.stories.ts similarity index 68% rename from libs/components/src/dialog/dialog-service.stories.ts rename to libs/components/src/dialog/simple-dialog.service.stories.ts index 50514d3c756..90963515aaa 100644 --- a/libs/components/src/dialog/dialog-service.stories.ts +++ b/libs/components/src/dialog/simple-dialog.service.stories.ts @@ -4,9 +4,10 @@ import { Meta, moduleMetadata, Story } from "@storybook/angular"; import { ButtonModule } from "../button"; -import { DialogCloseDirective } from "./dialog-close.directive"; import { DialogService } from "./dialog.service"; -import { DialogComponent } from "./dialog/dialog.component"; +import { DialogCloseDirective } from "./directives/dialog-close.directive"; +import { DialogTitleContainerDirective } from "./directives/dialog-title-container.directive"; +import { SimpleDialogComponent } from "./simple-dialog/simple-dialog.component"; interface Animal { animal: string; @@ -14,7 +15,7 @@ interface Animal { @Component({ selector: "app-story-dialog", - template: ``, + template: ``, }) class StoryDialogComponent { constructor(public dialogService: DialogService) {} @@ -31,18 +32,18 @@ class StoryDialogComponent { @Component({ selector: "story-dialog-content", template: ` - - Dialog Title - + + Dialog Title + Dialog body text goes here.
Animal: {{ animal }}
-
+
- + `, }) class StoryDialogContentComponent { @@ -54,11 +55,16 @@ class StoryDialogContentComponent { } export default { - title: "Component Library/Dialogs/Service", + title: "Component Library/Dialogs/Service/Simple", component: StoryDialogComponent, decorators: [ moduleMetadata({ - declarations: [DialogComponent, StoryDialogContentComponent, DialogCloseDirective], + declarations: [ + DialogCloseDirective, + SimpleDialogComponent, + DialogTitleContainerDirective, + StoryDialogContentComponent, + ], imports: [ButtonModule, DialogModule], providers: [DialogService], }), diff --git a/libs/components/src/dialog/simple-dialog/simple-dialog.component.html b/libs/components/src/dialog/simple-dialog/simple-dialog.component.html index 90a4a51e064..8ce31f89a13 100644 --- a/libs/components/src/dialog/simple-dialog/simple-dialog.component.html +++ b/libs/components/src/dialog/simple-dialog/simple-dialog.component.html @@ -1,19 +1,19 @@
-

- -

+

+ +

- +
- +
diff --git a/libs/components/src/dialog/simple-dialog/simple-dialog.stories.ts b/libs/components/src/dialog/simple-dialog/simple-dialog.stories.ts index a74220f3cb9..307b21b4c22 100644 --- a/libs/components/src/dialog/simple-dialog/simple-dialog.stories.ts +++ b/libs/components/src/dialog/simple-dialog/simple-dialog.stories.ts @@ -1,6 +1,7 @@ import { Meta, moduleMetadata, Story } from "@storybook/angular"; import { ButtonModule } from "../../button"; +import { DialogTitleContainerDirective } from "../directives/dialog-title-container.directive"; import { IconDirective, SimpleDialogComponent } from "./simple-dialog.component"; @@ -10,7 +11,7 @@ export default { decorators: [ moduleMetadata({ imports: [ButtonModule], - declarations: [IconDirective], + declarations: [IconDirective, DialogTitleContainerDirective], }), ], parameters: { @@ -25,9 +26,9 @@ const Template: Story = (args: SimpleDialogComponent) => props: args, template: ` - Alert Dialog - Message Content -
+ Alert Dialog + Message Content +
@@ -42,9 +43,9 @@ const TemplateWithIcon: Story = (args: SimpleDialogCompon template: ` - Premium Subscription Available - Message Content -
+ Premium Subscription Available + Message Content +
@@ -58,8 +59,8 @@ const TemplateScroll: Story = (args: SimpleDialogComponen props: args, template: ` - Alert Dialog - + Alert Dialog + Message Content Message text goes here.
@@ -67,7 +68,7 @@ const TemplateScroll: Story = (args: SimpleDialogComponen end of sequence!
-
+
diff --git a/libs/components/src/form-field/form-field.module.ts b/libs/components/src/form-field/form-field.module.ts index 1796bae4d71..c07f21bab99 100644 --- a/libs/components/src/form-field/form-field.module.ts +++ b/libs/components/src/form-field/form-field.module.ts @@ -1,10 +1,8 @@ -import { CommonModule } from "@angular/common"; -import { NgModule, Pipe, PipeTransform } from "@angular/core"; - -import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; +import { NgModule } from "@angular/core"; import { BitInputDirective } from "../input/input.directive"; import { InputModule } from "../input/input.module"; +import { SharedModule } from "../shared"; import { BitErrorSummary } from "./error-summary.component"; import { BitErrorComponent } from "./error.component"; @@ -14,22 +12,8 @@ import { BitLabel } from "./label.directive"; import { BitPrefixDirective } from "./prefix.directive"; import { BitSuffixDirective } from "./suffix.directive"; -/** - * Temporarily duplicate this pipe - */ -@Pipe({ - name: "i18n", -}) -export class I18nPipe implements PipeTransform { - constructor(private i18nService: I18nService) {} - - transform(id: string, p1?: string, p2?: string, p3?: string): string { - return this.i18nService.t(id, p1, p2, p3); - } -} - @NgModule({ - imports: [CommonModule, InputModule], + imports: [SharedModule, InputModule], exports: [ BitErrorComponent, BitErrorSummary, @@ -48,7 +32,6 @@ export class I18nPipe implements PipeTransform { BitLabel, BitPrefixDirective, BitSuffixDirective, - I18nPipe, ], }) export class FormFieldModule {} diff --git a/libs/components/src/shared/i18n.pipe.ts b/libs/components/src/shared/i18n.pipe.ts new file mode 100644 index 00000000000..f1ec9a29cc4 --- /dev/null +++ b/libs/components/src/shared/i18n.pipe.ts @@ -0,0 +1,17 @@ +import { Pipe, PipeTransform } from "@angular/core"; + +import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; + +/** + * Temporarily duplicate this pipe + */ +@Pipe({ + name: "i18n", +}) +export class I18nPipe implements PipeTransform { + constructor(private i18nService: I18nService) {} + + transform(id: string, p1?: string, p2?: string, p3?: string): string { + return this.i18nService.t(id, p1, p2, p3); + } +} diff --git a/libs/components/src/shared/index.ts b/libs/components/src/shared/index.ts new file mode 100644 index 00000000000..7a1160c4105 --- /dev/null +++ b/libs/components/src/shared/index.ts @@ -0,0 +1 @@ +export * from "./shared.module"; diff --git a/libs/components/src/shared/shared.module.ts b/libs/components/src/shared/shared.module.ts new file mode 100644 index 00000000000..dcf2e2bc05f --- /dev/null +++ b/libs/components/src/shared/shared.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; + +import { I18nPipe } from "./i18n.pipe"; + +@NgModule({ + imports: [CommonModule], + declarations: [I18nPipe], + exports: [CommonModule, I18nPipe], +}) +export class SharedModule {} diff --git a/libs/components/tailwind.config.base.js b/libs/components/tailwind.config.base.js index 820f132dd3b..1758416e3bd 100644 --- a/libs/components/tailwind.config.base.js +++ b/libs/components/tailwind.config.base.js @@ -80,6 +80,7 @@ module.exports = { }, maxWidth: ({ theme }) => ({ ...theme("width"), + "90vw": "90vw", }), }, }, diff --git a/libs/node/spec/cli/consoleLog.service.spec.ts.disabled b/libs/node/spec/cli/consoleLog.service.spec.ts similarity index 89% rename from libs/node/spec/cli/consoleLog.service.spec.ts.disabled rename to libs/node/spec/cli/consoleLog.service.spec.ts index eefc3f4c667..656a74ca55d 100644 --- a/libs/node/spec/cli/consoleLog.service.spec.ts.disabled +++ b/libs/node/spec/cli/consoleLog.service.spec.ts @@ -1,10 +1,7 @@ -import { - interceptConsole, - restoreConsole, -} from "@bitwarden/common/../spec/services/consolelog.service.spec"; - import { ConsoleLogService } from "@bitwarden/node/cli/services/consoleLog.service"; +import { interceptConsole, restoreConsole } from "../../../common/spec/shared/interceptConsole"; + let caughtMessage: any = {}; describe("CLI Console log service", () => { diff --git a/libs/shared/jest.config.base.js b/libs/shared/jest.config.base.js index 7538064c284..056e54e9a7e 100644 --- a/libs/shared/jest.config.base.js +++ b/libs/shared/jest.config.base.js @@ -10,10 +10,15 @@ module.exports = { // Also anecdotally improves performance when run locally maxWorkers: 3, - // Jest does not use tsconfig.spec.json by default globals: { "ts-jest": { + // Jest does not use tsconfig.spec.json by default tsconfig: "/tsconfig.spec.json", + // Further workaround for memory leak, recommended here: + // https://github.com/kulshekhar/ts-jest/issues/1967#issuecomment-697494014 + // Makes tests run faster and reduces size/rate of leak, but loses typechecking on test code + // See https://bitwarden.atlassian.net/browse/EC-497 for more info + isolatedModules: true, }, }, }; diff --git a/package-lock.json b/package-lock.json index bb37d6c63fd..ded274d4a2c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,7 +47,6 @@ "koa-json": "^2.0.2", "lowdb": "^1.0.0", "lunr": "^2.3.9", - "mousetrap": "^1.6.5", "multer": "^1.4.5-lts.1", "ngx-infinite-scroll": "^14.0.0", "ngx-toastr": "^15.0.0", @@ -96,7 +95,6 @@ "@types/koa-json": "^2.0.20", "@types/lowdb": "^1.0.11", "@types/lunr": "^2.3.4", - "@types/mousetrap": "^1.6.8", "@types/node": "^16.11.12", "@types/node-fetch": "^2.6.1", "@types/node-forge": "^1.0.2", @@ -182,11 +180,11 @@ }, "apps/browser": { "name": "@bitwarden/browser", - "version": "2022.8.0" + "version": "2022.9.0" }, "apps/cli": { "name": "@bitwarden/cli", - "version": "2022.8.0", + "version": "2022.9.0", "license": "GPL-3.0-only", "dependencies": { "@koa/multer": "^3.0.0", @@ -221,7 +219,7 @@ }, "apps/desktop": { "name": "@bitwarden/desktop", - "version": "2022.8.2", + "version": "2022.9.1", "hasInstallScript": true, "license": "GPL-3.0" }, @@ -12922,12 +12920,6 @@ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", "dev": true }, - "node_modules/@types/mousetrap": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.9.tgz", - "integrity": "sha512-HUAiN65VsRXyFCTicolwb5+I7FM6f72zjMWr+ajGk+YTvzBgXqa2A5U7d+rtsouAkunJ5U4Sb5lNJjo9w+nmXg==", - "dev": true - }, "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -31840,11 +31832,6 @@ "node": ">= 0.8" } }, - "node_modules/mousetrap": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz", - "integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==" - }, "node_modules/move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -52788,12 +52775,6 @@ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", "dev": true }, - "@types/mousetrap": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.9.tgz", - "integrity": "sha512-HUAiN65VsRXyFCTicolwb5+I7FM6f72zjMWr+ajGk+YTvzBgXqa2A5U7d+rtsouAkunJ5U4Sb5lNJjo9w+nmXg==", - "dev": true - }, "@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -67511,11 +67492,6 @@ } } }, - "mousetrap": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz", - "integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==" - }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", diff --git a/package.json b/package.json index cf058e3bbee..0260152ce47 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "@types/koa-json": "^2.0.20", "@types/lowdb": "^1.0.11", "@types/lunr": "^2.3.4", - "@types/mousetrap": "^1.6.8", "@types/node": "^16.11.12", "@types/node-fetch": "^2.6.1", "@types/node-forge": "^1.0.2", @@ -173,7 +172,6 @@ "koa-json": "^2.0.2", "lowdb": "^1.0.0", "lunr": "^2.3.9", - "mousetrap": "^1.6.5", "multer": "^1.4.5-lts.1", "ngx-infinite-scroll": "^14.0.0", "ngx-toastr": "^15.0.0",