diff --git a/.eslintignore b/.eslintignore index 68d426174ac..b6c475d3326 100644 --- a/.eslintignore +++ b/.eslintignore @@ -12,6 +12,7 @@ storybook-static apps/browser/config/config.js apps/browser/src/auth/scripts/duo.js +apps/browser/webpack/manifest.js apps/desktop/desktop_native apps/desktop/src/auth/scripts/duo.js diff --git a/.github/whitelist-capital-letters.txt b/.github/whitelist-capital-letters.txt index 3295dfc17df..a320149281b 100644 --- a/.github/whitelist-capital-letters.txt +++ b/.github/whitelist-capital-letters.txt @@ -5,16 +5,6 @@ ./apps/browser/store/windows/Assets ./bitwarden_license/README.md ./libs/angular/src/directives/cipherListVirtualScroll.directive.ts -./libs/angular/src/scss/webfonts/Open_Sans-italic-700.woff -./libs/angular/src/scss/webfonts/Open_Sans-normal-300.woff -./libs/angular/src/scss/webfonts/Open_Sans-normal-700.woff -./libs/angular/src/scss/webfonts/Open_Sans-italic-300.woff -./libs/angular/src/scss/webfonts/Open_Sans-italic-600.woff -./libs/angular/src/scss/webfonts/Open_Sans-italic-800.woff -./libs/angular/src/scss/webfonts/Open_Sans-italic-400.woff -./libs/angular/src/scss/webfonts/Open_Sans-normal-600.woff -./libs/angular/src/scss/webfonts/Open_Sans-normal-800.woff -./libs/angular/src/scss/webfonts/Open_Sans-normal-400.woff ./libs/admin-console/README.md ./libs/auth/README.md ./libs/billing/README.md diff --git a/.github/workflows/build-browser.yml b/.github/workflows/build-browser.yml index 42d012d5a98..7740e418e7b 100644 --- a/.github/workflows/build-browser.yml +++ b/.github/workflows/build-browser.yml @@ -27,7 +27,11 @@ on: workflow_call: inputs: {} workflow_dispatch: - inputs: {} + inputs: + sdk_branch: + description: "Custom SDK branch" + required: false + type: string defaults: run: @@ -164,16 +168,93 @@ jobs: zip -r browser-source.zip browser-source + - name: Upload browser source + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + with: + name: browser-source-${{ env._BUILD_NUMBER }}.zip + path: browser-source.zip + if-no-files-found: error + - name: NPM setup run: npm ci working-directory: browser-source/ - - name: Build - run: npm run dist + - name: Download SDK Artifacts + if: ${{ inputs.sdk_branch != '' }} + uses: bitwarden/gh-actions/download-artifacts@main + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: build-wasm-internal.yml + workflow_conclusion: success + branch: ${{ inputs.sdk_branch }} + artifacts: sdk-internal + repo: bitwarden/sdk-internal + path: sdk-internal + if_no_artifact_found: fail + + - name: Override SDK + if: ${{ inputs.sdk_branch != '' }} + working-directory: browser-source/ + run: | + npm link ../sdk-internal + + - name: Build Chrome + run: npm run dist:chrome working-directory: browser-source/apps/browser - - name: Build Manifest v3 - run: npm run dist:mv3 + - name: Upload Chrome MV3 artifact + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + with: + name: dist-chrome-MV3-${{ env._BUILD_NUMBER }}.zip + path: browser-source/apps/browser/dist/dist-chrome.zip + if-no-files-found: error + + - name: Build Edge + run: npm run dist:edge + working-directory: browser-source/apps/browser + + - name: Upload Edge artifact + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + with: + name: dist-edge-${{ env._BUILD_NUMBER }}.zip + path: browser-source/apps/browser/dist/dist-edge.zip + if-no-files-found: error + + - name: Build Edge (MV3) + run: npm run dist:edge:mv3 + working-directory: browser-source/apps/browser + + - name: Upload Edge MV3 artifact (DO NOT USE FOR PROD) + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + with: + name: DO-NOT-USE-FOR-PROD-dist-edge-MV3-${{ env._BUILD_NUMBER }}.zip + path: browser-source/apps/browser/dist/dist-edge.zip + if-no-files-found: error + + - name: Build Firefox + run: npm run dist:firefox + working-directory: browser-source/apps/browser + + - name: Upload Firefox artifact + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + with: + name: dist-firefox-${{ env._BUILD_NUMBER }}.zip + path: browser-source/apps/browser/dist/dist-firefox.zip + if-no-files-found: error + + - name: Build Firefox (MV3) + run: npm run dist:firefox:mv3 + working-directory: browser-source/apps/browser + + - name: Upload Firefox MV3 artifact (DO NOT USE FOR PROD) + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + with: + name: DO-NOT-USE-FOR-PROD-dist-firefox-MV3-${{ env._BUILD_NUMBER }}.zip + path: browser-source/apps/browser/dist/dist-firefox.zip + if-no-files-found: error + + - name: Build Opera + run: npm run dist:opera working-directory: browser-source/apps/browser - name: Upload Opera artifact @@ -183,53 +264,15 @@ jobs: path: browser-source/apps/browser/dist/dist-opera.zip if-no-files-found: error + - name: Build Opera (MV3) + run: npm run dist:opera:mv3 + working-directory: browser-source/apps/browser + - name: Upload Opera MV3 artifact (DO NOT USE FOR PROD) uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: DO-NOT-USE-FOR-PROD-dist-opera-MV3-${{ env._BUILD_NUMBER }}.zip - path: browser-source/apps/browser/dist/dist-opera-mv3.zip - if-no-files-found: error - - - name: Upload Chrome MV3 artifact - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: dist-chrome-MV3-${{ env._BUILD_NUMBER }}.zip - path: browser-source/apps/browser/dist/dist-chrome-mv3.zip - if-no-files-found: error - - - name: Upload Firefox artifact - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: dist-firefox-${{ env._BUILD_NUMBER }}.zip - path: browser-source/apps/browser/dist/dist-firefox.zip - if-no-files-found: error - - - name: Upload Firefox MV3 artifact (DO NOT USE FOR PROD) - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: DO-NOT-USE-FOR-PROD-dist-firefox-MV3-${{ env._BUILD_NUMBER }}.zip - path: browser-source/apps/browser/dist/dist-firefox-mv3.zip - if-no-files-found: error - - - name: Upload Edge artifact - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: dist-edge-${{ env._BUILD_NUMBER }}.zip - path: browser-source/apps/browser/dist/dist-edge.zip - if-no-files-found: error - - - name: Upload Edge MV3 artifact (DO NOT USE FOR PROD) - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: DO-NOT-USE-FOR-PROD-dist-edge-MV3-${{ env._BUILD_NUMBER }}.zip - path: browser-source/apps/browser/dist/dist-edge-mv3.zip - if-no-files-found: error - - - name: Upload browser source - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: browser-source-${{ env._BUILD_NUMBER }}.zip - path: browser-source.zip + path: browser-source/apps/browser/dist/dist-opera.zip if-no-files-found: error build-safari: @@ -331,6 +374,25 @@ jobs: run: npm ci working-directory: ./ + - name: Download SDK Artifacts + if: ${{ inputs.sdk_branch != '' }} + uses: bitwarden/gh-actions/download-artifacts@main + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: build-wasm-internal.yml + workflow_conclusion: success + branch: ${{ inputs.sdk_branch }} + artifacts: sdk-internal + repo: bitwarden/sdk-internal + path: ../sdk-internal + if_no_artifact_found: fail + + - name: Override SDK + if: ${{ inputs.sdk_branch != '' }} + working-directory: ./ + run: | + npm link ../sdk-internal + - name: Build Safari extension run: npm run dist:safari working-directory: apps/browser diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index ac39ab2608b..883dc61f49f 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -28,7 +28,11 @@ on: - '.github/workflows/build-cli.yml' - 'bitwarden_license/bit-cli/**' workflow_dispatch: - inputs: {} + inputs: + sdk_branch: + description: "Custom SDK branch" + required: false + type: string defaults: run: @@ -112,6 +116,26 @@ jobs: run: npm ci working-directory: ./ + - name: Download SDK Artifacts + if: ${{ inputs.sdk_branch != '' }} + uses: bitwarden/gh-actions/download-artifacts@main + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: build-wasm-internal.yml + workflow_conclusion: success + branch: ${{ inputs.sdk_branch }} + artifacts: sdk-internal + repo: bitwarden/sdk-internal + path: ../sdk-internal + if_no_artifact_found: fail + + - name: Override SDK + if: ${{ inputs.sdk_branch != '' }} + working-directory: ./ + run: | + ls -l ../ + npm link ../sdk-internal + - name: Build & Package Unix run: npm run dist:${{ matrix.license_type.build_prefix }}:${{ env.SHORT_RUNNER_OS }} --quiet @@ -247,6 +271,26 @@ jobs: run: npm ci working-directory: ./ + - name: Download SDK Artifacts + if: ${{ inputs.sdk_branch != '' }} + uses: bitwarden/gh-actions/download-artifacts@main + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: build-wasm-internal.yml + workflow_conclusion: success + branch: ${{ inputs.sdk_branch }} + artifacts: sdk-internal + repo: bitwarden/sdk-internal + path: ../sdk-internal + if_no_artifact_found: fail + + - name: Override SDK + if: ${{ inputs.sdk_branch != '' }} + working-directory: ./ + run: | + ls -l ../ + npm link ../sdk-internal + - name: Build & Package Windows run: npm run dist:${{ matrix.license_type.build_prefix }}:win --quiet diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index d21f4ac65bc..27995f1c787 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -26,7 +26,11 @@ on: - '!*.txt' - '.github/workflows/build-desktop.yml' workflow_dispatch: - inputs: {} + inputs: + sdk_branch: + description: "Custom SDK branch" + required: false + type: string defaults: run: @@ -182,6 +186,26 @@ jobs: run: npm ci working-directory: ./ + - name: Download SDK Artifacts + if: ${{ inputs.sdk_branch != '' }} + uses: bitwarden/gh-actions/download-artifacts@main + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: build-wasm-internal.yml + workflow_conclusion: success + branch: ${{ inputs.sdk_branch }} + artifacts: sdk-internal + repo: bitwarden/sdk-internal + path: ../sdk-internal + if_no_artifact_found: fail + + - name: Override SDK + if: ${{ inputs.sdk_branch != '' }} + working-directory: ./ + run: | + ls -l ../ + npm link ../sdk-internal + - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache @@ -328,6 +352,26 @@ jobs: run: npm ci working-directory: ./ + - name: Download SDK Artifacts + if: ${{ inputs.sdk_branch != '' }} + uses: bitwarden/gh-actions/download-artifacts@main + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: build-wasm-internal.yml + workflow_conclusion: success + branch: ${{ inputs.sdk_branch }} + artifacts: sdk-internal + repo: bitwarden/sdk-internal + path: ../sdk-internal + if_no_artifact_found: fail + + - name: Override SDK + if: ${{ inputs.sdk_branch != '' }} + working-directory: ./ + run: | + ls -l ../ + npm link ../sdk-internal + - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache @@ -616,6 +660,26 @@ jobs: run: npm ci working-directory: ./ + - name: Download SDK Artifacts + if: ${{ inputs.sdk_branch != '' }} + uses: bitwarden/gh-actions/download-artifacts@main + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: build-wasm-internal.yml + workflow_conclusion: success + branch: ${{ inputs.sdk_branch }} + artifacts: sdk-internal + repo: bitwarden/sdk-internal + path: ../sdk-internal + if_no_artifact_found: fail + + - name: Override SDK + if: ${{ inputs.sdk_branch != '' }} + working-directory: ./ + run: | + ls -l ../ + npm link ../sdk-internal + - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache @@ -784,6 +848,26 @@ jobs: run: npm ci working-directory: ./ + - name: Download SDK Artifacts + if: ${{ inputs.sdk_branch != '' }} + uses: bitwarden/gh-actions/download-artifacts@main + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: build-wasm-internal.yml + workflow_conclusion: success + branch: ${{ inputs.sdk_branch }} + artifacts: sdk-internal + repo: bitwarden/sdk-internal + path: ../sdk-internal + if_no_artifact_found: fail + + - name: Override SDK + if: ${{ inputs.sdk_branch != '' }} + working-directory: ./ + run: | + ls -l ../ + npm link ../sdk-internal + - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache @@ -1012,6 +1096,26 @@ jobs: run: npm ci working-directory: ./ + - name: Download SDK Artifacts + if: ${{ inputs.sdk_branch != '' }} + uses: bitwarden/gh-actions/download-artifacts@main + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: build-wasm-internal.yml + workflow_conclusion: success + branch: ${{ inputs.sdk_branch }} + artifacts: sdk-internal + repo: bitwarden/sdk-internal + path: ../sdk-internal + if_no_artifact_found: fail + + - name: Override SDK + if: ${{ inputs.sdk_branch != '' }} + working-directory: ./ + run: | + ls -l ../ + npm link ../sdk-internal + - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache @@ -1247,6 +1351,26 @@ jobs: run: npm ci working-directory: ./ + - name: Download SDK Artifacts + if: ${{ inputs.sdk_branch != '' }} + uses: bitwarden/gh-actions/download-artifacts@main + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: build-wasm-internal.yml + workflow_conclusion: success + branch: ${{ inputs.sdk_branch }} + artifacts: sdk-internal + repo: bitwarden/sdk-internal + path: ../sdk-internal + if_no_artifact_found: fail + + - name: Override SDK + if: ${{ inputs.sdk_branch != '' }} + working-directory: ./ + run: | + ls -l ../ + npm link ../sdk-internal + - name: Cache Native Module uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2 id: cache diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index 7e89a5c7cd7..350835d0ec7 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -32,6 +32,10 @@ on: custom_tag_extension: description: "Custom image tag extension" required: false + sdk_branch: + description: "Custom SDK branch" + required: false + type: string env: _AZ_REGISTRY: bitwardenprod.azurecr.io @@ -124,6 +128,26 @@ jobs: - name: Install dependencies run: npm ci + - name: Download SDK Artifacts + if: ${{ inputs.sdk_branch != '' }} + uses: bitwarden/gh-actions/download-artifacts@main + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: build-wasm-internal.yml + workflow_conclusion: success + branch: ${{ inputs.sdk_branch }} + artifacts: sdk-internal + repo: bitwarden/sdk-internal + path: ../sdk-internal + if_no_artifact_found: fail + + - name: Override SDK + if: ${{ inputs.sdk_branch != '' }} + working-directory: ./ + run: | + ls -l ../ + npm link ../sdk-internal + - name: Add Git metadata to build version working-directory: apps/web if: matrix.git_metadata diff --git a/.github/workflows/crowdin-pull.yml b/.github/workflows/crowdin-pull.yml index 540da77b554..f99cecf91d6 100644 --- a/.github/workflows/crowdin-pull.yml +++ b/.github/workflows/crowdin-pull.yml @@ -9,7 +9,7 @@ on: jobs: crowdin-sync: name: Autosync - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -35,11 +35,18 @@ jobs: with: keyvault: "bitwarden-ci" secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase" + + - name: Generate GH App token + uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0 + id: app-token + with: + app-id: ${{ secrets.BW_GHAPP_ID }} + private-key: ${{ secrets.BW_GHAPP_KEY }} - name: Download translations uses: bitwarden/gh-actions/crowdin@main env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_PROJECT_ID: ${{ matrix.crowdin_project_id }} with: diff --git a/.github/workflows/release-browser.yml b/.github/workflows/release-browser.yml index 4c3321c015d..75442187516 100644 --- a/.github/workflows/release-browser.yml +++ b/.github/workflows/release-browser.yml @@ -121,7 +121,7 @@ jobs: PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} run: | mv browser-source.zip browser-source-$PACKAGE_VERSION.zip - mv dist-chrome-mv3.zip dist-chrome-$PACKAGE_VERSION.zip + mv dist-chrome.zip dist-chrome-$PACKAGE_VERSION.zip mv dist-opera.zip dist-opera-$PACKAGE_VERSION.zip mv dist-firefox.zip dist-firefox-$PACKAGE_VERSION.zip mv dist-edge.zip dist-edge-$PACKAGE_VERSION.zip diff --git a/README.md b/README.md index da31a2d4893..22c8d329f1c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,8 @@ Please refer to the [Clients section](https://contributing.bitwarden.com/getting ## Related projects: - [bitwarden/server](https://github.com/bitwarden/server): The core infrastructure backend (API, database, Docker, etc). -- [bitwarden/mobile](https://github.com/bitwarden/mobile): The mobile app vault (iOS and Android). +- [bitwarden/ios](https://github.com/bitwarden/ios): Bitwarden mobile app for iOS. +- [bitwarden/android](https://github.com/bitwarden/android): Bitwarden mobile app for Android. - [bitwarden/directory-connector](https://github.com/bitwarden/directory-connector): A tool for syncing a directory (AD, LDAP, Azure, G Suite, Okta) to an organization. # We're Hiring! diff --git a/apps/browser/config/base.json b/apps/browser/config/base.json index 91d48309240..02bdc5d22af 100644 --- a/apps/browser/config/base.json +++ b/apps/browser/config/base.json @@ -1,7 +1,6 @@ { "devFlags": {}, "flags": { - "showPasswordless": true, "accountSwitching": false, "sdk": true } diff --git a/apps/browser/config/development.json b/apps/browser/config/development.json index cc28e15f38b..042a98c2c39 100644 --- a/apps/browser/config/development.json +++ b/apps/browser/config/development.json @@ -6,7 +6,6 @@ "skipWelcomeOnInstall": true }, "flags": { - "showPasswordless": true, "accountSwitching": true } } diff --git a/apps/browser/gulpfile.js b/apps/browser/gulpfile.js deleted file mode 100644 index ed977df4715..00000000000 --- a/apps/browser/gulpfile.js +++ /dev/null @@ -1,233 +0,0 @@ -const child = require("child_process"); -const fs = require("fs"); - -const { rimraf } = require("rimraf"); -const gulp = require("gulp"); -const gulpif = require("gulp-if"); -const jeditor = require("gulp-json-editor"); -const replace = require("gulp-replace"); - -const manifest = require("./src/manifest.json"); -const manifestVersion = parseInt(process.env.MANIFEST_VERSION || manifest.version); - -const paths = { - build: "./build/", - dist: "./dist/", - safari: "./src/safari/", -}; - -function buildString() { - var build = ""; - if (process.env.MANIFEST_VERSION) { - build = `-mv${process.env.MANIFEST_VERSION}`; - } - if (process.env.BUILD_NUMBER && process.env.BUILD_NUMBER !== "") { - build = `-${process.env.BUILD_NUMBER}`; - } - return build; -} - -function distFileName(browserName, ext) { - return `dist-${browserName}${buildString()}.${ext}`; -} - -async function dist(browserName, manifest) { - const { default: zip } = await import("gulp-zip"); - - return gulp - .src(paths.build + "**/*") - .pipe(gulpif("popup/index.html", replace("__BROWSER__", "browser_" + browserName))) - .pipe(gulpif("manifest.json", jeditor(manifest))) - .pipe(zip(distFileName(browserName, "zip"))) - .pipe(gulp.dest(paths.dist)); -} - -function distFirefox() { - return dist("firefox", (manifest) => { - if (manifestVersion === 3) { - const backgroundScript = manifest.background.service_worker; - delete manifest.background.service_worker; - manifest.background.scripts = [backgroundScript]; - } - delete manifest.storage; - delete manifest.sandbox; - manifest.optional_permissions = manifest.optional_permissions.filter( - (permission) => permission !== "privacy", - ); - return manifest; - }); -} - -function distOpera() { - return dist("opera", (manifest) => { - delete manifest.applications; - - // Mv3 on Opera does seem to have sidebar support, however it is not working as expected. - // On install, the extension will crash the browser entirely if the sidebar_action key is set. - // We will remove the sidebar_action key for now until opera implements a fix. - if (manifestVersion === 3) { - delete manifest.sidebar_action; - delete manifest.commands._execute_sidebar_action; - } - - return manifest; - }); -} - -function distChrome() { - return dist("chrome", (manifest) => { - delete manifest.applications; - delete manifest.sidebar_action; - delete manifest.commands._execute_sidebar_action; - return manifest; - }); -} - -function distEdge() { - return dist("edge", (manifest) => { - delete manifest.applications; - delete manifest.sidebar_action; - delete manifest.commands._execute_sidebar_action; - return manifest; - }); -} - -function distSafariMas(cb) { - return distSafariApp(cb, "mas"); -} - -function distSafariMasDev(cb) { - return distSafariApp(cb, "masdev"); -} - -function distSafariDmg(cb) { - return distSafariApp(cb, "dmg"); -} - -function distSafariApp(cb, subBuildPath) { - const buildPath = paths.dist + "Safari/" + subBuildPath + "/"; - const builtAppexPath = buildPath + "build/Release/safari.appex"; - const builtAppexFrameworkPath = buildPath + "build/Release/safari.appex/Contents/Frameworks/"; - const entitlementsPath = paths.safari + "safari/safari.entitlements"; - var args = [ - "--verbose", - "--force", - "-o", - "runtime", - "--sign", - "Developer ID Application: 8bit Solutions LLC", - "--entitlements", - entitlementsPath, - ]; - if (subBuildPath !== "dmg") { - args = [ - "--verbose", - "--force", - "--sign", - subBuildPath === "mas" - ? "3rd Party Mac Developer Application: Bitwarden Inc" - : "E7C9978F6FBCE0553429185C405E61F5380BE8EB", - "--entitlements", - entitlementsPath, - ]; - } - - return rimraf([buildPath + "**/*"], { glob: true }) - .then(() => safariCopyAssets(paths.safari + "**/*", buildPath)) - .then(() => safariCopyBuild(paths.build + "**/*", buildPath + "safari/app")) - .then(() => { - const proc = child.spawn("xcodebuild", [ - "-project", - buildPath + "desktop.xcodeproj", - "-alltargets", - "-configuration", - "Release", - ]); - stdOutProc(proc); - return new Promise((resolve) => proc.on("close", resolve)); - }) - .then(async () => { - const libs = fs - .readdirSync(builtAppexFrameworkPath) - .filter((p) => p.endsWith(".dylib")) - .map((p) => builtAppexFrameworkPath + p); - const libPromises = []; - libs.forEach((i) => { - const proc = child.spawn("codesign", args.concat([i])); - stdOutProc(proc); - libPromises.push(new Promise((resolve) => proc.on("close", resolve))); - }); - return Promise.all(libPromises); - }) - .then(() => { - const proc = child.spawn("codesign", args.concat([builtAppexPath])); - stdOutProc(proc); - return new Promise((resolve) => proc.on("close", resolve)); - }) - .then( - () => { - return cb; - }, - () => { - return cb; - }, - ); -} - -function safariCopyAssets(source, dest) { - return new Promise((resolve, reject) => { - gulp - .src(source) - .on("error", reject) - .pipe(gulpif("safari/Info.plist", replace("0.0.1", manifest.version))) - .pipe( - gulpif("safari/Info.plist", replace("0.0.2", process.env.BUILD_NUMBER || manifest.version)), - ) - .pipe(gulpif("desktop.xcodeproj/project.pbxproj", replace("../../../build", "../safari/app"))) - .pipe(gulp.dest(dest)) - .on("end", resolve); - }); -} - -async function safariCopyBuild(source, dest) { - return new Promise((resolve, reject) => { - gulp - .src(source) - .on("error", reject) - .pipe(gulpif("popup/index.html", replace("__BROWSER__", "browser_safari"))) - .pipe( - gulpif( - "manifest.json", - jeditor((manifest) => { - if (manifestVersion === 3) { - const backgroundScript = manifest.background.service_worker; - delete manifest.background.service_worker; - manifest.background.scripts = [backgroundScript]; - } - delete manifest.sidebar_action; - delete manifest.commands._execute_sidebar_action; - delete manifest.optional_permissions; - manifest.permissions.push("nativeMessaging"); - return manifest; - }), - ), - ) - .pipe(gulp.dest(dest)) - .on("end", resolve); - }); -} - -function stdOutProc(proc) { - proc.stdout.on("data", (data) => console.log(data.toString())); - proc.stderr.on("data", (data) => console.error(data.toString())); -} - -exports["dist:firefox"] = distFirefox; -exports["dist:chrome"] = distChrome; -exports["dist:opera"] = distOpera; -exports["dist:edge"] = distEdge; -exports["dist:safari"] = gulp.parallel(distSafariMas, distSafariMasDev, distSafariDmg); -exports["dist:safari:mas"] = distSafariMas; -exports["dist:safari:masdev"] = distSafariMasDev; -exports["dist:safari:dmg"] = distSafariDmg; -exports.dist = gulp.parallel(distFirefox, distChrome, distOpera, distEdge); diff --git a/apps/browser/package.json b/apps/browser/package.json index f79d646d851..ed0a8d36342 100644 --- a/apps/browser/package.json +++ b/apps/browser/package.json @@ -2,26 +2,32 @@ "name": "@bitwarden/browser", "version": "2024.11.1", "scripts": { - "build": "cross-env MANIFEST_VERSION=3 webpack", - "build:mv2": "webpack", + "build": "npm run build:chrome", + "build:chrome": "cross-env BROWSER=chrome MANIFEST_VERSION=3 webpack", + "build:edge": "cross-env BROWSER=edge webpack", + "build:firefox": "cross-env BROWSER=firefox webpack", + "build:opera": "cross-env BROWSER=opera webpack", + "build:safari": "cross-env BROWSER=safari webpack", "build:watch": "npm run build:watch:chrome", - "build:watch:chrome": "cross-env MANIFEST_VERSION=3 BROWSER=chrome webpack --watch", - "build:watch:firefox": "cross-env MANIFEST_VERSION=3 BROWSER=firefox webpack --watch", - "build:watch:safari": "cross-env MANIFEST_VERSION=3 BROWSER=safari webpack --watch", - "build:watch:mv2": "webpack --watch", - "build:prod": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" webpack", - "build:prod:watch": "cross-env NODE_ENV=production webpack --watch", - "dist": "npm run build:prod && gulp dist", - "dist:mv3": "cross-env MANIFEST_VERSION=3 npm run build:prod && cross-env MANIFEST_VERSION=3 gulp dist", - "dist:chrome": "npm run build:prod && gulp dist:chrome", - "dist:chrome:beta": "cross-env MANIFEST_VERSION=3 npm run build:prod:beta && cross-env MANIFEST_VERSION=3 BETA_BUILD=1 gulp dist:chrome", - "dist:firefox": "npm run build:prod && gulp dist:firefox", - "dist:opera": "npm run build:prod && gulp dist:opera", - "dist:safari": "cross-env BROWSER=safari npm run build:prod && gulp dist:safari", - "dist:safari:mv3": "cross-env MANIFEST_VERSION=3 BROWSER=safari run build:prod && cross-env MANIFEST_VERSION=3 BROWSER=safari gulp dist:safari", - "dist:safari:mas": "npm run build:prod && gulp dist:safari:mas", - "dist:safari:masdev": "npm run build:prod && gulp dist:safari:masdev", - "dist:safari:dmg": "npm run build:prod && gulp dist:safari:dmg", + "build:watch:chrome": "npm run build:chrome -- --watch", + "build:watch:edge": "npm run build:edge -- --watch", + "build:watch:firefox": "npm run build:firefox -- --watch", + "build:watch:opera": "npm run build:opera -- --watch", + "build:watch:safari": "npm run build:safari -- --watch", + "build:prod:chrome": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:chrome", + "build:prod:edge": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:edge", + "build:prod:firefox": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:firefox", + "build:prod:opera": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:opera", + "build:prod:safari": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:safari", + "dist:chrome": "npm run build:prod:chrome && mkdir -p dist && ./scripts/compress.ps1 dist-chrome.zip", + "dist:edge": "npm run build:prod:edge && mkdir -p dist && ./scripts/compress.ps1 dist-edge.zip", + "dist:firefox": "npm run build:prod:firefox && mkdir -p dist && ./scripts/compress.ps1 dist-firefox.zip", + "dist:opera": "npm run build:prod:opera && mkdir -p dist && ./scripts/compress.ps1 dist-opera.zip", + "dist:safari": "npm run build:prod:safari && ./scripts/package-safari.ps1", + "dist:edge:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:edge", + "dist:firefox:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:firefox", + "dist:opera:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:opera", + "dist:safari:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:safari", "test": "jest", "test:watch": "jest --watch", "test:watch:all": "jest --watchAll" diff --git a/apps/browser/scripts/compress.ps1 b/apps/browser/scripts/compress.ps1 new file mode 100755 index 00000000000..981a07c3c8c --- /dev/null +++ b/apps/browser/scripts/compress.ps1 @@ -0,0 +1,30 @@ +#!/usr/bin/env pwsh + +#### +# Compress the build directory into a zip file. +#### + +param ( + [Parameter(Mandatory = $true)] + [String] $fileName +) + +$buildDir = Join-Path $PSScriptRoot "../build" +$distDir = Join-Path $PSScriptRoot "../dist" + +# Create dist directory if it doesn't exist +if (-not (Test-Path $distDir)) { + New-Item -ItemType Directory -Path $distDir +} + +$distPath = Join-Path -Path $distDir -ChildPath $fileName + +if (Test-Path $distPath) { + Remove-Item $distPath +} + +# Compress build directory +if (Test-Path $buildDir) { + Compress-Archive -Path (Join-Path $buildDir "*") -DestinationPath $distPath + Write-Output "Zipped $buildDir into $distPath" +} diff --git a/apps/browser/scripts/package-safari.ps1 b/apps/browser/scripts/package-safari.ps1 new file mode 100755 index 00000000000..075ed606070 --- /dev/null +++ b/apps/browser/scripts/package-safari.ps1 @@ -0,0 +1,112 @@ +#!/usr/bin/env pwsh + +#### +# Builds the safari appex. +#### + +$buildDir = Join-Path $PSScriptRoot "../build" +$distDir = Join-Path $PSScriptRoot "../dist" + +Write-Output $PSScriptRoot + +if (-not (Test-Path $buildDir)) { + Write-Output "No build directory found. Exiting..." + exit +} + +# Create dist directory if it doesn't exist +if (-not (Test-Path $distDir)) { + New-Item -ItemType Directory -Path $distDir +} + +$subBuildPaths = @("mas", "masdev", "dmg") +$safariSrc = Join-Path $PSScriptRoot "../src/safari" +$safariDistPath = Join-Path -Path $distDir -ChildPath "Safari" + +if (-not (Test-Path $safariDistPath)) { + New-Item -ItemType Directory -Path $safariDistPath +} + +# Delete old safari dists +Remove-Item -LiteralPath $safariDistPath -Force -Recurse + +foreach ($subBuildPath in $subBuildPaths) { + $safariBuildPath = Join-Path -Path $safariDistPath -ChildPath $subBuildPath + $builtAppexPath = Join-Path -Path $safariBuildPath -ChildPath "build/Release/safari.appex" + $builtAppexFrameworkPath = Join-Path -Path $safariBuildPath -ChildPath "build/Release/safari.appex/Contents/Frameworks/" + $entitlementsPath = Join-Path -Path $safariSrc -ChildPath "safari/safari.entitlements" + + switch ($subBuildPath) { + "mas" { + $codesignArgs = @( + "--verbose", + "--force", + "--sign", + '"3rd Party Mac Developer Application: Bitwarden Inc"', + "--entitlements", + $entitlementsPath + ) + } + "masdev" { + $codesignArgs = @( + "--verbose", + "--force", + "--sign", + "E7C9978F6FBCE0553429185C405E61F5380BE8EB", + "--entitlements", + $entitlementsPath + ) + } + "dmg" { + $codesignArgs = @( + "--verbose", + "--force", + "-o", + "runtime", + "--sign", + '"Developer ID Application: 8bit Solutions LLC"', + "--entitlements", + $entitlementsPath + ) + } + } + + # Copy safari src + Copy-Item -Path $safariSrc -Destination $safariBuildPath -Recurse + + # Copy build + $target = Join-Path -Path $safariBuildPath -ChildPath "safari/app" + Copy-Item -Path $buildDir -Destination $target -Recurse + + # Update versions + $jsonFilePath = Join-Path $buildDir "manifest.json" + $jsonContent = Get-Content -Path $jsonFilePath -Raw + $jsonObject = $jsonContent | ConvertFrom-Json + + $infoFile = Join-Path -Path $safariBuildPath -ChildPath "safari/Info.plist" + (Get-Content $infoFile).Replace('0.0.1', $jsonObject.version).Replace('0.0.2', $jsonObject.version) | Set-Content $infoFile + + $projectFile = Join-Path -Path $safariBuildPath -ChildPath "desktop.xcodeproj/project.pbxproj" + (Get-Content $projectFile).Replace('../../../build', "../safari/app") | Set-Content $projectFile + + # Build using xcode + $xcodeBuildArgs = @( + "-project", + (Join-Path $safariBuildPath "desktop.xcodeproj"), + "-alltargets", + "-configuration", + "Release" + ) + $proc = Start-Process "xcodebuild" -ArgumentList $xcodeBuildArgs -NoNewWindow -PassThru + $proc.WaitForExit() + + # Codesign + $libs = Get-ChildItem -Path $builtAppexFrameworkPath -Filter "*.dylib" + foreach ($lib in $libs) { + $proc = Start-Process "codesign" -ArgumentList ($codesignArgs + $lib.FullName) -NoNewWindow -PassThru + $proc.WaitForExit() + } + + $proc = Start-Process "codesign" -ArgumentList ($codesignArgs + $builtAppexPath) -NoNewWindow -PassThru + $proc.WaitForExit() +} diff --git a/apps/browser/src/_locales/ar/messages.json b/apps/browser/src/_locales/ar/messages.json index b2f849964fa..54952f5e733 100644 --- a/apps/browser/src/_locales/ar/messages.json +++ b/apps/browser/src/_locales/ar/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "الهوية" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/az/messages.json b/apps/browser/src/_locales/az/messages.json index 94b1d9ea4c7..a3fefa68d4e 100644 --- a/apps/browser/src/_locales/az/messages.json +++ b/apps/browser/src/_locales/az/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Lisenziya nömrəsini kopyala" }, + "copyPrivateKey": { + "message": "Private açarı kopyala" + }, + "copyPublicKey": { + "message": "Public açarı kopyala" + }, + "copyFingerprint": { + "message": "Barmaq izini kopyala" + }, "copyCustomField": { "message": "$FIELD$ - kopyala", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Kimlik" }, + "typeSshKey": { + "message": "SSH açarı" + }, "newItemHeader": { "message": "Yeni $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Müəssisə siyasət tələbləri bu ayara tətbiq edildi" }, + "sshPrivateKey": { + "message": "Private açar" + }, + "sshPublicKey": { + "message": "Public açar" + }, + "sshFingerprint": { + "message": "Barmaq izi" + }, + "sshKeyAlgorithm": { + "message": "Açar növü" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Yenidən sına" }, diff --git a/apps/browser/src/_locales/be/messages.json b/apps/browser/src/_locales/be/messages.json index 294ffea0563..cb84cfa5014 100644 --- a/apps/browser/src/_locales/be/messages.json +++ b/apps/browser/src/_locales/be/messages.json @@ -20,7 +20,7 @@ "message": "Стварыць уліковы запіс" }, "newToBitwarden": { - "message": "Упершыню ў Bitwarden?" + "message": "New to Bitwarden?" }, "logInWithPasskey": { "message": "Log in with passkey" @@ -29,7 +29,7 @@ "message": "Use single sign-on" }, "welcomeBack": { - "message": "З вяртаннем" + "message": "Welcome back" }, "setAStrongPassword": { "message": "Прызначыць надзейны пароль" @@ -120,7 +120,7 @@ "message": "Скапіяваць пароль" }, "copyPassphrase": { - "message": "Скапіяваць парольную фразу" + "message": "Copy passphrase" }, "copyNote": { "message": "Скапіяваць нататку" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Скапіяваць нумар ліцэнзіі" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Скапіяваць $FIELD$", "placeholders": { @@ -168,7 +177,7 @@ "message": "Скапіяваць нататкі" }, "fill": { - "message": "Запоўніць", + "message": "Fill", "description": "This string is used on the vault page to indicate autofilling. Horizontal space is limited in the interface here so try and keep translations as concise as possible." }, "autoFill": { @@ -427,7 +436,7 @@ "message": "Генерыраваць пароль" }, "generatePassphrase": { - "message": "Згенерыраваць парольную фразу" + "message": "Generate passphrase" }, "regeneratePassword": { "message": "Паўторна генерыраваць пароль" @@ -591,7 +600,7 @@ "message": "Адкрыць сайт" }, "launchWebsiteName": { - "message": "Адкрыць сайт $ITEMNAME$", + "message": "Launch website $ITEMNAME$", "placeholders": { "itemname": { "content": "$1", @@ -846,7 +855,7 @@ "message": "Увайсці" }, "logInToBitwarden": { - "message": "Увайсці ў Bitwarden" + "message": "Log in to Bitwarden" }, "restartRegistration": { "message": "Restart registration" @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Пасведчанне" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "Новы $TYPE$", "placeholders": { @@ -1795,7 +1807,7 @@ "message": "Гісторыя пароляў" }, "generatorHistory": { - "message": "Гісторыя генератара" + "message": "Generator history" }, "clearGeneratorHistoryTitle": { "message": "Clear generator history" @@ -1920,7 +1932,7 @@ "message": "Ачысціць гісторыю" }, "nothingToShow": { - "message": "Адсутнічаюць элементы для паказу" + "message": "Nothing to show" }, "nothingGeneratedRecently": { "message": "You haven't generated anything recently" @@ -2932,7 +2944,7 @@ "message": "Генерыраваць псеўданім электроннай пошты са знешнім сэрвісам перасылкі." }, "forwarderDomainName": { - "message": "Дамен электроннай пошты", + "message": "Email domain", "description": "Labels the domain name email forwarder service option" }, "forwarderDomainNameHint": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, @@ -4648,11 +4684,11 @@ "description": "Confirmation message for saving a login to Bitwarden" }, "spaceCharacterDescriptor": { - "message": "Прагал", + "message": "Space", "description": "Represents the space key in screen reader content as a readable word" }, "tildeCharacterDescriptor": { - "message": "Тыльда", + "message": "Tilde", "description": "Represents the ~ key in screen reader content as a readable word" }, "backtickCharacterDescriptor": { @@ -4680,7 +4716,7 @@ "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { - "message": "Карэтка", + "message": "Caret", "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { @@ -4688,27 +4724,27 @@ "description": "Represents the & key in screen reader content as a readable word" }, "asteriskCharacterDescriptor": { - "message": "Зорачка", + "message": "Asterisk", "description": "Represents the * key in screen reader content as a readable word" }, "parenLeftCharacterDescriptor": { - "message": "Левая дужка", + "message": "Left parenthesis", "description": "Represents the ( key in screen reader content as a readable word" }, "parenRightCharacterDescriptor": { - "message": "Правая дужка", + "message": "Right parenthesis", "description": "Represents the ) key in screen reader content as a readable word" }, "hyphenCharacterDescriptor": { - "message": "Падкрэсленне", + "message": "Underscore", "description": "Represents the _ key in screen reader content as a readable word" }, "underscoreCharacterDescriptor": { - "message": "Злучок", + "message": "Hyphen", "description": "Represents the - key in screen reader content as a readable word" }, "plusCharacterDescriptor": { - "message": "Плюс", + "message": "Plus", "description": "Represents the + key in screen reader content as a readable word" }, "equalsCharacterDescriptor": { @@ -4716,23 +4752,23 @@ "description": "Represents the = key in screen reader content as a readable word" }, "braceLeftCharacterDescriptor": { - "message": "Левая фігурная дужка", + "message": "Left brace", "description": "Represents the { key in screen reader content as a readable word" }, "braceRightCharacterDescriptor": { - "message": "Правая фігурная дужка", + "message": "Right brace", "description": "Represents the } key in screen reader content as a readable word" }, "bracketLeftCharacterDescriptor": { - "message": "Левая квадратная дужка", + "message": "Left bracket", "description": "Represents the [ key in screen reader content as a readable word" }, "bracketRightCharacterDescriptor": { - "message": "Правая квадратная дужка", + "message": "Right bracket", "description": "Represents the ] key in screen reader content as a readable word" }, "pipeCharacterDescriptor": { - "message": "Раздзяляльнік", + "message": "Pipe", "description": "Represents the | key in screen reader content as a readable word" }, "backSlashCharacterDescriptor": { @@ -4740,39 +4776,39 @@ "description": "Represents the back slash key in screen reader content as a readable word" }, "colonCharacterDescriptor": { - "message": "Двукроп'е", + "message": "Colon", "description": "Represents the : key in screen reader content as a readable word" }, "semicolonCharacterDescriptor": { - "message": "Кропка з коскай", + "message": "Semicolon", "description": "Represents the ; key in screen reader content as a readable word" }, "doubleQuoteCharacterDescriptor": { - "message": "Падвойнае двукоссе", + "message": "Double quote", "description": "Represents the double quote key in screen reader content as a readable word" }, "singleQuoteCharacterDescriptor": { - "message": "Адзінарнае двукоссе", + "message": "Single quote", "description": "Represents the ' key in screen reader content as a readable word" }, "lessThanCharacterDescriptor": { - "message": "Менш", + "message": "Less than", "description": "Represents the < key in screen reader content as a readable word" }, "greaterThanCharacterDescriptor": { - "message": "Больш", + "message": "Greater than", "description": "Represents the > key in screen reader content as a readable word" }, "commaCharacterDescriptor": { - "message": "Коска", + "message": "Comma", "description": "Represents the , key in screen reader content as a readable word" }, "periodCharacterDescriptor": { - "message": "Кропка", + "message": "Period", "description": "Represents the . key in screen reader content as a readable word" }, "questionCharacterDescriptor": { - "message": "Пытальнік", + "message": "Question mark", "description": "Represents the ? key in screen reader content as a readable word" }, "forwardSlashCharacterDescriptor": { @@ -4780,12 +4816,12 @@ "description": "Represents the / key in screen reader content as a readable word" }, "lowercaseAriaLabel": { - "message": "Малыя літары" + "message": "Lowercase" }, "uppercaseAriaLabel": { - "message": "Вялікія літары" + "message": "Uppercase" }, "generatedPassword": { - "message": "Згенерыраваны пароль" + "message": "Generated password" } } diff --git a/apps/browser/src/_locales/bg/messages.json b/apps/browser/src/_locales/bg/messages.json index e8249decb6d..5a0854b8a7c 100644 --- a/apps/browser/src/_locales/bg/messages.json +++ b/apps/browser/src/_locales/bg/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Копиране на номера на свидетелството" }, + "copyPrivateKey": { + "message": "Копиране на частния ключ" + }, + "copyPublicKey": { + "message": "Копиране на публичния ключ" + }, + "copyFingerprint": { + "message": "Копиране на отпечатъка" + }, "copyCustomField": { "message": "Копиране на $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Самоличност" }, + "typeSshKey": { + "message": "SSH ключ" + }, "newItemHeader": { "message": "Ново $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Изискванията на политиката за големи компании бяха приложени към тази настройка" }, + "sshPrivateKey": { + "message": "Частен ключ" + }, + "sshPublicKey": { + "message": "Публичен ключ" + }, + "sshFingerprint": { + "message": "Отпечатък" + }, + "sshKeyAlgorithm": { + "message": "Тип на ключа" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048 бита" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072 бита" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096 бита" + }, "retry": { "message": "Повторен опит" }, diff --git a/apps/browser/src/_locales/bn/messages.json b/apps/browser/src/_locales/bn/messages.json index c05fd642e79..b1ba11bdb29 100644 --- a/apps/browser/src/_locales/bn/messages.json +++ b/apps/browser/src/_locales/bn/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "পরিচয়" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/bs/messages.json b/apps/browser/src/_locales/bs/messages.json index bc8d843045e..3f01ef5dbc8 100644 --- a/apps/browser/src/_locales/bs/messages.json +++ b/apps/browser/src/_locales/bs/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identity" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/ca/messages.json b/apps/browser/src/_locales/ca/messages.json index d3cdc23d8c5..e91afa303a8 100644 --- a/apps/browser/src/_locales/ca/messages.json +++ b/apps/browser/src/_locales/ca/messages.json @@ -120,7 +120,7 @@ "message": "Copia contrasenya" }, "copyPassphrase": { - "message": "Copia clau de pas" + "message": "Copy passphrase" }, "copyNote": { "message": "Copia nota" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copia el número de llicència" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copia $FIELD$", "placeholders": { @@ -427,7 +436,7 @@ "message": "Genera contrasenya" }, "generatePassphrase": { - "message": "Genera clau de pas" + "message": "Generate passphrase" }, "regeneratePassword": { "message": "Regenera contrasenya" @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identitat" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/cs/messages.json b/apps/browser/src/_locales/cs/messages.json index 9943cbebc12..0510d17dbf0 100644 --- a/apps/browser/src/_locales/cs/messages.json +++ b/apps/browser/src/_locales/cs/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Kopírovat číslo dokladu totožnosti" }, + "copyPrivateKey": { + "message": "Kopírovat soukromý klíč" + }, + "copyPublicKey": { + "message": "Kopírovat veřejný klíč" + }, + "copyFingerprint": { + "message": "Kopírovat otisk prstu" + }, "copyCustomField": { "message": "Kopírovat $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identita" }, + "typeSshKey": { + "message": "SSH klíč" + }, "newItemHeader": { "message": "Nové $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Na toto nastavení byly uplatněny požadavky podnikových zásad" }, + "sshPrivateKey": { + "message": "Soukromý klíč" + }, + "sshPublicKey": { + "message": "Veřejný klíč" + }, + "sshFingerprint": { + "message": "Otisk prstu" + }, + "sshKeyAlgorithm": { + "message": "Typ klíče" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048 bitový" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072 bitový" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096 bitový" + }, "retry": { "message": "Opakovat" }, diff --git a/apps/browser/src/_locales/cy/messages.json b/apps/browser/src/_locales/cy/messages.json index 5bec66dec95..de65c96e17f 100644 --- a/apps/browser/src/_locales/cy/messages.json +++ b/apps/browser/src/_locales/cy/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Hunaniaeth" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/da/messages.json b/apps/browser/src/_locales/da/messages.json index 60949c317aa..0529effb15a 100644 --- a/apps/browser/src/_locales/da/messages.json +++ b/apps/browser/src/_locales/da/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Kopier licensnummer" }, + "copyPrivateKey": { + "message": "Kopiér privat nøgle" + }, + "copyPublicKey": { + "message": "Kopiér offentlig nøgle" + }, + "copyFingerprint": { + "message": "Kopiér fingeraftryk" + }, "copyCustomField": { "message": "Kopiér $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identitet" }, + "typeSshKey": { + "message": "SSH-nøgle" + }, "newItemHeader": { "message": "Ny $TYPE$", "placeholders": { @@ -1801,7 +1813,7 @@ "message": "Ryd generatorhistorik" }, "cleargGeneratorHistoryDescription": { - "message": "Fortsættes, slettes alle poster permanent fra generatorens historik. Sikker på, at handlingen skal udføres?" + "message": "Fortsætter man, slettes alle poster permanent fra generatorens historik. Sikker på, at handlingen skal udføres?" }, "back": { "message": "Tilbage" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Virksomhedspolitikkrav er anvendt på denne indstilling" }, + "sshPrivateKey": { + "message": "Privat nøgle" + }, + "sshPublicKey": { + "message": "Offentlig nøgle" + }, + "sshFingerprint": { + "message": "Fingeraftryk" + }, + "sshKeyAlgorithm": { + "message": "Nøgletype" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Forsøg igen" }, diff --git a/apps/browser/src/_locales/de/messages.json b/apps/browser/src/_locales/de/messages.json index df664cf8d36..de915ac2717 100644 --- a/apps/browser/src/_locales/de/messages.json +++ b/apps/browser/src/_locales/de/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Lizenznummer kopieren" }, + "copyPrivateKey": { + "message": "Privaten Schlüssel kopieren" + }, + "copyPublicKey": { + "message": "Öffentlichen Schlüssel kopieren" + }, + "copyFingerprint": { + "message": "Fingerabdruck kopieren" + }, "copyCustomField": { "message": "$FIELD$ kopieren", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identität" }, + "typeSshKey": { + "message": "SSH-Schlüssel" + }, "newItemHeader": { "message": "Neue $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Unternehmens-Richtlinienanforderungen wurden auf diese Einstellung angewandt" }, + "sshPrivateKey": { + "message": "Privater Schlüssel" + }, + "sshPublicKey": { + "message": "Öffentlicher Schlüssel" + }, + "sshFingerprint": { + "message": "Fingerabdruck" + }, + "sshKeyAlgorithm": { + "message": "Schlüsseltyp" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Erneut versuchen" }, @@ -4656,7 +4692,7 @@ "description": "Represents the ~ key in screen reader content as a readable word" }, "backtickCharacterDescriptor": { - "message": "Gravis", + "message": "Abwärtsakzent", "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { @@ -4684,11 +4720,11 @@ "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { - "message": "Ampersand", + "message": "Und-Zeichen", "description": "Represents the & key in screen reader content as a readable word" }, "asteriskCharacterDescriptor": { - "message": "Sternzeichen", + "message": "Sternchen", "description": "Represents the * key in screen reader content as a readable word" }, "parenLeftCharacterDescriptor": { diff --git a/apps/browser/src/_locales/el/messages.json b/apps/browser/src/_locales/el/messages.json index bd2f76249bf..0e599b6a1d5 100644 --- a/apps/browser/src/_locales/el/messages.json +++ b/apps/browser/src/_locales/el/messages.json @@ -20,16 +20,16 @@ "message": "Δημιουργία λογαριασμού" }, "newToBitwarden": { - "message": "Νέος/α στο Bitwarden;" + "message": "New to Bitwarden?" }, "logInWithPasskey": { - "message": "Σύνδεση με κλειδί πρόσβασης" + "message": "Log in with passkey" }, "useSingleSignOn": { - "message": "Χρήση ενιαίας σύνδεσης" + "message": "Use single sign-on" }, "welcomeBack": { - "message": "Καλωσορίσατε και πάλι" + "message": "Welcome back" }, "setAStrongPassword": { "message": "Ορίστε έναν ισχυρό κωδικό πρόσβασης" @@ -120,7 +120,7 @@ "message": "Αντιγραφή κωδικού πρόσβασης" }, "copyPassphrase": { - "message": "Αντιγραφή φράσης πρόσβασης" + "message": "Copy passphrase" }, "copyNote": { "message": "Αντιγραφή σημείωσης" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Αντιγραφή αριθμού άδειας" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Αντιγραφή του «$FIELD$»", "placeholders": { @@ -168,7 +177,7 @@ "message": "Αντιγραφή σημειώσεων" }, "fill": { - "message": "Συμπλήρωση", + "message": "Fill", "description": "This string is used on the vault page to indicate autofilling. Horizontal space is limited in the interface here so try and keep translations as concise as possible." }, "autoFill": { @@ -427,7 +436,7 @@ "message": "Δημιουργία κωδικού πρόσβασης" }, "generatePassphrase": { - "message": "Δημιουργία φράσης πρόσβασης" + "message": "Generate passphrase" }, "regeneratePassword": { "message": "Επαναδημιουργία κωδικού πρόσβασης" @@ -591,7 +600,7 @@ "message": "Εκκίνηση ιστοσελίδας" }, "launchWebsiteName": { - "message": "Εκκίνηση ιστοσελίδας $ITEMNAME$", + "message": "Launch website $ITEMNAME$", "placeholders": { "itemname": { "content": "$1", @@ -846,7 +855,7 @@ "message": "Σύνδεση" }, "logInToBitwarden": { - "message": "Σύνδεση στο Bitwarden" + "message": "Log in to Bitwarden" }, "restartRegistration": { "message": "Επανεκκίνηση εγγραφής" @@ -1424,7 +1433,7 @@ "message": "URL Διακομιστή" }, "selfHostBaseUrl": { - "message": "URL διακομιστή αυτο-φιλοξενίας", + "message": "Self-host server URL", "description": "Label for field requesting a self-hosted integration service URL" }, "apiUrl": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Ταυτότητα" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "Νέα $TYPE$", "placeholders": { @@ -1795,13 +1807,13 @@ "message": "Ιστορικό κωδικού πρόσβασης" }, "generatorHistory": { - "message": "Ιστορικό γεννήτριας" + "message": "Generator history" }, "clearGeneratorHistoryTitle": { - "message": "Εκκαθάριση ιστορικού γεννήτριας" + "message": "Clear generator history" }, "cleargGeneratorHistoryDescription": { - "message": "Αν συνεχίσετε, όλες οι καταχωρήσεις θα διαγραφούν οριστικά από το ιστορικό της γεννήτριας. Είστε σίγουροι ότι θέλετε να συνεχίσετε;" + "message": "If you continue, all entries will be permanently deleted from generator's history. Are you sure you want to continue?" }, "back": { "message": "Πίσω" @@ -1920,10 +1932,10 @@ "message": "Διαγραφή ιστορικού" }, "nothingToShow": { - "message": "Τίποτα για προβολή" + "message": "Nothing to show" }, "nothingGeneratedRecently": { - "message": "Δεν έχετε δημιουργήσει τίποτα πρόσφατα" + "message": "You haven't generated anything recently" }, "remove": { "message": "Αφαίρεση" @@ -2512,7 +2524,7 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendPasswordDescV3": { - "message": "Προσθέστε έναν προαιρετικό κωδικό πρόσβασης για τους παραλήπτες για πρόσβαση σε αυτό το Send.", + "message": "Add an optional password for recipients to access this Send.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendNotesDesc": { @@ -2875,10 +2887,10 @@ "message": "Δημιουργία ονόματος χρήστη" }, "generateEmail": { - "message": "Δημιουργία email" + "message": "Generate email" }, "generatorBoundariesHint": { - "message": "Η τιμή πρέπει να είναι μεταξύ $MIN$ και $MAX$", + "message": "Value must be between $MIN$ and $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -2932,11 +2944,11 @@ "message": "Δημιουργήστε ένα alias email με μια εξωτερική υπηρεσία προώθησης." }, "forwarderDomainName": { - "message": "Τομέας ηλ. ταχυδρομείου", + "message": "Email domain", "description": "Labels the domain name email forwarder service option" }, "forwarderDomainNameHint": { - "message": "Επιλέξτε ένα τομέα που υποστηρίζεται από την επιλεγμένη υπηρεσία", + "message": "Choose a domain that is supported by the selected service", "description": "Guidance provided for email forwarding services that support multiple email domains." }, "forwarderError": { @@ -4564,13 +4576,13 @@ "message": "Τοποθεσία Αντικειμένου" }, "fileSend": { - "message": "Send αρχείου" + "message": "File Send" }, "fileSends": { "message": "Send αρχείων" }, "textSend": { - "message": "Send κειμένου" + "message": "Text Send" }, "textSends": { "message": "Send κειμένων" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Οι απαιτήσεις της πολιτικής για επιχειρήσεις έχουν εφαρμοστεί σε αυτήν τη ρύθμιση" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Επανάληψη" }, @@ -4636,23 +4672,23 @@ "message": "Ταυτοποίηση" }, "fillGeneratedPassword": { - "message": "Συμπληρώση του δημιουργημένου κωδικού πρόσβασης", + "message": "Fill generated password", "description": "Heading for the password generator within the inline menu" }, "passwordRegenerated": { - "message": "Ο κωδικός επαναδημιουργήθηκε", + "message": "Password regenerated", "description": "Notification message for when a password has been regenerated" }, "saveLoginToBitwarden": { - "message": "Αποθήκευση σύνδεσης στο Bitwarden;", + "message": "Save login to Bitwarden?", "description": "Confirmation message for saving a login to Bitwarden" }, "spaceCharacterDescriptor": { - "message": "Κενό", + "message": "Space", "description": "Represents the space key in screen reader content as a readable word" }, "tildeCharacterDescriptor": { - "message": "Περισπωμένη", + "message": "Tilde", "description": "Represents the ~ key in screen reader content as a readable word" }, "backtickCharacterDescriptor": { @@ -4660,23 +4696,23 @@ "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { - "message": "Θαυμαστικό", + "message": "Exclamation mark", "description": "Represents the ! key in screen reader content as a readable word" }, "atSignCharacterDescriptor": { - "message": "Παπάκι", + "message": "At sign", "description": "Represents the @ key in screen reader content as a readable word" }, "hashSignCharacterDescriptor": { - "message": "Δίεση", + "message": "Hash sign", "description": "Represents the # key in screen reader content as a readable word" }, "dollarSignCharacterDescriptor": { - "message": "Δολάριο", + "message": "Dollar sign", "description": "Represents the $ key in screen reader content as a readable word" }, "percentSignCharacterDescriptor": { - "message": "Τοις εκατό", + "message": "Percent sign", "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { @@ -4688,47 +4724,47 @@ "description": "Represents the & key in screen reader content as a readable word" }, "asteriskCharacterDescriptor": { - "message": "Αστερίσκος", + "message": "Asterisk", "description": "Represents the * key in screen reader content as a readable word" }, "parenLeftCharacterDescriptor": { - "message": "Αριστερή παρένθεση", + "message": "Left parenthesis", "description": "Represents the ( key in screen reader content as a readable word" }, "parenRightCharacterDescriptor": { - "message": "Δεξιά παρένθεση", + "message": "Right parenthesis", "description": "Represents the ) key in screen reader content as a readable word" }, "hyphenCharacterDescriptor": { - "message": "Κάτω παύλα", + "message": "Underscore", "description": "Represents the _ key in screen reader content as a readable word" }, "underscoreCharacterDescriptor": { - "message": "Παύλα", + "message": "Hyphen", "description": "Represents the - key in screen reader content as a readable word" }, "plusCharacterDescriptor": { - "message": "Συν", + "message": "Plus", "description": "Represents the + key in screen reader content as a readable word" }, "equalsCharacterDescriptor": { - "message": "Ίσον", + "message": "Equals", "description": "Represents the = key in screen reader content as a readable word" }, "braceLeftCharacterDescriptor": { - "message": "Αριστερό άγκιστρο", + "message": "Left brace", "description": "Represents the { key in screen reader content as a readable word" }, "braceRightCharacterDescriptor": { - "message": "Δεξί άγκιστρο", + "message": "Right brace", "description": "Represents the } key in screen reader content as a readable word" }, "bracketLeftCharacterDescriptor": { - "message": "Αριστερή αγκύλη", + "message": "Left bracket", "description": "Represents the [ key in screen reader content as a readable word" }, "bracketRightCharacterDescriptor": { - "message": "Δεξιά αγκύλη", + "message": "Right bracket", "description": "Represents the ] key in screen reader content as a readable word" }, "pipeCharacterDescriptor": { @@ -4740,7 +4776,7 @@ "description": "Represents the back slash key in screen reader content as a readable word" }, "colonCharacterDescriptor": { - "message": "Άνω κάτω τελεία", + "message": "Colon", "description": "Represents the : key in screen reader content as a readable word" }, "semicolonCharacterDescriptor": { @@ -4756,23 +4792,23 @@ "description": "Represents the ' key in screen reader content as a readable word" }, "lessThanCharacterDescriptor": { - "message": "Λιγότερο από", + "message": "Less than", "description": "Represents the < key in screen reader content as a readable word" }, "greaterThanCharacterDescriptor": { - "message": "Μεγαλύτερο από", + "message": "Greater than", "description": "Represents the > key in screen reader content as a readable word" }, "commaCharacterDescriptor": { - "message": "Κόμμα", + "message": "Comma", "description": "Represents the , key in screen reader content as a readable word" }, "periodCharacterDescriptor": { - "message": "Τελεία", + "message": "Period", "description": "Represents the . key in screen reader content as a readable word" }, "questionCharacterDescriptor": { - "message": "Αγγλικό ερωτηματικό", + "message": "Question mark", "description": "Represents the ? key in screen reader content as a readable word" }, "forwardSlashCharacterDescriptor": { @@ -4780,10 +4816,10 @@ "description": "Represents the / key in screen reader content as a readable word" }, "lowercaseAriaLabel": { - "message": "Πεζά" + "message": "Lowercase" }, "uppercaseAriaLabel": { - "message": "Κεφαλαία" + "message": "Uppercase" }, "generatedPassword": { "message": "Generated password" diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index a62dac05430..26fe9186cfe 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -2889,8 +2889,8 @@ "generateEmail": { "message": "Generate email" }, - "generatorBoundariesHint": { - "message": "Value must be between $MIN$ and $MAX$", + "spinboxBoundariesHint": { + "message": "Value must be between $MIN$ and $MAX$.", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -2903,6 +2903,26 @@ } } }, + "passwordLengthRecommendationHint": { + "message": " Use $RECOMMENDED$ characters or more to generate a strong password.", + "description": "Appended to `spinboxBoundariesHint` to recommend a length to the user. This must include any language-specific 'sentence' separator characters (e.g. a space in english).", + "placeholders": { + "recommended": { + "content": "$1", + "example": "14" + } + } + }, + "passphraseNumWordsRecommendationHint": { + "message": " Use $RECOMMENDED$ words or more to generate a strong passphrase.", + "description": "Appended to `spinboxBoundariesHint` to recommend a number of words to the user. This must include any language-specific 'sentence' separator characters (e.g. a space in english).", + "placeholders": { + "recommended": { + "content": "$1", + "example": "6" + } + } + }, "usernameType": { "message": "Username type" }, @@ -3150,12 +3170,27 @@ "resendNotification": { "message": "Resend notification" }, + "viewAllLogInOptions": { + "message": "View all log in options" + }, "viewAllLoginOptions": { "message": "View all log in options" }, "notificationSentDevice": { "message": "A notification has been sent to your device." }, + "aNotificationWasSentToYourDevice": { + "message": "A notification was sent to your device" + }, + "makeSureYourAccountIsUnlockedAndTheFingerprintEtc": { + "message": "Make sure your account is unlocked and the fingerprint phrase matches on the other device" + }, + "youWillBeNotifiedOnceTheRequestIsApproved": { + "message": "You will be notified once the request is approved" + }, + "needAnotherOptionV1": { + "message": "Need another option?" + }, "loginInitiated": { "message": "Login initiated" }, @@ -4252,6 +4287,21 @@ "filters": { "message": "Filters" }, + "filterVault": { + "message": "Filter vault" + }, + "filterApplied": { + "message": "One filter applied" + }, + "filterAppliedPlural": { + "message": "$COUNT$ filters applied", + "placeholders": { + "count": { + "content": "$1", + "example": "3" + } + } + }, "personalDetails": { "message": "Personal details" }, @@ -4823,5 +4873,11 @@ }, "generatedPassword": { "message": "Generated password" + }, + "compactMode": { + "message": "Compact mode" + }, + "beta": { + "message": "Beta" } } diff --git a/apps/browser/src/_locales/en_GB/messages.json b/apps/browser/src/_locales/en_GB/messages.json index 87eee8c90c0..43b5eba1702 100644 --- a/apps/browser/src/_locales/en_GB/messages.json +++ b/apps/browser/src/_locales/en_GB/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identity" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, @@ -4768,7 +4804,7 @@ "description": "Represents the , key in screen reader content as a readable word" }, "periodCharacterDescriptor": { - "message": "Full stop", + "message": "Period", "description": "Represents the . key in screen reader content as a readable word" }, "questionCharacterDescriptor": { diff --git a/apps/browser/src/_locales/en_IN/messages.json b/apps/browser/src/_locales/en_IN/messages.json index c5b294aa3a2..c515dae542f 100644 --- a/apps/browser/src/_locales/en_IN/messages.json +++ b/apps/browser/src/_locales/en_IN/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy licence number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identity" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/es/messages.json b/apps/browser/src/_locales/es/messages.json index 42e56a56ba4..bd1e097baa9 100644 --- a/apps/browser/src/_locales/es/messages.json +++ b/apps/browser/src/_locales/es/messages.json @@ -20,16 +20,16 @@ "message": "Crear cuenta" }, "newToBitwarden": { - "message": "¿Nuevo en Bitwarden?" + "message": "New to Bitwarden?" }, "logInWithPasskey": { - "message": "Iniciar sesión con clave de acceso" + "message": "Log in with passkey" }, "useSingleSignOn": { - "message": "Usar inicio de sesión único" + "message": "Use single sign-on" }, "welcomeBack": { - "message": "Bienvenido de nuevo" + "message": "Welcome back" }, "setAStrongPassword": { "message": "Establece una contraseña fuerte" @@ -120,7 +120,7 @@ "message": "Copiar contraseña" }, "copyPassphrase": { - "message": "Copiar frase de contraseña" + "message": "Copy passphrase" }, "copyNote": { "message": "Copiar nota" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copiar número de licencia" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copiar $FIELD$", "placeholders": { @@ -168,7 +177,7 @@ "message": "Copiar notas" }, "fill": { - "message": "Rellenar", + "message": "Fill", "description": "This string is used on the vault page to indicate autofilling. Horizontal space is limited in the interface here so try and keep translations as concise as possible." }, "autoFill": { @@ -427,7 +436,7 @@ "message": "Generar contraseña" }, "generatePassphrase": { - "message": "Generar frase de contraseña" + "message": "Generate passphrase" }, "regeneratePassword": { "message": "Regenerar contraseña" @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identidad" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "Nuevo $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, @@ -4708,11 +4744,11 @@ "description": "Represents the - key in screen reader content as a readable word" }, "plusCharacterDescriptor": { - "message": "Más", + "message": "Plus", "description": "Represents the + key in screen reader content as a readable word" }, "equalsCharacterDescriptor": { - "message": "Igual", + "message": "Equals", "description": "Represents the = key in screen reader content as a readable word" }, "braceLeftCharacterDescriptor": { @@ -4736,15 +4772,15 @@ "description": "Represents the | key in screen reader content as a readable word" }, "backSlashCharacterDescriptor": { - "message": "Contrabarra", + "message": "Back slash", "description": "Represents the back slash key in screen reader content as a readable word" }, "colonCharacterDescriptor": { - "message": "Dos puntos", + "message": "Colon", "description": "Represents the : key in screen reader content as a readable word" }, "semicolonCharacterDescriptor": { - "message": "Punto y coma", + "message": "Semicolon", "description": "Represents the ; key in screen reader content as a readable word" }, "doubleQuoteCharacterDescriptor": { diff --git a/apps/browser/src/_locales/et/messages.json b/apps/browser/src/_locales/et/messages.json index 81538f3bb22..f3bd66224f1 100644 --- a/apps/browser/src/_locales/et/messages.json +++ b/apps/browser/src/_locales/et/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Kopeeri litsentsi number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identiteet" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "Uus $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/eu/messages.json b/apps/browser/src/_locales/eu/messages.json index 3d0ac87989a..60525eb50f3 100644 --- a/apps/browser/src/_locales/eu/messages.json +++ b/apps/browser/src/_locales/eu/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identitatea" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/fa/messages.json b/apps/browser/src/_locales/fa/messages.json index 15aa92a669d..1f050f7e0ce 100644 --- a/apps/browser/src/_locales/fa/messages.json +++ b/apps/browser/src/_locales/fa/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "هویت" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "$TYPE$ جدید", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/fi/messages.json b/apps/browser/src/_locales/fi/messages.json index 054362a4a26..e902e2d241d 100644 --- a/apps/browser/src/_locales/fi/messages.json +++ b/apps/browser/src/_locales/fi/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Kopioi ajokortin numero" }, + "copyPrivateKey": { + "message": "Kopioi yksityinen avain" + }, + "copyPublicKey": { + "message": "Kopioi julkinen avain" + }, + "copyFingerprint": { + "message": "Kopioi sormenjälki" + }, "copyCustomField": { "message": "Kopioi $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Henkilöllisyys" }, + "typeSshKey": { + "message": "SSH-avain" + }, "newItemHeader": { "message": "Uusi $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Yrityskäytännön vaatimukset vaikuttavat tähän asetukseen" }, + "sshPrivateKey": { + "message": "Yksityinen avain" + }, + "sshPublicKey": { + "message": "Julkinen avain" + }, + "sshFingerprint": { + "message": "Sormenjälki" + }, + "sshKeyAlgorithm": { + "message": "Avaintyyppi" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Yritä uudelleen" }, @@ -4680,7 +4716,7 @@ "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { - "message": "Caret", + "message": "Hattu", "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { @@ -4708,7 +4744,7 @@ "description": "Represents the - key in screen reader content as a readable word" }, "plusCharacterDescriptor": { - "message": "Plus", + "message": "Plus-merkki", "description": "Represents the + key in screen reader content as a readable word" }, "equalsCharacterDescriptor": { diff --git a/apps/browser/src/_locales/fil/messages.json b/apps/browser/src/_locales/fil/messages.json index f779ead0dae..c077a8704c5 100644 --- a/apps/browser/src/_locales/fil/messages.json +++ b/apps/browser/src/_locales/fil/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Pagkakakilanlan" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/fr/messages.json b/apps/browser/src/_locales/fr/messages.json index 6aa0ad6d859..c32445ae96a 100644 --- a/apps/browser/src/_locales/fr/messages.json +++ b/apps/browser/src/_locales/fr/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copier la plaque d'immatriculation" }, + "copyPrivateKey": { + "message": "Copier la clé privée" + }, + "copyPublicKey": { + "message": "Copier la clé publique" + }, + "copyFingerprint": { + "message": "Copier l'empreinte digitale" + }, "copyCustomField": { "message": "Copier $FIELD$", "placeholders": { @@ -591,7 +600,7 @@ "message": "Ouvrir le site web" }, "launchWebsiteName": { - "message": "Lancer le site Web $ITEMNAME$", + "message": "Lancer le site web $ITEMNAME$", "placeholders": { "itemname": { "content": "$1", @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identité" }, + "typeSshKey": { + "message": "Clé SSH" + }, "newItemHeader": { "message": "Nouveau/nouvelle $TYPE$", "placeholders": { @@ -2936,7 +2948,7 @@ "description": "Labels the domain name email forwarder service option" }, "forwarderDomainNameHint": { - "message": "Choose a domain that is supported by the selected service", + "message": "Choisissez un domaine qui est supporté par le service sélectionné", "description": "Guidance provided for email forwarding services that support multiple email domains." }, "forwarderError": { @@ -4564,13 +4576,13 @@ "message": "Emplacement de l'élément" }, "fileSend": { - "message": "File Send" + "message": "Send en fichier" }, "fileSends": { "message": "File Sends" }, "textSend": { - "message": "Text Send" + "message": "Send en texte" }, "textSends": { "message": "Text Sends" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Les exigences de la politique d'entreprise ont été appliquées à ce paramètre" }, + "sshPrivateKey": { + "message": "Clé privée" + }, + "sshPublicKey": { + "message": "Clé publique" + }, + "sshFingerprint": { + "message": "Empreinte digitale" + }, + "sshKeyAlgorithm": { + "message": "Type de clé" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-bits" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-bits" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-bits" + }, "retry": { "message": "Réessayer" }, @@ -4656,7 +4692,7 @@ "description": "Represents the ~ key in screen reader content as a readable word" }, "backtickCharacterDescriptor": { - "message": "Backtick", + "message": "Accent grave", "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { @@ -4664,27 +4700,27 @@ "description": "Represents the ! key in screen reader content as a readable word" }, "atSignCharacterDescriptor": { - "message": "At sign", + "message": "Signe arobase", "description": "Represents the @ key in screen reader content as a readable word" }, "hashSignCharacterDescriptor": { - "message": "Hash sign", + "message": "Signe dièse", "description": "Represents the # key in screen reader content as a readable word" }, "dollarSignCharacterDescriptor": { - "message": "Signe du dollar", + "message": "Signe dollar", "description": "Represents the $ key in screen reader content as a readable word" }, "percentSignCharacterDescriptor": { - "message": "Percent sign", + "message": "Signe pourcentage", "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { - "message": "Caret", + "message": "Accent circonflexe", "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { - "message": "Ampersand", + "message": "Esperluette", "description": "Represents the & key in screen reader content as a readable word" }, "asteriskCharacterDescriptor": { @@ -4692,11 +4728,11 @@ "description": "Represents the * key in screen reader content as a readable word" }, "parenLeftCharacterDescriptor": { - "message": "Left parenthesis", + "message": "Parenthèse ouvrante", "description": "Represents the ( key in screen reader content as a readable word" }, "parenRightCharacterDescriptor": { - "message": "Right parenthesis", + "message": "Parenthèse fermante", "description": "Represents the ) key in screen reader content as a readable word" }, "hyphenCharacterDescriptor": { @@ -4716,23 +4752,23 @@ "description": "Represents the = key in screen reader content as a readable word" }, "braceLeftCharacterDescriptor": { - "message": "Accolade gauche", + "message": "Accolade ouvrante", "description": "Represents the { key in screen reader content as a readable word" }, "braceRightCharacterDescriptor": { - "message": "Accolade droite", + "message": "Accolade fermante", "description": "Represents the } key in screen reader content as a readable word" }, "bracketLeftCharacterDescriptor": { - "message": "Crochet gauche", + "message": "Crochet ouvrante", "description": "Represents the [ key in screen reader content as a readable word" }, "bracketRightCharacterDescriptor": { - "message": "Crochet droit", + "message": "Crochet fermante", "description": "Represents the ] key in screen reader content as a readable word" }, "pipeCharacterDescriptor": { - "message": "Pipe", + "message": "Barre", "description": "Represents the | key in screen reader content as a readable word" }, "backSlashCharacterDescriptor": { @@ -4740,7 +4776,7 @@ "description": "Represents the back slash key in screen reader content as a readable word" }, "colonCharacterDescriptor": { - "message": "Colon", + "message": "Deux-points", "description": "Represents the : key in screen reader content as a readable word" }, "semicolonCharacterDescriptor": { diff --git a/apps/browser/src/_locales/gl/messages.json b/apps/browser/src/_locales/gl/messages.json index 498dc34f1af..c128b556bdb 100644 --- a/apps/browser/src/_locales/gl/messages.json +++ b/apps/browser/src/_locales/gl/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identidade" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/he/messages.json b/apps/browser/src/_locales/he/messages.json index 0158ef20d67..4c200333464 100644 --- a/apps/browser/src/_locales/he/messages.json +++ b/apps/browser/src/_locales/he/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "זהות" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/hi/messages.json b/apps/browser/src/_locales/hi/messages.json index 24a4833e569..82a1190cd48 100644 --- a/apps/browser/src/_locales/hi/messages.json +++ b/apps/browser/src/_locales/hi/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "पहचान" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "नया $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "इस सेटिंग पर एंटरप्राइज़ नीति आवश्यकताएँ लागू की गई हैं" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "पुन: प्रयास करें" }, diff --git a/apps/browser/src/_locales/hr/messages.json b/apps/browser/src/_locales/hr/messages.json index 4f206edd301..3521a247a06 100644 --- a/apps/browser/src/_locales/hr/messages.json +++ b/apps/browser/src/_locales/hr/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Kopiraj OIB" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Kopiraj $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identitet" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "Novi $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Pravila tvrtke primijenjena su na ovu postavku" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Pokušaj ponovo" }, diff --git a/apps/browser/src/_locales/hu/messages.json b/apps/browser/src/_locales/hu/messages.json index add9cf6ab89..cffb6ac3ea1 100644 --- a/apps/browser/src/_locales/hu/messages.json +++ b/apps/browser/src/_locales/hu/messages.json @@ -20,16 +20,16 @@ "message": "Fiók létrehozása" }, "newToBitwarden": { - "message": "New to Bitwarden?" + "message": "Új vagyunk a Bitwardenben?" }, "logInWithPasskey": { - "message": "Log in with passkey" + "message": "Bejelentkezés hozzáférési kulccsal" }, "useSingleSignOn": { - "message": "Use single sign-on" + "message": "Egyszeri bejelentkezés használata" }, "welcomeBack": { - "message": "Welcome back" + "message": "Üdvözlet újra" }, "setAStrongPassword": { "message": "Erős jelszó beállítása" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Licensz szám másolása" }, + "copyPrivateKey": { + "message": "Személyes kulcs másolása" + }, + "copyPublicKey": { + "message": "Nyilvános kulcs másolása" + }, + "copyFingerprint": { + "message": "Ujjlenyomat másolása" + }, "copyCustomField": { "message": "$FIELD$ másolása", "placeholders": { @@ -846,7 +855,7 @@ "message": "Log in" }, "logInToBitwarden": { - "message": "Log in to Bitwarden" + "message": "Bejelentkezés a Bitwardenbe" }, "restartRegistration": { "message": "Restart registration" @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Személyazonosság" }, + "typeSshKey": { + "message": "SSH kulcs" + }, "newItemHeader": { "message": "Új $TYPE$", "placeholders": { @@ -1795,7 +1807,7 @@ "message": "Jelszó előzmények" }, "generatorHistory": { - "message": "Generator history" + "message": "Generátor előzmények" }, "clearGeneratorHistoryTitle": { "message": "Beenerátor előzmények kiürítése" @@ -1920,10 +1932,10 @@ "message": "Előzmények törlése" }, "nothingToShow": { - "message": "Nothing to show" + "message": "Nincs megjeleníthető elem" }, "nothingGeneratedRecently": { - "message": "You haven't generated anything recently" + "message": "Mostanában nem lett semmi generálva." }, "remove": { "message": "Eltávolítás" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Erre a beállításra a vállalkozás rendszabály követelmények lettek alkalmazva." }, + "sshPrivateKey": { + "message": "Személyes kulcs" + }, + "sshPublicKey": { + "message": "Nyilvános kulcs" + }, + "sshFingerprint": { + "message": "Ujjlenyomat" + }, + "sshKeyAlgorithm": { + "message": "Kulcs típusa" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Újra" }, @@ -4636,156 +4672,156 @@ "message": "Authenticating" }, "fillGeneratedPassword": { - "message": "Fill generated password", + "message": "Generált jelszó kitöltés", "description": "Heading for the password generator within the inline menu" }, "passwordRegenerated": { - "message": "Password regenerated", + "message": "A jelszó generálásra került.", "description": "Notification message for when a password has been regenerated" }, "saveLoginToBitwarden": { - "message": "Save login to Bitwarden?", + "message": "Bejelentkezés mentése a Bitwardenbe?", "description": "Confirmation message for saving a login to Bitwarden" }, "spaceCharacterDescriptor": { - "message": "Space", + "message": "Szóköz", "description": "Represents the space key in screen reader content as a readable word" }, "tildeCharacterDescriptor": { - "message": "Tilde", + "message": "Hullám karakter", "description": "Represents the ~ key in screen reader content as a readable word" }, "backtickCharacterDescriptor": { - "message": "Backtick", + "message": "Backtick karakter", "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { - "message": "Exclamation mark", + "message": "Felkiáltójel", "description": "Represents the ! key in screen reader content as a readable word" }, "atSignCharacterDescriptor": { - "message": "At sign", + "message": "@ karakter", "description": "Represents the @ key in screen reader content as a readable word" }, "hashSignCharacterDescriptor": { - "message": "Hash sign", + "message": "# karakter", "description": "Represents the # key in screen reader content as a readable word" }, "dollarSignCharacterDescriptor": { - "message": "Dollar sign", + "message": "$ karakter", "description": "Represents the $ key in screen reader content as a readable word" }, "percentSignCharacterDescriptor": { - "message": "Percent sign", + "message": "% karakter", "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { - "message": "Caret", + "message": "^ karakter", "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { - "message": "Ampersand", + "message": "& karakter", "description": "Represents the & key in screen reader content as a readable word" }, "asteriskCharacterDescriptor": { - "message": "Asterisk", + "message": "* karakter", "description": "Represents the * key in screen reader content as a readable word" }, "parenLeftCharacterDescriptor": { - "message": "Left parenthesis", + "message": "( karakter", "description": "Represents the ( key in screen reader content as a readable word" }, "parenRightCharacterDescriptor": { - "message": "Right parenthesis", + "message": ") karakter", "description": "Represents the ) key in screen reader content as a readable word" }, "hyphenCharacterDescriptor": { - "message": "Underscore", + "message": "_ karakter", "description": "Represents the _ key in screen reader content as a readable word" }, "underscoreCharacterDescriptor": { - "message": "Hyphen", + "message": "- karakter", "description": "Represents the - key in screen reader content as a readable word" }, "plusCharacterDescriptor": { - "message": "Plus", + "message": "+ karakter", "description": "Represents the + key in screen reader content as a readable word" }, "equalsCharacterDescriptor": { - "message": "Equals", + "message": "= karakter", "description": "Represents the = key in screen reader content as a readable word" }, "braceLeftCharacterDescriptor": { - "message": "Left brace", + "message": "{ karakter", "description": "Represents the { key in screen reader content as a readable word" }, "braceRightCharacterDescriptor": { - "message": "Right brace", + "message": "} karakter", "description": "Represents the } key in screen reader content as a readable word" }, "bracketLeftCharacterDescriptor": { - "message": "Left bracket", + "message": "[ karakter", "description": "Represents the [ key in screen reader content as a readable word" }, "bracketRightCharacterDescriptor": { - "message": "Right bracket", + "message": "] karakter", "description": "Represents the ] key in screen reader content as a readable word" }, "pipeCharacterDescriptor": { - "message": "Pipe", + "message": "| karakter", "description": "Represents the | key in screen reader content as a readable word" }, "backSlashCharacterDescriptor": { - "message": "Back slash", + "message": "\\ karakter", "description": "Represents the back slash key in screen reader content as a readable word" }, "colonCharacterDescriptor": { - "message": "Colon", + "message": ": karakter", "description": "Represents the : key in screen reader content as a readable word" }, "semicolonCharacterDescriptor": { - "message": "Semicolon", + "message": "; karakter", "description": "Represents the ; key in screen reader content as a readable word" }, "doubleQuoteCharacterDescriptor": { - "message": "Double quote", + "message": "\" karakter", "description": "Represents the double quote key in screen reader content as a readable word" }, "singleQuoteCharacterDescriptor": { - "message": "Single quote", + "message": "' karakter", "description": "Represents the ' key in screen reader content as a readable word" }, "lessThanCharacterDescriptor": { - "message": "Less than", + "message": "< karakter", "description": "Represents the < key in screen reader content as a readable word" }, "greaterThanCharacterDescriptor": { - "message": "Greater than", + "message": "> karakter", "description": "Represents the > key in screen reader content as a readable word" }, "commaCharacterDescriptor": { - "message": "Comma", + "message": ", karakter", "description": "Represents the , key in screen reader content as a readable word" }, "periodCharacterDescriptor": { - "message": "Period", + "message": ". karakter", "description": "Represents the . key in screen reader content as a readable word" }, "questionCharacterDescriptor": { - "message": "Question mark", + "message": "? karakter", "description": "Represents the ? key in screen reader content as a readable word" }, "forwardSlashCharacterDescriptor": { - "message": "Forward slash", + "message": "/ karakter", "description": "Represents the / key in screen reader content as a readable word" }, "lowercaseAriaLabel": { - "message": "Lowercase" + "message": "Kisbetű" }, "uppercaseAriaLabel": { - "message": "Uppercase" + "message": "Nagybetű" }, "generatedPassword": { - "message": "Generated password" + "message": "Generált jelszó" } } diff --git a/apps/browser/src/_locales/id/messages.json b/apps/browser/src/_locales/id/messages.json index 87a50d571b1..fbfc369ad05 100644 --- a/apps/browser/src/_locales/id/messages.json +++ b/apps/browser/src/_locales/id/messages.json @@ -14,7 +14,7 @@ "message": "Masuk atau buat akun baru untuk mengakses brankas Anda." }, "inviteAccepted": { - "message": "Invitation accepted" + "message": "Undangan diterima" }, "createAccount": { "message": "Buat Akun" @@ -32,10 +32,10 @@ "message": "Welcome back" }, "setAStrongPassword": { - "message": "Set a strong password" + "message": "Atur sebuah kata sandi yang kuat" }, "finishCreatingYourAccountBySettingAPassword": { - "message": "Finish creating your account by setting a password" + "message": "Selesaikan membuat akun Anda dengan mengatur sebuah kata sandi" }, "enterpriseSingleSignOn": { "message": "SSO Perusahaan" @@ -62,7 +62,7 @@ "message": "Petunjuk kata sandi utama dapat membantu Anda mengingat kata sandi Anda jika Anda melupakannya." }, "masterPassHintText": { - "message": "If you forget your password, the password hint can be sent to your email. $CURRENT$/$MAXIMUM$ character maximum.", + "message": "Jika Anda lupa kata sandi Anda, petunjuk kata sandi dapat dikirim ke surel Anda. Maksimal $CURRENT$/$MAXIMUM$ karakter.", "placeholders": { "current": { "content": "$1", @@ -81,10 +81,10 @@ "message": "Petunjuk Kata Sandi Utama (opsional)" }, "joinOrganization": { - "message": "Join organization" + "message": "Bergabung ke organisasi" }, "joinOrganizationName": { - "message": "Join $ORGANIZATIONNAME$", + "message": "Bergabung ke $ORGANIZATIONNAME$", "placeholders": { "organizationName": { "content": "$1", @@ -93,7 +93,7 @@ } }, "finishJoiningThisOrganizationBySettingAMasterPassword": { - "message": "Finish joining this organization by setting a master password." + "message": "Selesaikan penggabungan ke organisasi ini dengan mengatur sebuah kata sandi utama." }, "tab": { "message": "Tab" @@ -138,22 +138,31 @@ "message": "Salin Kode Keamanan" }, "copyName": { - "message": "Copy name" + "message": "Salin nama" }, "copyCompany": { - "message": "Copy company" + "message": "Salin perusahaan" }, "copySSN": { - "message": "Copy Social Security number" + "message": "Salin nomor Keamanan Sosial" }, "copyPassportNumber": { - "message": "Copy passport number" + "message": "Salin nomor paspor" }, "copyLicenseNumber": { - "message": "Copy license number" + "message": "Salin nomor lisensi" + }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" }, "copyCustomField": { - "message": "Copy $FIELD$", + "message": "Salin $FIELD$", "placeholders": { "field": { "content": "$1", @@ -162,10 +171,10 @@ } }, "copyWebsite": { - "message": "Copy website" + "message": "Salin situs web" }, "copyNotes": { - "message": "Copy notes" + "message": "Salin catatan" }, "fill": { "message": "Fill", @@ -223,16 +232,16 @@ "message": "Tambah Item" }, "accountEmail": { - "message": "Account email" + "message": "Akun surel" }, "requestHint": { - "message": "Request hint" + "message": "Minta petunjuk" }, "requestPasswordHint": { - "message": "Request password hint" + "message": "Minta petunjuk kata sandi" }, "enterYourAccountEmailAddressAndYourPasswordHintWillBeSentToYou": { - "message": "Enter your account email address and your password hint will be sent to you" + "message": "Masukkan alamat surel akun Anda dan petunjuk kata sandi Anda akan dikirimkan kepada Anda" }, "passwordHint": { "message": "Petunjuk Kata Sandi" @@ -280,7 +289,7 @@ "message": "Lanjut ke pasar ekstensi peramban?" }, "continueToBrowserExtensionStoreDesc": { - "message": "Help others find out if Bitwarden is right for them. Visit your browser's extension store and leave a rating now." + "message": "Bantu orang lain menemukan apakah Bitwarden sesuai untuk mereka. Kunjungi toko ekstensi peramban Anda dan tinggalkan sebuah ulasan sekarang." }, "changeMasterPasswordOnWebConfirmation": { "message": "Anda dapat merubah sandi utama di aplikasi Bitwarden web." @@ -300,43 +309,43 @@ "message": "Keluar" }, "aboutBitwarden": { - "message": "About Bitwarden" + "message": "Tentang Bitwarden" }, "about": { "message": "Tentang" }, "moreFromBitwarden": { - "message": "More from Bitwarden" + "message": "Selebihnya dari Bitwarden" }, "continueToBitwardenDotCom": { - "message": "Continue to bitwarden.com?" + "message": "Lanjutkan ke bitwarden.com?" }, "bitwardenForBusiness": { - "message": "Bitwarden for Business" + "message": "Bitwarden untuk Bisnis" }, "bitwardenAuthenticator": { - "message": "Bitwarden Authenticator" + "message": "Pengotentikasi Bitwarden" }, "continueToAuthenticatorPageDesc": { - "message": "Bitwarden Authenticator allows you to store authenticator keys and generate TOTP codes for 2-step verification flows. Learn more on the bitwarden.com website" + "message": "Pengotentikasi Bitwarden membolehkan Anda untuk menyimpan kunci pengotentikasi dan menghasilkan kode TOTP untuk alur verifikasi dua-langkah. Pelajari lebih lanjut di situs web bitwarden.com" }, "bitwardenSecretsManager": { - "message": "Bitwarden Secrets Manager" + "message": "Pengelola Rahasia Bitwarden" }, "continueToSecretsManagerPageDesc": { - "message": "Securely store, manage, and share developer secrets with Bitwarden Secrets Manager. Learn more on the bitwarden.com website." + "message": "Simpan, kelola, dan bagikan secara aman rahasia pengembang dengan Pengelola Rahasia Bitwarden. Pelajari lebih lanjut di situs web bitwarden.com." }, "passwordlessDotDev": { "message": "Passwordless.dev" }, "continueToPasswordlessDotDevPageDesc": { - "message": "Create smooth and secure login experiences free from traditional passwords with Passwordless.dev. Learn more on the bitwarden.com website." + "message": "Buat pengalaman masuk yang lancar dan aman dari kata sandi tradisional dengan Passwordless.dev. Pelajari lebih lanjut di situs web bitwarden.com." }, "freeBitwardenFamilies": { - "message": "Free Bitwarden Families" + "message": "Bitwarden Keluarga Gratis" }, "freeBitwardenFamiliesPageDesc": { - "message": "You are eligible for Free Bitwarden Families. Redeem this offer today in the web app." + "message": "Anda berhak untuk Bitwarden Keluarga Gratis. Tukarkan penawaran ini hari ini di aplikasi web." }, "version": { "message": "Versi" @@ -357,22 +366,22 @@ "message": "Sunting Folder" }, "newFolder": { - "message": "New folder" + "message": "Folder baru" }, "folderName": { - "message": "Folder name" + "message": "Nama folder" }, "folderHintText": { - "message": "Nest a folder by adding the parent folder's name followed by a “/”. Example: Social/Forums" + "message": "Sarangkan sebuah folder dengan menambahkan nama folder induk diikuti dengan sebuah \"/\". Contoh: Sosial/Forum" }, "noFoldersAdded": { - "message": "No folders added" + "message": "Tidak ada folder yang ditambahkan" }, "createFoldersToOrganize": { - "message": "Create folders to organize your vault items" + "message": "Buat folder untuk mengorganisasi benda-benda di brankas Anda" }, "deleteFolderPermanently": { - "message": "Are you sure you want to permanently delete this folder?" + "message": "Apakah Anda yakin akan menghapus folder ini selamanya?" }, "deleteFolder": { "message": "Hapus Folder" @@ -415,7 +424,7 @@ "message": "Secara otomatis membuat sandi yang kuat dan unik untuk info masuk Anda." }, "bitWebVaultApp": { - "message": "Bitwarden web app" + "message": "Aplikasi web Bitwarden" }, "importItems": { "message": "Impor Item" @@ -458,11 +467,11 @@ "description": "deprecated. Use specialCharactersLabel instead." }, "include": { - "message": "Include", + "message": "Sertakan", "description": "Card header for password generator include block" }, "uppercaseDescription": { - "message": "Include uppercase characters", + "message": "Sertakan karakter huruf kapital", "description": "Tooltip for the password generator uppercase character checkbox" }, "uppercaseLabel": { @@ -470,7 +479,7 @@ "description": "Label for the password generator uppercase character checkbox" }, "lowercaseDescription": { - "message": "Include lowercase characters", + "message": "Sertakan karakter huruf kecil", "description": "Full description for the password generator lowercase character checkbox" }, "lowercaseLabel": { @@ -478,7 +487,7 @@ "description": "Label for the password generator lowercase character checkbox" }, "numbersDescription": { - "message": "Include numbers", + "message": "Sertakan angka", "description": "Full description for the password generator numbers checkbox" }, "numbersLabel": { @@ -486,7 +495,7 @@ "description": "Label for the password generator numbers checkbox" }, "specialCharactersDescription": { - "message": "Include special characters", + "message": "Sertakan karakter khusus", "description": "Full description for the password generator special characters checkbox" }, "specialCharactersLabel": { @@ -517,11 +526,11 @@ "description": "deprecated. Use avoidAmbiguous instead." }, "avoidAmbiguous": { - "message": "Avoid ambiguous characters", + "message": "Hindari karakter ambigu", "description": "Label for the avoid ambiguous characters checkbox." }, "generatorPolicyInEffect": { - "message": "Enterprise policy requirements have been applied to your generator options.", + "message": "Persyaratan kebijakan perusahaan telah diterapkan ke pilihan penghasil Anda.", "description": "Indicates that a policy limits the credential generator screen." }, "searchVault": { @@ -555,19 +564,19 @@ "message": "Favorit" }, "unfavorite": { - "message": "Unfavorite" + "message": "Batalkan favorit" }, "itemAddedToFavorites": { - "message": "Item added to favorites" + "message": "Benda telah ditambahkan ke kesukaan" }, "itemRemovedFromFavorites": { - "message": "Item removed from favorites" + "message": "Benda telah dihapus dari kesukaan" }, "notes": { "message": "Catatan" }, "privateNote": { - "message": "Private note" + "message": "Catatan pribadi" }, "note": { "message": "Catatan" @@ -588,7 +597,7 @@ "message": "Luncurkan" }, "launchWebsite": { - "message": "Launch website" + "message": "Buka situs web" }, "launchWebsiteName": { "message": "Launch website $ITEMNAME$", @@ -624,7 +633,7 @@ "message": "Batas waktu sesi" }, "vaultTimeoutHeader": { - "message": "Vault timeout" + "message": "Batas waktu brankas" }, "otherOptions": { "message": "Opsi lainnya" @@ -645,13 +654,13 @@ "message": "Brankas Anda terkunci. Verifikasi kata sandi utama Anda untuk melanjutkan." }, "yourVaultIsLockedV2": { - "message": "Your vault is locked" + "message": "Brankas Anda terkunci" }, "yourAccountIsLocked": { - "message": "Your account is locked" + "message": "Akun Anda terkunci" }, "or": { - "message": "or" + "message": "atau" }, "unlock": { "message": "Buka Kunci" @@ -676,7 +685,7 @@ "message": "Batas Waktu Brankas" }, "vaultTimeout1": { - "message": "Timeout" + "message": "Batas waktu" }, "lockNow": { "message": "Kunci Sekarang" @@ -730,16 +739,16 @@ "message": "Keamanan" }, "confirmMasterPassword": { - "message": "Confirm master password" + "message": "Konfirmasi kata sandi utama" }, "masterPassword": { - "message": "Master password" + "message": "Kata sandi utama" }, "masterPassImportant": { - "message": "Your master password cannot be recovered if you forget it!" + "message": "Kata sandi utama Anda tidak dapat dipulihkan jika Anda melupakannya!" }, "masterPassHintLabel": { - "message": "Master password hint" + "message": "Petunjuk kata sandi utama" }, "errorOccurred": { "message": "Terjadi kesalahan" @@ -773,10 +782,10 @@ "message": "Akun baru Anda telah dibuat! Sekarang Anda bisa masuk." }, "newAccountCreated2": { - "message": "Your new account has been created!" + "message": "Akun baru Anda telah dibuat!" }, "youHaveBeenLoggedIn": { - "message": "You have been logged in!" + "message": "Anda telah masuk!" }, "youSuccessfullyLoggedIn": { "message": "Anda berhasil masuk" @@ -791,7 +800,7 @@ "message": "Kode verifikasi diperlukan." }, "webauthnCancelOrTimeout": { - "message": "The authentication was cancelled or took too long. Please try again." + "message": "Otentikasi dibatalkan atau terlalu lama. Mohon coba kembali." }, "invalidVerificationCode": { "message": "Kode verifikasi tidak valid" @@ -819,16 +828,16 @@ "message": "Pindai kode QR autentikator dari laman ini" }, "totpHelperTitle": { - "message": "Make 2-step verification seamless" + "message": "Buat verifikasi dua-langkah lancar" }, "totpHelper": { - "message": "Bitwarden can store and fill 2-step verification codes. Copy and paste the key into this field." + "message": "Bitwarden dapat menyimpan dan mengisikan kode verifikasi dua-langkah. Salin dan tempel kunci ke kolom ini." }, "totpHelperWithCapture": { - "message": "Bitwarden can store and fill 2-step verification codes. Select the camera icon to take a screenshot of this website's authenticator QR code, or copy and paste the key into this field." + "message": "Bitwarden dapat menyimpan dan mengisikan kode verifikasi dua-langkah. Pilih ikon kamera untuk mengambil tangkapan layar dari kode QR otentikasi dari situs web ini, atau salin dan tempel kunci ke kolom ini." }, "learnMoreAboutAuthenticators": { - "message": "Learn more about authenticators" + "message": "Pelajari lebih lanjut tentang pengotentikasi" }, "copyTOTP": { "message": "Salin kunci Autentikator (TOTP)" @@ -837,28 +846,28 @@ "message": "Keluar" }, "loggedOutDesc": { - "message": "You have been logged out of your account." + "message": "Anda telah keluar dari akun Anda." }, "loginExpired": { "message": "Sesi masuk Anda telah berakhir." }, "logIn": { - "message": "Log in" + "message": "Masuk" }, "logInToBitwarden": { "message": "Log in to Bitwarden" }, "restartRegistration": { - "message": "Restart registration" + "message": "Mulai ulang pendaftaran" }, "expiredLink": { - "message": "Expired link" + "message": "Tautan telah kadaluwarsa" }, "pleaseRestartRegistrationOrTryLoggingIn": { - "message": "Please restart registration or try logging in." + "message": "Mohon mulai ulang pendaftaran atau coba masuk." }, "youMayAlreadyHaveAnAccount": { - "message": "You may already have an account" + "message": "Anda mungkin telah memiliki sebuah akun" }, "logOutConfirmation": { "message": "Anda yakin ingin keluar?" @@ -882,10 +891,10 @@ "message": "Info masuk dua langkah membuat akun Anda lebih aman dengan mengharuskan Anda memverifikasi info masuk Anda dengan peranti lain seperti kode keamanan, aplikasi autentikasi, SMK, panggilan telepon, atau email. Info masuk dua langkah dapat diaktifkan di brankas web bitwarden.com. Anda ingin mengunjungi situs web sekarang?" }, "twoStepLoginConfirmationContent": { - "message": "Make your account more secure by setting up two-step login in the Bitwarden web app." + "message": "Buat akun Anda lebih aman dengan mengatur masuk dua-langkah pada aplikasi web Bitwarden." }, "twoStepLoginConfirmationTitle": { - "message": "Continue to web app?" + "message": "Lanjutkan ke aplikasi web?" }, "editedFolder": { "message": "Folder yang disunting" @@ -928,7 +937,7 @@ "message": "URl Baru" }, "addDomain": { - "message": "Add domain", + "message": "Tambah domain", "description": "'Domain' here refers to an internet domain name (e.g. 'bitwarden.com') and the message in whole described the act of putting a domain value into the context." }, "addedItem": { @@ -972,31 +981,31 @@ "message": "Tanya untuk penambahan login" }, "vaultSaveOptionsTitle": { - "message": "Save to vault options" + "message": "Simpan ke pilihan brankas" }, "addLoginNotificationDesc": { "message": "\"Notifikasi Penambahan Info Masuk\" secara otomatis akan meminta Anda untuk menyimpan info masuk baru ke brankas Anda saat Anda masuk untuk pertama kalinya." }, "addLoginNotificationDescAlt": { - "message": "Ask to add an item if one isn't found in your vault. Applies to all logged in accounts." + "message": "Tanyakan untuk menambah sebuah benda jika benda itu tidak ditemukan di brankas Anda. Diterapkan ke seluruh akun yang telah masuk." }, "showCardsInVaultView": { - "message": "Show cards as Autofill suggestions on Vault view" + "message": "Tampilkan kartu sebagai saran isi otomatis pada tampilan Brankas" }, "showCardsCurrentTab": { - "message": "Show cards on Tab page" + "message": "Tamplikan kartu pada halaman Tab" }, "showCardsCurrentTabDesc": { - "message": "List card items on the Tab page for easy autofill." + "message": "Buat tampilan daftar benda dari kartu pada halaman Tab untuk isi otomatis yang mudah." }, "showIdentitiesInVaultView": { - "message": "Show identities as Autofill suggestions on Vault view" + "message": "Tampilkan identitas sebagai saran isi otomatis pada tampilan Brankas" }, "showIdentitiesCurrentTab": { - "message": "Show identities on Tab page" + "message": "Tampilkan identitas pada halaman Tab" }, "showIdentitiesCurrentTabDesc": { - "message": "List identity items on the Tab page for easy autofill." + "message": "Buat tampilan daftar benda dari identitas pada halaman Tab untuk isi otomatis yang mudah." }, "clearClipboard": { "message": "Hapus Papan Klip", @@ -1013,19 +1022,19 @@ "message": "Iya, Simpan Sekarang" }, "enableChangedPasswordNotification": { - "message": "Ask to update existing login" + "message": "Tanyakan untuk memperbarui masuk yang sudah ada" }, "changedPasswordNotificationDesc": { - "message": "Ask to update a login's password when a change is detected on a website." + "message": "Tanyakan untuk memperbarui kata sandi masuk ketika mendeteksi perubahan pada situs web." }, "changedPasswordNotificationDescAlt": { - "message": "Ask to update a login's password when a change is detected on a website. Applies to all logged in accounts." + "message": "Tanyakan untuk memperbarui kata sandi masuk ketika mendeteksi perubahan pada situs web. Diterapkan ke semua akun yang telah masuk." }, "enableUsePasskeys": { - "message": "Ask to save and use passkeys" + "message": "Tanyakan untuk menyimpan dan menggunakan kunci sandi" }, "usePasskeysDesc": { - "message": "Ask to save new passkeys or log in with passkeys stored in your vault. Applies to all logged in accounts." + "message": "Tanyakan untuk menyimpan kunci sandi baru atau masuk dengan kunci sandi yang tersimpan di brankas Anda. Diterapkan ke semua akun yang telah masuk." }, "notificationChangeDesc": { "message": "Apakah Anda ingin memperbarui kata sandi ini di Bitwarden?" @@ -1034,22 +1043,22 @@ "message": "Iya, Perbarui Sekarang" }, "notificationUnlockDesc": { - "message": "Unlock your Bitwarden vault to complete the autofill request." + "message": "Buka brankan Bitwarden Anda untuk melengkapi permintaan isi otomatis." }, "notificationUnlock": { - "message": "Unlock" + "message": "Buka" }, "additionalOptions": { - "message": "Additional options" + "message": "Pilihan tambahan" }, "enableContextMenuItem": { - "message": "Show context menu options" + "message": "Tampilkan pilihan menu konteks" }, "contextMenuItemDesc": { - "message": "Use a secondary click to access password generation and matching logins for the website." + "message": "Gunakan tombol sekunder untuk mengakses pembuat kata sandi dan mencocokkan login untuk situs web." }, "contextMenuItemDescAlt": { - "message": "Use a secondary click to access password generation and matching logins for the website. Applies to all logged in accounts." + "message": "Gunakan tombol sekunder untuk mengakses pembuat kata sandi dan mencocokkan login untuk situs web. Diterapkan ke semua akun yang telah masuk." }, "defaultUriMatchDetection": { "message": "Deteksi Kecocokan URI Bawaan", @@ -1065,7 +1074,7 @@ "message": "Ubah tema warna aplikasi." }, "themeDescAlt": { - "message": "Change the application's color theme. Applies to all logged in accounts." + "message": "Ubah warna tema aplikasi. Diterapkan ke semua akun yang telah masuk." }, "dark": { "message": "Gelap", @@ -1080,7 +1089,7 @@ "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." }, "exportFrom": { - "message": "Export from" + "message": "Ekspor dari" }, "exportVault": { "message": "Ekspor Brankas" @@ -1089,28 +1098,28 @@ "message": "Format Berkas" }, "fileEncryptedExportWarningDesc": { - "message": "This file export will be password protected and require the file password to decrypt." + "message": "Ekpor berkas ini akan akan dilindungi oleh kata sandi dan membutuhkan kata sandi berkas untuk mendekripsikannya." }, "filePassword": { - "message": "File password" + "message": "Kata sandi berkas" }, "exportPasswordDescription": { - "message": "This password will be used to export and import this file" + "message": "Kata sandi ini akan digunakan untuk mengekspor dan mengimpor berkas ini" }, "accountRestrictedOptionDescription": { - "message": "Use your account encryption key, derived from your account's username and Master Password, to encrypt the export and restrict import to only the current Bitwarden account." + "message": "Gunakan kunci enkripsi akun Anda, diturunkan dari nama pengguna akun Anda dan kata sandi utama, untuk mengenkripsi ekspor dan membatasi impor menjadi hanya akun Bitwarden saat ini." }, "passwordProtectedOptionDescription": { - "message": "Set a file password to encrypt the export and import it to any Bitwarden account using the password for decryption." + "message": "Atur kata sandi berkas untuk mengenkripsi ekspor dan mengimpornya ke sebarang akun Bitwarden menggunakan kata sandi untuk dekripsi." }, "exportTypeHeading": { - "message": "Export type" + "message": "Jenis ekspor" }, "accountRestricted": { - "message": "Account restricted" + "message": "Akun dibatasi" }, "filePasswordAndConfirmFilePasswordDoNotMatch": { - "message": "“File password” and “Confirm file password“ do not match." + "message": "\"Kata sandi berkas\" dan \"Konfirmasi kata sandi berkas\" tidak cocok." }, "warning": { "message": "PERINGATAN", @@ -1135,7 +1144,7 @@ "message": "Dibagikan" }, "bitwardenForBusinessPageDesc": { - "message": "Bitwarden for Business allows you to share your vault items with others by using an organization. Learn more on the bitwarden.com website." + "message": "Bitwarden untuk Bisnis membolehkan Anda untuk membagikan benda-benda di brankas Anda dengan orang lain dengan menggunakan sebuah organisasi. Pelajari lebih lanjut pada situs web bitwarden.com." }, "moveToOrganization": { "message": "Pindah ke Organisasi" @@ -1196,7 +1205,7 @@ "message": "Berkas" }, "fileToShare": { - "message": "File to share" + "message": "Berkas untuk dibagikan" }, "selectFile": { "message": "Pilih berkas." @@ -1208,7 +1217,7 @@ "message": "Fitur Tidak Tersedia" }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Kunci enkripsi migrasi dibutuhkan. Silakan masuk melalui brankas web untuk memperbarui kunci enkripsi Anda." }, "premiumMembership": { "message": "Keanggotaan Premium" @@ -1232,10 +1241,10 @@ "message": "1 GB penyimpanan berkas yang dienkripsi." }, "premiumSignUpEmergency": { - "message": "Emergency access." + "message": "Akses darurat." }, "premiumSignUpTwoStepOptions": { - "message": "Proprietary two-step login options such as YubiKey and Duo." + "message": "Pilihan masuk dua-langkah yang dipatenkan seperti YubiKey dan Duo." }, "ppremiumSignUpReports": { "message": "Kebersihan kata sandi, kesehatan akun, dan laporan kebocoran data untuk tetap menjaga keamanan brankas Anda." @@ -1256,7 +1265,7 @@ "message": "Anda dapat membeli keanggotaan premium di brankas web bitwarden.com. Anda ingin mengunjungi situs web sekarang?" }, "premiumPurchaseAlertV2": { - "message": "You can purchase Premium from your account settings on the Bitwarden web app." + "message": "Anda dapat membeli Premium dari pilihan akun Anda pada aplikasi web Bitwarden." }, "premiumCurrentMember": { "message": "Anda adalah anggota premium!" @@ -1265,7 +1274,7 @@ "message": "Terima kasih telah mendukung Bitwarden." }, "premiumFeatures": { - "message": "Upgrade to Premium and receive:" + "message": "Tingkatkan ke Premium dan dapatkan:" }, "premiumPrice": { "message": "Semua itu hanya $PRICE$ /tahun!", @@ -1277,7 +1286,7 @@ } }, "premiumPriceV2": { - "message": "All for just $PRICE$ per year!", + "message": "Semua itu hanya $PRICE$ tiap tahun!", "placeholders": { "price": { "content": "$1", @@ -1295,7 +1304,7 @@ "message": "Jika info masuk Anda memiliki kunci autentikasi yang menyertainya, kode verifikasi TOTP akan disalin secara otomatis ke clipboard Anda setiap kali Anda mengisi info masuk secara otomatis." }, "enableAutoBiometricsPrompt": { - "message": "Ask for biometrics on launch" + "message": "Tanyakan untuk biometrik pada saat diluncurkan" }, "premiumRequired": { "message": "Membutuhkan Keanggotaan Premium" @@ -1370,17 +1379,17 @@ "message": "Aplikasi Otentikasi" }, "authenticatorAppDescV2": { - "message": "Enter a code generated by an authenticator app like Bitwarden Authenticator.", + "message": "Masukkan kode yang dihasilkan dari aplikasi pengotentikasi seperti Pengotentikasi Bitwarden.", "description": "'Bitwarden Authenticator' is a product name and should not be translated." }, "yubiKeyTitleV2": { - "message": "Yubico OTP Security Key" + "message": "Kunci Keamanan OTP Yubico" }, "yubiKeyDesc": { "message": "Gunakan YubiKey untuk mengakses akun Anda. Bekerja dengan YubiKey 4, 4 Nano, 4C, dan peranti NEO." }, "duoDescV2": { - "message": "Enter a code generated by Duo Security.", + "message": "Masukkan kode yang dihasilkan oleh Duo Security.", "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." }, "duoOrganizationDesc": { @@ -1397,7 +1406,7 @@ "message": "Email" }, "emailDescV2": { - "message": "Enter a code sent to your email." + "message": "Masukkan kode yang dikirim ke surel Anda." }, "selfHostedEnvironment": { "message": "Lingkungan Penyedia Personal" @@ -1406,13 +1415,13 @@ "message": "Tetapkan URL dasar penyedia personal pemasangan Bitwarden Anda." }, "selfHostedBaseUrlHint": { - "message": "Specify the base URL of your on-premises hosted Bitwarden installation. Example: https://bitwarden.company.com" + "message": "Tentukan URL dasar dari pemasangan Bitwarden di server Anda. Contoh: https://bitwarden.company.com" }, "selfHostedCustomEnvHeader": { - "message": "For advanced configuration, you can specify the base URL of each service independently." + "message": "Untuk pengaturan tingkat lanjut, Anda dapat menentukan URL dasar dari setiap layanan secara terpisah." }, "selfHostedEnvFormInvalid": { - "message": "You must add either the base Server URL or at least one custom environment." + "message": "Anda harus menambahkan antara URL dasar server atau paling tidak satu lingkungan ubahsuai." }, "customEnvironment": { "message": "Lingkungan Khusus" @@ -1446,47 +1455,47 @@ "message": "URL dari semua lingkungan telah disimpan." }, "showAutoFillMenuOnFormFields": { - "message": "Show autofill menu on form fields", + "message": "Tampilkan menu isi otomatis pada kolom formulir", "description": "Represents the message for allowing the user to enable the autofill overlay" }, "autofillSuggestionsSectionTitle": { - "message": "Autofill suggestions" + "message": "Saran isi otomatis" }, "showInlineMenuLabel": { - "message": "Show autofill suggestions on form fields" + "message": "Tampilkan saran isi otomatis pada kolom formulir" }, "showInlineMenuIdentitiesLabel": { - "message": "Display identities as suggestions" + "message": "Tampilkan identitas sebagai saran" }, "showInlineMenuCardsLabel": { - "message": "Display cards as suggestions" + "message": "Tampilkan kartu sebagai saran" }, "showInlineMenuOnIconSelectionLabel": { - "message": "Display suggestions when icon is selected" + "message": "Tampilkan saran ketika ikon dipilih" }, "showInlineMenuOnFormFieldsDescAlt": { - "message": "Applies to all logged in accounts." + "message": "Diterapkan ke semua akun yang telah masuk." }, "turnOffBrowserBuiltInPasswordManagerSettings": { - "message": "Turn off your browser's built in password manager settings to avoid conflicts." + "message": "Matikan pengaturan pengelola kata sandi bawaan peramban Anda untuk menghindari benturan." }, "turnOffBrowserBuiltInPasswordManagerSettingsLink": { - "message": "Edit browser settings." + "message": "Sunting pengaturan peramban." }, "autofillOverlayVisibilityOff": { - "message": "Off", + "message": "Mati", "description": "Overlay setting select option for disabling autofill overlay" }, "autofillOverlayVisibilityOnFieldFocus": { - "message": "When field is selected (on focus)", + "message": "Ketika kolom dipilih (ketika difokuskan)", "description": "Overlay appearance select option for showing the field on focus of the input element" }, "autofillOverlayVisibilityOnButtonClick": { - "message": "When autofill icon is selected", + "message": "Ketika ikon isi otomatis dipilih", "description": "Overlay appearance select option for showing the field on click of the overlay icon" }, "enableAutoFillOnPageLoadSectionTitle": { - "message": "Autofill on page load" + "message": "Isi otomatis ketika halaman dimuat" }, "enableAutoFillOnPageLoad": { "message": "Aktifkan Isi-Otomatis Saat Memuat Laman" @@ -1495,7 +1504,7 @@ "message": "Jika formulir info masuk terdeteksi, secara otomatis melakukan pengisian otomatis ketika memuat laman web." }, "autofillOnPageLoadWarning": { - "message": "$OPENTAG$Warning:$CLOSETAG$ Compromised or untrusted websites can exploit autofill on page load.", + "message": "$OPENTAG$Peringatan:$CLOSETAG$ Situs web yang disusupi atau tidak terpercaya dapat memanfaatkan isi otomatis ketika halaman dimuat.", "placeholders": { "openTag": { "content": "$1", @@ -1508,13 +1517,13 @@ } }, "experimentalFeature": { - "message": "Compromised or untrusted websites can exploit autofill on page load." + "message": "Situs web yang disusupi atau tidak terpercaya dapat memanfaatkan isi otomatis ketika halaman dimuat." }, "learnMoreAboutAutofillOnPageLoadLinkText": { - "message": "Learn more about risks" + "message": "Pelajari lebih lanjut tentang risiko" }, "learnMoreAboutAutofill": { - "message": "Learn more about autofill" + "message": "Pelajari lebih lanjut tentang isi otomatis" }, "defaultAutoFillOnPageLoad": { "message": "Konfigurasi autofill standard untuk item login." @@ -1541,13 +1550,13 @@ "message": "Buka brankas di bilah samping" }, "commandAutofillLoginDesc": { - "message": "Autofill the last used login for the current website" + "message": "Isi otomatis login yang terakhir digunakan untuk situs web saat ini" }, "commandAutofillCardDesc": { - "message": "Autofill the last used card for the current website" + "message": "Isi otomatis kartu yang terakhir digunakan untuk situs web saat ini" }, "commandAutofillIdentityDesc": { - "message": "Autofill the last used identity for the current website" + "message": "Isi otomatis identitas yang terakhir digunakan untuk situs web saat ini" }, "commandGeneratePasswordDesc": { "message": "Buat dan salin kata sandi acak baru ke papan klip." @@ -1580,14 +1589,14 @@ "message": "Boolean" }, "cfTypeCheckbox": { - "message": "Checkbox" + "message": "Kotak centang" }, "cfTypeLinked": { "message": "Terhubung", "description": "This describes a field that is 'linked' (tied) to another field." }, "linkedValue": { - "message": "Linked value", + "message": "Nilai terkait", "description": "This describes a value that is 'linked' (tied) to another value." }, "popup2faCloseMessage": { @@ -1597,19 +1606,19 @@ "message": "Peramban ini tidak bisa memproses permintaan U2F di jendela popup ini. Apakah Anda ingin membuka popup ini di jendela baru sehingga Anda dapat masuk menggunakan U2F?" }, "enableFavicon": { - "message": "Show website icons" + "message": "Tampilkan ikon situs web" }, "faviconDesc": { - "message": "Show a recognizable image next to each login." + "message": "Tampilkan sebuah gambar yang dapat dikenali di setiap masuk." }, "faviconDescAlt": { - "message": "Show a recognizable image next to each login. Applies to all logged in accounts." + "message": "Tampilkan sebuah gambar yang dapat dikenali di sebelah tiap login. Diterapkan ke semua akun yang telah masuk." }, "enableBadgeCounter": { - "message": "Show badge counter" + "message": "Tampilkan hitungan di lencana" }, "badgeCounterDesc": { - "message": "Indicate how many logins you have for the current web page." + "message": "Tunjukkan seberapa banyak login yang Anda miliki untuk halaman web saat ini." }, "cardholderName": { "message": "Nama Pemegang Kartu" @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identitas" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -2282,16 +2294,16 @@ "message": "Please unlock this user in the desktop application and try again." }, "biometricsNotAvailableTitle": { - "message": "Biometric unlock unavailable" + "message": "Buka dengan biometrik tidak tersedia" }, "biometricsNotAvailableDesc": { - "message": "Biometric unlock is currently unavailable. Please try again later." + "message": "Buka dengan biometrik tidak tersedia untuk saat ini. Mohon coba kembali nanti." }, "biometricsFailedTitle": { - "message": "Biometrics failed" + "message": "Biometrik gagal" }, "biometricsFailedDesc": { - "message": "Biometrics cannot be completed, consider using a master password or logging out. If this persists, please contact Bitwarden support." + "message": "Biometrik tidak dapat diselesaikan, pertimbangkan untuk menggunakan sebuah kata sandi utama atau keluar. Jika hal ini tetap berlangsung, mohon hubungi dukungan Bitwarden." }, "nativeMessaginPermissionErrorTitle": { "message": "Izin tidak diberikan" @@ -2312,10 +2324,10 @@ "message": "Kebijakan organisasi memengaruhi opsi kepemilikan Anda." }, "personalOwnershipPolicyInEffectImports": { - "message": "An organization policy has blocked importing items into your individual vault." + "message": "Sebuah kebijakan organisasi telah menghalangi mengimpor benda-benda ke brankas pribadi Anda." }, "domainsTitle": { - "message": "Domains", + "message": "Domain", "description": "A category title describing the concept of web domains" }, "excludedDomains": { @@ -2325,10 +2337,10 @@ "message": "Bitwarden tidak akan meminta untuk menyimpan detail login untuk domain ini. Anda harus menyegarkan halaman agar perubahan diterapkan." }, "excludedDomainsDescAlt": { - "message": "Bitwarden will not ask to save login details for these domains for all logged in accounts. You must refresh the page for changes to take effect." + "message": "Bitwarden tidak akan meminta untuk menyimpan rincian login untuk domain tersebut. Anda harus menyegarkan halaman agar perubahan diterapkan." }, "websiteItemLabel": { - "message": "Website $number$ (URI)", + "message": "Situs web $number$ (URI)", "placeholders": { "number": { "content": "$1", @@ -2346,17 +2358,17 @@ } }, "excludedDomainsSavedSuccess": { - "message": "Excluded domain changes saved" + "message": "Perubahan domain yang diabaikan telah disimpan" }, "limitSendViews": { - "message": "Limit views" + "message": "Batasi tampilan" }, "limitSendViewsHint": { - "message": "No one can view this Send after the limit is reached.", + "message": "Tidak ada yang dapat melihat Kiriman ini setelah mencapai batasan.", "description": "Displayed under the limit views field on Send" }, "limitSendViewsCount": { - "message": "$ACCESSCOUNT$ views left", + "message": "$ACCESSCOUNT$ tampilan tersisa", "description": "Displayed under the limit views field on Send", "placeholders": { "accessCount": { @@ -2370,7 +2382,7 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendDetails": { - "message": "Send details", + "message": "Rincian Send", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "searchSends": { @@ -2385,7 +2397,7 @@ "message": "Teks" }, "sendTypeTextToShare": { - "message": "Text to share" + "message": "Teks untuk dibagikan" }, "sendTypeFile": { "message": "Berkas" @@ -2395,7 +2407,7 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "hideTextByDefault": { - "message": "Hide text by default" + "message": "Sembunyikan teks secara bawaan" }, "maxAccessCountReached": { "message": "Jumlah akses maksimum tercapai", @@ -2411,7 +2423,7 @@ "message": "Dilindungi kata sandi" }, "copyLink": { - "message": "Copy link" + "message": "Salin tautan" }, "copySendLink": { "message": "Salin tautan Send", @@ -2449,7 +2461,7 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "deleteSendPermanentConfirmation": { - "message": "Are you sure you want to permanently delete this Send?", + "message": "Apakah Anda yakin ingin menghapus Send ini selamanya?", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "editSend": { @@ -2475,7 +2487,7 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "deletionDateDescV2": { - "message": "The Send will be permanently deleted on this date.", + "message": "Send akan dihapus selamanya pada tanggal ini.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "expirationDate": { @@ -2557,15 +2569,15 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "createdSendSuccessfully": { - "message": "Send created successfully!", + "message": "Send berhasil dibuat!", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendExpiresInHoursSingle": { - "message": "The Send will be available to anyone with the link for the next 1 hour.", + "message": "Send akan tersedia ke setiap orang yang memiliki tautan untuk 1 jam ke depan.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendExpiresInHours": { - "message": "The Send will be available to anyone with the link for the next $HOURS$ hours.", + "message": "Send akan tersedia ke setiap orang yang memiliki tautan untuk $HOURS$ jam ke depan.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.", "placeholders": { "hours": { @@ -2575,11 +2587,11 @@ } }, "sendExpiresInDaysSingle": { - "message": "The Send will be available to anyone with the link for the next 1 day.", + "message": "Send akan tersedia ke setiap orang yang memiliki tautan untuk 1 hari ke depan.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendExpiresInDays": { - "message": "The Send will be available to anyone with the link for the next $DAYS$ days.", + "message": "Send akan tersedia ke setiap orang yang memiliki tautan untuk $DAYS$ hari ke depan.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.", "placeholders": { "days": { @@ -2589,7 +2601,7 @@ } }, "sendLinkCopied": { - "message": "Send link copied", + "message": "Tautan Send disalin", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "editedSend": { @@ -2597,11 +2609,11 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendFilePopoutDialogText": { - "message": "Pop out extension?", + "message": "Sembulkan ekstensi?", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendFilePopoutDialogDesc": { - "message": "To create a file Send, you need to pop out the extension to a new window.", + "message": "Untuk membuat sebuah berkas Send, Anda perlu menyembulkan ekstensi ke sebuah jendela baru.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendLinuxChromiumFileWarning": { @@ -2614,7 +2626,7 @@ "message": "Untuk memilih file menggunakan Safari, keluar ke jendela baru dengan mengklik spanduk ini." }, "popOut": { - "message": "Pop out" + "message": "Sembulkan" }, "sendFileCalloutHeader": { "message": "Sebelum kamu memulai" @@ -2650,7 +2662,7 @@ "message": "Sembunyikan alamat surel dari penerima." }, "hideYourEmail": { - "message": "Hide your email address from viewers." + "message": "Sembunyikan alamat surel Anda dari penonton." }, "sendOptionsPolicyInEffect": { "message": "Satu atau lebih kebijakan organisasi mempengaruhi pengaturan feature Send anda." @@ -2668,7 +2680,7 @@ "message": "Verifikasi Email Diperlukan" }, "emailVerifiedV2": { - "message": "Email verified" + "message": "Surel telah diverifikasi" }, "emailVerificationRequiredDesc": { "message": "Anda harus memverifikasi email Anda untuk menggunakan fitur ini. Anda dapat memverifikasi email Anda di brankas web." @@ -2683,10 +2695,10 @@ "message": "Kata Sandi Utama Anda baru-baru ini diubah oleh administrator organisasi Anda. Untuk mengakses brankas tersebut, Anda diharuskan memperbarui Kata Sandi Utama Anda sekarang. Jika Anda melanjutkan, Anda akan keluar dari sesi saat ini, yang mana mengharuskan Anda untuk login kembali. Sesi yang aktif di perangkat lain akan tetap aktif selama satu jam kedepan." }, "updateWeakMasterPasswordWarning": { - "message": "Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + "message": "Kata sandi utama Anda tidak memenuhi satu atau lebih dari kebijakan organisasi Anda. Untuk dapat mengakses brankas, Anda harus memperbarui kata sandi utama Anda sekarang. Melanjutkan akan mengeluarkan Anda dari sesi saat ini, memerlukan Anda untuk masuk kembali. Sesi aktif pada perangkat lainnya dapat tetap aktif hingga satu jam." }, "tdeDisabledMasterPasswordRequired": { - "message": "Your organization has disabled trusted device encryption. Please set a master password to access your vault." + "message": "Organisasi Anda telah mematikan enkripsi perangkat terpercaya. Mohon mengatur kata sandi utama untuk mengakses brankas Anda." }, "resetPasswordPolicyAutoEnroll": { "message": "Pendaftaran Otomatis" @@ -2698,19 +2710,19 @@ "message": "Pilih Folder..." }, "noFoldersFound": { - "message": "No folders found", + "message": "Tidak ada folder yang ditemukan", "description": "Used as a message within the notification bar when no folders are found" }, "orgPermissionsUpdatedMustSetPassword": { - "message": "Your organization permissions were updated, requiring you to set a master password.", + "message": "Perizinan organisasi Anda telah diperbarui, memerlukan Anda untuk mengatur kata sandi utama.", "description": "Used as a card title description on the set password page to explain why the user is there" }, "orgRequiresYouToSetPassword": { - "message": "Your organization requires you to set a master password.", + "message": "Organisasi Anda memerlukan Anda untuk mengatur sebuah kata sandi utama.", "description": "Used as a card title description on the set password page to explain why the user is there" }, "cardMetrics": { - "message": "out of $TOTAL$", + "message": "dari $TOTAL$", "placeholders": { "total": { "content": "$1", @@ -2719,7 +2731,7 @@ } }, "verificationRequired": { - "message": "Verification required", + "message": "Memerlukan verifikasi", "description": "Default title for the user verification dialog." }, "hours": { @@ -2729,7 +2741,7 @@ "message": "Menit" }, "vaultTimeoutPolicyAffectingOptions": { - "message": "Enterprise policy requirements have been applied to your timeout options" + "message": "Persyaratan kebijakan perusahaan telah diterapkan ke pilihan batas waktu Anda" }, "vaultTimeoutPolicyInEffect": { "message": "Kebijakan organisasi Anda memengaruhi waktu tunggu brankas Anda. Batas maksimal Waktu Tunggu Brankas yang diizinkan adalah $HOURS$ jam dan $MINUTES$ menit", @@ -2745,7 +2757,7 @@ } }, "vaultTimeoutPolicyInEffect1": { - "message": "$HOURS$ hour(s) and $MINUTES$ minute(s) maximum.", + "message": "Maksimal $HOURS$ jam dan $MINUTES$ menit.", "placeholders": { "hours": { "content": "$1", @@ -2758,7 +2770,7 @@ } }, "vaultTimeoutPolicyMaximumError": { - "message": "Timeout exceeds the restriction set by your organization: $HOURS$ hour(s) and $MINUTES$ minute(s) maximum", + "message": "Batas waktu melebihi dari batasan yang telah ditetapkan oleh organisasi Anda: maksimal $HOURS$ jam dan $MINUTES$ menit", "placeholders": { "hours": { "content": "$1", @@ -2771,7 +2783,7 @@ } }, "vaultTimeoutPolicyWithActionInEffect": { - "message": "Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is $HOURS$ hour(s) and $MINUTES$ minute(s). Your vault timeout action is set to $ACTION$.", + "message": "Kebijakan organisasi Anda mempengaruhi batas waktu brankas Anda. Batas waktu maksimum yang dibolehkan adalah $HOURS$ jam dan $MINUTES$ menit. Batas waktu tindakan brankas Anda diatur ke $ACTION$.", "placeholders": { "hours": { "content": "$1", @@ -2788,7 +2800,7 @@ } }, "vaultTimeoutActionPolicyInEffect": { - "message": "Your organization policies have set your vault timeout action to $ACTION$.", + "message": "Kebijakan organisasi Anda telah mengatur batas waktu tindakan brankas Anda ke $ACTION$.", "placeholders": { "action": { "content": "$1", @@ -2797,7 +2809,7 @@ } }, "vaultTimeoutTooLarge": { - "message": "Your vault timeout exceeds the restrictions set by your organization." + "message": "Batas waktu brankas Anda melebihi batasan yang telah ditetapkan oleh organisasi Anda." }, "vaultExportDisabled": { "message": "Ekspor Brankas Dinonaktifkan" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/it/messages.json b/apps/browser/src/_locales/it/messages.json index 0023b9755a5..2f42e12a0ee 100644 --- a/apps/browser/src/_locales/it/messages.json +++ b/apps/browser/src/_locales/it/messages.json @@ -20,16 +20,16 @@ "message": "Crea account" }, "newToBitwarden": { - "message": "Nuovo a Bitwarden?" + "message": "New to Bitwarden?" }, "logInWithPasskey": { - "message": "Accedi con passkey" + "message": "Log in with passkey" }, "useSingleSignOn": { - "message": "Usa il Single Sign-On" + "message": "Use single sign-on" }, "welcomeBack": { - "message": "Bentornato" + "message": "Welcome back" }, "setAStrongPassword": { "message": "Imposta una password robusta" @@ -120,7 +120,7 @@ "message": "Copia password" }, "copyPassphrase": { - "message": "Copia passphrase" + "message": "Copy passphrase" }, "copyNote": { "message": "Copia nota" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copia numero licenza" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copia $FIELD$", "placeholders": { @@ -168,7 +177,7 @@ "message": "Copia note" }, "fill": { - "message": "Riempi", + "message": "Fill", "description": "This string is used on the vault page to indicate autofilling. Horizontal space is limited in the interface here so try and keep translations as concise as possible." }, "autoFill": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identità" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "Nuovo $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "I requisiti della policy aziendale sono stati applicati a questa impostazione" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, @@ -4786,6 +4822,6 @@ "message": "Uppercase" }, "generatedPassword": { - "message": "Password generata" + "message": "Generated password" } } diff --git a/apps/browser/src/_locales/ja/messages.json b/apps/browser/src/_locales/ja/messages.json index f0baa16f9f3..6e9c58e2efe 100644 --- a/apps/browser/src/_locales/ja/messages.json +++ b/apps/browser/src/_locales/ja/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "免許証番号をコピー" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "$FIELD$ をコピー", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "ID" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "$TYPE$ を新規作成", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "エンタープライズポリシー要件がこの設定に適用されました" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "再試行" }, diff --git a/apps/browser/src/_locales/ka/messages.json b/apps/browser/src/_locales/ka/messages.json index f57b4a50e48..45d26f402ce 100644 --- a/apps/browser/src/_locales/ka/messages.json +++ b/apps/browser/src/_locales/ka/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "იდენტიფიკაცია" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "თავიდან ცდა" }, diff --git a/apps/browser/src/_locales/km/messages.json b/apps/browser/src/_locales/km/messages.json index b8075804229..a4668a65add 100644 --- a/apps/browser/src/_locales/km/messages.json +++ b/apps/browser/src/_locales/km/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identity" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/kn/messages.json b/apps/browser/src/_locales/kn/messages.json index a479b47fa46..4ac769431bf 100644 --- a/apps/browser/src/_locales/kn/messages.json +++ b/apps/browser/src/_locales/kn/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "ಗುರುತಿಸುವಿಕೆ" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/ko/messages.json b/apps/browser/src/_locales/ko/messages.json index ed1f9ded490..d86473794a9 100644 --- a/apps/browser/src/_locales/ko/messages.json +++ b/apps/browser/src/_locales/ko/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "운전면허 번호 복사" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "신원" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/lt/messages.json b/apps/browser/src/_locales/lt/messages.json index 07d5b3bf8c3..547d42b27bf 100644 --- a/apps/browser/src/_locales/lt/messages.json +++ b/apps/browser/src/_locales/lt/messages.json @@ -14,7 +14,7 @@ "message": "Prisijunkite arba sukurkite naują paskyrą, kad galėtumėte pasiekti saugyklą." }, "inviteAccepted": { - "message": "Invitation accepted" + "message": "Kvietimas priimtas" }, "createAccount": { "message": "Sukurti paskyrą" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -730,16 +739,16 @@ "message": "Apsauga" }, "confirmMasterPassword": { - "message": "Confirm master password" + "message": "Patvirtinkite pagrindinį slaptažodį" }, "masterPassword": { - "message": "Master password" + "message": "Pagrindinis slaptažodis" }, "masterPassImportant": { - "message": "Your master password cannot be recovered if you forget it!" + "message": "Pagrindinio slaptažodžio negalima atkurti, jei jį pamiršite." }, "masterPassHintLabel": { - "message": "Master password hint" + "message": "Pagrindinio slaptažodžio užuomina" }, "errorOccurred": { "message": "Įvyko klaida" @@ -791,7 +800,7 @@ "message": "Būtinas patvirtinimo kodas." }, "webauthnCancelOrTimeout": { - "message": "The authentication was cancelled or took too long. Please try again." + "message": "Tapatybės nustatymas buvo atšauktas arba užtruko per ilgai. Bandykite dar kartą." }, "invalidVerificationCode": { "message": "Neteisingas patvirtinimo kodas" @@ -843,7 +852,7 @@ "message": "Sesijos laikas baigėsi." }, "logIn": { - "message": "Log in" + "message": "Prisijungti" }, "logInToBitwarden": { "message": "Log in to Bitwarden" @@ -852,7 +861,7 @@ "message": "Restart registration" }, "expiredLink": { - "message": "Expired link" + "message": "Nebegaliojanti nuoroda" }, "pleaseRestartRegistrationOrTryLoggingIn": { "message": "Please restart registration or try logging in." @@ -928,7 +937,7 @@ "message": "Naujas URI" }, "addDomain": { - "message": "Add domain", + "message": "Pridėti domeną", "description": "'Domain' here refers to an internet domain name (e.g. 'bitwarden.com') and the message in whole described the act of putting a domain value into the context." }, "addedItem": { @@ -1580,7 +1589,7 @@ "message": "Taip/Ne" }, "cfTypeCheckbox": { - "message": "Checkbox" + "message": "Žymimasis langelis" }, "cfTypeLinked": { "message": "Susieta", @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Tapatybė" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "Naujas $TYPE$", "placeholders": { @@ -1783,7 +1795,7 @@ } }, "viewItemHeader": { - "message": "View $TYPE$", + "message": "Peržiūrėti $TYPE$", "placeholders": { "type": { "content": "$1", @@ -2315,7 +2327,7 @@ "message": "Organizacijos politika blokavo elementų importavimą į Jūsų individualią saugyklą." }, "domainsTitle": { - "message": "Domains", + "message": "Domenai", "description": "A category title describing the concept of web domains" }, "excludedDomains": { @@ -2668,7 +2680,7 @@ "message": "Reikalingas elektroninio pašto patvirtinimas" }, "emailVerifiedV2": { - "message": "Email verified" + "message": "Patvirtintas el. paštas" }, "emailVerificationRequiredDesc": { "message": "Turite patvirtinti savo el. paštą, kad galėtumėte naudotis šia funkcija. Savo el. pašto adresą galite patvirtinti žiniatinklio saugykloje." @@ -3317,11 +3329,11 @@ "message": "Patikimas įrenginys" }, "sendsNoItemsTitle": { - "message": "No active Sends", + "message": "Nėra aktyvų „Sends“", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendsNoItemsMessage": { - "message": "Use Send to securely share encrypted information with anyone.", + "message": "Naudokite „Send“, kad saugiai bendrintumėte užšifruotą informaciją su bet kuriuo asmeniu.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "inputRequired": { @@ -3518,7 +3530,7 @@ "description": "Button text to display in overlay when the account is locked." }, "unlockAccountAria": { - "message": "Unlock your account, opens in a new window", + "message": "Atrakinti savo paskyrą, atidaromas naujame lange", "description": "Screen reader text (aria-label) for unlock account button in overlay" }, "fillCredentialsFor": { @@ -3546,7 +3558,7 @@ "description": "Button text to display within inline menu when there are no matching items on a login field" }, "addNewLoginItemAria": { - "message": "Add new vault login item, opens in a new window", + "message": "Pridėti naują saugyklos prisijungimo elementą, atidaromas naujame lange", "description": "Screen reader text (aria-label) for new login button within inline menu" }, "newCard": { @@ -3554,15 +3566,15 @@ "description": "Button text to display within inline menu when there are no matching items on a credit card field" }, "addNewCardItemAria": { - "message": "Add new vault card item, opens in a new window", + "message": "Pridėti naują saugyklos kortelės elementą, atidaromas naujame lange", "description": "Screen reader text (aria-label) for new card button within inline menu" }, "newIdentity": { - "message": "New identity", + "message": "Nauja tapatybė", "description": "Button text to display within inline menu when there are no matching items on an identity field" }, "addNewIdentityItemAria": { - "message": "Add new vault identity item, opens in a new window", + "message": "Pridėti naują saugyklos tapatybės elementą, atidaromas naujame lange", "description": "Screen reader text (aria-label) for new identity button within inline menu" }, "bitwardenOverlayMenuAvailable": { @@ -3652,7 +3664,7 @@ } }, "duoHealthCheckResultsInNullAuthUrlError": { - "message": "Error connecting with the Duo service. Use a different two-step login method or contact Duo for assistance." + "message": "Klaida prijungiant su „Duo“ paslauga. Naudokite kitą dvigubo prisijungimo būdą arba susisiekite su „Duo“ dėl pagalbos." }, "launchDuoAndFollowStepsToFinishLoggingIn": { "message": "Paleisk DUO ir sek veiksmus, kad baigtum prisijungti." @@ -4090,7 +4102,7 @@ "message": "No values to copy" }, "assignToCollections": { - "message": "Assign to collections" + "message": "Priskirti į kolekcijas" }, "copyEmail": { "message": "Copy email" @@ -4184,22 +4196,22 @@ "message": "Items in deactivated organizations cannot be accessed. Contact your organization owner for assistance." }, "additionalInformation": { - "message": "Additional information" + "message": "Papildoma informacija" }, "itemHistory": { - "message": "Item history" + "message": "Elemento istorija" }, "lastEdited": { - "message": "Last edited" + "message": "Paskutinį kartą redaguota" }, "ownerYou": { - "message": "Owner: You" + "message": "Savininkas: Jūs" }, "linked": { - "message": "Linked" + "message": "Susieta" }, "copySuccessful": { - "message": "Copy Successful" + "message": "Kopijavimas sėkmingas" }, "upload": { "message": "Įkelti" @@ -4241,16 +4253,16 @@ "message": "Filtrai" }, "personalDetails": { - "message": "Personal details" + "message": "Asmeniniai duomenys" }, "identification": { - "message": "Identification" + "message": "Identifikavimas" }, "contactInfo": { - "message": "Contact info" + "message": "Kontaktinė informacija" }, "downloadAttachment": { - "message": "Download - $ITEMNAME$", + "message": "Atsisiųsti – $ITEMNAME$", "placeholders": { "itemname": { "content": "$1", @@ -4259,14 +4271,14 @@ } }, "cardNumberEndsWith": { - "message": "card number ends with", + "message": "kortelės numeris baigiasi su", "description": "Used within the inline menu to provide an aria description when users are attempting to fill a card cipher." }, "loginCredentials": { - "message": "Login credentials" + "message": "Prisijungimo kredencialai" }, "authenticatorKey": { - "message": "Authenticator key" + "message": "Autentifikatoriaus raktas" }, "autofillOptions": { "message": "Autofill options" @@ -4352,10 +4364,10 @@ "message": "Pridėti paskyrą" }, "loading": { - "message": "Loading" + "message": "Įkeliama" }, "data": { - "message": "Data" + "message": "Duomenys" }, "passkeys": { "message": "Passkeys", @@ -4370,7 +4382,7 @@ "description": "ARIA label for the inline menu button that logs in with a passkey." }, "assign": { - "message": "Assign" + "message": "Priskirti" }, "bulkCollectionAssignmentDialogDescriptionSingular": { "message": "Only organization members with access to these collections will be able to see the item." @@ -4391,25 +4403,25 @@ } }, "addField": { - "message": "Add field" + "message": "Pridėti lauką" }, "add": { - "message": "Add" + "message": "Pridėti" }, "fieldType": { - "message": "Field type" + "message": "Lauko tipas" }, "fieldLabel": { - "message": "Field label" + "message": "Lauko etiketė" }, "textHelpText": { - "message": "Use text fields for data like security questions" + "message": "Naudokite tekstinius laukus duomenims, pavyzdžiui, saugumo klausimams" }, "hiddenHelpText": { - "message": "Use hidden fields for sensitive data like a password" + "message": "Naudokite paslėptus laukus slaptiems duomenims, pavyzdžiui, slaptažodžiams" }, "checkBoxHelpText": { - "message": "Use checkboxes if you'd like to autofill a form's checkbox, like a remember email" + "message": "Naudokite žymimuosius langelius, jei norite automatiškai užpildyti formos žymimąjį langelį, pavyzdžiui, prisiminti el. paštą" }, "linkedHelpText": { "message": "Use a linked field when you are experiencing autofill issues for a specific website." @@ -4418,10 +4430,10 @@ "message": "Enter the the field's html id, name, aria-label, or placeholder." }, "editField": { - "message": "Edit field" + "message": "Redaguoti lauką" }, "editFieldLabel": { - "message": "Edit $LABEL$", + "message": "Redaguoti $LABEL$", "placeholders": { "label": { "content": "$1", @@ -4430,7 +4442,7 @@ } }, "deleteCustomField": { - "message": "Delete $LABEL$", + "message": "Ištrinti $LABEL$", "placeholders": { "label": { "content": "$1", @@ -4439,7 +4451,7 @@ } }, "fieldAdded": { - "message": "$LABEL$ added", + "message": "Pridėtas $LABEL$", "placeholders": { "label": { "content": "$1", @@ -4561,7 +4573,7 @@ } }, "itemLocation": { - "message": "Item Location" + "message": "Elemento vieta" }, "fileSend": { "message": "File Send" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/lv/messages.json b/apps/browser/src/_locales/lv/messages.json index 870c1e7bef7..88c08977b7e 100644 --- a/apps/browser/src/_locales/lv/messages.json +++ b/apps/browser/src/_locales/lv/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Ievietot licences numuru starpliktuvē" }, + "copyPrivateKey": { + "message": "Ievietot starpliktuvē privāto atslēgu" + }, + "copyPublicKey": { + "message": "Ievietot starpliktuvē publisko atslēgu" + }, + "copyFingerprint": { + "message": "Ievietot starpliktuvē pirkstu nospiedumu" + }, "copyCustomField": { "message": "Ievietot $FIELD$ starpliktuvē", "placeholders": { @@ -591,7 +600,7 @@ "message": "Atvērt tīmekļvietni" }, "launchWebsiteName": { - "message": "Palaist tīmekļvietni $ITEMNAME$", + "message": "Atvērt tīmekļvietni $ITEMNAME$", "placeholders": { "itemname": { "content": "$1", @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identitāte" }, + "typeSshKey": { + "message": "SSH atslēga" + }, "newItemHeader": { "message": "Jauns/a $TYPE$", "placeholders": { @@ -2512,7 +2524,7 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendPasswordDescV3": { - "message": "Pēc izvēles pievieno paroli, lai saņēmēji varētu piekļūt šim Send!", + "message": "Pēc izvēles var pievienot paroli, lai saņēmēji varētu piekļūt šim Send.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendNotesDesc": { @@ -2875,7 +2887,7 @@ "message": "Izveidot lietotājvārdu" }, "generateEmail": { - "message": "Izveidot e-pastu" + "message": "Izveidot e-pasta adresi" }, "generatorBoundariesHint": { "message": "Vērtībai jābūt starp $MIN$ un $MAX$", @@ -2929,7 +2941,7 @@ "message": "Pārvirzīto e-pastu aizstājvārds" }, "forwardedEmailDesc": { - "message": "Izveidot e-pastu aizstājvārdu ar ārēju pārvirzīšanas pakalpojumu." + "message": "Izveidot e-pasta aizstājadresi ar ārēju pārvirzīšanas pakalpojumu." }, "forwarderDomainName": { "message": "E-pasta domēns", @@ -4564,7 +4576,7 @@ "message": "Vienuma atrašanās vieta" }, "fileSend": { - "message": "Datnes Send" + "message": "Datņu Send" }, "fileSends": { "message": "Datņu Send" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Šim iestatījumam tika piemērotas uzņēmējdarbības nosacījumu prasības" }, + "sshPrivateKey": { + "message": "Privātā atslēga" + }, + "sshPublicKey": { + "message": "Publiskā atslēga" + }, + "sshFingerprint": { + "message": "Pirkstu nospiedums" + }, + "sshKeyAlgorithm": { + "message": "Atslēgas veids" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Mēģināt vēlreiz" }, @@ -4692,11 +4728,11 @@ "description": "Represents the * key in screen reader content as a readable word" }, "parenLeftCharacterDescriptor": { - "message": "Kreisās iekavas", + "message": "Kreisā iekava", "description": "Represents the ( key in screen reader content as a readable word" }, "parenRightCharacterDescriptor": { - "message": "Labās iekavas", + "message": "Labā iekava", "description": "Represents the ) key in screen reader content as a readable word" }, "hyphenCharacterDescriptor": { diff --git a/apps/browser/src/_locales/ml/messages.json b/apps/browser/src/_locales/ml/messages.json index 0dcc887200b..79fbf209846 100644 --- a/apps/browser/src/_locales/ml/messages.json +++ b/apps/browser/src/_locales/ml/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "ഐഡന്റിറ്റി" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/mr/messages.json b/apps/browser/src/_locales/mr/messages.json index 150d3197ac6..88748b19b95 100644 --- a/apps/browser/src/_locales/mr/messages.json +++ b/apps/browser/src/_locales/mr/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identity" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/my/messages.json b/apps/browser/src/_locales/my/messages.json index b8075804229..a4668a65add 100644 --- a/apps/browser/src/_locales/my/messages.json +++ b/apps/browser/src/_locales/my/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identity" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/nb/messages.json b/apps/browser/src/_locales/nb/messages.json index 9b647c650bf..8a04c78ed5a 100644 --- a/apps/browser/src/_locales/nb/messages.json +++ b/apps/browser/src/_locales/nb/messages.json @@ -29,7 +29,7 @@ "message": "Use single sign-on" }, "welcomeBack": { - "message": "Velkommen tilbake" + "message": "Welcome back" }, "setAStrongPassword": { "message": "Set a strong password" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -168,7 +177,7 @@ "message": "Copy notes" }, "fill": { - "message": "Fyll", + "message": "Fill", "description": "This string is used on the vault page to indicate autofilling. Horizontal space is limited in the interface here so try and keep translations as concise as possible." }, "autoFill": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identitet" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -1920,7 +1932,7 @@ "message": "Tøm historikk" }, "nothingToShow": { - "message": "Ingenting å vise" + "message": "Nothing to show" }, "nothingGeneratedRecently": { "message": "You haven't generated anything recently" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Prøv igjen" }, @@ -4648,7 +4684,7 @@ "description": "Confirmation message for saving a login to Bitwarden" }, "spaceCharacterDescriptor": { - "message": "Mellomrom", + "message": "Space", "description": "Represents the space key in screen reader content as a readable word" }, "tildeCharacterDescriptor": { @@ -4656,15 +4692,15 @@ "description": "Represents the ~ key in screen reader content as a readable word" }, "backtickCharacterDescriptor": { - "message": "Baklengs apostrof", + "message": "Backtick", "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { - "message": "Utropstegn", + "message": "Exclamation mark", "description": "Represents the ! key in screen reader content as a readable word" }, "atSignCharacterDescriptor": { - "message": "Alfakrøll", + "message": "At sign", "description": "Represents the @ key in screen reader content as a readable word" }, "hashSignCharacterDescriptor": { @@ -4672,7 +4708,7 @@ "description": "Represents the # key in screen reader content as a readable word" }, "dollarSignCharacterDescriptor": { - "message": "Dollartegn", + "message": "Dollar sign", "description": "Represents the $ key in screen reader content as a readable word" }, "percentSignCharacterDescriptor": { @@ -4684,7 +4720,7 @@ "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { - "message": "Prosenttegn", + "message": "Ampersand", "description": "Represents the & key in screen reader content as a readable word" }, "asteriskCharacterDescriptor": { @@ -4700,7 +4736,7 @@ "description": "Represents the ) key in screen reader content as a readable word" }, "hyphenCharacterDescriptor": { - "message": "Understrek", + "message": "Underscore", "description": "Represents the _ key in screen reader content as a readable word" }, "underscoreCharacterDescriptor": { @@ -4740,11 +4776,11 @@ "description": "Represents the back slash key in screen reader content as a readable word" }, "colonCharacterDescriptor": { - "message": "Kolon", + "message": "Colon", "description": "Represents the : key in screen reader content as a readable word" }, "semicolonCharacterDescriptor": { - "message": "Semikolon", + "message": "Semicolon", "description": "Represents the ; key in screen reader content as a readable word" }, "doubleQuoteCharacterDescriptor": { @@ -4756,7 +4792,7 @@ "description": "Represents the ' key in screen reader content as a readable word" }, "lessThanCharacterDescriptor": { - "message": "Mindre enn", + "message": "Less than", "description": "Represents the < key in screen reader content as a readable word" }, "greaterThanCharacterDescriptor": { @@ -4764,7 +4800,7 @@ "description": "Represents the > key in screen reader content as a readable word" }, "commaCharacterDescriptor": { - "message": "Komma", + "message": "Comma", "description": "Represents the , key in screen reader content as a readable word" }, "periodCharacterDescriptor": { @@ -4772,7 +4808,7 @@ "description": "Represents the . key in screen reader content as a readable word" }, "questionCharacterDescriptor": { - "message": "Spørsmålstegn", + "message": "Question mark", "description": "Represents the ? key in screen reader content as a readable word" }, "forwardSlashCharacterDescriptor": { @@ -4780,10 +4816,10 @@ "description": "Represents the / key in screen reader content as a readable word" }, "lowercaseAriaLabel": { - "message": "Små bokstaver" + "message": "Lowercase" }, "uppercaseAriaLabel": { - "message": "Store bokstaver" + "message": "Uppercase" }, "generatedPassword": { "message": "Generated password" diff --git a/apps/browser/src/_locales/ne/messages.json b/apps/browser/src/_locales/ne/messages.json index b8075804229..a4668a65add 100644 --- a/apps/browser/src/_locales/ne/messages.json +++ b/apps/browser/src/_locales/ne/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identity" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/nl/messages.json b/apps/browser/src/_locales/nl/messages.json index 1361b657f24..2a9294c3f00 100644 --- a/apps/browser/src/_locales/nl/messages.json +++ b/apps/browser/src/_locales/nl/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Kenteken kopiëren" }, + "copyPrivateKey": { + "message": "Privésleutel kopiëren" + }, + "copyPublicKey": { + "message": "Publieke sleutel kopiëren" + }, + "copyFingerprint": { + "message": "Vingerafdruk kopiëren" + }, "copyCustomField": { "message": "$FIELD$ kopiëren", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identiteit" }, + "typeSshKey": { + "message": "SSH-sleutel" + }, "newItemHeader": { "message": "Nieuwe $TYPE$", "placeholders": { @@ -4570,7 +4582,7 @@ "message": "Bestand-Sends" }, "textSend": { - "message": "Text Send" + "message": "Tekst-Sends" }, "textSends": { "message": "Tekst-Sends" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Bedrijfsbeleidseisen zijn op deze instelling toegepast" }, + "sshPrivateKey": { + "message": "Privésleutel" + }, + "sshPublicKey": { + "message": "Publieke sleutel" + }, + "sshFingerprint": { + "message": "Vingerafdruk" + }, + "sshKeyAlgorithm": { + "message": "Sleuteltype" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-bit" + }, "retry": { "message": "Opnieuw proberen" }, @@ -4636,19 +4672,19 @@ "message": "Aan het inloggen" }, "fillGeneratedPassword": { - "message": "Fill generated password", + "message": "Gegenereerd wachtwoordin vullen", "description": "Heading for the password generator within the inline menu" }, "passwordRegenerated": { - "message": "Password regenerated", + "message": "Wachtwoord opnieuw gegenereerd", "description": "Notification message for when a password has been regenerated" }, "saveLoginToBitwarden": { - "message": "Save login to Bitwarden?", + "message": "Login opslaan in Bitwarden?", "description": "Confirmation message for saving a login to Bitwarden" }, "spaceCharacterDescriptor": { - "message": "Space", + "message": "Spatie", "description": "Represents the space key in screen reader content as a readable word" }, "tildeCharacterDescriptor": { @@ -4660,51 +4696,51 @@ "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { - "message": "Exclamation mark", + "message": "Uitroepteken", "description": "Represents the ! key in screen reader content as a readable word" }, "atSignCharacterDescriptor": { - "message": "At sign", + "message": "Apenstaartje", "description": "Represents the @ key in screen reader content as a readable word" }, "hashSignCharacterDescriptor": { - "message": "Hash sign", + "message": "Hekje", "description": "Represents the # key in screen reader content as a readable word" }, "dollarSignCharacterDescriptor": { - "message": "Dollar sign", + "message": "Dollarteken", "description": "Represents the $ key in screen reader content as a readable word" }, "percentSignCharacterDescriptor": { - "message": "Percent sign", + "message": "Procentteken", "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { - "message": "Caret", + "message": "Dakje", "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { - "message": "Ampersand", + "message": "En-teken", "description": "Represents the & key in screen reader content as a readable word" }, "asteriskCharacterDescriptor": { - "message": "Asterisk", + "message": "Sterretje", "description": "Represents the * key in screen reader content as a readable word" }, "parenLeftCharacterDescriptor": { - "message": "Left parenthesis", + "message": "Haakje opnenen", "description": "Represents the ( key in screen reader content as a readable word" }, "parenRightCharacterDescriptor": { - "message": "Right parenthesis", + "message": "Haakje sluiten", "description": "Represents the ) key in screen reader content as a readable word" }, "hyphenCharacterDescriptor": { - "message": "Underscore", + "message": "Liggend streepje", "description": "Represents the _ key in screen reader content as a readable word" }, "underscoreCharacterDescriptor": { - "message": "Hyphen", + "message": "Koppelteken", "description": "Represents the - key in screen reader content as a readable word" }, "plusCharacterDescriptor": { @@ -4712,80 +4748,80 @@ "description": "Represents the + key in screen reader content as a readable word" }, "equalsCharacterDescriptor": { - "message": "Equals", + "message": "Gelijkteken", "description": "Represents the = key in screen reader content as a readable word" }, "braceLeftCharacterDescriptor": { - "message": "Left brace", + "message": "Accolade openen", "description": "Represents the { key in screen reader content as a readable word" }, "braceRightCharacterDescriptor": { - "message": "Right brace", + "message": "Accolade sluiten", "description": "Represents the } key in screen reader content as a readable word" }, "bracketLeftCharacterDescriptor": { - "message": "Left bracket", + "message": "Blokhaak openen", "description": "Represents the [ key in screen reader content as a readable word" }, "bracketRightCharacterDescriptor": { - "message": "Right bracket", + "message": "Blokhaak sluiten", "description": "Represents the ] key in screen reader content as a readable word" }, "pipeCharacterDescriptor": { - "message": "Pipe", + "message": "Verticale streep", "description": "Represents the | key in screen reader content as a readable word" }, "backSlashCharacterDescriptor": { - "message": "Back slash", + "message": "Backslash", "description": "Represents the back slash key in screen reader content as a readable word" }, "colonCharacterDescriptor": { - "message": "Colon", + "message": "Dubbele punt", "description": "Represents the : key in screen reader content as a readable word" }, "semicolonCharacterDescriptor": { - "message": "Semicolon", + "message": "Puntkomma", "description": "Represents the ; key in screen reader content as a readable word" }, "doubleQuoteCharacterDescriptor": { - "message": "Double quote", + "message": "Dubbel aanhalingsteken", "description": "Represents the double quote key in screen reader content as a readable word" }, "singleQuoteCharacterDescriptor": { - "message": "Single quote", + "message": "Enkel aanhalingsteken", "description": "Represents the ' key in screen reader content as a readable word" }, "lessThanCharacterDescriptor": { - "message": "Less than", + "message": "Kleiner dan", "description": "Represents the < key in screen reader content as a readable word" }, "greaterThanCharacterDescriptor": { - "message": "Greater than", + "message": "Groter dan", "description": "Represents the > key in screen reader content as a readable word" }, "commaCharacterDescriptor": { - "message": "Comma", + "message": "Komma", "description": "Represents the , key in screen reader content as a readable word" }, "periodCharacterDescriptor": { - "message": "Period", + "message": "Punt", "description": "Represents the . key in screen reader content as a readable word" }, "questionCharacterDescriptor": { - "message": "Question mark", + "message": "Vraagteken", "description": "Represents the ? key in screen reader content as a readable word" }, "forwardSlashCharacterDescriptor": { - "message": "Forward slash", + "message": "Slash", "description": "Represents the / key in screen reader content as a readable word" }, "lowercaseAriaLabel": { - "message": "Lowercase" + "message": "Kleine letters" }, "uppercaseAriaLabel": { - "message": "Uppercase" + "message": "Hoofdletters" }, "generatedPassword": { - "message": "Generated password" + "message": "Gegenereerd wachtwoord" } } diff --git a/apps/browser/src/_locales/nn/messages.json b/apps/browser/src/_locales/nn/messages.json index b8075804229..a4668a65add 100644 --- a/apps/browser/src/_locales/nn/messages.json +++ b/apps/browser/src/_locales/nn/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identity" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/or/messages.json b/apps/browser/src/_locales/or/messages.json index b8075804229..a4668a65add 100644 --- a/apps/browser/src/_locales/or/messages.json +++ b/apps/browser/src/_locales/or/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identity" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/pl/messages.json b/apps/browser/src/_locales/pl/messages.json index c3c48b34e8a..b8a1f1a2e02 100644 --- a/apps/browser/src/_locales/pl/messages.json +++ b/apps/browser/src/_locales/pl/messages.json @@ -20,16 +20,16 @@ "message": "Utwórz konto" }, "newToBitwarden": { - "message": "Nowy użytkownik Bitwarden?" + "message": "New to Bitwarden?" }, "logInWithPasskey": { - "message": "Zaloguj się używając passkey" + "message": "Log in with passkey" }, "useSingleSignOn": { - "message": "Użyj jednokrotnego logowania" + "message": "Use single sign-on" }, "welcomeBack": { - "message": "Witaj ponownie" + "message": "Welcome back" }, "setAStrongPassword": { "message": "Ustaw silne hasło" @@ -120,7 +120,7 @@ "message": "Kopiuj hasło" }, "copyPassphrase": { - "message": "Kopiuj frazę bezpieczeństwa" + "message": "Copy passphrase" }, "copyNote": { "message": "Kopiuj notatkę" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Kopiuj numer licencji" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Kopiuj $FIELD$", "placeholders": { @@ -168,7 +177,7 @@ "message": "Kopiuj notatki" }, "fill": { - "message": "Uzupełnij", + "message": "Fill", "description": "This string is used on the vault page to indicate autofilling. Horizontal space is limited in the interface here so try and keep translations as concise as possible." }, "autoFill": { @@ -427,7 +436,7 @@ "message": "Wygeneruj hasło" }, "generatePassphrase": { - "message": "Wygenruj frazę zabezpieczającą" + "message": "Generate passphrase" }, "regeneratePassword": { "message": "Wygeneruj ponownie hasło" @@ -591,7 +600,7 @@ "message": "Otwórz stronę" }, "launchWebsiteName": { - "message": "Otwórz stronę internetową $ITEMNAME$", + "message": "Launch website $ITEMNAME$", "placeholders": { "itemname": { "content": "$1", @@ -846,7 +855,7 @@ "message": "Zaloguj się" }, "logInToBitwarden": { - "message": "Zaloguj się do Bitwarden" + "message": "Log in to Bitwarden" }, "restartRegistration": { "message": "Zrestartuj rejestrację" @@ -1424,7 +1433,7 @@ "message": "Adres URL serwera" }, "selfHostBaseUrl": { - "message": "URL samodzielnie hostowanego serwera", + "message": "Self-host server URL", "description": "Label for field requesting a self-hosted integration service URL" }, "apiUrl": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Tożsamość" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "Nowy $TYPE$", "placeholders": { @@ -1795,13 +1807,13 @@ "message": "Historia hasła" }, "generatorHistory": { - "message": "Historia generatora" + "message": "Generator history" }, "clearGeneratorHistoryTitle": { - "message": "Wyczyść historię generatora" + "message": "Clear generator history" }, "cleargGeneratorHistoryDescription": { - "message": "Jeśli kontynuujesz, wszystkie elementy zostaną usunięte z historii generatora. Czy chcesz kontynuować mimo to?" + "message": "If you continue, all entries will be permanently deleted from generator's history. Are you sure you want to continue?" }, "back": { "message": "Powrót" @@ -1920,10 +1932,10 @@ "message": "Wyczyść historię" }, "nothingToShow": { - "message": "Nic do pokazania" + "message": "Nothing to show" }, "nothingGeneratedRecently": { - "message": "Nic nie zostało wygenerowane przez ciebie w ostatnim czasie" + "message": "You haven't generated anything recently" }, "remove": { "message": "Usuń" @@ -2512,7 +2524,7 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendPasswordDescV3": { - "message": "Zabezpiecz tę wiadomość hasłem, które będzie wymagane, aby uzyskać do niej dostęp.", + "message": "Add an optional password for recipients to access this Send.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendNotesDesc": { @@ -2875,7 +2887,7 @@ "message": "Wygeneruj nazwę użytkownika" }, "generateEmail": { - "message": "Wygenruj adres e-mail" + "message": "Generate email" }, "generatorBoundariesHint": { "message": "Value must be between $MIN$ and $MAX$", @@ -2932,7 +2944,7 @@ "message": "Wygeneruj alias adresu e-mail z zewnętrznej usługi przekierowania." }, "forwarderDomainName": { - "message": "Domena adresu e-mail", + "message": "Email domain", "description": "Labels the domain name email forwarder service option" }, "forwarderDomainNameHint": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Do tego ustalenia zastosowano wymogi polityki przedsiębiorstw" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Powtórz" }, @@ -4640,15 +4676,15 @@ "description": "Heading for the password generator within the inline menu" }, "passwordRegenerated": { - "message": "Hasło zostało ponownie wygenerowane", + "message": "Password regenerated", "description": "Notification message for when a password has been regenerated" }, "saveLoginToBitwarden": { - "message": "Zapisać dane logowania w Bitwarden?", + "message": "Save login to Bitwarden?", "description": "Confirmation message for saving a login to Bitwarden" }, "spaceCharacterDescriptor": { - "message": "Spacja", + "message": "Space", "description": "Represents the space key in screen reader content as a readable word" }, "tildeCharacterDescriptor": { @@ -4660,23 +4696,23 @@ "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { - "message": "Wykrzyknik", + "message": "Exclamation mark", "description": "Represents the ! key in screen reader content as a readable word" }, "atSignCharacterDescriptor": { - "message": "Małpa", + "message": "At sign", "description": "Represents the @ key in screen reader content as a readable word" }, "hashSignCharacterDescriptor": { - "message": "Hashtag", + "message": "Hash sign", "description": "Represents the # key in screen reader content as a readable word" }, "dollarSignCharacterDescriptor": { - "message": "Znak dolara", + "message": "Dollar sign", "description": "Represents the $ key in screen reader content as a readable word" }, "percentSignCharacterDescriptor": { - "message": "Znak procenta", + "message": "Percent sign", "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { @@ -4688,7 +4724,7 @@ "description": "Represents the & key in screen reader content as a readable word" }, "asteriskCharacterDescriptor": { - "message": "Gwiazdka", + "message": "Asterisk", "description": "Represents the * key in screen reader content as a readable word" }, "parenLeftCharacterDescriptor": { @@ -4700,7 +4736,7 @@ "description": "Represents the ) key in screen reader content as a readable word" }, "hyphenCharacterDescriptor": { - "message": "Podkreślenie", + "message": "Underscore", "description": "Represents the _ key in screen reader content as a readable word" }, "underscoreCharacterDescriptor": { @@ -4712,23 +4748,23 @@ "description": "Represents the + key in screen reader content as a readable word" }, "equalsCharacterDescriptor": { - "message": "Znak równości", + "message": "Equals", "description": "Represents the = key in screen reader content as a readable word" }, "braceLeftCharacterDescriptor": { - "message": "Lewy nawias klamrowy", + "message": "Left brace", "description": "Represents the { key in screen reader content as a readable word" }, "braceRightCharacterDescriptor": { - "message": "Prawy nawias klamrowy", + "message": "Right brace", "description": "Represents the } key in screen reader content as a readable word" }, "bracketLeftCharacterDescriptor": { - "message": "Lewy nawias kwadratowy", + "message": "Left bracket", "description": "Represents the [ key in screen reader content as a readable word" }, "bracketRightCharacterDescriptor": { - "message": "Prawy nawias kwadratowy", + "message": "Right bracket", "description": "Represents the ] key in screen reader content as a readable word" }, "pipeCharacterDescriptor": { diff --git a/apps/browser/src/_locales/pt_BR/messages.json b/apps/browser/src/_locales/pt_BR/messages.json index 047ca09e7a4..6bdb8fc331b 100644 --- a/apps/browser/src/_locales/pt_BR/messages.json +++ b/apps/browser/src/_locales/pt_BR/messages.json @@ -20,16 +20,16 @@ "message": "Criar Conta" }, "newToBitwarden": { - "message": "New to Bitwarden?" + "message": "Novo no Bitwarden?" }, "logInWithPasskey": { - "message": "Log in with passkey" + "message": "Iniciar sessão com a chave de acesso" }, "useSingleSignOn": { - "message": "Use single sign-on" + "message": "Usar login único" }, "welcomeBack": { - "message": "Welcome back" + "message": "Bem vindo de volta" }, "setAStrongPassword": { "message": "Defina uma senha forte" @@ -84,7 +84,7 @@ "message": "Juntar-se à organização" }, "joinOrganizationName": { - "message": "Join $ORGANIZATIONNAME$", + "message": "Entrar em $ORGANIZATIONNAME$", "placeholders": { "organizationName": { "content": "$1", @@ -120,7 +120,7 @@ "message": "Copiar Senha" }, "copyPassphrase": { - "message": "Copy passphrase" + "message": "Copiar senha" }, "copyNote": { "message": "Copiar Nota" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copiar número da CNH" }, + "copyPrivateKey": { + "message": "Copiar chave privada" + }, + "copyPublicKey": { + "message": "Copiar chave pública" + }, + "copyFingerprint": { + "message": "Copiar impressão digital" + }, "copyCustomField": { "message": "Copiar $FIELD$", "placeholders": { @@ -168,7 +177,7 @@ "message": "Copiar Notas" }, "fill": { - "message": "Fill", + "message": "Preencher", "description": "This string is used on the vault page to indicate autofilling. Horizontal space is limited in the interface here so try and keep translations as concise as possible." }, "autoFill": { @@ -427,7 +436,7 @@ "message": "Gerar Senha" }, "generatePassphrase": { - "message": "Generate passphrase" + "message": "Gerar frase secreta" }, "regeneratePassword": { "message": "Gerar Nova Senha" @@ -591,7 +600,7 @@ "message": "Abrir site" }, "launchWebsiteName": { - "message": "Launch website $ITEMNAME$", + "message": "Iniciar site $ITEMNAME$", "placeholders": { "itemname": { "content": "$1", @@ -645,13 +654,13 @@ "message": "Seu cofre está trancado. Verifique sua identidade para continuar." }, "yourVaultIsLockedV2": { - "message": "Your vault is locked" + "message": "Seu cofre está bloqueado" }, "yourAccountIsLocked": { - "message": "Your account is locked" + "message": "Sua conta está bloqueada" }, "or": { - "message": "or" + "message": "ou" }, "unlock": { "message": "Desbloquear" @@ -846,7 +855,7 @@ "message": "Fazer login" }, "logInToBitwarden": { - "message": "Log in to Bitwarden" + "message": "Inicie a sessão no Bitwarden" }, "restartRegistration": { "message": "Reiniciar registro" @@ -1424,7 +1433,7 @@ "message": "URL do Servidor" }, "selfHostBaseUrl": { - "message": "Self-host server URL", + "message": "URL do servidor auto-host", "description": "Label for field requesting a self-hosted integration service URL" }, "apiUrl": { @@ -1456,10 +1465,10 @@ "message": "Mostrar sugestões de preenchimento automático nos campos de formulários" }, "showInlineMenuIdentitiesLabel": { - "message": "Display identities as suggestions" + "message": "Exibir identidades como sugestões" }, "showInlineMenuCardsLabel": { - "message": "Display cards as suggestions" + "message": "Exibir cards como sugestões" }, "showInlineMenuOnIconSelectionLabel": { "message": "Exibir sugestões quando o ícone for selecionado" @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identidade" }, + "typeSshKey": { + "message": "Chave SSH" + }, "newItemHeader": { "message": "Nova $TYPE$", "placeholders": { @@ -1795,13 +1807,13 @@ "message": "Histórico de Senha" }, "generatorHistory": { - "message": "Generator history" + "message": "Histórico do gerador" }, "clearGeneratorHistoryTitle": { - "message": "Clear generator history" + "message": "Limpar histórico do gerador" }, "cleargGeneratorHistoryDescription": { - "message": "If you continue, all entries will be permanently deleted from generator's history. Are you sure you want to continue?" + "message": "Se continuar, todas as entradas serão permanentemente excluídas do histórico do gerador. Tem certeza que deseja continuar?" }, "back": { "message": "Voltar" @@ -1920,10 +1932,10 @@ "message": "Limpar histórico" }, "nothingToShow": { - "message": "Nothing to show" + "message": "Nada para mostrar" }, "nothingGeneratedRecently": { - "message": "You haven't generated anything recently" + "message": "Você não gerou nada recentemente" }, "remove": { "message": "Remover" @@ -2008,7 +2020,7 @@ "message": "Desbloquear com a biometria" }, "unlockWithMasterPassword": { - "message": "Unlock with master password" + "message": "Desbloquear com a senha mestra" }, "awaitDesktop": { "message": "Aguardando confirmação do desktop" @@ -2512,7 +2524,7 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendPasswordDescV3": { - "message": "Add an optional password for recipients to access this Send.", + "message": "Adicione uma senha opcional para os destinatários para acessar este Envio.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendNotesDesc": { @@ -2561,11 +2573,11 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendExpiresInHoursSingle": { - "message": "The Send will be available to anyone with the link for the next 1 hour.", + "message": "O envio estará disponível para qualquer pessoa com o link para a próxima 1 hora.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendExpiresInHours": { - "message": "The Send will be available to anyone with the link for the next $HOURS$ hours.", + "message": "O envio estará disponível para qualquer pessoa com o link para as próximas $HOURS$ horas.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.", "placeholders": { "hours": { @@ -2575,11 +2587,11 @@ } }, "sendExpiresInDaysSingle": { - "message": "The Send will be available to anyone with the link for the next 1 day.", + "message": "O envio estará disponível para qualquer pessoa com o link para o próximo 1 dia.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendExpiresInDays": { - "message": "The Send will be available to anyone with the link for the next $DAYS$ days.", + "message": "O envio estará disponível para qualquer pessoa com o link para os próximos $DAYS$ dias.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.", "placeholders": { "days": { @@ -2710,7 +2722,7 @@ "description": "Used as a card title description on the set password page to explain why the user is there" }, "cardMetrics": { - "message": "out of $TOTAL$", + "message": "fora do $TOTAL$", "placeholders": { "total": { "content": "$1", @@ -2875,10 +2887,10 @@ "message": "Gerar Usuário" }, "generateEmail": { - "message": "Generate email" + "message": "Gerar e-mail" }, "generatorBoundariesHint": { - "message": "Value must be between $MIN$ and $MAX$", + "message": "Valor deve ser entre $MIN$ e $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -2932,11 +2944,11 @@ "message": "Gere um apelido de e-mail com um serviço de encaminhamento externo." }, "forwarderDomainName": { - "message": "Email domain", + "message": "Domínio de e-mail", "description": "Labels the domain name email forwarder service option" }, "forwarderDomainNameHint": { - "message": "Choose a domain that is supported by the selected service", + "message": "Escolha um domínio que seja suportado pelo serviço selecionado", "description": "Guidance provided for email forwarding services that support multiple email domains." }, "forwarderError": { @@ -3747,7 +3759,7 @@ "message": "Chave de acesso" }, "accessing": { - "message": "Accessing" + "message": "Acessando" }, "passkeyNotCopied": { "message": "A chave de acesso não será copiada" @@ -3774,7 +3786,7 @@ "message": "Sem credenciais correspondentes para este site" }, "searchSavePasskeyNewLogin": { - "message": "Search or save passkey as new login" + "message": "Pesquisar ou salvar senha como novo login" }, "confirm": { "message": "Confirmar" @@ -4564,13 +4576,13 @@ "message": "Localização do Item" }, "fileSend": { - "message": "File Send" + "message": "Arquivo enviado" }, "fileSends": { "message": "Arquivos enviados" }, "textSend": { - "message": "Text Send" + "message": "Enviar texto" }, "textSends": { "message": "Texto enviado" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Os requisitos de política empresarial foram aplicados nesta configuração" }, + "sshPrivateKey": { + "message": "Chave privada" + }, + "sshPublicKey": { + "message": "Chave pública" + }, + "sshFingerprint": { + "message": "Impressão digital" + }, + "sshKeyAlgorithm": { + "message": "Tipo de chave" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Tente novamente" }, @@ -4636,99 +4672,99 @@ "message": "Autenticando" }, "fillGeneratedPassword": { - "message": "Fill generated password", + "message": "Preencher a senha gerada", "description": "Heading for the password generator within the inline menu" }, "passwordRegenerated": { - "message": "Password regenerated", + "message": "Senha regenerada", "description": "Notification message for when a password has been regenerated" }, "saveLoginToBitwarden": { - "message": "Save login to Bitwarden?", + "message": "Salvar login no Bitwarden?", "description": "Confirmation message for saving a login to Bitwarden" }, "spaceCharacterDescriptor": { - "message": "Space", + "message": "Espaço", "description": "Represents the space key in screen reader content as a readable word" }, "tildeCharacterDescriptor": { - "message": "Tilde", + "message": "Linear", "description": "Represents the ~ key in screen reader content as a readable word" }, "backtickCharacterDescriptor": { - "message": "Backtick", + "message": "Bastão", "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { - "message": "Exclamation mark", + "message": "Ponto de exclamação", "description": "Represents the ! key in screen reader content as a readable word" }, "atSignCharacterDescriptor": { - "message": "At sign", + "message": "Arroba", "description": "Represents the @ key in screen reader content as a readable word" }, "hashSignCharacterDescriptor": { - "message": "Hash sign", + "message": "Jogo da velha", "description": "Represents the # key in screen reader content as a readable word" }, "dollarSignCharacterDescriptor": { - "message": "Dollar sign", + "message": "cifrão", "description": "Represents the $ key in screen reader content as a readable word" }, "percentSignCharacterDescriptor": { - "message": "Percent sign", + "message": "Porcentagem", "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { - "message": "Caret", + "message": "Circunflexo", "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { - "message": "Ampersand", + "message": "E Comercial", "description": "Represents the & key in screen reader content as a readable word" }, "asteriskCharacterDescriptor": { - "message": "Asterisk", + "message": "Asterísco", "description": "Represents the * key in screen reader content as a readable word" }, "parenLeftCharacterDescriptor": { - "message": "Left parenthesis", + "message": "Parêntese esquerdo", "description": "Represents the ( key in screen reader content as a readable word" }, "parenRightCharacterDescriptor": { - "message": "Right parenthesis", + "message": "Parênteses direito", "description": "Represents the ) key in screen reader content as a readable word" }, "hyphenCharacterDescriptor": { - "message": "Underscore", + "message": "Sublinhado", "description": "Represents the _ key in screen reader content as a readable word" }, "underscoreCharacterDescriptor": { - "message": "Hyphen", + "message": "Hífen", "description": "Represents the - key in screen reader content as a readable word" }, "plusCharacterDescriptor": { - "message": "Plus", + "message": "Mais", "description": "Represents the + key in screen reader content as a readable word" }, "equalsCharacterDescriptor": { - "message": "Equals", + "message": "iguais", "description": "Represents the = key in screen reader content as a readable word" }, "braceLeftCharacterDescriptor": { - "message": "Left brace", + "message": "Abre chaves", "description": "Represents the { key in screen reader content as a readable word" }, "braceRightCharacterDescriptor": { - "message": "Right brace", + "message": "Fecha chaves", "description": "Represents the } key in screen reader content as a readable word" }, "bracketLeftCharacterDescriptor": { - "message": "Left bracket", + "message": "Abre colchetes", "description": "Represents the [ key in screen reader content as a readable word" }, "bracketRightCharacterDescriptor": { - "message": "Right bracket", + "message": "Fecha colchetes", "description": "Represents the ] key in screen reader content as a readable word" }, "pipeCharacterDescriptor": { @@ -4736,56 +4772,56 @@ "description": "Represents the | key in screen reader content as a readable word" }, "backSlashCharacterDescriptor": { - "message": "Back slash", + "message": "Barra Invertida", "description": "Represents the back slash key in screen reader content as a readable word" }, "colonCharacterDescriptor": { - "message": "Colon", + "message": "Dois Pontos", "description": "Represents the : key in screen reader content as a readable word" }, "semicolonCharacterDescriptor": { - "message": "Semicolon", + "message": "Ponto e vírgula", "description": "Represents the ; key in screen reader content as a readable word" }, "doubleQuoteCharacterDescriptor": { - "message": "Double quote", + "message": "Aspas duplas", "description": "Represents the double quote key in screen reader content as a readable word" }, "singleQuoteCharacterDescriptor": { - "message": "Single quote", + "message": "Aspas simples", "description": "Represents the ' key in screen reader content as a readable word" }, "lessThanCharacterDescriptor": { - "message": "Less than", + "message": "Menor que", "description": "Represents the < key in screen reader content as a readable word" }, "greaterThanCharacterDescriptor": { - "message": "Greater than", + "message": "Maior que", "description": "Represents the > key in screen reader content as a readable word" }, "commaCharacterDescriptor": { - "message": "Comma", + "message": "Virgula", "description": "Represents the , key in screen reader content as a readable word" }, "periodCharacterDescriptor": { - "message": "Period", + "message": "Ponto", "description": "Represents the . key in screen reader content as a readable word" }, "questionCharacterDescriptor": { - "message": "Question mark", + "message": "Ponto de interrogação", "description": "Represents the ? key in screen reader content as a readable word" }, "forwardSlashCharacterDescriptor": { - "message": "Forward slash", + "message": "Barra", "description": "Represents the / key in screen reader content as a readable word" }, "lowercaseAriaLabel": { - "message": "Lowercase" + "message": "Letras minúsculas" }, "uppercaseAriaLabel": { - "message": "Uppercase" + "message": "Letras maiúsculas" }, "generatedPassword": { - "message": "Generated password" + "message": "Senha gerada" } } diff --git a/apps/browser/src/_locales/pt_PT/messages.json b/apps/browser/src/_locales/pt_PT/messages.json index 3885f6bad64..f7197d512d7 100644 --- a/apps/browser/src/_locales/pt_PT/messages.json +++ b/apps/browser/src/_locales/pt_PT/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copiar número da carta de condução" }, + "copyPrivateKey": { + "message": "Copiar chave privada" + }, + "copyPublicKey": { + "message": "Copiar chave pública" + }, + "copyFingerprint": { + "message": "Copiar impressão digital" + }, "copyCustomField": { "message": "Copiar $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identidade" }, + "typeSshKey": { + "message": "Chave SSH" + }, "newItemHeader": { "message": "Novo(a) $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Os requisitos da política empresarial foram aplicados a esta definição" }, + "sshPrivateKey": { + "message": "Chave privada" + }, + "sshPublicKey": { + "message": "Chave pública" + }, + "sshFingerprint": { + "message": "Impressão digital" + }, + "sshKeyAlgorithm": { + "message": "Tipo de chave" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Tentar novamente" }, diff --git a/apps/browser/src/_locales/ro/messages.json b/apps/browser/src/_locales/ro/messages.json index f25897f38f6..29ee5bf4b49 100644 --- a/apps/browser/src/_locales/ro/messages.json +++ b/apps/browser/src/_locales/ro/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copiați numărul de licență" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copiază $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identitate" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/ru/messages.json b/apps/browser/src/_locales/ru/messages.json index 7c7a70c82ff..dd6f067f114 100644 --- a/apps/browser/src/_locales/ru/messages.json +++ b/apps/browser/src/_locales/ru/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Скопировать номер лицензии" }, + "copyPrivateKey": { + "message": "Скопировать приватный ключ" + }, + "copyPublicKey": { + "message": "Скопировать публичный ключ" + }, + "copyFingerprint": { + "message": "Скопировать отпечаток" + }, "copyCustomField": { "message": "Скопировать $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Личная информация" }, + "typeSshKey": { + "message": "Ключ SSH" + }, "newItemHeader": { "message": "Новый $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "К этой настройке были применены требования корпоративной политики" }, + "sshPrivateKey": { + "message": "Приватный ключ" + }, + "sshPublicKey": { + "message": "Публичный ключ" + }, + "sshFingerprint": { + "message": "Отпечаток" + }, + "sshKeyAlgorithm": { + "message": "Тип ключа" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Повторить" }, diff --git a/apps/browser/src/_locales/si/messages.json b/apps/browser/src/_locales/si/messages.json index 4dd1bfeb898..d642e31ba28 100644 --- a/apps/browser/src/_locales/si/messages.json +++ b/apps/browser/src/_locales/si/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "අනන්යතාවය" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/sk/messages.json b/apps/browser/src/_locales/sk/messages.json index dc46b0fdb85..9c8a3031164 100644 --- a/apps/browser/src/_locales/sk/messages.json +++ b/apps/browser/src/_locales/sk/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Kopírovať číslo licencie" }, + "copyPrivateKey": { + "message": "Kopírovať súkromný kľúč" + }, + "copyPublicKey": { + "message": "Kopírovať verejný kľúč" + }, + "copyFingerprint": { + "message": "Kopírovať odtlačok" + }, "copyCustomField": { "message": "Kopírovať $FIELD$", "placeholders": { @@ -846,7 +855,7 @@ "message": "Prihlásiť sa" }, "logInToBitwarden": { - "message": "Prihlásiť sa do Bitwardenu" + "message": "Prihlásenie do Bitwardenu" }, "restartRegistration": { "message": "Zopakovať registráciu" @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identita" }, + "typeSshKey": { + "message": "Kľúč SSH" + }, "newItemHeader": { "message": "Nové $TYPE$", "placeholders": { @@ -1920,7 +1932,7 @@ "message": "Vymazať históriu" }, "nothingToShow": { - "message": "Nič na zobrazenie" + "message": "Nie je čo zobraziť" }, "nothingGeneratedRecently": { "message": "V poslednej dobe ste nič negenerovali" @@ -3747,7 +3759,7 @@ "message": "Prístupový kľúč" }, "accessing": { - "message": "Accessing" + "message": "Pristupovanie" }, "passkeyNotCopied": { "message": "Prístupový kód sa neskopíruje" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Na toto nastavenie boli uplatnené požiadavky pravidiel spoločnosti" }, + "sshPrivateKey": { + "message": "Súkromný kľúč" + }, + "sshPublicKey": { + "message": "Verejný kľúč" + }, + "sshFingerprint": { + "message": "Odtlačok" + }, + "sshKeyAlgorithm": { + "message": "Typ kľúča" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Znova" }, @@ -4652,11 +4688,11 @@ "description": "Represents the space key in screen reader content as a readable word" }, "tildeCharacterDescriptor": { - "message": "Tilda", + "message": "Vlnovka", "description": "Represents the ~ key in screen reader content as a readable word" }, "backtickCharacterDescriptor": { - "message": "Opačný dĺžeň", + "message": "Obrátená čiarka", "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { @@ -4680,7 +4716,7 @@ "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { - "message": "Striežka", + "message": "Strieška", "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { @@ -4732,7 +4768,7 @@ "description": "Represents the ] key in screen reader content as a readable word" }, "pipeCharacterDescriptor": { - "message": "Rúra", + "message": "Zvislá čiara", "description": "Represents the | key in screen reader content as a readable word" }, "backSlashCharacterDescriptor": { diff --git a/apps/browser/src/_locales/sl/messages.json b/apps/browser/src/_locales/sl/messages.json index d2af5a49008..24ad943bcc4 100644 --- a/apps/browser/src/_locales/sl/messages.json +++ b/apps/browser/src/_locales/sl/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identiteta" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/sr/messages.json b/apps/browser/src/_locales/sr/messages.json index b1dcec00b1a..d39949ecd07 100644 --- a/apps/browser/src/_locales/sr/messages.json +++ b/apps/browser/src/_locales/sr/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Копирај број лиценце" }, + "copyPrivateKey": { + "message": "Копирај приватни кључ" + }, + "copyPublicKey": { + "message": "Копирај јавни кључ" + }, + "copyFingerprint": { + "message": "Копирати отисак" + }, "copyCustomField": { "message": "Копирати $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Идентитет" }, + "typeSshKey": { + "message": "SSH кључ" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -3401,7 +3413,7 @@ "message": "1 поље захтева вашу пажњу." }, "multipleFieldsNeedAttention": { - "message": "$COUNT$ fields need your attention.", + "message": "$COUNT$ поља захтевају вашу пажњу.", "placeholders": { "count": { "content": "$1", @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Захтеви политике предузећа су примењени на ово подешавање" }, + "sshPrivateKey": { + "message": "Приватни кључ" + }, + "sshPublicKey": { + "message": "Јавни кључ" + }, + "sshFingerprint": { + "message": "Отисак прста" + }, + "sshKeyAlgorithm": { + "message": "Врста кључа" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-бита" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-бита" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-бита" + }, "retry": { "message": "Пробај поново" }, @@ -4680,35 +4716,35 @@ "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { - "message": "Знак за уметање", + "message": "Caret", "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { - "message": "Знак Ampersand", + "message": "Ampersand", "description": "Represents the & key in screen reader content as a readable word" }, "asteriskCharacterDescriptor": { - "message": "Знак звездица", + "message": "Asterisk", "description": "Represents the * key in screen reader content as a readable word" }, "parenLeftCharacterDescriptor": { - "message": "Отворена заграда", + "message": "Left parenthesis", "description": "Represents the ( key in screen reader content as a readable word" }, "parenRightCharacterDescriptor": { - "message": "Затворена заграда", + "message": "Right parenthesis", "description": "Represents the ) key in screen reader content as a readable word" }, "hyphenCharacterDescriptor": { - "message": "Доња црта", + "message": "Underscore", "description": "Represents the _ key in screen reader content as a readable word" }, "underscoreCharacterDescriptor": { - "message": "Цртица", + "message": "Hyphen", "description": "Represents the - key in screen reader content as a readable word" }, "plusCharacterDescriptor": { - "message": "Плус", + "message": "Plus", "description": "Represents the + key in screen reader content as a readable word" }, "equalsCharacterDescriptor": { diff --git a/apps/browser/src/_locales/sv/messages.json b/apps/browser/src/_locales/sv/messages.json index e58a262d59c..e64855b383e 100644 --- a/apps/browser/src/_locales/sv/messages.json +++ b/apps/browser/src/_locales/sv/messages.json @@ -150,7 +150,16 @@ "message": "Kopiera passnummer" }, "copyLicenseNumber": { - "message": "Copy license number" + "message": "Kopiera licensnummer" + }, + "copyPrivateKey": { + "message": "Kopiera privat nyckel" + }, + "copyPublicKey": { + "message": "Kopiera offentlig nyckel" + }, + "copyFingerprint": { + "message": "Kopiera fingeravtryck" }, "copyCustomField": { "message": "Kopiera $FIELD$", @@ -168,7 +177,7 @@ "message": "Kopiera anteckningar" }, "fill": { - "message": "Fill", + "message": "Fyll", "description": "This string is used on the vault page to indicate autofilling. Horizontal space is limited in the interface here so try and keep translations as concise as possible." }, "autoFill": { @@ -366,7 +375,7 @@ "message": "Nest a folder by adding the parent folder's name followed by a “/”. Example: Social/Forums" }, "noFoldersAdded": { - "message": "No folders added" + "message": "Inga mappar tillagda" }, "createFoldersToOrganize": { "message": "Skapa mappar för att organisera dina valvobjekt" @@ -458,11 +467,11 @@ "description": "deprecated. Use specialCharactersLabel instead." }, "include": { - "message": "Include", + "message": "Inkludera", "description": "Card header for password generator include block" }, "uppercaseDescription": { - "message": "Include uppercase characters", + "message": "Inkludera versaler", "description": "Tooltip for the password generator uppercase character checkbox" }, "uppercaseLabel": { @@ -470,7 +479,7 @@ "description": "Label for the password generator uppercase character checkbox" }, "lowercaseDescription": { - "message": "Include lowercase characters", + "message": "Inkludera gemener", "description": "Full description for the password generator lowercase character checkbox" }, "lowercaseLabel": { @@ -478,7 +487,7 @@ "description": "Label for the password generator lowercase character checkbox" }, "numbersDescription": { - "message": "Include numbers", + "message": "Inkludera siffror", "description": "Full description for the password generator numbers checkbox" }, "numbersLabel": { @@ -486,7 +495,7 @@ "description": "Label for the password generator numbers checkbox" }, "specialCharactersDescription": { - "message": "Include special characters", + "message": "Inkludera specialtecken", "description": "Full description for the password generator special characters checkbox" }, "specialCharactersLabel": { @@ -517,7 +526,7 @@ "description": "deprecated. Use avoidAmbiguous instead." }, "avoidAmbiguous": { - "message": "Avoid ambiguous characters", + "message": "Undvik tvetydiga tecken", "description": "Label for the avoid ambiguous characters checkbox." }, "generatorPolicyInEffect": { @@ -549,7 +558,7 @@ "message": "Authenticator secret" }, "passphrase": { - "message": "Lösenordsfras" + "message": "Lösenfras" }, "favorite": { "message": "Favorit" @@ -828,7 +837,7 @@ "message": "Bitwarden can store and fill 2-step verification codes. Select the camera icon to take a screenshot of this website's authenticator QR code, or copy and paste the key into this field." }, "learnMoreAboutAuthenticators": { - "message": "Learn more about authenticators" + "message": "Läs mer om autentiserare" }, "copyTOTP": { "message": "Kopiera autentiseringsnyckel (TOTP)" @@ -1397,7 +1406,7 @@ "message": "E-post" }, "emailDescV2": { - "message": "Enter a code sent to your email." + "message": "Ange en kod som skickar per e-post." }, "selfHostedEnvironment": { "message": "Egen-hostad miljö" @@ -1514,7 +1523,7 @@ "message": "Läs mer om risker" }, "learnMoreAboutAutofill": { - "message": "Läs mer om automatisk ifyllnad" + "message": "Läs mer om autofyll" }, "defaultAutoFillOnPageLoad": { "message": "Standardinställning för autofyll för inloggningsobjekt" @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identitet" }, + "typeSshKey": { + "message": "SSH-nyckel" + }, "newItemHeader": { "message": "Ny $TYPE$", "placeholders": { @@ -2189,7 +2201,7 @@ "message": "Unsubscribe" }, "atAnyTime": { - "message": "at any time." + "message": "när som helst." }, "byContinuingYouAgreeToThe": { "message": "By continuing, you agree to the" @@ -2328,7 +2340,7 @@ "message": "Bitwarden will not ask to save login details for these domains for all logged in accounts. You must refresh the page for changes to take effect." }, "websiteItemLabel": { - "message": "Website $number$ (URI)", + "message": "Webbplats $number$ (URI)", "placeholders": { "number": { "content": "$1", @@ -2920,7 +2932,7 @@ "message": "Vad skulle du vilja generera?" }, "passwordType": { - "message": "Typ av lösenord" + "message": "Lösenordstyp" }, "service": { "message": "Tjänst" @@ -2932,7 +2944,7 @@ "message": "Skapa ett e-postalias med en extern vidarebefordranstjänst." }, "forwarderDomainName": { - "message": "Email domain", + "message": "E-postdomän", "description": "Labels the domain name email forwarder service option" }, "forwarderDomainNameHint": { @@ -3846,7 +3858,7 @@ "message": "Godkänn inloggningsbegäran i din autentiseringsapp eller ange en engångskod." }, "passcode": { - "message": "Passcode" + "message": "Lösenkod" }, "lastPassMasterPassword": { "message": "LastPass Huvudlösenord" @@ -4037,7 +4049,7 @@ } }, "copyNoteTitle": { - "message": "Copy Note - $ITEMNAME$", + "message": "Kopiera anteckning - $ITEMNAME$", "description": "Title for a button copies a note to the clipboard.", "placeholders": { "itemname": { @@ -4067,7 +4079,7 @@ } }, "viewItemTitle": { - "message": "View item - $ITEMNAME$", + "message": "Visa objekt - $ITEMNAME$", "description": "Title for a link that opens a view for an item.", "placeholders": { "itemname": { @@ -4093,7 +4105,7 @@ "message": "Assign to collections" }, "copyEmail": { - "message": "Copy email" + "message": "Kopiera e-postadress" }, "copyPhone": { "message": "Kopiera telefon" @@ -4211,7 +4223,7 @@ "message": "Maximal filstorlek är 500 MB" }, "deleteAttachmentName": { - "message": "Delete attachment $NAME$", + "message": "Radera bilaga $NAME$", "placeholders": { "name": { "content": "$1", @@ -4244,7 +4256,7 @@ "message": "Personal details" }, "identification": { - "message": "Identification" + "message": "Identifikation" }, "contactInfo": { "message": "Contact info" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Privat nyckel" + }, + "sshPublicKey": { + "message": "Offentlig nyckel" + }, + "sshFingerprint": { + "message": "Fingeravtryck" + }, + "sshKeyAlgorithm": { + "message": "Nyckeltyp" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Försök igen" }, @@ -4660,7 +4696,7 @@ "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { - "message": "Exclamation mark", + "message": "Utropstecken", "description": "Represents the ! key in screen reader content as a readable word" }, "atSignCharacterDescriptor": { @@ -4744,7 +4780,7 @@ "description": "Represents the : key in screen reader content as a readable word" }, "semicolonCharacterDescriptor": { - "message": "Semikolon", + "message": "Semicolon", "description": "Represents the ; key in screen reader content as a readable word" }, "doubleQuoteCharacterDescriptor": { @@ -4756,11 +4792,11 @@ "description": "Represents the ' key in screen reader content as a readable word" }, "lessThanCharacterDescriptor": { - "message": "Mindre än", + "message": "Less than", "description": "Represents the < key in screen reader content as a readable word" }, "greaterThanCharacterDescriptor": { - "message": "Större än", + "message": "Greater than", "description": "Represents the > key in screen reader content as a readable word" }, "commaCharacterDescriptor": { @@ -4780,10 +4816,10 @@ "description": "Represents the / key in screen reader content as a readable word" }, "lowercaseAriaLabel": { - "message": "Lowercase" + "message": "Gemen" }, "uppercaseAriaLabel": { - "message": "Uppercase" + "message": "Versal" }, "generatedPassword": { "message": "Generated password" diff --git a/apps/browser/src/_locales/te/messages.json b/apps/browser/src/_locales/te/messages.json index b8075804229..a4668a65add 100644 --- a/apps/browser/src/_locales/te/messages.json +++ b/apps/browser/src/_locales/te/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Identity" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/th/messages.json b/apps/browser/src/_locales/th/messages.json index 9f111f9bec7..ecac21c82b8 100644 --- a/apps/browser/src/_locales/th/messages.json +++ b/apps/browser/src/_locales/th/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Copy license number" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "ข้อมูลระบุตัวตน" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "New $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/tr/messages.json b/apps/browser/src/_locales/tr/messages.json index e49ada7538e..7c67428539d 100644 --- a/apps/browser/src/_locales/tr/messages.json +++ b/apps/browser/src/_locales/tr/messages.json @@ -20,16 +20,16 @@ "message": "Hesap oluştur" }, "newToBitwarden": { - "message": "Bitwarden'da yeni misiniz?" + "message": "New to Bitwarden?" }, "logInWithPasskey": { - "message": "Geçiş anahtarıyla giriş yap" + "message": "Log in with passkey" }, "useSingleSignOn": { - "message": "Çoklu oturum açma kullan" + "message": "Use single sign-on" }, "welcomeBack": { - "message": "Tekrar hoş geldiniz" + "message": "Welcome back" }, "setAStrongPassword": { "message": "Güçlü bir parola belirleyin" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Ruhsat numarasını kopyala" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "$FIELD$ alanını kopyala", "placeholders": { @@ -168,7 +177,7 @@ "message": "Notları kopyala" }, "fill": { - "message": "Doldur", + "message": "Fill", "description": "This string is used on the vault page to indicate autofilling. Horizontal space is limited in the interface here so try and keep translations as concise as possible." }, "autoFill": { @@ -591,7 +600,7 @@ "message": "Web sitesini aç" }, "launchWebsiteName": { - "message": "$ITEMNAME$ web sitesini aç", + "message": "Launch website $ITEMNAME$", "placeholders": { "itemname": { "content": "$1", @@ -846,7 +855,7 @@ "message": "Giriş yap" }, "logInToBitwarden": { - "message": "Bitwarden'a giriş yapın" + "message": "Log in to Bitwarden" }, "restartRegistration": { "message": "Kaydı yeniden başlat" @@ -1424,7 +1433,7 @@ "message": "Sunucu URL'si" }, "selfHostBaseUrl": { - "message": "Kendi kendine barındırılan sunucu URL'si", + "message": "Self-host server URL", "description": "Label for field requesting a self-hosted integration service URL" }, "apiUrl": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Kimlik" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "Yeni $TYPE$", "placeholders": { @@ -1795,13 +1807,13 @@ "message": "Parola geçmişi" }, "generatorHistory": { - "message": "Üreteç geçmişi" + "message": "Generator history" }, "clearGeneratorHistoryTitle": { - "message": "Üreteç geçmişini temizle" + "message": "Clear generator history" }, "cleargGeneratorHistoryDescription": { - "message": "Devam ederseniz üreteç geçmişindeki tüm kayıtlar kalıcı olarak silinecektir. Devam etmek istediğinizden emin misiniz?" + "message": "If you continue, all entries will be permanently deleted from generator's history. Are you sure you want to continue?" }, "back": { "message": "Geri" @@ -1920,10 +1932,10 @@ "message": "Geçmişi temizle" }, "nothingToShow": { - "message": "Gösterilecek bir şey yok" + "message": "Nothing to show" }, "nothingGeneratedRecently": { - "message": "Yakın zamanda herhangi bir şey üretmediniz" + "message": "You haven't generated anything recently" }, "remove": { "message": "Kaldır" @@ -2512,7 +2524,7 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendPasswordDescV3": { - "message": "Alıcıların bu Send'e erişmesi için isterseniz parola ekleyebilirsiniz.", + "message": "Add an optional password for recipients to access this Send.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendNotesDesc": { @@ -2875,10 +2887,10 @@ "message": "Kullanıcı adı oluştur" }, "generateEmail": { - "message": "E-posta oluştur" + "message": "Generate email" }, "generatorBoundariesHint": { - "message": "Değer $MIN$ ile $MAX$ arasında olmalıdır", + "message": "Value must be between $MIN$ and $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -2932,11 +2944,11 @@ "message": "Harici bir yönlendirme servisiyle e-posta maskesi oluştur." }, "forwarderDomainName": { - "message": "E-posta alan adı", + "message": "Email domain", "description": "Labels the domain name email forwarder service option" }, "forwarderDomainNameHint": { - "message": "Seçtiğiniz servisin desteklediği bir alan adı seçin", + "message": "Choose a domain that is supported by the selected service", "description": "Guidance provided for email forwarding services that support multiple email domains." }, "forwarderError": { @@ -4514,7 +4526,7 @@ "message": "Successfully assigned collections" }, "nothingSelected": { - "message": "You have not selected anything." + "message": "Hiçbir şey seçmediniz." }, "movedItemsToOrg": { "message": "Selected items moved to $ORGNAME$", @@ -4526,7 +4538,7 @@ } }, "itemsMovedToOrg": { - "message": "Items moved to $ORGNAME$", + "message": "Kayıtlar $ORGNAME$ kuruluşuna taşındı", "placeholders": { "orgname": { "content": "$1", @@ -4535,7 +4547,7 @@ } }, "itemMovedToOrg": { - "message": "Item moved to $ORGNAME$", + "message": "Kayıt $ORGNAME$ kuruluşuna taşındı", "placeholders": { "orgname": { "content": "$1", @@ -4564,13 +4576,13 @@ "message": "Kayıt konumu" }, "fileSend": { - "message": "Dosya Send'i" + "message": "File Send" }, "fileSends": { "message": "Dosya Send'leri" }, "textSend": { - "message": "Metin Send'i" + "message": "Text Send" }, "textSends": { "message": "Metin Send'leri" @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Bu ayara kurumsal ilke gereksinimleri uygulandı" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Yeniden dene" }, @@ -4636,19 +4672,19 @@ "message": "Kimlik doğrulanıyor" }, "fillGeneratedPassword": { - "message": "Üretilen parolayı doldur", + "message": "Fill generated password", "description": "Heading for the password generator within the inline menu" }, "passwordRegenerated": { - "message": "Parola yeniden üretildi", + "message": "Password regenerated", "description": "Notification message for when a password has been regenerated" }, "saveLoginToBitwarden": { - "message": "Hesap Bitwarden'a kaydedilsin mi?", + "message": "Save login to Bitwarden?", "description": "Confirmation message for saving a login to Bitwarden" }, "spaceCharacterDescriptor": { - "message": "Boşluk", + "message": "Space", "description": "Represents the space key in screen reader content as a readable word" }, "tildeCharacterDescriptor": { @@ -4656,136 +4692,136 @@ "description": "Represents the ~ key in screen reader content as a readable word" }, "backtickCharacterDescriptor": { - "message": "Ters tırnak", + "message": "Backtick", "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { - "message": "Ünlem işareti", + "message": "Exclamation mark", "description": "Represents the ! key in screen reader content as a readable word" }, "atSignCharacterDescriptor": { - "message": "At işareti", + "message": "At sign", "description": "Represents the @ key in screen reader content as a readable word" }, "hashSignCharacterDescriptor": { - "message": "Kare işareti", + "message": "Hash sign", "description": "Represents the # key in screen reader content as a readable word" }, "dollarSignCharacterDescriptor": { - "message": "Dolar işareti", + "message": "Dollar sign", "description": "Represents the $ key in screen reader content as a readable word" }, "percentSignCharacterDescriptor": { - "message": "Yüzde işareti", + "message": "Percent sign", "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { - "message": "Düzeltme işareti", + "message": "Caret", "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { - "message": "Ve işareti", + "message": "Ampersand", "description": "Represents the & key in screen reader content as a readable word" }, "asteriskCharacterDescriptor": { - "message": "Yıldız işareti", + "message": "Asterisk", "description": "Represents the * key in screen reader content as a readable word" }, "parenLeftCharacterDescriptor": { - "message": "Sol parantez", + "message": "Left parenthesis", "description": "Represents the ( key in screen reader content as a readable word" }, "parenRightCharacterDescriptor": { - "message": "Sağ parantez", + "message": "Right parenthesis", "description": "Represents the ) key in screen reader content as a readable word" }, "hyphenCharacterDescriptor": { - "message": "Alt çizgi", + "message": "Underscore", "description": "Represents the _ key in screen reader content as a readable word" }, "underscoreCharacterDescriptor": { - "message": "Tire", + "message": "Hyphen", "description": "Represents the - key in screen reader content as a readable word" }, "plusCharacterDescriptor": { - "message": "Artı", + "message": "Plus", "description": "Represents the + key in screen reader content as a readable word" }, "equalsCharacterDescriptor": { - "message": "Eşittir", + "message": "Equals", "description": "Represents the = key in screen reader content as a readable word" }, "braceLeftCharacterDescriptor": { - "message": "Sol küme parantezi", + "message": "Left brace", "description": "Represents the { key in screen reader content as a readable word" }, "braceRightCharacterDescriptor": { - "message": "Sağ küme parantezi", + "message": "Right brace", "description": "Represents the } key in screen reader content as a readable word" }, "bracketLeftCharacterDescriptor": { - "message": "Sol köşeli parantez", + "message": "Left bracket", "description": "Represents the [ key in screen reader content as a readable word" }, "bracketRightCharacterDescriptor": { - "message": "Sağ köşeli parantez", + "message": "Right bracket", "description": "Represents the ] key in screen reader content as a readable word" }, "pipeCharacterDescriptor": { - "message": "Çubuk", + "message": "Pipe", "description": "Represents the | key in screen reader content as a readable word" }, "backSlashCharacterDescriptor": { - "message": "Ters eğik çizgi", + "message": "Back slash", "description": "Represents the back slash key in screen reader content as a readable word" }, "colonCharacterDescriptor": { - "message": "İki nokta", + "message": "Colon", "description": "Represents the : key in screen reader content as a readable word" }, "semicolonCharacterDescriptor": { - "message": "Noktalı virgül", + "message": "Semicolon", "description": "Represents the ; key in screen reader content as a readable word" }, "doubleQuoteCharacterDescriptor": { - "message": "Çift tırnak", + "message": "Double quote", "description": "Represents the double quote key in screen reader content as a readable word" }, "singleQuoteCharacterDescriptor": { - "message": "Tek tırnak", + "message": "Single quote", "description": "Represents the ' key in screen reader content as a readable word" }, "lessThanCharacterDescriptor": { - "message": "Küçüktür", + "message": "Less than", "description": "Represents the < key in screen reader content as a readable word" }, "greaterThanCharacterDescriptor": { - "message": "Büyüktür", + "message": "Greater than", "description": "Represents the > key in screen reader content as a readable word" }, "commaCharacterDescriptor": { - "message": "Virgül", + "message": "Comma", "description": "Represents the , key in screen reader content as a readable word" }, "periodCharacterDescriptor": { - "message": "Nokta", + "message": "Period", "description": "Represents the . key in screen reader content as a readable word" }, "questionCharacterDescriptor": { - "message": "Soru işareti", + "message": "Question mark", "description": "Represents the ? key in screen reader content as a readable word" }, "forwardSlashCharacterDescriptor": { - "message": "Bölü işareti", + "message": "Forward slash", "description": "Represents the / key in screen reader content as a readable word" }, "lowercaseAriaLabel": { - "message": "Küçük harf" + "message": "Lowercase" }, "uppercaseAriaLabel": { - "message": "Büyük harf" + "message": "Uppercase" }, "generatedPassword": { - "message": "Üretilen parola" + "message": "Generated password" } } diff --git a/apps/browser/src/_locales/uk/messages.json b/apps/browser/src/_locales/uk/messages.json index 01cdc4cab9e..f0de5d7f4d7 100644 --- a/apps/browser/src/_locales/uk/messages.json +++ b/apps/browser/src/_locales/uk/messages.json @@ -26,7 +26,7 @@ "message": "Увійти з ключем доступу" }, "useSingleSignOn": { - "message": "Використовувати єдиний вхід" + "message": "Використати єдиний вхід" }, "welcomeBack": { "message": "З поверненням" @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Копіювати номер ліцензії" }, + "copyPrivateKey": { + "message": "Копіювати закритий ключ" + }, + "copyPublicKey": { + "message": "Копіювати відкритий ключ" + }, + "copyFingerprint": { + "message": "Копіювати відбиток" + }, "copyCustomField": { "message": "Копіювати $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Посвідчення" }, + "typeSshKey": { + "message": "Ключ SSH" + }, "newItemHeader": { "message": "Новий $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "До цього налаштування застосовано вимоги політики компанії" }, + "sshPrivateKey": { + "message": "Закритий ключ" + }, + "sshPublicKey": { + "message": "Відкритий ключ" + }, + "sshFingerprint": { + "message": "Цифровий відбиток" + }, + "sshKeyAlgorithm": { + "message": "Тип ключа" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Повторити спробу" }, @@ -4656,7 +4692,7 @@ "description": "Represents the ~ key in screen reader content as a readable word" }, "backtickCharacterDescriptor": { - "message": "Зворотна лапка", + "message": "Зворотний апостроф", "description": "Represents the ` key in screen reader content as a readable word" }, "exclamationCharacterDescriptor": { diff --git a/apps/browser/src/_locales/vi/messages.json b/apps/browser/src/_locales/vi/messages.json index 61e211063de..05038eb1125 100644 --- a/apps/browser/src/_locales/vi/messages.json +++ b/apps/browser/src/_locales/vi/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "Sao chép số giấy phép" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "Copy $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "Danh tính" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "$TYPE$ mới", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/_locales/zh_CN/messages.json b/apps/browser/src/_locales/zh_CN/messages.json index e19cf428f42..ad92ca8bbae 100644 --- a/apps/browser/src/_locales/zh_CN/messages.json +++ b/apps/browser/src/_locales/zh_CN/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "复制许可证号码" }, + "copyPrivateKey": { + "message": "复制私钥" + }, + "copyPublicKey": { + "message": "复制公钥" + }, + "copyFingerprint": { + "message": "复制指纹" + }, "copyCustomField": { "message": "复制 $FIELD$", "placeholders": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "身份" }, + "typeSshKey": { + "message": "SSH 密钥" + }, "newItemHeader": { "message": "新增 $TYPE$", "placeholders": { @@ -2875,7 +2887,7 @@ "message": "生成用户名" }, "generateEmail": { - "message": "生成邮件地址" + "message": "生成电子邮件地址" }, "generatorBoundariesHint": { "message": "值必须在 $MIN$ 和 $MAX$ 之间", @@ -2932,7 +2944,7 @@ "message": "使用外部转发服务生成一个电子邮件别名。" }, "forwarderDomainName": { - "message": "邮件域名", + "message": "电子邮件域名", "description": "Labels the domain name email forwarder service option" }, "forwarderDomainNameHint": { @@ -3425,7 +3437,7 @@ "message": "清除全部" }, "plusNMore": { - "message": "+ $QUANTITY$ more", + "message": "还有 $QUANTITY$ 个", "placeholders": { "quantity": { "content": "$1", @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "企业策略要求已应用于此设置" }, + "sshPrivateKey": { + "message": "私钥" + }, + "sshPublicKey": { + "message": "公钥" + }, + "sshFingerprint": { + "message": "指纹" + }, + "sshKeyAlgorithm": { + "message": "密钥类型" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "重试" }, @@ -4680,7 +4716,7 @@ "description": "Represents the % key in screen reader content as a readable word" }, "caretCharacterDescriptor": { - "message": "脱字符", + "message": "插入符", "description": "Represents the ^ key in screen reader content as a readable word" }, "ampersandCharacterDescriptor": { @@ -4786,6 +4822,6 @@ "message": "大写" }, "generatedPassword": { - "message": "生成密码" + "message": "生成了密码" } } diff --git a/apps/browser/src/_locales/zh_TW/messages.json b/apps/browser/src/_locales/zh_TW/messages.json index 26bbbd0054f..8a4ff40e9c5 100644 --- a/apps/browser/src/_locales/zh_TW/messages.json +++ b/apps/browser/src/_locales/zh_TW/messages.json @@ -152,6 +152,15 @@ "copyLicenseNumber": { "message": "複製駕照號碼" }, + "copyPrivateKey": { + "message": "Copy private key" + }, + "copyPublicKey": { + "message": "Copy public key" + }, + "copyFingerprint": { + "message": "Copy fingerprint" + }, "copyCustomField": { "message": "複製 $FIELD$", "placeholders": { @@ -168,7 +177,7 @@ "message": "複製備註" }, "fill": { - "message": "填入", + "message": "Fill", "description": "This string is used on the vault page to indicate autofilling. Horizontal space is limited in the interface here so try and keep translations as concise as possible." }, "autoFill": { @@ -1764,6 +1773,9 @@ "typeIdentity": { "message": "身分" }, + "typeSshKey": { + "message": "SSH key" + }, "newItemHeader": { "message": "新增 $TYPE$", "placeholders": { @@ -4593,6 +4605,30 @@ "enterprisePolicyRequirementsApplied": { "message": "Enterprise policy requirements have been applied to this setting" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, "retry": { "message": "Retry" }, diff --git a/apps/browser/src/auth/popup/login-v1.component.html b/apps/browser/src/auth/popup/login-v1.component.html index 9d2b4fccad7..145a9cbc754 100644 --- a/apps/browser/src/auth/popup/login-v1.component.html +++ b/apps/browser/src/auth/popup/login-v1.component.html @@ -64,7 +64,7 @@ > -
+
diff --git a/apps/browser/src/auth/popup/login-v1.component.ts b/apps/browser/src/auth/popup/login-v1.component.ts index eee1bcc4d3f..a64f4ef384d 100644 --- a/apps/browser/src/auth/popup/login-v1.component.ts +++ b/apps/browser/src/auth/popup/login-v1.component.ts @@ -25,14 +25,11 @@ import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.serv import { ToastService } from "@bitwarden/components"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; -import { flagEnabled } from "../../platform/flags"; - @Component({ selector: "app-login", templateUrl: "login-v1.component.html", }) export class LoginComponentV1 extends BaseLoginComponent implements OnInit { - showPasswordless = false; constructor( devicesApiService: DevicesApiServiceAbstraction, appIdService: AppIdService, @@ -82,14 +79,11 @@ export class LoginComponentV1 extends BaseLoginComponent implements OnInit { await syncService.fullSync(true); }; this.successRoute = "/tabs/vault"; - this.showPasswordless = flagEnabled("showPasswordless"); } async ngOnInit(): Promise { await super.ngOnInit(); - if (this.showPasswordless) { - await this.validateEmail(); - } + await this.validateEmail(); } settings() { diff --git a/apps/browser/src/auth/popup/login-via-auth-request.component.html b/apps/browser/src/auth/popup/login-via-auth-request-v1.component.html similarity index 100% rename from apps/browser/src/auth/popup/login-via-auth-request.component.html rename to apps/browser/src/auth/popup/login-via-auth-request-v1.component.html diff --git a/apps/browser/src/auth/popup/login-via-auth-request.component.ts b/apps/browser/src/auth/popup/login-via-auth-request-v1.component.ts similarity index 91% rename from apps/browser/src/auth/popup/login-via-auth-request.component.ts rename to apps/browser/src/auth/popup/login-via-auth-request-v1.component.ts index 9dc0d7d5454..66c69d0a41a 100644 --- a/apps/browser/src/auth/popup/login-via-auth-request.component.ts +++ b/apps/browser/src/auth/popup/login-via-auth-request-v1.component.ts @@ -2,7 +2,7 @@ import { Location } from "@angular/common"; import { Component } from "@angular/core"; import { Router } from "@angular/router"; -import { LoginViaAuthRequestComponent as BaseLoginWithDeviceComponent } from "@bitwarden/angular/auth/components/login-via-auth-request.component"; +import { LoginViaAuthRequestComponentV1 as BaseLoginViaAuthRequestComponentV1 } from "@bitwarden/angular/auth/components/login-via-auth-request-v1.component"; import { AuthRequestServiceAbstraction, LoginStrategyServiceAbstraction, @@ -27,9 +27,9 @@ import { KeyService } from "@bitwarden/key-management"; @Component({ selector: "app-login-via-auth-request", - templateUrl: "login-via-auth-request.component.html", + templateUrl: "login-via-auth-request-v1.component.html", }) -export class LoginViaAuthRequestComponent extends BaseLoginWithDeviceComponent { +export class LoginViaAuthRequestComponentV1 extends BaseLoginViaAuthRequestComponentV1 { constructor( router: Router, keyService: KeyService, diff --git a/apps/browser/src/auth/popup/login/extension-login-component.service.spec.ts b/apps/browser/src/auth/popup/login/extension-login-component.service.spec.ts index a7e29171015..4d3a7763013 100644 --- a/apps/browser/src/auth/popup/login/extension-login-component.service.spec.ts +++ b/apps/browser/src/auth/popup/login/extension-login-component.service.spec.ts @@ -8,7 +8,6 @@ import { EnvironmentService } from "@bitwarden/common/platform/abstractions/envi import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; -import { flagEnabled } from "../../../platform/flags"; import { BrowserPlatformUtilsService } from "../../../platform/services/platform-utils/browser-platform-utils.service"; import { ExtensionAnonLayoutWrapperDataService } from "../extension-anon-layout-wrapper/extension-anon-layout-wrapper-data.service"; @@ -62,18 +61,6 @@ describe("ExtensionLoginComponentService", () => { expect(service).toBeTruthy(); }); - describe("isLoginViaAuthRequestSupported", () => { - it("returns true if showPasswordless flag is enabled", () => { - (flagEnabled as jest.Mock).mockReturnValue(true); - expect(service.isLoginViaAuthRequestSupported()).toBe(true); - }); - - it("returns false if showPasswordless flag is disabled", () => { - (flagEnabled as jest.Mock).mockReturnValue(false); - expect(service.isLoginViaAuthRequestSupported()).toBeFalsy(); - }); - }); - describe("showBackButton", () => { it("sets showBackButton in extensionAnonLayoutWrapperDataService", () => { service.showBackButton(true); diff --git a/apps/browser/src/auth/popup/login/extension-login-component.service.ts b/apps/browser/src/auth/popup/login/extension-login-component.service.ts index 8630030e8e2..3b643fe9c87 100644 --- a/apps/browser/src/auth/popup/login/extension-login-component.service.ts +++ b/apps/browser/src/auth/popup/login/extension-login-component.service.ts @@ -7,7 +7,6 @@ import { EnvironmentService } from "@bitwarden/common/platform/abstractions/envi import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; -import { flagEnabled } from "../../../platform/flags"; import { ExtensionAnonLayoutWrapperDataService } from "../extension-anon-layout-wrapper/extension-anon-layout-wrapper-data.service"; @Injectable() @@ -33,10 +32,6 @@ export class ExtensionLoginComponentService this.clientType = this.platformUtilsService.getClientType(); } - isLoginViaAuthRequestSupported(): boolean { - return flagEnabled("showPasswordless"); - } - showBackButton(showBackButton: boolean): void { this.extensionAnonLayoutWrapperDataService.setAnonLayoutWrapperData({ showBackButton }); } diff --git a/apps/browser/src/auth/popup/settings/account-security.component.html b/apps/browser/src/auth/popup/settings/account-security.component.html index 00e1fd17150..e0dfde7be77 100644 --- a/apps/browser/src/auth/popup/settings/account-security.component.html +++ b/apps/browser/src/auth/popup/settings/account-security.component.html @@ -65,17 +65,14 @@ {{ "vaultTimeoutAction1" | i18n }} - + + + + {{ "vaultTimeoutActionDesc" | i18n }} diff --git a/apps/browser/src/autofill/services/autofill.service.ts b/apps/browser/src/autofill/services/autofill.service.ts index e79f6f69a36..24054794b62 100644 --- a/apps/browser/src/autofill/services/autofill.service.ts +++ b/apps/browser/src/autofill/services/autofill.service.ts @@ -1597,16 +1597,6 @@ export default class AutofillService implements AutofillServiceInterface { ) { fillFields.email = f; break; - } else if ( - !fillFields.address && - AutofillService.isFieldMatch( - f[attr], - IdentityAutoFillConstants.AddressFieldNames, - IdentityAutoFillConstants.AddressFieldNameValues, - ) - ) { - fillFields.address = f; - break; } else if ( !fillFields.address1 && AutofillService.isFieldMatch(f[attr], IdentityAutoFillConstants.Address1FieldNames) @@ -1625,6 +1615,16 @@ export default class AutofillService implements AutofillServiceInterface { ) { fillFields.address3 = f; break; + } else if ( + !fillFields.address && + AutofillService.isFieldMatch( + f[attr], + IdentityAutoFillConstants.AddressFieldNames, + IdentityAutoFillConstants.AddressFieldNameValues, + ) + ) { + fillFields.address = f; + break; } else if ( !fillFields.postalCode && AutofillService.isFieldMatch(f[attr], IdentityAutoFillConstants.PostalCodeFieldNames) @@ -1818,11 +1818,6 @@ export default class AutofillService implements AutofillServiceInterface { continue; } - if (this.shouldMakeIdentityAddressFillScript(filledFields, keywordsList)) { - this.makeIdentityAddressFillScript(fillScript, filledFields, field, identity); - continue; - } - if (this.shouldMakeIdentityAddress1FillScript(filledFields, keywordsCombined)) { this.makeScriptActionWithValue(fillScript, identity.address1, field, filledFields); continue; @@ -1838,6 +1833,11 @@ export default class AutofillService implements AutofillServiceInterface { continue; } + if (this.shouldMakeIdentityAddressFillScript(filledFields, keywordsList)) { + this.makeIdentityAddressFillScript(fillScript, filledFields, field, identity); + continue; + } + if (this.shouldMakeIdentityPostalCodeFillScript(filledFields, keywordsCombined)) { this.makeScriptActionWithValue(fillScript, identity.postalCode, field, filledFields); continue; diff --git a/apps/browser/src/autofill/shared/styles/variables.scss b/apps/browser/src/autofill/shared/styles/variables.scss index 208e2bef0a3..ad3924e37a9 100644 --- a/apps/browser/src/autofill/shared/styles/variables.scss +++ b/apps/browser/src/autofill/shared/styles/variables.scss @@ -2,7 +2,7 @@ $dark-icon-themes: "theme_dark", "theme_solarizedDark", "theme_nord"; -$font-family-sans-serif: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +$font-family-sans-serif: "DM Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; $font-family-source-code-pro: "Source Code Pro", monospace; $font-size-base: 14px; $text-color: #212529; diff --git a/apps/browser/src/manifest.json b/apps/browser/src/manifest.json index 46aa3cefd70..9c2d2d610bc 100644 --- a/apps/browser/src/manifest.json +++ b/apps/browser/src/manifest.json @@ -52,19 +52,37 @@ "permissions": [ "", "*://*/*", - "tabs", - "contextMenus", - "storage", - "unlimitedStorage", + "alarms", "clipboardRead", "clipboardWrite", + "contextMenus", "idle", - "alarms", + "storage", + "tabs", + "unlimitedStorage", + "webNavigation", "webRequest", - "webRequestBlocking", - "webNavigation" + "webRequestBlocking" + ], + "__safari__permissions": [ + "", + "*://*/*", + "alarms", + "clipboardRead", + "clipboardWrite", + "contextMenus", + "idle", + "nativeMessaging", + "storage", + "tabs", + "unlimitedStorage", + "webNavigation", + "webRequest", + "webRequestBlocking" ], "optional_permissions": ["nativeMessaging", "privacy"], + "__firefox__optional_permissions": ["nativeMessaging"], + "__safari__optional_permissions": null, "content_security_policy": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'", "sandbox": { "pages": [ @@ -75,6 +93,7 @@ ], "content_security_policy": "sandbox allow-scripts; script-src 'self'" }, + "__firefox__sandbox": null, "commands": { "_execute_browser_action": { "suggested_key": { @@ -83,7 +102,14 @@ }, "description": "__MSG_commandOpenPopup__" }, - "_execute_sidebar_action": { + "__firefox___execute_sidebar_action": { + "suggested_key": { + "default": "Alt+Shift+Y", + "linux": "Alt+Shift+U" + }, + "description": "__MSG_commandOpenSidebar__" + }, + "__opera___execute_sidebar_action": { "suggested_key": { "default": "Alt+Shift+Y", "linux": "Alt+Shift+U" @@ -125,20 +151,26 @@ "overlay/list.html", "popup/fonts/*" ], - "applications": { + "__firefox__browser_specific_settings": { "gecko": { "id": "{446900e4-71c2-419f-a6a7-df9c091e268b}", "strict_min_version": "91.0" } }, - "sidebar_action": { + "__firefox__sidebar_action": { "default_title": "Bitwarden", "default_panel": "popup/index.html?uilocation=sidebar", "default_icon": "images/icon19.png", "open_at_install": false, "browser_style": false }, - "storage": { - "managed_schema": "managed_schema.json" - } + "__opera__sidebar_action": { + "default_title": "Bitwarden", + "default_panel": "popup/index.html?uilocation=sidebar", + "default_icon": "images/icon19.png", + "open_at_install": false, + "browser_style": false + }, + "storage": { "managed_schema": "managed_schema.json" }, + "__firefox__storage": null } diff --git a/apps/browser/src/manifest.v3.json b/apps/browser/src/manifest.v3.json index 8118c212fc7..fb44505ae8d 100644 --- a/apps/browser/src/manifest.v3.json +++ b/apps/browser/src/manifest.v3.json @@ -41,6 +41,9 @@ "background": { "service_worker": "background.js" }, + "__firefox__background": { + "scripts": ["background.js"] + }, "action": { "default_icon": { "19": "images/icon19.png", @@ -51,21 +54,40 @@ }, "permissions": [ "activeTab", - "tabs", - "contextMenus", - "storage", - "unlimitedStorage", + "alarms", "clipboardRead", "clipboardWrite", + "contextMenus", "idle", - "alarms", - "scripting", "offscreen", + "scripting", + "storage", + "tabs", + "unlimitedStorage", + "webNavigation", "webRequest", - "webRequestAuthProvider", - "webNavigation" + "webRequestAuthProvider" + ], + "__safari__permissions": [ + "activeTab", + "alarms", + "clipboardRead", + "clipboardWrite", + "contextMenus", + "idle", + "nativeMessaging", + "offscreen", + "scripting", + "storage", + "tabs", + "unlimitedStorage", + "webNavigation", + "webRequest", + "webRequestAuthProvider" ], "optional_permissions": ["nativeMessaging", "privacy"], + "__firefox__optional_permissions": ["nativeMessaging"], + "__safari__optional_permissions": null, "host_permissions": ["https://*/*", "http://*/*"], "content_security_policy": { "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'", @@ -79,6 +101,7 @@ "overlay/list.html" ] }, + "__firefox__sandbox": null, "commands": { "_execute_action": { "suggested_key": { @@ -87,7 +110,7 @@ }, "description": "__MSG_commandOpenPopup__" }, - "_execute_sidebar_action": { + "__firefox___execute_sidebar_action": { "suggested_key": { "default": "Alt+Shift+Y", "linux": "Alt+Shift+U" @@ -133,13 +156,13 @@ "matches": [""] } ], - "applications": { + "__firefox__browser_specific_settings": { "gecko": { "id": "{446900e4-71c2-419f-a6a7-df9c091e268b}", "strict_min_version": "91.0" } }, - "sidebar_action": { + "__firefox__sidebar_action": { "default_title": "Bitwarden", "default_panel": "popup/index.html?uilocation=sidebar", "default_icon": "images/icon19.png", @@ -147,5 +170,6 @@ }, "storage": { "managed_schema": "managed_schema.json" - } + }, + "__firefox__storage": null } diff --git a/apps/browser/src/platform/popup/layout/popup-compact-mode.service.ts b/apps/browser/src/platform/popup/layout/popup-compact-mode.service.ts new file mode 100644 index 00000000000..ffcd2321b15 --- /dev/null +++ b/apps/browser/src/platform/popup/layout/popup-compact-mode.service.ts @@ -0,0 +1,31 @@ +import { inject, Injectable } from "@angular/core"; +import { map, Observable } from "rxjs"; + +import { GlobalStateProvider, KeyDefinition, THEMING_DISK } from "@bitwarden/common/platform/state"; +import { CompactModeService } from "@bitwarden/components"; + +const COMPACT_MODE = new KeyDefinition(THEMING_DISK, "compactMode", { + deserializer: (s) => s, +}); + +/** + * Service to persist Compact Mode to state / user settings. + **/ +@Injectable({ providedIn: "root" }) +export class PopupCompactModeService implements CompactModeService { + private state = inject(GlobalStateProvider).get(COMPACT_MODE); + + enabled$: Observable = this.state.state$.pipe(map((state) => state ?? false)); + + init() { + this.enabled$.subscribe((enabled) => { + enabled + ? document.body.classList.add("tw-bit-compact") + : document.body.classList.remove("tw-bit-compact"); + }); + } + + async setEnabled(enabled: boolean) { + await this.state.update(() => enabled); + } +} diff --git a/apps/browser/src/platform/popup/layout/popup-footer.component.html b/apps/browser/src/platform/popup/layout/popup-footer.component.html index 777e0ab60da..50ad535c891 100644 --- a/apps/browser/src/platform/popup/layout/popup-footer.component.html +++ b/apps/browser/src/platform/popup/layout/popup-footer.component.html @@ -1,7 +1,7 @@
-
+
diff --git a/apps/browser/src/platform/popup/layout/popup-header.component.html b/apps/browser/src/platform/popup/layout/popup-header.component.html index fefc7154314..ac52a630900 100644 --- a/apps/browser/src/platform/popup/layout/popup-header.component.html +++ b/apps/browser/src/platform/popup/layout/popup-header.component.html @@ -1,5 +1,5 @@
-

+

{{ pageTitle }}

diff --git a/apps/browser/src/platform/popup/layout/popup-layout.stories.ts b/apps/browser/src/platform/popup/layout/popup-layout.stories.ts index 4851541576f..5b9417a6a19 100644 --- a/apps/browser/src/platform/popup/layout/popup-layout.stories.ts +++ b/apps/browser/src/platform/popup/layout/popup-layout.stories.ts @@ -39,7 +39,7 @@ class ExtensionContainerComponent {} @Component({ selector: "vault-placeholder", template: ` - + +

+ {{ supportingText }} +

+
+ {{ numberOfAppliedFilters$ | async }} +
+
+
+ +
+ +
+
diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-header/vault-header-v2.component.spec.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-header/vault-header-v2.component.spec.ts new file mode 100644 index 00000000000..38ec6056d19 --- /dev/null +++ b/apps/browser/src/vault/popup/components/vault-v2/vault-header/vault-header-v2.component.spec.ts @@ -0,0 +1,162 @@ +import { CommonModule } from "@angular/common"; +import { ComponentFixture, TestBed } from "@angular/core/testing"; +import { FormBuilder } from "@angular/forms"; +import { By } from "@angular/platform-browser"; +import { ActivatedRoute } from "@angular/router"; +import { mock } from "jest-mock-extended"; +import { BehaviorSubject, Subject } from "rxjs"; + +import { CollectionService } from "@bitwarden/admin-console/common"; +import { SearchService } from "@bitwarden/common/abstractions/search.service"; +import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; +import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { MessageSender } from "@bitwarden/common/platform/messaging"; +import { StateProvider } from "@bitwarden/common/platform/state"; +import { SyncService } from "@bitwarden/common/platform/sync"; +import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; +import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; +import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service"; +import { PasswordRepromptService } from "@bitwarden/vault"; + +import { AutofillService } from "../../../../../autofill/services/abstractions/autofill.service"; +import { VaultPopupItemsService } from "../../../../../vault/popup/services/vault-popup-items.service"; +import { + PopupListFilter, + VaultPopupListFiltersService, +} from "../../../../../vault/popup/services/vault-popup-list-filters.service"; + +import { VaultHeaderV2Component } from "./vault-header-v2.component"; + +describe("VaultHeaderV2Component", () => { + let component: VaultHeaderV2Component; + let fixture: ComponentFixture; + + const emptyForm: PopupListFilter = { + organization: null, + collection: null, + folder: null, + cipherType: null, + }; + + const numberOfAppliedFilters$ = new BehaviorSubject(0); + const state$ = new Subject(); + + // Mock state provider update + const update = jest.fn().mockResolvedValue(undefined); + + /** When it exists, returns the notification badge debug element */ + const getBadge = () => fixture.debugElement.query(By.css('[data-testid="filter-badge"]')); + + beforeEach(async () => { + update.mockClear(); + + await TestBed.configureTestingModule({ + imports: [VaultHeaderV2Component, CommonModule], + providers: [ + { + provide: CipherService, + useValue: mock({ cipherViews$: new BehaviorSubject([]) }), + }, + { provide: VaultSettingsService, useValue: mock() }, + { provide: FolderService, useValue: mock() }, + { provide: OrganizationService, useValue: mock() }, + { provide: CollectionService, useValue: mock() }, + { provide: PolicyService, useValue: mock() }, + { provide: SearchService, useValue: mock() }, + { provide: PlatformUtilsService, useValue: mock() }, + { provide: AutofillService, useValue: mock() }, + { provide: PasswordRepromptService, useValue: mock() }, + { provide: MessageSender, useValue: mock() }, + { provide: AccountService, useValue: mock() }, + { provide: LogService, useValue: mock() }, + { + provide: VaultPopupItemsService, + useValue: mock({ latestSearchText$: new BehaviorSubject("") }), + }, + { + provide: SyncService, + useValue: mock({ activeUserLastSync$: () => new Subject() }), + }, + { provide: ActivatedRoute, useValue: { queryParams: new BehaviorSubject({}) } }, + { provide: I18nService, useValue: { t: (key: string) => key } }, + { + provide: VaultPopupListFiltersService, + useValue: { + numberOfAppliedFilters$, + filters$: new BehaviorSubject(emptyForm), + filterForm: new FormBuilder().group(emptyForm), + filterVisibilityState$: state$, + updateFilterVisibility: update, + }, + }, + { + provide: StateProvider, + useValue: { getGlobal: () => ({ state$, update }) }, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(VaultHeaderV2Component); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it("does not show filter badge when no filters are selected", () => { + state$.next(false); + numberOfAppliedFilters$.next(0); + fixture.detectChanges(); + + expect(getBadge()).toBeNull(); + }); + + it("does not show filter badge when disclosure is open", () => { + state$.next(true); + numberOfAppliedFilters$.next(1); + fixture.detectChanges(); + + expect(getBadge()).toBeNull(); + }); + + it("shows the notification badge when there are populated filters and the disclosure is closed", async () => { + state$.next(false); + numberOfAppliedFilters$.next(1); + fixture.detectChanges(); + + expect(getBadge()).not.toBeNull(); + }); + + it("displays the number of filters populated", () => { + numberOfAppliedFilters$.next(1); + state$.next(false); + fixture.detectChanges(); + + expect(getBadge().nativeElement.textContent.trim()).toBe("1"); + + numberOfAppliedFilters$.next(2); + + fixture.detectChanges(); + + expect(getBadge().nativeElement.textContent.trim()).toBe("2"); + + numberOfAppliedFilters$.next(4); + + fixture.detectChanges(); + + expect(getBadge().nativeElement.textContent.trim()).toBe("4"); + }); + + it("defaults the initial state to true", (done) => { + // The initial value of the `state$` variable above is undefined + component["initialDisclosureVisibility$"].subscribe((initialVisibility) => { + expect(initialVisibility).toBeTrue(); + done(); + }); + + // Update the state to null + state$.next(null); + }); +}); diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-header/vault-header-v2.component.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-header/vault-header-v2.component.ts new file mode 100644 index 00000000000..c7183f6fa28 --- /dev/null +++ b/apps/browser/src/vault/popup/components/vault-v2/vault-header/vault-header-v2.component.ts @@ -0,0 +1,70 @@ +import { CommonModule } from "@angular/common"; +import { Component, inject, NgZone, ViewChild } from "@angular/core"; +import { combineLatest, map, take } from "rxjs"; + +import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { DisclosureTriggerForDirective, IconButtonModule } from "@bitwarden/components"; + +import { DisclosureComponent } from "../../../../../../../../libs/components/src/disclosure/disclosure.component"; +import { runInsideAngular } from "../../../../../platform/browser/run-inside-angular.operator"; +import { VaultPopupListFiltersService } from "../../../../../vault/popup/services/vault-popup-list-filters.service"; +import { VaultListFiltersComponent } from "../vault-list-filters/vault-list-filters.component"; +import { VaultV2SearchComponent } from "../vault-search/vault-v2-search.component"; + +@Component({ + selector: "app-vault-header-v2", + templateUrl: "vault-header-v2.component.html", + standalone: true, + imports: [ + VaultV2SearchComponent, + VaultListFiltersComponent, + DisclosureComponent, + IconButtonModule, + DisclosureTriggerForDirective, + CommonModule, + JslibModule, + ], +}) +export class VaultHeaderV2Component { + @ViewChild(DisclosureComponent) disclosure: DisclosureComponent; + + /** Emits the visibility status of the disclosure component. */ + protected isDisclosureShown$ = this.vaultPopupListFiltersService.filterVisibilityState$.pipe( + runInsideAngular(inject(NgZone)), // Browser state updates can happen outside of `ngZone` + map((v) => v ?? true), + ); + + // Only use the first value to avoid an infinite loop from two-way binding + protected initialDisclosureVisibility$ = this.isDisclosureShown$.pipe(take(1)); + + protected numberOfAppliedFilters$ = this.vaultPopupListFiltersService.numberOfAppliedFilters$; + + /** Emits true when the number of filters badge should be applied. */ + protected showBadge$ = combineLatest([ + this.numberOfAppliedFilters$, + this.isDisclosureShown$, + ]).pipe(map(([numberOfFilters, disclosureShown]) => numberOfFilters !== 0 && !disclosureShown)); + + protected buttonSupportingText$ = this.numberOfAppliedFilters$.pipe( + map((numberOfFilters) => { + if (numberOfFilters === 0) { + return null; + } + if (numberOfFilters === 1) { + return this.i18nService.t("filterApplied"); + } + + return this.i18nService.t("filterAppliedPlural", numberOfFilters); + }), + ); + + constructor( + private vaultPopupListFiltersService: VaultPopupListFiltersService, + private i18nService: I18nService, + ) {} + + async toggleFilters(isShown: boolean) { + await this.vaultPopupListFiltersService.updateFilterVisibility(isShown); + } +} diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-list-filters/vault-list-filters.component.html b/apps/browser/src/vault/popup/components/vault-v2/vault-list-filters/vault-list-filters.component.html index d9c4fbeee15..56f35c41f6d 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/vault-list-filters/vault-list-filters.component.html +++ b/apps/browser/src/vault/popup/components/vault-v2/vault-list-filters/vault-list-filters.component.html @@ -1,4 +1,4 @@ -
+
@@ -30,7 +30,7 @@ (click)="onViewCipher(cipher)" (dblclick)="launchCipher(cipher)" [appA11yTitle]="'viewItemTitle' | i18n: cipher.name" - class="{{ ItemHeightClass }}" + class="{{ itemHeightClass }}" > {{ cipher.name }} diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts index 653255ac78d..fa2c8a440e0 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.ts @@ -1,7 +1,8 @@ import { ScrollingModule } from "@angular/cdk/scrolling"; import { CommonModule } from "@angular/common"; -import { booleanAttribute, Component, EventEmitter, Input, Output } from "@angular/core"; +import { booleanAttribute, Component, EventEmitter, inject, Input, Output } from "@angular/core"; import { Router, RouterLink } from "@angular/router"; +import { map } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; @@ -9,9 +10,8 @@ import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.servi import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { BadgeModule, - BitItemHeight, - BitItemHeightClass, ButtonModule, + CompactModeService, IconButtonModule, ItemModule, SectionComponent, @@ -49,8 +49,25 @@ import { ItemMoreOptionsComponent } from "../item-more-options/item-more-options standalone: true, }) export class VaultListItemsContainerComponent { - protected ItemHeightClass = BitItemHeightClass; - protected ItemHeight = BitItemHeight; + private compactModeService = inject(CompactModeService); + + /** + * The class used to set the height of a bit item's inner content. + */ + protected readonly itemHeightClass = `tw-h-[52px]`; + + /** + * The height of a bit item in pixels. Includes any margin, padding, or border. Used by the virtual scroll + * to estimate how many items can be displayed at once and how large the virtual container should be. + * Needs to be updated if the item height or spacing changes. + * + * Default: 52px + 1px border + 6px bottom margin = 59px + * + * Compact mode: 52px + 1px border = 53px + */ + protected readonly itemHeight$ = this.compactModeService.enabled$.pipe( + map((enabled) => (enabled ? 53 : 59)), + ); /** * Timeout used to add a small delay when selecting a cipher to allow for double click to launch diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-search/vault-v2-search.component.html b/apps/browser/src/vault/popup/components/vault-v2/vault-search/vault-v2-search.component.html index 898d93da32c..7cf154c0ee8 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/vault-search/vault-v2-search.component.html +++ b/apps/browser/src/vault/popup/components/vault-v2/vault-search/vault-v2-search.component.html @@ -1,9 +1,7 @@ -
- - -
+ + diff --git a/apps/browser/src/vault/popup/components/vault/vault-v2.component.html b/apps/browser/src/vault/popup/components/vault/vault-v2.component.html index 04b6bed469b..4798ddf4dfb 100644 --- a/apps/browser/src/vault/popup/components/vault/vault-v2.component.html +++ b/apps/browser/src/vault/popup/components/vault/vault-v2.component.html @@ -23,14 +23,12 @@
-
- - -
+ +
-
+
{ policyAppliesToActiveUser$: jest.fn(() => policyAppliesToActiveUser$), }; + const state$ = new BehaviorSubject(false); + const update = jest.fn().mockResolvedValue(undefined); + beforeEach(() => { memberOrganizations$.next([]); decryptedCollections$.next([]); @@ -83,6 +87,10 @@ describe("VaultPopupListFiltersService", () => { provide: PolicyService, useValue: policyService, }, + { + provide: StateProvider, + useValue: { getGlobal: () => ({ state$, update }) }, + }, { provide: FormBuilder, useClass: FormBuilder }, ], }); @@ -102,6 +110,20 @@ describe("VaultPopupListFiltersService", () => { }); }); + describe("numberOfAppliedFilters$", () => { + it("updates as the form value changes", (done) => { + service.numberOfAppliedFilters$.subscribe((number) => { + expect(number).toBe(2); + done(); + }); + + service.filterForm.patchValue({ + organization: { id: "1234" } as Organization, + folder: { id: "folder11" } as FolderView, + }); + }); + }); + describe("organizations$", () => { it('does not add "myVault" to the list of organizations when there are no organizations', (done) => { memberOrganizations$.next([]); @@ -451,4 +473,24 @@ describe("VaultPopupListFiltersService", () => { }); }); }); + + describe("filterVisibilityState", () => { + it("exposes stored state through filterVisibilityState$", (done) => { + state$.next(true); + + service.filterVisibilityState$.subscribe((filterVisibility) => { + expect(filterVisibility).toBeTrue(); + done(); + }); + }); + + it("updates stored filter state", async () => { + await service.updateFilterVisibility(false); + + expect(update).toHaveBeenCalledOnce(); + // Get callback passed to `update` + const updateCallback = update.mock.calls[0][0]; + expect(updateCallback()).toBe(false); + }); + }); }); diff --git a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts index 590807cff60..32eaeb27d4e 100644 --- a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts +++ b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts @@ -6,6 +6,7 @@ import { distinctUntilChanged, map, Observable, + shareReplay, startWith, switchMap, tap, @@ -20,6 +21,11 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga import { ProductTierType } from "@bitwarden/common/billing/enums"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; +import { + KeyDefinition, + StateProvider, + VAULT_SETTINGS_DISK, +} from "@bitwarden/common/platform/state"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; import { CipherType } from "@bitwarden/common/vault/enums"; @@ -29,6 +35,10 @@ import { FolderView } from "@bitwarden/common/vault/models/view/folder.view"; import { ServiceUtils } from "@bitwarden/common/vault/service-utils"; import { ChipSelectOption } from "@bitwarden/components"; +const FILTER_VISIBILITY_KEY = new KeyDefinition(VAULT_SETTINGS_DISK, "filterVisibility", { + deserializer: (obj) => obj, +}); + /** All available cipher filters */ export type PopupListFilter = { organization: Organization | null; @@ -66,6 +76,15 @@ export class VaultPopupListFiltersService { startWith(INITIAL_FILTERS), ) as Observable; + /** Emits the number of applied filters. */ + numberOfAppliedFilters$ = this.filters$.pipe( + map((filters) => Object.values(filters).filter((filter) => Boolean(filter)).length), + shareReplay({ refCount: true, bufferSize: 1 }), + ); + + /** Stored state for the visibility of the filters. */ + private filterVisibilityState = this.stateProvider.getGlobal(FILTER_VISIBILITY_KEY); + /** * Static list of ciphers views used in synchronous context */ @@ -89,12 +108,16 @@ export class VaultPopupListFiltersService { private collectionService: CollectionService, private formBuilder: FormBuilder, private policyService: PolicyService, + private stateProvider: StateProvider, ) { this.filterForm.controls.organization.valueChanges .pipe(takeUntilDestroyed()) .subscribe(this.validateOrganizationChange.bind(this)); } + /** Stored state for the visibility of the filters. */ + filterVisibilityState$ = this.filterVisibilityState.state$; + /** * Observable whose value is a function that filters an array of `CipherView` objects based on the current filters */ @@ -332,6 +355,11 @@ export class VaultPopupListFiltersService { ), ); + /** Updates the stored state for filter visibility. */ + async updateFilterVisibility(isVisible: boolean): Promise { + await this.filterVisibilityState.update(() => isVisible); + } + /** * Converts the given item into the `ChipSelectOption` structure */ diff --git a/apps/browser/src/vault/popup/settings/appearance-v2.component.html b/apps/browser/src/vault/popup/settings/appearance-v2.component.html index b267e1c5cb2..466cffa216a 100644 --- a/apps/browser/src/vault/popup/settings/appearance-v2.component.html +++ b/apps/browser/src/vault/popup/settings/appearance-v2.component.html @@ -18,6 +18,14 @@ + + + {{ "compactMode" | i18n }} + {{ "beta" | i18n }} + + {{ "showNumberOfAutofillSuggestions" | i18n }} diff --git a/apps/browser/src/vault/popup/settings/appearance-v2.component.spec.ts b/apps/browser/src/vault/popup/settings/appearance-v2.component.spec.ts index bbd210b65a3..b2da3245b5c 100644 --- a/apps/browser/src/vault/popup/settings/appearance-v2.component.spec.ts +++ b/apps/browser/src/vault/popup/settings/appearance-v2.component.spec.ts @@ -13,6 +13,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { ThemeType } from "@bitwarden/common/platform/enums"; import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service"; +import { PopupCompactModeService } from "../../../platform/popup/layout/popup-compact-mode.service"; import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component"; import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.component"; @@ -43,10 +44,12 @@ describe("AppearanceV2Component", () => { const enableBadgeCounter$ = new BehaviorSubject(true); const selectedTheme$ = new BehaviorSubject(ThemeType.Nord); const enableRoutingAnimation$ = new BehaviorSubject(true); + const enableCompactMode$ = new BehaviorSubject(false); const setSelectedTheme = jest.fn().mockResolvedValue(undefined); const setShowFavicons = jest.fn().mockResolvedValue(undefined); const setEnableBadgeCounter = jest.fn().mockResolvedValue(undefined); const setEnableRoutingAnimation = jest.fn().mockResolvedValue(undefined); + const setEnableCompactMode = jest.fn().mockResolvedValue(undefined); beforeEach(async () => { setSelectedTheme.mockClear(); @@ -71,6 +74,10 @@ describe("AppearanceV2Component", () => { provide: BadgeSettingsServiceAbstraction, useValue: { enableBadgeCounter$, setEnableBadgeCounter }, }, + { + provide: PopupCompactModeService, + useValue: { enabled$: enableCompactMode$, setEnabled: setEnableCompactMode }, + }, ], }) .overrideComponent(AppearanceV2Component, { @@ -94,6 +101,7 @@ describe("AppearanceV2Component", () => { enableFavicon: true, enableBadgeCounter: true, theme: ThemeType.Nord, + enableCompactMode: false, }); }); diff --git a/apps/browser/src/vault/popup/settings/appearance-v2.component.ts b/apps/browser/src/vault/popup/settings/appearance-v2.component.ts index 9d600ec83e8..c20bc48bfea 100644 --- a/apps/browser/src/vault/popup/settings/appearance-v2.component.ts +++ b/apps/browser/src/vault/popup/settings/appearance-v2.component.ts @@ -1,5 +1,5 @@ import { CommonModule } from "@angular/common"; -import { Component, DestroyRef, OnInit } from "@angular/core"; +import { Component, DestroyRef, inject, OnInit } from "@angular/core"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { FormBuilder, ReactiveFormsModule } from "@angular/forms"; import { firstValueFrom } from "rxjs"; @@ -12,12 +12,13 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { ThemeType } from "@bitwarden/common/platform/enums"; import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service"; -import { CheckboxModule } from "@bitwarden/components"; +import { BadgeModule, CheckboxModule } from "@bitwarden/components"; import { CardComponent } from "../../../../../../libs/components/src/card/card.component"; import { FormFieldModule } from "../../../../../../libs/components/src/form-field/form-field.module"; import { SelectModule } from "../../../../../../libs/components/src/select/select.module"; import { PopOutComponent } from "../../../platform/popup/components/pop-out.component"; +import { PopupCompactModeService } from "../../../platform/popup/layout/popup-compact-mode.service"; import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component"; import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.component"; @@ -35,14 +36,18 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co SelectModule, ReactiveFormsModule, CheckboxModule, + BadgeModule, ], }) export class AppearanceV2Component implements OnInit { + private compactModeService = inject(PopupCompactModeService); + appearanceForm = this.formBuilder.group({ enableFavicon: false, enableBadgeCounter: true, theme: ThemeType.System, enableAnimations: true, + enableCompactMode: false, }); /** To avoid flashes of inaccurate values, only show the form after the entire form is populated. */ @@ -75,6 +80,7 @@ export class AppearanceV2Component implements OnInit { const enableAnimations = await firstValueFrom( this.animationControlService.enableRoutingAnimation$, ); + const enableCompactMode = await firstValueFrom(this.compactModeService.enabled$); // Set initial values for the form this.appearanceForm.setValue({ @@ -82,6 +88,7 @@ export class AppearanceV2Component implements OnInit { enableBadgeCounter, theme, enableAnimations, + enableCompactMode, }); this.formLoading = false; @@ -109,6 +116,12 @@ export class AppearanceV2Component implements OnInit { .subscribe((enableBadgeCounter) => { void this.updateAnimations(enableBadgeCounter); }); + + this.appearanceForm.controls.enableCompactMode.valueChanges + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((enableCompactMode) => { + void this.updateCompactMode(enableCompactMode); + }); } async updateFavicon(enableFavicon: boolean) { @@ -127,4 +140,8 @@ export class AppearanceV2Component implements OnInit { async updateAnimations(enableAnimations: boolean) { await this.animationControlService.setEnableRoutingAnimation(enableAnimations); } + + async updateCompactMode(enableCompactMode: boolean) { + await this.compactModeService.setEnabled(enableCompactMode); + } } diff --git a/apps/browser/webpack.config.js b/apps/browser/webpack.config.js index 5436e51011a..6ba74d7df43 100644 --- a/apps/browser/webpack.config.js +++ b/apps/browser/webpack.config.js @@ -7,58 +7,14 @@ const { AngularWebpackPlugin } = require("@ngtools/webpack"); const TerserPlugin = require("terser-webpack-plugin"); const { TsconfigPathsPlugin } = require("tsconfig-paths-webpack-plugin"); const configurator = require("./config/config"); +const manifest = require("./webpack/manifest"); if (process.env.NODE_ENV == null) { process.env.NODE_ENV = "development"; } const ENV = (process.env.ENV = process.env.NODE_ENV); const manifestVersion = process.env.MANIFEST_VERSION == 3 ? 3 : 2; -const browser = process.env.BROWSER; - -function modifyManifestV3(buffer) { - if (manifestVersion === 2 || !browser) { - return buffer; - } - - const manifest = JSON.parse(buffer.toString()); - - if (browser === "chrome") { - // Remove unsupported properties - delete manifest.applications; - delete manifest.sidebar_action; - delete manifest.commands._execute_sidebar_action; - - return JSON.stringify(manifest, null, 2); - } - - // Update the background script reference to be an event page - const backgroundScript = manifest.background.service_worker; - delete manifest.background.service_worker; - manifest.background.scripts = [backgroundScript]; - - // Remove unsupported properties - delete manifest.content_security_policy.sandbox; - delete manifest.sandbox; - delete manifest.applications; - - manifest.permissions = manifest.permissions.filter((permission) => permission !== "offscreen"); - - if (browser === "safari") { - delete manifest.sidebar_action; - delete manifest.commands._execute_sidebar_action; - delete manifest.optional_permissions; - manifest.permissions.push("nativeMessaging"); - } - - if (browser === "firefox") { - delete manifest.storage; - manifest.optional_permissions = manifest.optional_permissions.filter( - (permission) => permission !== "privacy", - ); - } - - return JSON.stringify(manifest, null, 2); -} +const browser = process.env.BROWSER ?? "chrome"; console.log(`Building Manifest Version ${manifestVersion} app`); @@ -142,9 +98,10 @@ const requiredPlugins = [ const plugins = [ new HtmlWebpackPlugin({ - template: "./src/popup/index.html", + template: "./src/popup/index.ejs", filename: "popup/index.html", chunks: ["popup/polyfills", "popup/vendor-angular", "popup/vendor", "popup/main"], + browser: browser, }), new HtmlWebpackPlugin({ template: "./src/autofill/notification/bar.html", @@ -178,13 +135,11 @@ const plugins = [ }), new CopyWebpackPlugin({ patterns: [ - manifestVersion == 3 - ? { - from: "./src/manifest.v3.json", - to: "manifest.json", - transform: (content) => modifyManifestV3(content), - } - : "./src/manifest.json", + { + from: manifestVersion == 3 ? "./src/manifest.v3.json" : "./src/manifest.json", + to: "manifest.json", + transform: manifest.transform(browser), + }, { from: "./src/managed_schema.json", to: "managed_schema.json" }, { from: "./src/_locales", to: "_locales" }, { from: "./src/images", to: "images" }, diff --git a/apps/browser/webpack/manifest.js b/apps/browser/webpack/manifest.js new file mode 100644 index 00000000000..cf8296707bb --- /dev/null +++ b/apps/browser/webpack/manifest.js @@ -0,0 +1,72 @@ +/** + * Transform the manifest template into a browser specific manifest. + * + * We support a simple browser prefix to the manifest keys. Example: + * + * ```json + * { + * "name": "Default name", + * "__chrome__name": "Chrome override" + * } + * ``` + * + * Will result in the following manifest: + * + * ```json + * { + * "name": "Chrome override" + * } + * ``` + * + * for Chrome. + */ +function transform(browser) { + return (buffer) => { + let manifest = JSON.parse(buffer.toString()); + + manifest = transformPrefixes(manifest, browser); + + return JSON.stringify(manifest, null, 2); + }; +} + +const browsers = ["chrome", "edge", "firefox", "opera", "safari"]; + +/** + * Flatten the browser prefixes in the manifest. + * + * - Removes unrelated browser prefixes. + * - A null value deletes the non prefixed key. + */ +function transformPrefixes(manifest, browser) { + const prefix = `__${browser}__`; + + function transformObject(obj) { + return Object.keys(obj).reduce((acc, key) => { + // Determine if we need to recurse into the object. + const nested = typeof obj[key] === "object" && obj[key] !== null && !Array.isArray(obj[key]); + + if (key.startsWith(prefix)) { + const newKey = key.slice(prefix.length); + + // Null values are used to remove keys. + if (obj[key] == null) { + delete acc[newKey]; + return acc; + } + + acc[newKey] = nested ? transformObject(obj[key]) : obj[key]; + } else if (!browsers.some((b) => key.startsWith(`__${b}__`))) { + acc[key] = nested ? transformObject(obj[key]) : obj[key]; + } + + return acc; + }, {}); + } + + return transformObject(manifest); +} + +module.exports = { + transform, +}; diff --git a/apps/cli/package.json b/apps/cli/package.json index 8ddb5daccd2..e48507373f5 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -80,7 +80,7 @@ "papaparse": "5.4.1", "proper-lockfile": "4.1.2", "rxjs": "7.8.1", - "tldts": "6.1.60", + "tldts": "6.1.61", "zxcvbn": "4.4.2" } } diff --git a/apps/cli/src/program.ts b/apps/cli/src/program.ts index 7e0f75de4e0..ca2adb85755 100644 --- a/apps/cli/src/program.ts +++ b/apps/cli/src/program.ts @@ -1,5 +1,6 @@ import * as chalk from "chalk"; import { program, Command, OptionValues } from "commander"; +import { firstValueFrom } from "rxjs"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; @@ -102,6 +103,14 @@ export class Program extends BaseProgram { writeLn("", true); }); + program + .command("sdk-version") + .description("Print the SDK version.") + .action(async () => { + const sdkVersion = await firstValueFrom(this.serviceContainer.sdkService.version$); + writeLn(sdkVersion, true); + }); + program .command("login [email] [password]") .description("Log into a user account.") diff --git a/apps/desktop/desktop_native/core/Cargo.toml b/apps/desktop/desktop_native/core/Cargo.toml index 4f6fdb47fdf..039cd19c6a4 100644 --- a/apps/desktop/desktop_native/core/Cargo.toml +++ b/apps/desktop/desktop_native/core/Cargo.toml @@ -27,24 +27,24 @@ anyhow = "=1.0.93" arboard = { version = "=3.4.1", default-features = false, features = [ "wayland-data-control", ] } -async-stream = "0.3.5" +async-stream = "=0.3.5" base64 = "=0.22.1" -byteorder = "1.5.0" +byteorder = "=1.5.0" cbc = { version = "=0.1.2", features = ["alloc"] } -homedir = "0.3.3" +homedir = "=0.3.3" libc = "=0.2.162" -pin-project = "1.1.5" +pin-project = "=1.1.5" dirs = "=5.0.1" futures = "=0.3.31" interprocess = { version = "=2.2.1", features = ["tokio"] } log = "=0.4.22" rand = "=0.8.5" retry = "=2.0.0" -russh-cryptovec = "0.7.3" +russh-cryptovec = "=0.7.3" scopeguard = "=1.2.0" sha2 = "=0.10.8" -ssh-encoding = "0.2.0" -ssh-key = { version = "0.6.6", default-features = false, features = [ +ssh-encoding = "=0.2.0" +ssh-key = { version = "=0.6.6", default-features = false, features = [ "encryption", "ed25519", "rsa", @@ -53,7 +53,7 @@ ssh-key = { version = "0.6.6", default-features = false, features = [ bitwarden-russh = { git = "https://github.com/bitwarden/bitwarden-russh.git", branch = "km/pm-10098/clean-russh-implementation" } tokio = { version = "=1.40.0", features = ["io-util", "sync", "macros", "net"] } tokio-stream = { version = "=0.1.15", features = ["net"] } -tokio-util = "=0.7.12" +tokio-util = { version = "0.7.11", features = ["codec"] } thiserror = "=1.0.69" typenum = "=1.17.0" rand_chacha = "=0.3.1" diff --git a/apps/desktop/desktop_native/core/src/ipc/client.rs b/apps/desktop/desktop_native/core/src/ipc/client.rs index 7eff8a10974..6c4ca0a6053 100644 --- a/apps/desktop/desktop_native/core/src/ipc/client.rs +++ b/apps/desktop/desktop_native/core/src/ipc/client.rs @@ -1,13 +1,11 @@ use std::path::PathBuf; +use futures::{SinkExt, StreamExt}; use interprocess::local_socket::{ tokio::{prelude::*, Stream}, GenericFilePath, ToFsName, }; use log::{error, info}; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; - -use crate::ipc::NATIVE_MESSAGING_BUFFER_SIZE; pub async fn connect( path: PathBuf, @@ -17,7 +15,9 @@ pub async fn connect( info!("Attempting to connect to {}", path.display()); let name = path.as_os_str().to_fs_name::()?; - let mut conn = Stream::connect(name).await?; + let conn = Stream::connect(name).await?; + + let mut conn = crate::ipc::internal_ipc_codec(conn); info!("Connected to {}", path.display()); @@ -26,8 +26,6 @@ pub async fn connect( // As it's only two, we hardcode the JSON values to avoid pulling in a JSON library. send.send("{\"command\":\"connected\"}".to_owned()).await?; - let mut buffer = vec![0; NATIVE_MESSAGING_BUFFER_SIZE]; - // Listen to IPC messages loop { tokio::select! { @@ -35,7 +33,7 @@ pub async fn connect( msg = recv.recv() => { match msg { Some(msg) => { - conn.write_all(msg.as_bytes()).await?; + conn.send(msg.into()).await?; } None => { info!("Client channel closed"); @@ -45,18 +43,18 @@ pub async fn connect( }, // Forward messages from the IPC server - res = conn.read(&mut buffer[..]) => { + res = conn.next() => { match res { - Err(e) => { + Some(Err(e)) => { error!("Error reading from IPC server: {e}"); break; } - Ok(0) => { + None => { info!("Connection closed"); break; } - Ok(n) => { - let message = String::from_utf8_lossy(&buffer[..n]).to_string(); + Some(Ok(bytes)) => { + let message = String::from_utf8_lossy(&bytes).to_string(); send.send(message).await?; } } diff --git a/apps/desktop/desktop_native/core/src/ipc/mod.rs b/apps/desktop/desktop_native/core/src/ipc/mod.rs index d406b6aa137..6873f0cfb80 100644 --- a/apps/desktop/desktop_native/core/src/ipc/mod.rs +++ b/apps/desktop/desktop_native/core/src/ipc/mod.rs @@ -1,3 +1,6 @@ +use tokio::io::{AsyncRead, AsyncWrite}; +use tokio_util::codec::{Framed, LengthDelimitedCodec}; + pub mod client; pub mod server; @@ -16,6 +19,16 @@ pub const NATIVE_MESSAGING_BUFFER_SIZE: usize = 1024 * 1024; /// but ideally the messages should be processed as quickly as possible. pub const MESSAGE_CHANNEL_BUFFER: usize = 32; +/// This is the codec used for communication through the UNIX socket / Windows named pipe. +/// It's an internal implementation detail, but we want to make sure that both the client +/// and the server use the same one. +fn internal_ipc_codec(inner: T) -> Framed { + LengthDelimitedCodec::builder() + .max_frame_length(NATIVE_MESSAGING_BUFFER_SIZE) + .native_endian() + .new_framed(inner) +} + /// Resolve the path to the IPC socket. pub fn path(name: &str) -> std::path::PathBuf { #[cfg(target_os = "windows")] diff --git a/apps/desktop/desktop_native/core/src/ipc/server.rs b/apps/desktop/desktop_native/core/src/ipc/server.rs index 053b4322203..a1c77e7ab16 100644 --- a/apps/desktop/desktop_native/core/src/ipc/server.rs +++ b/apps/desktop/desktop_native/core/src/ipc/server.rs @@ -1,17 +1,20 @@ -use std::{error::Error, path::Path, vec}; +use std::{ + error::Error, + path::{Path, PathBuf}, +}; -use futures::TryFutureExt; +use futures::{SinkExt, StreamExt, TryFutureExt}; use anyhow::Result; use interprocess::local_socket::{tokio::prelude::*, GenericFilePath, ListenerOptions}; use log::{error, info}; use tokio::{ - io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}, + io::{AsyncRead, AsyncWrite}, sync::{broadcast, mpsc}, }; use tokio_util::sync::CancellationToken; -use super::{MESSAGE_CHANNEL_BUFFER, NATIVE_MESSAGING_BUFFER_SIZE}; +use super::MESSAGE_CHANNEL_BUFFER; #[derive(Debug)] pub struct Message { @@ -29,6 +32,7 @@ pub enum MessageType { } pub struct Server { + pub path: PathBuf, cancel_token: CancellationToken, server_to_clients_send: broadcast::Sender, } @@ -66,6 +70,7 @@ impl Server { // Create the server and start listening for incoming connections // in a separate task to avoid blocking the current task let server = Server { + path: path.to_owned(), cancel_token: cancel_token.clone(), server_to_clients_send, }; @@ -152,7 +157,7 @@ async fn listen_incoming( } async fn handle_connection( - mut client_stream: impl AsyncRead + AsyncWrite + Unpin, + client_stream: impl AsyncRead + AsyncWrite + Unpin, client_to_server_send: mpsc::Sender, mut server_to_clients_recv: broadcast::Receiver, cancel_token: CancellationToken, @@ -166,7 +171,7 @@ async fn handle_connection( }) .await?; - let mut buf = vec![0u8; NATIVE_MESSAGING_BUFFER_SIZE]; + let mut client_stream = crate::ipc::internal_ipc_codec(client_stream); loop { tokio::select! { @@ -179,7 +184,7 @@ async fn handle_connection( msg = server_to_clients_recv.recv() => { match msg { Ok(msg) => { - client_stream.write_all(msg.as_bytes()).await?; + client_stream.send(msg.into()).await?; }, Err(e) => { info!("Error reading message: {}", e); @@ -191,9 +196,9 @@ async fn handle_connection( // Forwards messages from the IPC clients to the server // Note that we also send connect and disconnect events so that // the server can keep track of multiple clients - result = client_stream.read(&mut buf) => { + result = client_stream.next() => { match result { - Err(e) => { + Some(Err(e)) => { info!("Error reading from client {client_id}: {e}"); client_to_server_send.send(Message { @@ -203,7 +208,7 @@ async fn handle_connection( }).await?; break; }, - Ok(0) => { + None => { info!("Client {client_id} disconnected."); client_to_server_send.send(Message { @@ -213,8 +218,8 @@ async fn handle_connection( }).await?; break; }, - Ok(size) => { - let msg = std::str::from_utf8(&buf[..size])?; + Some(Ok(bytes)) => { + let msg = std::str::from_utf8(&bytes)?; client_to_server_send.send(Message { client_id, diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/importer.rs b/apps/desktop/desktop_native/core/src/ssh_agent/importer.rs index 3d643e764c7..c9f66107cc8 100644 --- a/apps/desktop/desktop_native/core/src/ssh_agent/importer.rs +++ b/apps/desktop/desktop_native/core/src/ssh_agent/importer.rs @@ -392,4 +392,33 @@ mod tests { let result = import_key(private_key.to_string(), "".to_string()).unwrap(); assert_eq!(result.status, SshKeyImportStatus::UnsupportedKeyType); } + + // Putty-exported keys should be supported, but are not due to a parser incompatibility. + // Should this test start failing, please change it to expect a correct key, and + // make sure the documentation support for putty-exported keys this is updated. + // https://bitwarden.atlassian.net/browse/PM-14989 + #[test] + fn import_key_ed25519_putty() { + let private_key = include_str!("./test_keys/ed25519_putty_openssh_unencrypted"); + let result = import_key(private_key.to_string(), "".to_string()).unwrap(); + assert_eq!(result.status, SshKeyImportStatus::ParsingError); + } + + // Putty-exported keys should be supported, but are not due to a parser incompatibility. + // Should this test start failing, please change it to expect a correct key, and + // make sure the documentation support for putty-exported keys this is updated. + // https://bitwarden.atlassian.net/browse/PM-14989 + #[test] + fn import_key_rsa_openssh_putty() { + let private_key = include_str!("./test_keys/rsa_putty_openssh_unencrypted"); + let result = import_key(private_key.to_string(), "".to_string()).unwrap(); + assert_eq!(result.status, SshKeyImportStatus::ParsingError); + } + + #[test] + fn import_key_rsa_pkcs8_putty() { + let private_key = include_str!("./test_keys/rsa_putty_pkcs1_unencrypted"); + let result = import_key(private_key.to_string(), "".to_string()).unwrap(); + assert_eq!(result.status, SshKeyImportStatus::UnsupportedKeyType); + } } diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/mod.rs b/apps/desktop/desktop_native/core/src/ssh_agent/mod.rs index ad0ac837afc..8cbcd97d91e 100644 --- a/apps/desktop/desktop_native/core/src/ssh_agent/mod.rs +++ b/apps/desktop/desktop_native/core/src/ssh_agent/mod.rs @@ -20,18 +20,16 @@ pub struct BitwardenDesktopAgent { show_ui_request_tx: tokio::sync::mpsc::Sender<(u32, String)>, get_ui_response_rx: Arc>>, request_id: Arc>, -} - -impl BitwardenDesktopAgent { - async fn get_request_id(&self) -> u32 { - let mut request_id = self.request_id.lock().await; - *request_id += 1; - *request_id - } + is_running: Arc>, } impl ssh_agent::Agent for BitwardenDesktopAgent { async fn confirm(&self, ssh_key: Key) -> bool { + if !*self.is_running.lock().await { + println!("[BitwardenDesktopAgent] Agent is not running, but tried to call confirm"); + return false; + } + let request_id = self.get_request_id().await; let mut rx_channel = self.get_ui_response_rx.lock().await.resubscribe(); @@ -50,6 +48,12 @@ impl ssh_agent::Agent for BitwardenDesktopAgent { impl BitwardenDesktopAgent { pub fn stop(&self) { + if !*self.is_running.blocking_lock() { + println!("[BitwardenDesktopAgent] Tried to stop agent while it is not running"); + return; + } + + *self.is_running.blocking_lock() = false; self.cancellation_token.cancel(); self.keystore .0 @@ -62,6 +66,12 @@ impl BitwardenDesktopAgent { &mut self, new_keys: Vec<(String, String, String)>, ) -> Result<(), anyhow::Error> { + if !*self.is_running.blocking_lock() { + return Err(anyhow::anyhow!( + "[BitwardenDesktopAgent] Tried to set keys while agent is not running" + )); + } + let keystore = &mut self.keystore; keystore.0.write().expect("RwLock is not poisoned").clear(); @@ -91,6 +101,12 @@ impl BitwardenDesktopAgent { } pub fn lock(&mut self) -> Result<(), anyhow::Error> { + if !*self.is_running.blocking_lock() { + return Err(anyhow::anyhow!( + "[BitwardenDesktopAgent] Tried to lock agent, but it is not running" + )); + } + let keystore = &mut self.keystore; keystore .0 @@ -102,6 +118,21 @@ impl BitwardenDesktopAgent { }); Ok(()) } + + async fn get_request_id(&self) -> u32 { + if !*self.is_running.lock().await { + println!("[BitwardenDesktopAgent] Agent is not running, but tried to get request id"); + return 0; + } + + let mut request_id = self.request_id.lock().await; + *request_id += 1; + *request_id + } + + pub fn is_running(self) -> bool { + return self.is_running.blocking_lock().clone(); + } } fn parse_key_safe(pem: &str) -> Result { diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/named_pipe_listener_stream.rs b/apps/desktop/desktop_native/core/src/ssh_agent/named_pipe_listener_stream.rs index 69399ae7530..49c3aa80612 100644 --- a/apps/desktop/desktop_native/core/src/ssh_agent/named_pipe_listener_stream.rs +++ b/apps/desktop/desktop_native/core/src/ssh_agent/named_pipe_listener_stream.rs @@ -1,7 +1,5 @@ use std::{ - io, - pin::Pin, - task::{Context, Poll}, + io, pin::Pin, sync::Arc, task::{Context, Poll} }; use futures::Stream; @@ -19,14 +17,23 @@ pub struct NamedPipeServerStream { } impl NamedPipeServerStream { - pub fn new(cancellation_token: CancellationToken) -> Self { + pub fn new(cancellation_token: CancellationToken, is_running: Arc>) -> Self { let (tx, rx) = tokio::sync::mpsc::channel(16); tokio::spawn(async move { println!( "[SSH Agent Native Module] Creating named pipe server on {}", PIPE_NAME ); - let mut listener = ServerOptions::new().create(PIPE_NAME).unwrap(); + let mut listener = match ServerOptions::new().create(PIPE_NAME) { + Ok(pipe) => pipe, + Err(err) => { + println!("[SSH Agent Native Module] Encountered an error creating the first pipe. The system's openssh service must likely be disabled"); + println!("[SSH Agent Natvie Module] error: {}", err); + cancellation_token.cancel(); + *is_running.lock().await = false; + return; + } + }; loop { println!("[SSH Agent Native Module] Waiting for connection"); select! { @@ -37,7 +44,16 @@ impl NamedPipeServerStream { _ = listener.connect() => { println!("[SSH Agent Native Module] Incoming connection"); tx.send(listener).await.unwrap(); - listener = ServerOptions::new().create(PIPE_NAME).unwrap(); + + listener = match ServerOptions::new().create(PIPE_NAME) { + Ok(pipe) => pipe, + Err(err) => { + println!("[SSH Agent Native Module] Encountered an error creating a new pipe {}", err); + cancellation_token.cancel(); + *is_running.lock().await = false; + return; + } + }; } } } diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/test_keys/ed25519_putty_openssh_unencrypted b/apps/desktop/desktop_native/core/src/ssh_agent/test_keys/ed25519_putty_openssh_unencrypted new file mode 100644 index 00000000000..aa9c01b8dbe --- /dev/null +++ b/apps/desktop/desktop_native/core/src/ssh_agent/test_keys/ed25519_putty_openssh_unencrypted @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtz +c2gtZWQyNTUxOQAAACDp0/9zFBCyZs5BFqXCJN5i1DTanzPGHpUeo2LP8FmQ9wAA +AKCyIXPqsiFz6gAAAAtzc2gtZWQyNTUxOQAAACDp0/9zFBCyZs5BFqXCJN5i1DTa +nzPGHpUeo2LP8FmQ9wAAAEDQioomhjmD+sh2nsxfQLJ5YYGASNUAlUZHe9Jx0p47 +H+nT/3MUELJmzkEWpcIk3mLUNNqfM8YelR6jYs/wWZD3AAAAEmVkZHNhLWtleS0y +MDI0MTExOAECAwQFBgcICQoL +-----END OPENSSH PRIVATE KEY----- diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/test_keys/rsa_putty_openssh_unencrypted b/apps/desktop/desktop_native/core/src/ssh_agent/test_keys/rsa_putty_openssh_unencrypted new file mode 100644 index 00000000000..bbb8edfe362 --- /dev/null +++ b/apps/desktop/desktop_native/core/src/ssh_agent/test_keys/rsa_putty_openssh_unencrypted @@ -0,0 +1,30 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdz +c2gtcnNhAAAAAwEAAQAAAQEAootgTLcKjSgPLS2+RT3ZElhktL1CwIyM/+3IqEq0 +0fl/rRHBT8otklV3Ld7DOR50HVZSoV0u9qs0WOdxcjEJlJACDClmxZmFr0BQ/E2y +V5xzuMZj3Mj+fL26jTmM3ueRHZ0tU5ubSFvINIFyDGG70F7VgkpBA8zsviineMSU +t1iIPi/6feL6h7QAFUk6JdQJpPTs9Nb2+DAQ9lMS2614cxLXkfUIXA4NvHMfZGdU +dq1mBJIAWZ4PPJ6naUcu0lVYjuVEAOE4UoHxr6YlW4yyAF/I1YXBFpcHG7P0egvg +neTPli5Wzum0XDsOPivqr6z2E5k7nzyGXUaP5MjRfDDVLwAAA9D6lTpR+pU6UQAA +AAdzc2gtcnNhAAABAQCii2BMtwqNKA8tLb5FPdkSWGS0vULAjIz/7cioSrTR+X+t +EcFPyi2SVXct3sM5HnQdVlKhXS72qzRY53FyMQmUkAIMKWbFmYWvQFD8TbJXnHO4 +xmPcyP58vbqNOYze55EdnS1Tm5tIW8g0gXIMYbvQXtWCSkEDzOy+KKd4xJS3WIg+ +L/p94vqHtAAVSTol1Amk9Oz01vb4MBD2UxLbrXhzEteR9QhcDg28cx9kZ1R2rWYE +kgBZng88nqdpRy7SVViO5UQA4ThSgfGvpiVbjLIAX8jVhcEWlwcbs/R6C+Cd5M+W +LlbO6bRcOw4+K+qvrPYTmTufPIZdRo/kyNF8MNUvAAAAAwEAAQAAAQB6YVPVDq9s +DfA3RMyQF3vbOyA/kIu0q13xx1cflnfD7AT8CnUwnPloxt5fc+wqkko8WGUIRz93 +yvkzwrYAkvkymKZh/734IpmrlFIlVF5lZk8enIhNkCtDQho2AFGW9mSlFlUtMOhe +N3RqS9fRiLg+r1gzq7J9qQnKNpO48tFBpLkIqr8nZOVhEn8IASrQYBUoocClNrv6 +Pdl8ni5jqnZ/0K0nq4+41Ag1VMI4LUcRCucid8ci1HKdOmGXkvClbzuFMWv3UC0k +qDgzg/gOIgj75I7B34FYVx47UGZ6jmC7iRkHd6RiCHYkmsDSjRQHR6eRbtLPdl9w +TlG2NrwkbSlhAAAAgQCapfJLqew9aK8PKfe3FwiC9sb0itCAXPXHhD+pQ6Tl9UMZ +hmnG2g9qbowCprz3/kyix+nWL/Kx7eKAZYH2MBz6cxfqs2A+BSuxvX/hsnvF96BP +u1I47rGrd0NC78DTY2NDO4Ccirx6uN+AoCl4cC+KC00Kykww6TTEBrQsdQTk5QAA +AIEA7JwbIIMwDiQUt3EY/VU0SYvg67aOiyOYEWplSWCGdT58jnfS1H95kGVw+qXR +eSQ0VNv6LBz7XDRpfQlNXDNJRnDZuHBbk+T9ZwnynRLWuzK7VqZBPJoNoyLFSMW2 +DBhLVKIrg0MsBAnRBMDUlVDlzs2LoNLEra3dj8Zb9vMdlbEAAACBAK/db27GfXXg +OikZkIqWiFgBArtj0T4iFc7BLUJUeFtl0RP9LLjfvaxSdA1cmVYzzkgmuc2iZLF0 +37zuPkDrfYVRiw8rSihT3D+WDt3/Tt013WCuxVQOQSW+Qtw6yZpM92DKncbvYsUy +5DNklW1+TYxyn2ltM7SaZjmF8UeoTnDfAAAAEHJzYS1rZXktMjAyNDExMTgBAgME +BQYHCAkK +-----END OPENSSH PRIVATE KEY----- diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/test_keys/rsa_putty_pkcs1_unencrypted b/apps/desktop/desktop_native/core/src/ssh_agent/test_keys/rsa_putty_pkcs1_unencrypted new file mode 100644 index 00000000000..e5bedfbdd24 --- /dev/null +++ b/apps/desktop/desktop_native/core/src/ssh_agent/test_keys/rsa_putty_pkcs1_unencrypted @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAootgTLcKjSgPLS2+RT3ZElhktL1CwIyM/+3IqEq00fl/rRHB +T8otklV3Ld7DOR50HVZSoV0u9qs0WOdxcjEJlJACDClmxZmFr0BQ/E2yV5xzuMZj +3Mj+fL26jTmM3ueRHZ0tU5ubSFvINIFyDGG70F7VgkpBA8zsviineMSUt1iIPi/6 +feL6h7QAFUk6JdQJpPTs9Nb2+DAQ9lMS2614cxLXkfUIXA4NvHMfZGdUdq1mBJIA +WZ4PPJ6naUcu0lVYjuVEAOE4UoHxr6YlW4yyAF/I1YXBFpcHG7P0egvgneTPli5W +zum0XDsOPivqr6z2E5k7nzyGXUaP5MjRfDDVLwIDAQABAoIBAHphU9UOr2wN8DdE +zJAXe9s7ID+Qi7SrXfHHVx+Wd8PsBPwKdTCc+WjG3l9z7CqSSjxYZQhHP3fK+TPC +tgCS+TKYpmH/vfgimauUUiVUXmVmTx6ciE2QK0NCGjYAUZb2ZKUWVS0w6F43dGpL +19GIuD6vWDOrsn2pCco2k7jy0UGkuQiqvydk5WESfwgBKtBgFSihwKU2u/o92Xye +LmOqdn/QrSerj7jUCDVUwjgtRxEK5yJ3xyLUcp06YZeS8KVvO4Uxa/dQLSSoODOD ++A4iCPvkjsHfgVhXHjtQZnqOYLuJGQd3pGIIdiSawNKNFAdHp5Fu0s92X3BOUbY2 +vCRtKWECgYEA7JwbIIMwDiQUt3EY/VU0SYvg67aOiyOYEWplSWCGdT58jnfS1H95 +kGVw+qXReSQ0VNv6LBz7XDRpfQlNXDNJRnDZuHBbk+T9ZwnynRLWuzK7VqZBPJoN +oyLFSMW2DBhLVKIrg0MsBAnRBMDUlVDlzs2LoNLEra3dj8Zb9vMdlbECgYEAr91v +bsZ9deA6KRmQipaIWAECu2PRPiIVzsEtQlR4W2XRE/0suN+9rFJ0DVyZVjPOSCa5 +zaJksXTfvO4+QOt9hVGLDytKKFPcP5YO3f9O3TXdYK7FVA5BJb5C3DrJmkz3YMqd +xu9ixTLkM2SVbX5NjHKfaW0ztJpmOYXxR6hOcN8CgYASLZAb+Fg5zeXVjhfYZrJk +sB1wno7m+64UMHNlpsfNvCY/n88Pyldhk5mReCnWv8RRfLEEsJlTJSexloReAAay +JbtkYyV2AFLDls0P6kGbEjO4XX+Hk2JW1TYI+D+bQEaRUwA6zm9URBjN3661Zgix +0bLXgTnhCgmKoTexik4MkQKBgEZR14XGzlG81+SpOTeBG4F83ffJ4NfkTy395jf4 +iKubGa/Rcvl1VWU7DvZsyU9Dpb8J5Q+JWJPwdKoZ5UCWKPmO8nidSai4Z3/xY352 +4LTpHdzT5UlH7drGqftfck9FaUEFo3LxM2BAiijWlj1S3HVFO+Ku7JbRigCEQ0bw +0HSnAoGBAJql8kup7D1orw8p97cXCIL2xvSK0IBc9ceEP6lDpOX1QxmGacbaD2pu +jAKmvPf+TKLH6dYv8rHt4oBlgfYwHPpzF+qzYD4FK7G9f+Gye8X3oE+7Ujjusat3 +Q0LvwNNjY0M7gJyKvHq434CgKXhwL4oLTQrKTDDpNMQGtCx1BOTl +-----END RSA PRIVATE KEY----- diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/unix.rs b/apps/desktop/desktop_native/core/src/ssh_agent/unix.rs index c1a39506660..27f27998ce9 100644 --- a/apps/desktop/desktop_native/core/src/ssh_agent/unix.rs +++ b/apps/desktop/desktop_native/core/src/ssh_agent/unix.rs @@ -1,5 +1,7 @@ use std::{ collections::HashMap, + fs, + os::unix::fs::PermissionsExt, sync::{Arc, RwLock}, }; @@ -15,14 +17,13 @@ impl BitwardenDesktopAgent { auth_request_tx: tokio::sync::mpsc::Sender<(u32, String)>, auth_response_rx: Arc>>, ) -> Result { - use std::path::PathBuf; - let agent = BitwardenDesktopAgent { keystore: ssh_agent::KeyStore(Arc::new(RwLock::new(HashMap::new()))), cancellation_token: CancellationToken::new(), show_ui_request_tx: auth_request_tx, get_ui_response_rx: auth_response_rx, request_id: Arc::new(tokio::sync::Mutex::new(0)), + is_running: Arc::new(tokio::sync::Mutex::new(false)), }; let cloned_agent_state = agent.clone(); tokio::spawn(async move { @@ -33,7 +34,12 @@ impl BitwardenDesktopAgent { let ssh_agent_directory = match my_home() { Ok(Some(home)) => home, - _ => PathBuf::from("/tmp/"), + _ => { + println!( + "[SSH Agent Native Module] Could not determine home directory" + ); + return; + } }; ssh_agent_directory .join(".bitwarden-ssh-agent.sock") @@ -48,19 +54,38 @@ impl BitwardenDesktopAgent { ssh_path ); let sockname = std::path::Path::new(&ssh_path); - let _ = std::fs::remove_file(sockname); + if let Err(e) = std::fs::remove_file(sockname) { + println!( + "[SSH Agent Native Module] Could not remove existing socket file: {}", + e + ); + return; + } + match UnixListener::bind(sockname) { Ok(listener) => { + // Only the current user should be able to access the socket + if let Err(e) = fs::set_permissions(sockname, fs::Permissions::from_mode(0o600)) + { + println!( + "[SSH Agent Native Module] Could not set socket permissions: {}", + e + ); + return; + } + let wrapper = tokio_stream::wrappers::UnixListenerStream::new(listener); let cloned_keystore = cloned_agent_state.keystore.clone(); let cloned_cancellation_token = cloned_agent_state.cancellation_token.clone(); + *cloned_agent_state.is_running.lock().await = true; let _ = ssh_agent::serve( wrapper, - cloned_agent_state, + cloned_agent_state.clone(), cloned_keystore, cloned_cancellation_token, ) .await; + *cloned_agent_state.is_running.lock().await = false; println!("[SSH Agent Native Module] SSH Agent server exited"); } Err(e) => { diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/windows.rs b/apps/desktop/desktop_native/core/src/ssh_agent/windows.rs index fd6d9dacb9f..9ccae7af675 100644 --- a/apps/desktop/desktop_native/core/src/ssh_agent/windows.rs +++ b/apps/desktop/desktop_native/core/src/ssh_agent/windows.rs @@ -21,13 +21,16 @@ impl BitwardenDesktopAgent { get_ui_response_rx: auth_response_rx, cancellation_token: CancellationToken::new(), request_id: Arc::new(tokio::sync::Mutex::new(0)), + is_running: Arc::new(tokio::sync::Mutex::new(true)), }; let stream = named_pipe_listener_stream::NamedPipeServerStream::new( agent_state.cancellation_token.clone(), + agent_state.is_running.clone(), ); let cloned_agent_state = agent_state.clone(); tokio::spawn(async move { + *cloned_agent_state.is_running.lock().await = true; let _ = ssh_agent::serve( stream, cloned_agent_state.clone(), @@ -35,6 +38,7 @@ impl BitwardenDesktopAgent { cloned_agent_state.cancellation_token.clone(), ) .await; + *cloned_agent_state.is_running.lock().await = false; }); Ok(agent_state) } diff --git a/apps/desktop/desktop_native/napi/index.d.ts b/apps/desktop/desktop_native/napi/index.d.ts index 6d1a7b8abbc..62e448d4800 100644 --- a/apps/desktop/desktop_native/napi/index.d.ts +++ b/apps/desktop/desktop_native/napi/index.d.ts @@ -71,6 +71,7 @@ export declare namespace sshagent { } export function serve(callback: (err: Error | null, arg: string) => any): Promise export function stop(agentState: SshAgentState): void + export function isRunning(agentState: SshAgentState): boolean export function setKeys(agentState: SshAgentState, newKeys: Array): void export function lock(agentState: SshAgentState): void export function importKey(encodedKey: string, password: string): SshKeyImportResult @@ -109,6 +110,8 @@ export declare namespace ipc { * @param callback This function will be called whenever a message is received from a client. */ static listen(name: string, callback: (error: null | Error, message: IpcMessage) => void): Promise + /** Return the path to the IPC server. */ + getPath(): string /** Stop the IPC server. */ stop(): void /** diff --git a/apps/desktop/desktop_native/napi/src/lib.rs b/apps/desktop/desktop_native/napi/src/lib.rs index 60a8326a8e5..8e156eb3efa 100644 --- a/apps/desktop/desktop_native/napi/src/lib.rs +++ b/apps/desktop/desktop_native/napi/src/lib.rs @@ -307,6 +307,12 @@ pub mod sshagent { Ok(()) } + #[napi] + pub fn is_running(agent_state: &mut SshAgentState) -> bool { + let bitwarden_agent_state = agent_state.state.clone(); + bitwarden_agent_state.is_running() + } + #[napi] pub fn set_keys( agent_state: &mut SshAgentState, @@ -487,6 +493,12 @@ pub mod ipc { Ok(IpcServer { server }) } + /// Return the path to the IPC server. + #[napi] + pub fn get_path(&self) -> String { + self.server.path.to_string_lossy().to_string() + } + /// Stop the IPC server. #[napi] pub fn stop(&self) -> napi::Result<()> { diff --git a/apps/desktop/desktop_native/proxy/Cargo.toml b/apps/desktop/desktop_native/proxy/Cargo.toml index a1cefca7a3f..0208b2f0334 100644 --- a/apps/desktop/desktop_native/proxy/Cargo.toml +++ b/apps/desktop/desktop_native/proxy/Cargo.toml @@ -9,11 +9,11 @@ publish = false [dependencies] anyhow = "=1.0.93" desktop_core = { path = "../core", default-features = false } -futures = "0.3.30" -log = "0.4.22" -simplelog = "0.12.2" -tokio = { version = "1.38.0", features = ["io-std", "io-util", "macros", "rt"] } -tokio-util = { version = "0.7.11", features = ["codec"] } +futures = "=0.3.31" +log = "=0.4.22" +simplelog = "=0.12.2" +tokio = { version = "=1.40.0", features = ["io-std", "io-util", "macros", "rt"] } +tokio-util = { version = "=0.7.12", features = ["codec"] } [target.'cfg(target_os = "macos")'.dependencies] -embed_plist = "1.2.2" +embed_plist = "=1.2.2" diff --git a/apps/desktop/desktop_native/proxy/src/main.rs b/apps/desktop/desktop_native/proxy/src/main.rs index 7d3b4ecfca7..bfd84b206d7 100644 --- a/apps/desktop/desktop_native/proxy/src/main.rs +++ b/apps/desktop/desktop_native/proxy/src/main.rs @@ -8,14 +8,14 @@ use tokio_util::codec::LengthDelimitedCodec; #[cfg(target_os = "macos")] embed_plist::embed_info_plist!("../../../resources/info.desktop_proxy.plist"); -fn init_logging(log_path: &Path, level: log::LevelFilter) { +fn init_logging(log_path: &Path, console_level: LevelFilter, file_level: LevelFilter) { use simplelog::{ColorChoice, CombinedLogger, Config, SharedLogger, TermLogger, TerminalMode}; let config = Config::default(); let mut loggers: Vec> = Vec::new(); loggers.push(TermLogger::new( - level, + console_level, config.clone(), TerminalMode::Stderr, ColorChoice::Auto, @@ -23,7 +23,7 @@ fn init_logging(log_path: &Path, level: log::LevelFilter) { match std::fs::File::create(log_path) { Ok(file) => { - loggers.push(simplelog::WriteLogger::new(level, config, file)); + loggers.push(simplelog::WriteLogger::new(file_level, config, file)); } Err(e) => { eprintln!("Can't create file: {}", e); @@ -57,7 +57,12 @@ async fn main() { path }; - init_logging(&log_path, LevelFilter::Info); + let level = std::env::var("PROXY_LOG_LEVEL") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(LevelFilter::Info); + + init_logging(&log_path, level, LevelFilter::Info); info!("Starting Bitwarden IPC Proxy."); diff --git a/apps/desktop/package.json b/apps/desktop/package.json index ae19e5f93c9..be285f2cc18 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": "2024.11.0", + "version": "2024.11.1", "keywords": [ "bitwarden", "password", diff --git a/apps/desktop/src/app/app-routing.module.ts b/apps/desktop/src/app/app-routing.module.ts index f5023cb4249..c1e4fd18692 100644 --- a/apps/desktop/src/app/app-routing.module.ts +++ b/apps/desktop/src/app/app-routing.module.ts @@ -18,10 +18,12 @@ import { extensionRefreshRedirect } from "@bitwarden/angular/utils/extension-ref import { AnonLayoutWrapperComponent, AnonLayoutWrapperData, + DevicesIcon, LoginComponent, LoginSecondaryContentComponent, LockIcon, LockV2Component, + LoginViaAuthRequestComponent, PasswordHintComponent, RegistrationFinishComponent, RegistrationLockAltIcon, @@ -42,7 +44,7 @@ import { HintComponent } from "../auth/hint.component"; import { LockComponent } from "../auth/lock.component"; import { LoginDecryptionOptionsComponent } from "../auth/login/login-decryption-options/login-decryption-options.component"; import { LoginComponentV1 } from "../auth/login/login-v1.component"; -import { LoginViaAuthRequestComponent } from "../auth/login/login-via-auth-request.component"; +import { LoginViaAuthRequestComponentV1 } from "../auth/login/login-via-auth-request-v1.component"; import { RegisterComponent } from "../auth/register.component"; import { RemovePasswordComponent } from "../auth/remove-password.component"; import { SetPasswordComponent } from "../auth/set-password.component"; @@ -75,14 +77,6 @@ const routes: Routes = [ canActivate: [lockGuard()], canMatch: [extensionRefreshRedirect("/lockV2")], }, - { - path: "login-with-device", - component: LoginViaAuthRequestComponent, - }, - { - path: "admin-approval-requested", - component: LoginViaAuthRequestComponent, - }, ...twofactorRefactorSwap( TwoFactorComponent, AnonLayoutWrapperComponent, @@ -130,6 +124,53 @@ const routes: Routes = [ component: RemovePasswordComponent, canActivate: [authGuard], }, + ...unauthUiRefreshSwap( + LoginViaAuthRequestComponentV1, + AnonLayoutWrapperComponent, + { + path: "login-with-device", + }, + { + path: "login-with-device", + data: { + pageIcon: DevicesIcon, + pageTitle: { + key: "loginInitiated", + }, + pageSubtitle: { + key: "aNotificationWasSentToYourDevice", + }, + } satisfies AnonLayoutWrapperData, + children: [ + { path: "", component: LoginViaAuthRequestComponent }, + { + path: "", + component: EnvironmentSelectorComponent, + outlet: "environment-selector", + }, + ], + }, + ), + ...unauthUiRefreshSwap( + LoginViaAuthRequestComponentV1, + AnonLayoutWrapperComponent, + { + path: "admin-approval-requested", + }, + { + path: "admin-approval-requested", + data: { + pageIcon: DevicesIcon, + pageTitle: { + key: "adminApprovalRequested", + }, + pageSubtitle: { + key: "adminApprovalRequestSentToAdmins", + }, + } satisfies AnonLayoutWrapperData, + children: [{ path: "", component: LoginViaAuthRequestComponent }], + }, + ), ...unauthUiRefreshSwap( HintComponent, AnonLayoutWrapperComponent, diff --git a/apps/desktop/src/app/components/avatar.component.ts b/apps/desktop/src/app/components/avatar.component.ts index 10007340636..59005352d13 100644 --- a/apps/desktop/src/app/components/avatar.component.ts +++ b/apps/desktop/src/app/components/avatar.component.ts @@ -111,7 +111,7 @@ export class AvatarComponent implements OnChanges, OnInit { textTag.setAttribute("fill", Utils.pickTextColorBasedOnBgColor(color, 135, true)); textTag.setAttribute( "font-family", - '"Open Sans","Helvetica Neue",Helvetica,Arial,' + + '"DM Sans","Helvetica Neue",Helvetica,Arial,' + 'sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"', ); textTag.textContent = character; diff --git a/apps/desktop/src/app/services/init.service.ts b/apps/desktop/src/app/services/init.service.ts index 627a9b62228..0068a03d685 100644 --- a/apps/desktop/src/app/services/init.service.ts +++ b/apps/desktop/src/app/services/init.service.ts @@ -22,6 +22,7 @@ import { KeyService as KeyServiceAbstraction } from "@bitwarden/key-management"; import { I18nRendererService } from "../../platform/services/i18n.renderer.service"; import { SshAgentService } from "../../platform/services/ssh-agent.service"; +import { VersionService } from "../../platform/services/version.service"; import { NativeMessagingService } from "../../services/native-messaging.service"; @Injectable() @@ -42,6 +43,7 @@ export class InitService { private encryptService: EncryptService, private userAutoUnlockKeyService: UserAutoUnlockKeyService, private accountService: AccountService, + private versionService: VersionService, private sshAgentService: SshAgentService, @Inject(DOCUMENT) private document: Document, ) {} @@ -76,6 +78,8 @@ export class InitService { htmlEl.classList.add("os_" + this.platformUtilsService.getDeviceString()); this.themingService.applyThemeChangesTo(this.document); + this.versionService.init(); + const containerService = new ContainerService(this.keyService, this.encryptService); containerService.attachToGlobal(this.win); }; diff --git a/apps/desktop/src/auth/login/desktop-login-component.service.ts b/apps/desktop/src/auth/login/desktop-login-component.service.ts index c9b01c5624f..ef0faaee1c6 100644 --- a/apps/desktop/src/auth/login/desktop-login-component.service.ts +++ b/apps/desktop/src/auth/login/desktop-login-component.service.ts @@ -71,8 +71,4 @@ export class DesktopLoginComponentService }); } } - - isLoginViaAuthRequestSupported(): boolean { - return true; - } } diff --git a/apps/desktop/src/auth/login/login-via-auth-request.component.html b/apps/desktop/src/auth/login/login-via-auth-request-v1.component.html similarity index 100% rename from apps/desktop/src/auth/login/login-via-auth-request.component.html rename to apps/desktop/src/auth/login/login-via-auth-request-v1.component.html diff --git a/apps/desktop/src/auth/login/login-via-auth-request.component.ts b/apps/desktop/src/auth/login/login-via-auth-request-v1.component.ts similarity index 93% rename from apps/desktop/src/auth/login/login-via-auth-request.component.ts rename to apps/desktop/src/auth/login/login-via-auth-request-v1.component.ts index 8459dc7441e..b59e0778371 100644 --- a/apps/desktop/src/auth/login/login-via-auth-request.component.ts +++ b/apps/desktop/src/auth/login/login-via-auth-request-v1.component.ts @@ -2,7 +2,7 @@ import { Location } from "@angular/common"; import { Component, ViewChild, ViewContainerRef } from "@angular/core"; import { Router } from "@angular/router"; -import { LoginViaAuthRequestComponent as BaseLoginWithDeviceComponent } from "@bitwarden/angular/auth/components/login-via-auth-request.component"; +import { LoginViaAuthRequestComponentV1 as BaseLoginViaAuthRequestComponentV1 } from "@bitwarden/angular/auth/components/login-via-auth-request-v1.component"; import { ModalService } from "@bitwarden/angular/services/modal.service"; import { AuthRequestServiceAbstraction, @@ -30,9 +30,9 @@ import { EnvironmentComponent } from "../environment.component"; @Component({ selector: "app-login-via-auth-request", - templateUrl: "login-via-auth-request.component.html", + templateUrl: "login-via-auth-request-v1.component.html", }) -export class LoginViaAuthRequestComponent extends BaseLoginWithDeviceComponent { +export class LoginViaAuthRequestComponentV1 extends BaseLoginViaAuthRequestComponentV1 { @ViewChild("environment", { read: ViewContainerRef, static: true }) environmentModal: ViewContainerRef; showingModal = false; diff --git a/apps/desktop/src/auth/login/login.module.ts b/apps/desktop/src/auth/login/login.module.ts index c0b330bf2dd..20c0bc97c6c 100644 --- a/apps/desktop/src/auth/login/login.module.ts +++ b/apps/desktop/src/auth/login/login.module.ts @@ -7,16 +7,16 @@ import { SharedModule } from "../../app/shared/shared.module"; import { LoginDecryptionOptionsComponent } from "./login-decryption-options/login-decryption-options.component"; import { LoginComponentV1 } from "./login-v1.component"; -import { LoginViaAuthRequestComponent } from "./login-via-auth-request.component"; +import { LoginViaAuthRequestComponentV1 } from "./login-via-auth-request-v1.component"; @NgModule({ imports: [SharedModule, RouterModule], declarations: [ LoginComponentV1, - LoginViaAuthRequestComponent, + LoginViaAuthRequestComponentV1, EnvironmentSelectorComponent, LoginDecryptionOptionsComponent, ], - exports: [LoginComponentV1, LoginViaAuthRequestComponent], + exports: [LoginComponentV1, LoginViaAuthRequestComponentV1], }) export class LoginModule {} diff --git a/apps/desktop/src/images/loading.svg b/apps/desktop/src/images/loading.svg index 70763105168..3f2033303db 100644 --- a/apps/desktop/src/images/loading.svg +++ b/apps/desktop/src/images/loading.svg @@ -1,5 +1,5 @@  - Loading... diff --git a/apps/desktop/src/locales/af/messages.json b/apps/desktop/src/locales/af/messages.json index 3b7701c5d67..550820726f6 100644 --- a/apps/desktop/src/locales/af/messages.json +++ b/apps/desktop/src/locales/af/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Beveiligde Nota" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Vouers" }, @@ -177,6 +180,48 @@ "address": { "message": "Adres" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premie word vereis" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopieer Wagwoord" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/ar/messages.json b/apps/desktop/src/locales/ar/messages.json index 6c4b52797b7..7732bf86847 100644 --- a/apps/desktop/src/locales/ar/messages.json +++ b/apps/desktop/src/locales/ar/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "ملاحظة آمنة" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "مجلدات" }, @@ -177,6 +180,48 @@ "address": { "message": "العنوان" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "مطلوب اشتراك بريميوم" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "نسخ كلمة المرور" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/az/messages.json b/apps/desktop/src/locales/az/messages.json index 5a5bac19bc1..fd2af247be1 100644 --- a/apps/desktop/src/locales/az/messages.json +++ b/apps/desktop/src/locales/az/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Güvənli qeyd" }, + "typeSshKey": { + "message": "SSH açarı" + }, "folders": { "message": "Qovluqlar" }, @@ -177,6 +180,48 @@ "address": { "message": "Ünvan" }, + "sshPrivateKey": { + "message": "Private açar" + }, + "sshPublicKey": { + "message": "Public açar" + }, + "sshFingerprint": { + "message": "Barmaq izi" + }, + "sshKeyAlgorithm": { + "message": "Açar növü" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "Yeni bir SSH açarı yaradıldı" + }, + "sshAgentUnlockRequired": { + "message": "SSH açar tələbini təsdiqləmək üçün seyfinizin kilidini açın." + }, + "sshAgentUnlockTimeout": { + "message": "SSH açar tələbinin vaxtı bitdi." + }, + "enableSshAgent": { + "message": "SSH agenti fəallaşdır" + }, + "enableSshAgentDesc": { + "message": "SSH tələblərini birbaşa Bitwarden seyfinizdən imzalamaq üçün SSH agentini fəallaşdırın." + }, + "enableSshAgentHelp": { + "message": "SSH agenti, SSH tələblərini birbaşa Bitwarden seyfinizdən imzalamağa imkan verən developerlərə yönəlmiş bir xidmətdir." + }, "premiumRequired": { "message": "Premium üzvlük lazımdır" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Parolu kopyala" }, + "regenerateSshKey": { + "message": "SSH açarını yenidən yarat" + }, + "copySshPrivateKey": { + "message": "SSH private açarını kopyala" + }, "copyPassphrase": { "message": "Keçid ifadəsini kopyala", "description": "Copy passphrase to clipboard" @@ -2394,7 +2445,7 @@ "message": "E-poçt yarat" }, "generatorBoundariesHint": { - "message": "Dəyər $MIN$-$MAX$ arasında olmalıdır", + "message": "Value must be between $MIN$ and $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -3225,6 +3276,36 @@ "ssoError": { "message": "SSO giriş üçün açıq port tapıla bilmədi." }, + "authorize": { + "message": "Səlahiyyət ver" + }, + "deny": { + "message": "Rədd et" + }, + "sshkeyApprovalTitle": { + "message": "SSH açar istifadəsini təsdiqlə" + }, + "sshkeyApprovalMessageInfix": { + "message": "bura müraciət tələb edir:" + }, + "unknownApplication": { + "message": "Bir tətbiq" + }, + "sshKeyPasswordUnsupported": { + "message": "Parolla qorunan SSH açarlarının daxilə köçürülməsi hələ dəstəklənmir" + }, + "invalidSshKey": { + "message": "SSH açarı yararsızdır" + }, + "sshKeyTypeUnsupported": { + "message": "SSH açar növü dəstəklənmir" + }, + "importSshKeyFromClipboard": { + "message": "Açarı lövhədən daxilə köçür" + }, + "sshKeyPasted": { + "message": "SSH açarı uğurla daxilə köçürüldü" + }, "fileSavedToDevice": { "message": "Fayl cihazda saxlanıldı. Endirilənləri cihazınızdan idarə edin." } diff --git a/apps/desktop/src/locales/be/messages.json b/apps/desktop/src/locales/be/messages.json index 3ed643aec14..76d2ecbf91b 100644 --- a/apps/desktop/src/locales/be/messages.json +++ b/apps/desktop/src/locales/be/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Бяспечныя нататкі" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Папкі" }, @@ -177,6 +180,48 @@ "address": { "message": "Адрас" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Патрабуецца прэміяльны статус" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Скапіяваць пароль" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/bg/messages.json b/apps/desktop/src/locales/bg/messages.json index b60ac35472d..ec4db6c3bfb 100644 --- a/apps/desktop/src/locales/bg/messages.json +++ b/apps/desktop/src/locales/bg/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Защитена бележка" }, + "typeSshKey": { + "message": "SSH ключ" + }, "folders": { "message": "Папки" }, @@ -177,6 +180,48 @@ "address": { "message": "Адрес" }, + "sshPrivateKey": { + "message": "Частен ключ" + }, + "sshPublicKey": { + "message": "Публичен ключ" + }, + "sshFingerprint": { + "message": "Отпечатък" + }, + "sshKeyAlgorithm": { + "message": "Тип на ключа" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048 бита" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072 бита" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096 бита" + }, + "sshKeyGenerated": { + "message": "Генериран е нов SSH ключ" + }, + "sshAgentUnlockRequired": { + "message": "Отключете трезора си, за да одобрите заявката за SSH ключ." + }, + "sshAgentUnlockTimeout": { + "message": "Времето на заявката за SSH ключ е изтекло." + }, + "enableSshAgent": { + "message": "Включване на SSH-агента" + }, + "enableSshAgentDesc": { + "message": "Включете SSH-агента, за да подписвате заявки за SSH направо от трезора си в Битуорден." + }, + "enableSshAgentHelp": { + "message": "SSH-агентът е услуга, предназначена за разработчици, чрез която можете да подписвате заявки за SSH направо от трезора си в Битуорден." + }, "premiumRequired": { "message": "Изисква се платен абонамент" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Копиране на паролата" }, + "regenerateSshKey": { + "message": "Генериране на нов SSH ключ" + }, + "copySshPrivateKey": { + "message": "Копиране на частния SSH ключ" + }, "copyPassphrase": { "message": "Копиране на паролата-фраза", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Не могат да бъдат открити свободни портове за еднократната идентификация." }, + "authorize": { + "message": "Упълномощаване" + }, + "deny": { + "message": "Отказване" + }, + "sshkeyApprovalTitle": { + "message": "Потвърждаване на употребата на SSH ключа" + }, + "sshkeyApprovalMessageInfix": { + "message": "иска достъп до" + }, + "unknownApplication": { + "message": "Приложение" + }, + "sshKeyPasswordUnsupported": { + "message": "Внасянето на SSH ключ, които са защитени с парола, все още не се поддържа" + }, + "invalidSshKey": { + "message": "SSH ключът е неправилен" + }, + "sshKeyTypeUnsupported": { + "message": "Типът на SSH ключа не се поддържа" + }, + "importSshKeyFromClipboard": { + "message": "Внасяне на ключ от буфера за обмен" + }, + "sshKeyPasted": { + "message": "SSH ключът е внесен успешно" + }, "fileSavedToDevice": { "message": "Файлът е запазен на устройството. Можете да го намерите в мястото за сваляния на устройството." } diff --git a/apps/desktop/src/locales/bn/messages.json b/apps/desktop/src/locales/bn/messages.json index cc824c57f69..4bdfc563be5 100644 --- a/apps/desktop/src/locales/bn/messages.json +++ b/apps/desktop/src/locales/bn/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "সুরক্ষিত নোট" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "ফোল্ডারসমূহ" }, @@ -177,6 +180,48 @@ "address": { "message": "ঠিকানা" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "প্রিমিয়াম আবশ্যক" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "পাসওয়ার্ড অনুলিপিত করুন" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/bs/messages.json b/apps/desktop/src/locales/bs/messages.json index 9de9617c8b3..db1c7befd3a 100644 --- a/apps/desktop/src/locales/bs/messages.json +++ b/apps/desktop/src/locales/bs/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Sigurna bilješka" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Folderi" }, @@ -177,6 +180,48 @@ "address": { "message": "Adresa" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Potrebno premium članstvo" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopirajte lozinku" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/ca/messages.json b/apps/desktop/src/locales/ca/messages.json index 39791d09a2b..10a6bc077ff 100644 --- a/apps/desktop/src/locales/ca/messages.json +++ b/apps/desktop/src/locales/ca/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Nota segura" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Carpetes" }, @@ -177,6 +180,48 @@ "address": { "message": "Adreça" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium requerit" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copia contrasenya" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/cs/messages.json b/apps/desktop/src/locales/cs/messages.json index 555014f09a1..b20ac2df87e 100644 --- a/apps/desktop/src/locales/cs/messages.json +++ b/apps/desktop/src/locales/cs/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Zabezpečená poznámka" }, + "typeSshKey": { + "message": "SSH klíč" + }, "folders": { "message": "Složky" }, @@ -177,6 +180,48 @@ "address": { "message": "Adresa" }, + "sshPrivateKey": { + "message": "Soukromý klíč" + }, + "sshPublicKey": { + "message": "Veřejný klíč" + }, + "sshFingerprint": { + "message": "Otisk prstu" + }, + "sshKeyAlgorithm": { + "message": "Typ klíče" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048 bitový" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072 bitový" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096 bitový" + }, + "sshKeyGenerated": { + "message": "Byl vygenerován nový SSH klíč" + }, + "sshAgentUnlockRequired": { + "message": "Pro schválení požadavku na SSH klíč odemkněte Váš trezor." + }, + "sshAgentUnlockTimeout": { + "message": "Vypršel časový limit požadavku SSH klíče." + }, + "enableSshAgent": { + "message": "Povolit SSH agenta" + }, + "enableSshAgentDesc": { + "message": "Povolí SSH agentovi podepisovat SSH požadavky přímo z Vašeho trezoru." + }, + "enableSshAgentHelp": { + "message": "SSH agent je služba určená vývojářům; umožňuje Vám podepisovat požadavky SSH přímo z Vašeho trezoru." + }, "premiumRequired": { "message": "Je vyžadováno členství Premium" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopírovat heslo" }, + "regenerateSshKey": { + "message": "Znovu vygenerovat SSH klíč" + }, + "copySshPrivateKey": { + "message": "Kopírovat soukromý SSH klíč" + }, "copyPassphrase": { "message": "Kopírovat heslovou frázi", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Pro přihlášení SSO nebyly nalezeny žádné volné porty." }, + "authorize": { + "message": "Autorizovat" + }, + "deny": { + "message": "Zamítnout" + }, + "sshkeyApprovalTitle": { + "message": "Potvrdit použití SSH klíče" + }, + "sshkeyApprovalMessageInfix": { + "message": "žádá o přístup k" + }, + "unknownApplication": { + "message": "Aplikace" + }, + "sshKeyPasswordUnsupported": { + "message": "Import šifrovaných SSH klíčů není zatím podporován" + }, + "invalidSshKey": { + "message": "SSH klíč je neplatný" + }, + "sshKeyTypeUnsupported": { + "message": "Typ SSH klíče není podporován" + }, + "importSshKeyFromClipboard": { + "message": "Importovat klíč ze schránky" + }, + "sshKeyPasted": { + "message": "SSH klíč byl úspěšně importován" + }, "fileSavedToDevice": { "message": "Soubor byl uložen. Můžete jej nalézt ve stažené složce v zařízení." } diff --git a/apps/desktop/src/locales/cy/messages.json b/apps/desktop/src/locales/cy/messages.json index 8d8e807026d..de70d993d3a 100644 --- a/apps/desktop/src/locales/cy/messages.json +++ b/apps/desktop/src/locales/cy/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Secure note" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Folders" }, @@ -177,6 +180,48 @@ "address": { "message": "Address" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copy password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/da/messages.json b/apps/desktop/src/locales/da/messages.json index a4bb7ce4e4a..6a8a887434c 100644 --- a/apps/desktop/src/locales/da/messages.json +++ b/apps/desktop/src/locales/da/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Sikret notat" }, + "typeSshKey": { + "message": "SSH-nøgle" + }, "folders": { "message": "Mapper" }, @@ -177,6 +180,48 @@ "address": { "message": "Adresse" }, + "sshPrivateKey": { + "message": "Privat nøgle" + }, + "sshPublicKey": { + "message": "Offentlig nøgle" + }, + "sshFingerprint": { + "message": "Fingeraftryk" + }, + "sshKeyAlgorithm": { + "message": "Nøgletype" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "En ny SSH-nøgle er genereret" + }, + "sshAgentUnlockRequired": { + "message": "Oplås boksen op for at godkende SSH-nøgleanmodningen." + }, + "sshAgentUnlockTimeout": { + "message": "SSH-nøgleanmodning fik timeout." + }, + "enableSshAgent": { + "message": "Aktivér SSH-agent" + }, + "enableSshAgentDesc": { + "message": "Aktivér SSH-agenten for at signere SSH-forespørgsler direkte fra Bitwarden-boksen." + }, + "enableSshAgentHelp": { + "message": "SSH-agent er en tjeneste rettet mod udviklere, der muliggør at signere SSH-forespørgsler direkte fra Bitwarden-boksen." + }, "premiumRequired": { "message": "Premium kræves" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopiér adgangskode" }, + "regenerateSshKey": { + "message": "Regenerér SSH-nøgle" + }, + "copySshPrivateKey": { + "message": "Kopiér SSH privat nøgle" + }, "copyPassphrase": { "message": "Kopiér adgangssætning", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Ingen ledige porte fundet til SSO-login." }, + "authorize": { + "message": "Godkend" + }, + "deny": { + "message": "Afvis" + }, + "sshkeyApprovalTitle": { + "message": "Bekræft brug af SSH-nøgle" + }, + "sshkeyApprovalMessageInfix": { + "message": "anmoder om adgang til" + }, + "unknownApplication": { + "message": "En applikation" + }, + "sshKeyPasswordUnsupported": { + "message": "Import af adgangskodebeskyttede SSH-nøgler understøttes endnu ikke" + }, + "invalidSshKey": { + "message": "SSH-nøglen er ugyldig" + }, + "sshKeyTypeUnsupported": { + "message": "SSH-nøgletypen understøttes ikke" + }, + "importSshKeyFromClipboard": { + "message": "Importér nøgle fra udklipsholder" + }, + "sshKeyPasted": { + "message": "SSH-nøgle er importeret" + }, "fileSavedToDevice": { "message": "Fil gemt på enheden. Håndtér fra enhedens downloads." } diff --git a/apps/desktop/src/locales/de/messages.json b/apps/desktop/src/locales/de/messages.json index 070da06de04..f049b4c3ff2 100644 --- a/apps/desktop/src/locales/de/messages.json +++ b/apps/desktop/src/locales/de/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Sichere Notiz" }, + "typeSshKey": { + "message": "SSH-Schlüssel" + }, "folders": { "message": "Ordner" }, @@ -177,6 +180,48 @@ "address": { "message": "Adresse" }, + "sshPrivateKey": { + "message": "Privater Schlüssel" + }, + "sshPublicKey": { + "message": "Öffentlicher Schlüssel" + }, + "sshFingerprint": { + "message": "Fingerabdruck" + }, + "sshKeyAlgorithm": { + "message": "Schlüsseltyp" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "Ein neuer SSH-Schlüssel wurde generiert" + }, + "sshAgentUnlockRequired": { + "message": "Bitte entsperre deinen Tresor, um die SSH-Schlüsselanfrage zu genehmigen." + }, + "sshAgentUnlockTimeout": { + "message": "Zeitüberschreitung bei der SSH-Schlüsselanfrage." + }, + "enableSshAgent": { + "message": "SSH-Agent aktivieren" + }, + "enableSshAgentDesc": { + "message": "Aktiviere den SSH-Agenten, um SSH-Anfragen direkt aus deinem Bitwarden-Tresor aus zu signieren." + }, + "enableSshAgentHelp": { + "message": "Der SSH-Agent ist ein Dienst, der sich an Entwickler richtet, mit dem du SSH-Anfragen direkt aus deinem Bitwarden-Tresor aus signieren kannst." + }, "premiumRequired": { "message": "Premium notwendig" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Passwort kopieren" }, + "regenerateSshKey": { + "message": "SSH-Schlüssel neu generieren" + }, + "copySshPrivateKey": { + "message": "Privaten SSH-Schlüssel kopieren" + }, "copyPassphrase": { "message": "Passphrase kopieren", "description": "Copy passphrase to clipboard" @@ -576,7 +627,7 @@ "message": "Mit Passkey anmelden" }, "loginWithDevice": { - "message": "Mit Gerät anmelden" + "message": "Anmelden mit einem anderen Gerät" }, "useSingleSignOn": { "message": "Single Sign-on verwenden" @@ -2394,7 +2445,7 @@ "message": "E-Mail generieren" }, "generatorBoundariesHint": { - "message": "Wert muss zwischen $MIN$ und $MAX$ liegen", + "message": "Value must be between $MIN$ and $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Es konnten keine freien Ports für die SSO-Anmeldung gefunden werden." }, + "authorize": { + "message": "Autorisieren" + }, + "deny": { + "message": "Ablehnen" + }, + "sshkeyApprovalTitle": { + "message": "Verwendung des SSH-Schlüssels bestätigen" + }, + "sshkeyApprovalMessageInfix": { + "message": "fragt den Zugriff an für" + }, + "unknownApplication": { + "message": "Eine Anwendung" + }, + "sshKeyPasswordUnsupported": { + "message": "Das Importieren passwortgeschützter SSH-Schlüssel wird noch nicht unterstützt" + }, + "invalidSshKey": { + "message": "Der SSH-Schlüssel ist ungültig" + }, + "sshKeyTypeUnsupported": { + "message": "Der SSH-Schlüsseltyp wird nicht unterstützt" + }, + "importSshKeyFromClipboard": { + "message": "Schlüssel aus Zwischenablage importieren" + }, + "sshKeyPasted": { + "message": "SSH-Schlüssel erfolgreich importiert" + }, "fileSavedToDevice": { "message": "Datei auf Gerät gespeichert. Greife darauf über die Downloads deines Geräts zu." } diff --git a/apps/desktop/src/locales/el/messages.json b/apps/desktop/src/locales/el/messages.json index ed067effeb2..113924b6016 100644 --- a/apps/desktop/src/locales/el/messages.json +++ b/apps/desktop/src/locales/el/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Ασφαλής σημείωση" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Φάκελοι" }, @@ -61,7 +64,7 @@ } }, "welcomeBack": { - "message": "Καλωσορίσατε και πάλι" + "message": "Welcome back" }, "moveToOrgDesc": { "message": "Επιλέξτε έναν οργανισμό στον οποίο θέλετε να μετακινήσετε αυτό το στοιχείο. Η μετακίνηση σε έναν οργανισμό μεταβιβάζει την ιδιοκτησία του στοιχείου σε αυτό τον οργανισμό. Δεν θα είστε πλέον ο άμεσος ιδιοκτήτης αυτού του στοιχείου μόλις το μετακινήσετε." @@ -177,6 +180,48 @@ "address": { "message": "Διεύθυνση" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Απαιτείται Premium" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Αντιγραφή κωδικού πρόσβασης" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Αντιγραφή φράσης πρόσβασης", "description": "Copy passphrase to clipboard" @@ -558,7 +609,7 @@ "message": "Δημιουργία λογαριασμού" }, "newToBitwarden": { - "message": "Νέος/α στο Bitwarden;" + "message": "New to Bitwarden?" }, "setAStrongPassword": { "message": "Ορίστε έναν ισχυρό κωδικό πρόσβασης" @@ -570,16 +621,16 @@ "message": "Είσοδος" }, "logInToBitwarden": { - "message": "Σύνδεση στο Bitwarden" + "message": "Log in to Bitwarden" }, "logInWithPasskey": { - "message": "Σύνδεση με κλειδί πρόσβασης" + "message": "Log in with passkey" }, "loginWithDevice": { - "message": "Σύνδεση με χρήση συσκευής" + "message": "Log in with device" }, "useSingleSignOn": { - "message": "Χρήση ενιαίας σύνδεσης" + "message": "Use single sign-on" }, "submit": { "message": "Υποβολή" @@ -1684,10 +1735,10 @@ "message": "Η διαγραφή του λογαριασμού σας είναι μόνιμη. Δεν μπορεί να αναιρεθεί." }, "cannotDeleteAccount": { - "message": "Αδυναμία διαγραφής λογαριασμού" + "message": "Cannot delete account" }, "cannotDeleteAccountDesc": { - "message": "Αυτή η ενέργεια δεν μπορεί να ολοκληρωθεί επειδή ο λογαριασμός σας ανήκει σε έναν οργανισμό. Επικοινωνήστε με το διαχειριστή του οργανισμού σας για πρόσθετες λεπτομέρειες." + "message": "This action cannot be completed because your account is owned by an organization. Contact your organization administrator for additional details." }, "accountDeleted": { "message": "Ο λογαριασμός διαγράφηκε" @@ -2394,7 +2445,7 @@ "message": "Δημιουργία διεύθυνσης ηλ. ταχυδρομείου" }, "generatorBoundariesHint": { - "message": "Η τιμή πρέπει να είναι μεταξύ $MIN$ και $MAX$", + "message": "Value must be between $MIN$ and $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Δεν βρέθηκαν ελεύθερες θύρες για τη σύνδεση sso." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "Το αρχείο αποθηκεύτηκε στη συσκευή. Διαχείριση από τις λήψεις της συσκευής σας." } diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json index 83fa064a35e..e9f26d23e94 100644 --- a/apps/desktop/src/locales/en/messages.json +++ b/apps/desktop/src/locales/en/messages.json @@ -2444,8 +2444,8 @@ "generateEmail": { "message": "Generate email" }, - "generatorBoundariesHint": { - "message": "Value must be between $MIN$ and $MAX$", + "spinboxBoundariesHint": { + "message": "Value must be between $MIN$ and $MAX$.", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -2458,6 +2458,26 @@ } } }, + "passwordLengthRecommendationHint": { + "message": " Use $RECOMMENDED$ characters or more to generate a strong password.", + "description": "Appended to `spinboxBoundariesHint` to recommend a length to the user. This must include any language-specific 'sentence' separator characters (e.g. a space in english).", + "placeholders": { + "recommended": { + "content": "$1", + "example": "14" + } + } + }, + "passphraseNumWordsRecommendationHint": { + "message": " Use $RECOMMENDED$ words or more to generate a strong passphrase.", + "description": "Appended to `spinboxBoundariesHint` to recommend a number of words to the user. This must include any language-specific 'sentence' separator characters (e.g. a space in english).", + "placeholders": { + "recommended": { + "content": "$1", + "example": "6" + } + } + }, "usernameType": { "message": "Username type" }, @@ -2669,15 +2689,30 @@ "notificationSentDevice": { "message": "A notification has been sent to your device." }, + "aNotificationWasSentToYourDevice": { + "message": "A notification was sent to your device" + }, + "makeSureYourAccountIsUnlockedAndTheFingerprintEtc": { + "message": "Make sure your account is unlocked and the fingerprint phrase matches on the other device" + }, + "needAnotherOptionV1": { + "message": "Need another option?" + }, "fingerprintMatchInfo": { "message": "Please make sure your vault is unlocked and Fingerprint phrase matches the other device." }, "fingerprintPhraseHeader": { "message": "Fingerprint phrase" }, + "youWillBeNotifiedOnceTheRequestIsApproved": { + "message": "You will be notified once the request is approved" + }, "needAnotherOption": { "message": "Log in with device must be set up in the settings of the Bitwarden app. Need another option?" }, + "viewAllLogInOptions": { + "message": "View all log in options" + }, "viewAllLoginOptions": { "message": "View all login options" }, diff --git a/apps/desktop/src/locales/en_GB/messages.json b/apps/desktop/src/locales/en_GB/messages.json index 5c994e8ba56..60d7843208b 100644 --- a/apps/desktop/src/locales/en_GB/messages.json +++ b/apps/desktop/src/locales/en_GB/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Secure note" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Folders" }, @@ -177,6 +180,48 @@ "address": { "message": "Address" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copy password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorise" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/en_IN/messages.json b/apps/desktop/src/locales/en_IN/messages.json index 34e269d5d70..ed1e1a5dfc3 100644 --- a/apps/desktop/src/locales/en_IN/messages.json +++ b/apps/desktop/src/locales/en_IN/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Secure note" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Folders" }, @@ -177,6 +180,48 @@ "address": { "message": "Address" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copy password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorise" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/eo/messages.json b/apps/desktop/src/locales/eo/messages.json index b6500674e44..c9b2f923866 100644 --- a/apps/desktop/src/locales/eo/messages.json +++ b/apps/desktop/src/locales/eo/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Sekura noto" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Dosierujoj" }, @@ -177,6 +180,48 @@ "address": { "message": "Adreso" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copy password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/es/messages.json b/apps/desktop/src/locales/es/messages.json index 1bdc8ab8340..ebaccfe9a3f 100644 --- a/apps/desktop/src/locales/es/messages.json +++ b/apps/desktop/src/locales/es/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Nota segura" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Carpetas" }, @@ -177,6 +180,48 @@ "address": { "message": "Dirección" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium requerido" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copiar contraseña" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/et/messages.json b/apps/desktop/src/locales/et/messages.json index c129a6c4bb0..5cd053f832c 100644 --- a/apps/desktop/src/locales/et/messages.json +++ b/apps/desktop/src/locales/et/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Turvaline märkus" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Kaustad" }, @@ -177,6 +180,48 @@ "address": { "message": "Aadress" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Vajalik on Preemium versioon" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopeeri parool" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "SSO-ga sisselogimiseks ei leitud ühtegi vaba porti." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "Fail salvestatud. Halda oma seadmesse allalaaditud faile." } diff --git a/apps/desktop/src/locales/eu/messages.json b/apps/desktop/src/locales/eu/messages.json index 46d29321515..0c649a5d8ec 100644 --- a/apps/desktop/src/locales/eu/messages.json +++ b/apps/desktop/src/locales/eu/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Ohar segurua" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Karpetak" }, @@ -177,6 +180,48 @@ "address": { "message": "Helbidea" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium izatea beharrezkoa da" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopiatu pasahitza" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/fa/messages.json b/apps/desktop/src/locales/fa/messages.json index 65ad1be1cbb..a8e819019a5 100644 --- a/apps/desktop/src/locales/fa/messages.json +++ b/apps/desktop/src/locales/fa/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "یادداشت امن" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "پوشه‌ها" }, @@ -177,6 +180,48 @@ "address": { "message": "نشانی" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "در نسخه پرمیوم کار می‌کند" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "کپی کلمه عبور" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/fi/messages.json b/apps/desktop/src/locales/fi/messages.json index cf6025e0423..486aee42e8a 100644 --- a/apps/desktop/src/locales/fi/messages.json +++ b/apps/desktop/src/locales/fi/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Salattu muistio" }, + "typeSshKey": { + "message": "SSH-avain" + }, "folders": { "message": "Kansiot" }, @@ -177,6 +180,48 @@ "address": { "message": "Osoite" }, + "sshPrivateKey": { + "message": "Yksityinen avain" + }, + "sshPublicKey": { + "message": "Julkinen avain" + }, + "sshFingerprint": { + "message": "Sormenjälki" + }, + "sshKeyAlgorithm": { + "message": "Avaintyyppi" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "Uusi SSH-avain luotiin" + }, + "sshAgentUnlockRequired": { + "message": "Ole hyvä ja avaa holvisi hyväksyäksesi SSH-avainpyynnön." + }, + "sshAgentUnlockTimeout": { + "message": "SSH-avainpyyntö aikakatkaistiin." + }, + "enableSshAgent": { + "message": "Ota SSH-agentti käyttöön" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium vaaditaan" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopioi salasana" }, + "regenerateSshKey": { + "message": "Luo SSH-avain uudelleen" + }, + "copySshPrivateKey": { + "message": "Kopioi yksityinen SSH-avain" + }, "copyPassphrase": { "message": "Kopioi salalause", "description": "Copy passphrase to clipboard" @@ -558,7 +609,7 @@ "message": "Luo tili" }, "newToBitwarden": { - "message": "Oletko uusi Bitwardenissa?" + "message": "Oletko uusi Bitwarden-käyttäjä?" }, "setAStrongPassword": { "message": "Aseta vahva salasana" @@ -1687,7 +1738,7 @@ "message": "Tiliä ei voi poistaa" }, "cannotDeleteAccountDesc": { - "message": "Tätä toimintoa ei voida suorittaa, koska tilisi on organisaation omistama. Ota yhteyttä organisaation ylläpitäjään saadaksesi lisätietoja." + "message": "This action cannot be completed because your account is owned by an organization. Contact your organization administrator for additional details." }, "accountDeleted": { "message": "Tili poistettiin" @@ -2394,7 +2445,7 @@ "message": "Luo sähköpostiosoite" }, "generatorBoundariesHint": { - "message": "Arvon tulee olla väliltä $MIN$ - $MAX$", + "message": "Value must be between $MIN$ and $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Kertakirjautumiselle ei löytynyt vapaita portteja." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "SSH-avain on virheellinen" + }, + "sshKeyTypeUnsupported": { + "message": "SSH-avaintyyppiä ei ole tuettui" + }, + "importSshKeyFromClipboard": { + "message": "Tuo avain leikepöydältä" + }, + "sshKeyPasted": { + "message": "SSH-avain on tuotu" + }, "fileSavedToDevice": { "message": "Tiedosto tallennettiin laitteelle. Hallitse sitä laitteesi latauksista." } diff --git a/apps/desktop/src/locales/fil/messages.json b/apps/desktop/src/locales/fil/messages.json index f721bb17253..5146903c913 100644 --- a/apps/desktop/src/locales/fil/messages.json +++ b/apps/desktop/src/locales/fil/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Secure na tala" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Mga Folder" }, @@ -177,6 +180,48 @@ "address": { "message": "Address" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Kailangan ng premium" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopyahin ang password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/fr/messages.json b/apps/desktop/src/locales/fr/messages.json index 99c99150ad9..b357f2ece6a 100644 --- a/apps/desktop/src/locales/fr/messages.json +++ b/apps/desktop/src/locales/fr/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Note sécurisée" }, + "typeSshKey": { + "message": "Clé SSH" + }, "folders": { "message": "Dossiers" }, @@ -177,6 +180,48 @@ "address": { "message": "Adresse" }, + "sshPrivateKey": { + "message": "Clé privée" + }, + "sshPublicKey": { + "message": "Clé publique" + }, + "sshFingerprint": { + "message": "Empreinte digitale" + }, + "sshKeyAlgorithm": { + "message": "Type de clé" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-bits" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-bits" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-bits" + }, + "sshKeyGenerated": { + "message": "Une nouvelle clé SSH a été générée" + }, + "sshAgentUnlockRequired": { + "message": "Veuillez déverrouiller votre coffre pour approuver la demande de clé SSH." + }, + "sshAgentUnlockTimeout": { + "message": "La requête de clé SSH a expiré." + }, + "enableSshAgent": { + "message": "Activer l'agent SSH" + }, + "enableSshAgentDesc": { + "message": "Activez l'agent SSH pour signer les requêtes SSH directement depuis votre coffre Bitwarden." + }, + "enableSshAgentHelp": { + "message": "L'agent SSH est un service destiné aux développeurs qui vous permet de signer des requêtes SSH directement depuis votre coffre Bitwarden." + }, "premiumRequired": { "message": "Premium requis" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copier le mot de passe" }, + "regenerateSshKey": { + "message": "Régénérer la clé SSH" + }, + "copySshPrivateKey": { + "message": "Copier la clé privée SSH" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Autoriser" + }, + "deny": { + "message": "Refuser" + }, + "sshkeyApprovalTitle": { + "message": "Confirmer l'utilisation de la clé SSH" + }, + "sshkeyApprovalMessageInfix": { + "message": "demande l'accès à" + }, + "unknownApplication": { + "message": "Une application" + }, + "sshKeyPasswordUnsupported": { + "message": "L'importation de clés SSH protégées par mot de passe n'est pas encore prise en charge" + }, + "invalidSshKey": { + "message": "La clé SSH est invalide" + }, + "sshKeyTypeUnsupported": { + "message": "Le type de clé SSH n'est pas pris en charge" + }, + "importSshKeyFromClipboard": { + "message": "Importer une clé depuis le presse-papiers" + }, + "sshKeyPasted": { + "message": "Clé SSH importée avec succès" + }, "fileSavedToDevice": { "message": "Fichier enregistré sur l'appareil. Gérez à partir des téléchargements de votre appareil." } diff --git a/apps/desktop/src/locales/gl/messages.json b/apps/desktop/src/locales/gl/messages.json index 811885b464d..e9ab6d58e7d 100644 --- a/apps/desktop/src/locales/gl/messages.json +++ b/apps/desktop/src/locales/gl/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Secure note" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Folders" }, @@ -177,6 +180,48 @@ "address": { "message": "Address" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copy password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/he/messages.json b/apps/desktop/src/locales/he/messages.json index ead5dc7384c..fb1ce4e7ca6 100644 --- a/apps/desktop/src/locales/he/messages.json +++ b/apps/desktop/src/locales/he/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "פתק מאובטח" }, + "typeSshKey": { + "message": "מפתח SSH" + }, "folders": { "message": "תיקיות" }, @@ -61,7 +64,7 @@ } }, "welcomeBack": { - "message": "Welcome back" + "message": "ברוך שובך" }, "moveToOrgDesc": { "message": "בחר ארגון שאליו תרצה להעביר פריט זה. העברה לארגון מעבירה את הבעלות על הפריט לאותו ארגון. לאחר העברת פריט זה לא תהיה יותר הבעלים הישיר." @@ -177,6 +180,48 @@ "address": { "message": "כתובת" }, + "sshPrivateKey": { + "message": "מפתח פרטי" + }, + "sshPublicKey": { + "message": "מפתח ציבורי" + }, + "sshFingerprint": { + "message": "טביעת אצבע" + }, + "sshKeyAlgorithm": { + "message": "סוג מפתח" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA‏ 2048 סיביות" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA‏ 3072 סיביות" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA‏ 4096 סיביות" + }, + "sshKeyGenerated": { + "message": "נוצר מפתח SSH חדש" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "הפעלת סוכן SSH" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "נדרש חשבון פרימיום" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "העתק סיסמה" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -2394,7 +2445,7 @@ "message": "Generate email" }, "generatorBoundariesHint": { - "message": "Value must be between $MIN$ and $MAX$", + "message": "הערך חייב להיות בין $MIN$ ל־$MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/hi/messages.json b/apps/desktop/src/locales/hi/messages.json index 421c2665d4f..2351e8f11c9 100644 --- a/apps/desktop/src/locales/hi/messages.json +++ b/apps/desktop/src/locales/hi/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Secure note" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Folders" }, @@ -177,6 +180,48 @@ "address": { "message": "Address" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copy password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/hr/messages.json b/apps/desktop/src/locales/hr/messages.json index 47bb80f1542..7ade22dd632 100644 --- a/apps/desktop/src/locales/hr/messages.json +++ b/apps/desktop/src/locales/hr/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Sigurna bilješka" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Mape" }, @@ -177,6 +180,48 @@ "address": { "message": "Adresa" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Potrebno Premium članstvo" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopiraj lozinku" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Nisu nađeni slobodni portovi za SSO prijavu." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "Datoteka spremljena na uređaj. Upravljaj u preuzimanjima svog uređaja." } diff --git a/apps/desktop/src/locales/hu/messages.json b/apps/desktop/src/locales/hu/messages.json index cc147ae5ead..bd865471d27 100644 --- a/apps/desktop/src/locales/hu/messages.json +++ b/apps/desktop/src/locales/hu/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Biztonságos jegyzet" }, + "typeSshKey": { + "message": "SSH kulcs" + }, "folders": { "message": "Mappák" }, @@ -177,6 +180,48 @@ "address": { "message": "Postai cím" }, + "sshPrivateKey": { + "message": "Személyes kulcs" + }, + "sshPublicKey": { + "message": "Nyilvános kulcs" + }, + "sshFingerprint": { + "message": "Ujjlenyomat" + }, + "sshKeyAlgorithm": { + "message": "Kulcs típusa" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "Új SSH-kulcs jött létre." + }, + "sshAgentUnlockRequired": { + "message": "Az SSH-kulcskérés jóváhagyásához oldjuk fel a széfet." + }, + "sshAgentUnlockTimeout": { + "message": "Az SSH-kulcs kérése időtúllépést okozott." + }, + "enableSshAgent": { + "message": "SSH ügynök engedélyezése" + }, + "enableSshAgentDesc": { + "message": "Engedélyezzük az SSH ügynök számára az SSH kérelmek aláírását közvetlenül a Bitwarden széfből." + }, + "enableSshAgentHelp": { + "message": "Az SSH ügynök egy fejlesztőknek szánt szolgáltatás, amely lehetővé teszi az SSH kérések közvetlenül a Bitwarden széfből történő aláírását." + }, "premiumRequired": { "message": "Prémium szükséges" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Jelszó másolása" }, + "regenerateSshKey": { + "message": "SSH kulcs újragenerálása" + }, + "copySshPrivateKey": { + "message": "SSH személyes kulcs másolása" + }, "copyPassphrase": { "message": "Jelmondat másolása", "description": "Copy passphrase to clipboard" @@ -573,7 +624,7 @@ "message": "Bejelentkezés a Bitwardenbe" }, "logInWithPasskey": { - "message": "Bejelentkezés azonosító kulcssal" + "message": "Bejelentkezés hozzáférési kulccsal" }, "loginWithDevice": { "message": "Bejelentkezés eszközzel" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Nem található szabad port az sso bejelentkezéshez." }, + "authorize": { + "message": "Hitelesítés" + }, + "deny": { + "message": "Elutasítás" + }, + "sshkeyApprovalTitle": { + "message": "SSH kulcs használat megerősítése" + }, + "sshkeyApprovalMessageInfix": { + "message": "hozzáférést kér:" + }, + "unknownApplication": { + "message": "Egy alkalmazás" + }, + "sshKeyPasswordUnsupported": { + "message": "A jelszóval védett SSH kulcsok importálása még nem támogatott." + }, + "invalidSshKey": { + "message": "Az SSH kulcs érvénytelen." + }, + "sshKeyTypeUnsupported": { + "message": "Az SSH kulcstípus nem támogatott." + }, + "importSshKeyFromClipboard": { + "message": "Kulcs importálása vágólapból" + }, + "sshKeyPasted": { + "message": "Az SSH kulcs sikeresen importálásra került." + }, "fileSavedToDevice": { "message": "A fájl mentésre került az eszközre. Kezeljük az eszközről a letöltéseket." } diff --git a/apps/desktop/src/locales/id/messages.json b/apps/desktop/src/locales/id/messages.json index a5aeb3e4f40..faefebcc422 100644 --- a/apps/desktop/src/locales/id/messages.json +++ b/apps/desktop/src/locales/id/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Catatan yang aman" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Folder" }, @@ -177,6 +180,48 @@ "address": { "message": "Alamat" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Memerlukan Keanggotaan Premium" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Salin Kata Sandi" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/it/messages.json b/apps/desktop/src/locales/it/messages.json index 92732544785..f262bb159b2 100644 --- a/apps/desktop/src/locales/it/messages.json +++ b/apps/desktop/src/locales/it/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Nota sicura" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Cartelle" }, @@ -177,6 +180,48 @@ "address": { "message": "Indirizzo" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium necessario" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copia password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copia passphrase", "description": "Copy passphrase to clipboard" @@ -573,13 +624,13 @@ "message": "Log in to Bitwarden" }, "logInWithPasskey": { - "message": "Accedi con passkey" + "message": "Log in with passkey" }, "loginWithDevice": { - "message": "Accedi con dispositivo" + "message": "Log in with device" }, "useSingleSignOn": { - "message": "Usa il Single Sign-On" + "message": "Use single sign-on" }, "submit": { "message": "Invia" @@ -1684,10 +1735,10 @@ "message": "L'eliminazione del tuo account è permanente. Non può essere annullata." }, "cannotDeleteAccount": { - "message": "Impossibile eliminare account" + "message": "Cannot delete account" }, "cannotDeleteAccountDesc": { - "message": "Questa azione non può essere completata perché il tuo account è di proprietà di un'organizzazione. Contatta l'amministratore della tua organizzazione per dettagli." + "message": "This action cannot be completed because your account is owned by an organization. Contact your organization administrator for additional details." }, "accountDeleted": { "message": "Account eliminato" @@ -2394,7 +2445,7 @@ "message": "Genera e-mail" }, "generatorBoundariesHint": { - "message": "Il valore deve essere compreso tra $MIN$ e $MAX$", + "message": "Value must be between $MIN$ and $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Non è stato possibile trovare nessuna porta libera per il login Sso." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File salvato sul dispositivo. Gestisci dai download del dispositivo." } diff --git a/apps/desktop/src/locales/ja/messages.json b/apps/desktop/src/locales/ja/messages.json index 8024c41d83f..5cf83707744 100644 --- a/apps/desktop/src/locales/ja/messages.json +++ b/apps/desktop/src/locales/ja/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "セキュアメモ" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "フォルダー" }, @@ -177,6 +180,48 @@ "address": { "message": "住所" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "プレミアム会員専用" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "パスワードのコピー" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "SSO ログインのための空きポートが見つかりませんでした。" }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "ファイルをデバイスに保存しました。デバイスのダウンロードで管理できます。" } diff --git a/apps/desktop/src/locales/ka/messages.json b/apps/desktop/src/locales/ka/messages.json index fe2d8b280a1..0bb3a3fdcd6 100644 --- a/apps/desktop/src/locales/ka/messages.json +++ b/apps/desktop/src/locales/ka/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Secure note" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "საქაღალდეები" }, @@ -177,6 +180,48 @@ "address": { "message": "მისამართი" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "პაროლის კოპირება" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/km/messages.json b/apps/desktop/src/locales/km/messages.json index 811885b464d..e9ab6d58e7d 100644 --- a/apps/desktop/src/locales/km/messages.json +++ b/apps/desktop/src/locales/km/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Secure note" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Folders" }, @@ -177,6 +180,48 @@ "address": { "message": "Address" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copy password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/kn/messages.json b/apps/desktop/src/locales/kn/messages.json index e4e1f85f2b7..81c4082e6be 100644 --- a/apps/desktop/src/locales/kn/messages.json +++ b/apps/desktop/src/locales/kn/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "ಸುರಕ್ಷಿತ ಟಿಪ್ಪಣಿ" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "ಫೋಲ್ಡರ್‌ಗಳು" }, @@ -177,6 +180,48 @@ "address": { "message": "ವಿಳಾಸ" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "ಪ್ರೀಮಿಯಂ ಅಗತ್ಯವಿದೆ" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "ಪಾಸ್ವರ್ಡ್ ನಕಲಿಸಿ" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/ko/messages.json b/apps/desktop/src/locales/ko/messages.json index f0eb10fa2a1..69b78ac35da 100644 --- a/apps/desktop/src/locales/ko/messages.json +++ b/apps/desktop/src/locales/ko/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "보안 메모" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "폴더" }, @@ -177,6 +180,48 @@ "address": { "message": "주소" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "프리미엄 멤버십 필요" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "비밀번호 복사" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/lt/messages.json b/apps/desktop/src/locales/lt/messages.json index e065b4ebfb8..87c8819c737 100644 --- a/apps/desktop/src/locales/lt/messages.json +++ b/apps/desktop/src/locales/lt/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Saugus įrašas" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Aplankai" }, @@ -177,6 +180,48 @@ "address": { "message": "Adresas" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Reikalinga Premium narystė" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopijuoti slaptažodį" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/lv/messages.json b/apps/desktop/src/locales/lv/messages.json index 264f65fc9b7..e74c0223e6f 100644 --- a/apps/desktop/src/locales/lv/messages.json +++ b/apps/desktop/src/locales/lv/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Droša piezīme" }, + "typeSshKey": { + "message": "SSH atslēga" + }, "folders": { "message": "Mapes" }, @@ -177,6 +180,48 @@ "address": { "message": "Adrese" }, + "sshPrivateKey": { + "message": "Privātā atslēga" + }, + "sshPublicKey": { + "message": "Publiskā atslēga" + }, + "sshFingerprint": { + "message": "Pirkstu nospiedums" + }, + "sshKeyAlgorithm": { + "message": "Atslēgas veids" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "Tika izveidota jauna SSH atslēga" + }, + "sshAgentUnlockRequired": { + "message": "Lūgums atslēgt savu glabātavu, lai apstiprinātu SSH atslēgas pieprasījumu." + }, + "sshAgentUnlockTimeout": { + "message": "SSH atslēgas pieprasījumam iestājās noildze." + }, + "enableSshAgent": { + "message": "Iespējot SSH aģentu" + }, + "enableSshAgentDesc": { + "message": "Iespējo SSH aģentu, lai parakstītu SSH pieprasījumus tieši no savas Bitwarden glabātavas." + }, + "enableSshAgentHelp": { + "message": "SSH aģents ir izstrādātājiem paredzēts pakalpojums, kas ļauj parakstīt SSH pieprasījumus tieši no savas Bitwarden glabātavas." + }, "premiumRequired": { "message": "Nepieciešams Premium" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Ievietot paroli starpliktuvē" }, + "regenerateSshKey": { + "message": "Atkārtoti izveidot SSH atslēgu" + }, + "copySshPrivateKey": { + "message": "Ievietot privāto SSH atslēgu starpliktuvē" + }, "copyPassphrase": { "message": "Ievietot paroles vārdkopu starpliktuvē", "description": "Copy passphrase to clipboard" @@ -2391,10 +2442,10 @@ "message": "Izveidot lietotājvārdu" }, "generateEmail": { - "message": "Izveidot e-pastu" + "message": "Izveidot e-pasta adresi" }, "generatorBoundariesHint": { - "message": "Vērtībai jābūt starp $MIN$ un $MAX$", + "message": "Value must be between $MIN$ and $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -2448,7 +2499,7 @@ "message": "Pārvirzīto e-pastu aizstājvārds" }, "forwardedEmailDesc": { - "message": "Izveidot e-pastu aizstājvārdu ar ārēju pārvirzīšanas pakalpojumu." + "message": "Izveidot e-pasta aizstājadresi ar ārēju pārvirzīšanas pakalpojumu." }, "forwarderDomainName": { "message": "E-pasta domēns", @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Netika atrasti brīvi vienotās (SSO) pieteikšanās porti." }, + "authorize": { + "message": "Pilnvarot" + }, + "deny": { + "message": "Noraidīt" + }, + "sshkeyApprovalTitle": { + "message": "Apstiprināt SSH atslēgas lietojumu" + }, + "sshkeyApprovalMessageInfix": { + "message": "pieprasa piekļuvi" + }, + "unknownApplication": { + "message": "Lietotne" + }, + "sshKeyPasswordUnsupported": { + "message": "Ar paroli aizsargātu SSH atslēgu ievietošana pagaidām netiek nodrošināta" + }, + "invalidSshKey": { + "message": "SSH atslēga ir nederīga" + }, + "sshKeyTypeUnsupported": { + "message": "SSH atslēgas veids netiek atbalstīts" + }, + "importSshKeyFromClipboard": { + "message": "Ievietot atslēgu no starpliktuves" + }, + "sshKeyPasted": { + "message": "SSH atslēga tika veiksmīgi ievietota" + }, "fileSavedToDevice": { "message": "Datne saglabāta ierīcē. Tā ir atrodama ierīces lejupielāžu mapē." } diff --git a/apps/desktop/src/locales/me/messages.json b/apps/desktop/src/locales/me/messages.json index 1562c6f1f4f..f5d61400ed2 100644 --- a/apps/desktop/src/locales/me/messages.json +++ b/apps/desktop/src/locales/me/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Sigurna belješka" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Fascikle" }, @@ -177,6 +180,48 @@ "address": { "message": "Adresa" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium obavezan" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopiraj lozinku" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/ml/messages.json b/apps/desktop/src/locales/ml/messages.json index 9b947278f62..74760b47e46 100644 --- a/apps/desktop/src/locales/ml/messages.json +++ b/apps/desktop/src/locales/ml/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "സുരക്ഷിത കുറിപ്പ്" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "ഫോൾഡറുകൾ" }, @@ -177,6 +180,48 @@ "address": { "message": "മേൽവിലാസം" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "പ്രീമിയം അംഗത്വം ആവശ്യമാണ്" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "പാസ്‌വേഡ് പകർത്തുക" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/mr/messages.json b/apps/desktop/src/locales/mr/messages.json index 811885b464d..e9ab6d58e7d 100644 --- a/apps/desktop/src/locales/mr/messages.json +++ b/apps/desktop/src/locales/mr/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Secure note" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Folders" }, @@ -177,6 +180,48 @@ "address": { "message": "Address" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copy password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/my/messages.json b/apps/desktop/src/locales/my/messages.json index e30721d1d0e..370a24457eb 100644 --- a/apps/desktop/src/locales/my/messages.json +++ b/apps/desktop/src/locales/my/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "လုံခြုံတဲ့မှတ်စု" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Folders" }, @@ -177,6 +180,48 @@ "address": { "message": "Address" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copy password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/nb/messages.json b/apps/desktop/src/locales/nb/messages.json index 9459cd43eb5..7e2cd855c70 100644 --- a/apps/desktop/src/locales/nb/messages.json +++ b/apps/desktop/src/locales/nb/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Sikker notis" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Mapper" }, @@ -177,6 +180,48 @@ "address": { "message": "Adresse" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium er påkrevd" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopier passordet" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/ne/messages.json b/apps/desktop/src/locales/ne/messages.json index 5182547dbc7..b836f2c3503 100644 --- a/apps/desktop/src/locales/ne/messages.json +++ b/apps/desktop/src/locales/ne/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "सुरक्षित नोट" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "फोल्डरहरू" }, @@ -177,6 +180,48 @@ "address": { "message": "ठेगाना" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "प्रिमियम आवश्यक छ" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "पासवर्ड प्रतिलिपि गर्नुहोस्" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/nl/messages.json b/apps/desktop/src/locales/nl/messages.json index bf1aadfeccb..b5ad5f5ddef 100644 --- a/apps/desktop/src/locales/nl/messages.json +++ b/apps/desktop/src/locales/nl/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Veilige notitie" }, + "typeSshKey": { + "message": "SSH-sleutel" + }, "folders": { "message": "Mappen" }, @@ -177,6 +180,48 @@ "address": { "message": "Adres" }, + "sshPrivateKey": { + "message": "Privésleutel" + }, + "sshPublicKey": { + "message": "Publieke sleutel" + }, + "sshFingerprint": { + "message": "Vingerafdruk" + }, + "sshKeyAlgorithm": { + "message": "Sleuteltype" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-bit" + }, + "sshKeyGenerated": { + "message": "Nieuwe SSH-sleutel gegenereerd" + }, + "sshAgentUnlockRequired": { + "message": "Ontgrendel je kluis voor het goedkeuren van het SSH-sleutelverzoek." + }, + "sshAgentUnlockTimeout": { + "message": "Time-out SSH-sleutelaanvraag." + }, + "enableSshAgent": { + "message": "SSH-agent inschakelen" + }, + "enableSshAgentDesc": { + "message": "Schakel de SSH-agent in om SSH-verzoeken rechtstreeks vanuit je Bitwarden-kluis te ondertekenen." + }, + "enableSshAgentHelp": { + "message": "De SSH-agent is een dienst gericht op ontwikkelaars waarmee je SSH-verzoeken rechtstreeks vanuit je Bitwarden-kluis kunt ondertekenen." + }, "premiumRequired": { "message": "Premium vereist" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopieer wachtwoord" }, + "regenerateSshKey": { + "message": "SSH-sleutel opnieuw genereren" + }, + "copySshPrivateKey": { + "message": "Privésleutel kopiëren" + }, "copyPassphrase": { "message": "Wachtwoordzin kopiëren", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Er zijn geen vrije poorten gevonden voor de sso-login." }, + "authorize": { + "message": "Autoriseren" + }, + "deny": { + "message": "Afwijzen" + }, + "sshkeyApprovalTitle": { + "message": "Gebruik SSH-sleutel bevestigen" + }, + "sshkeyApprovalMessageInfix": { + "message": "vraagt toegang tot" + }, + "unknownApplication": { + "message": "Een applicatie" + }, + "sshKeyPasswordUnsupported": { + "message": "Importeren van met wachtwoord beveiligde SSH-sleutels wordt nog niet ondersteund" + }, + "invalidSshKey": { + "message": "De SSH-sleutel is ongeldig" + }, + "sshKeyTypeUnsupported": { + "message": "Het type SSH-sleutel is niet ondersteund" + }, + "importSshKeyFromClipboard": { + "message": "Sleutel van klembord importeren" + }, + "sshKeyPasted": { + "message": "SSH-sleutel succesvol geïmporteerd" + }, "fileSavedToDevice": { "message": "Bestand op apparaat opgeslagen. Beheer vanaf de downloads op je apparaat." } diff --git a/apps/desktop/src/locales/nn/messages.json b/apps/desktop/src/locales/nn/messages.json index 4609c02f3b7..c0f01354ba0 100644 --- a/apps/desktop/src/locales/nn/messages.json +++ b/apps/desktop/src/locales/nn/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Trygg notat" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Mapper" }, @@ -177,6 +180,48 @@ "address": { "message": "Adresse" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium er påkravt" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopier passordet" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/or/messages.json b/apps/desktop/src/locales/or/messages.json index b38af07eb28..089329cfde7 100644 --- a/apps/desktop/src/locales/or/messages.json +++ b/apps/desktop/src/locales/or/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Secure note" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "ଫୋଲ୍ଡର୍" }, @@ -177,6 +180,48 @@ "address": { "message": "Address" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copy password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/pl/messages.json b/apps/desktop/src/locales/pl/messages.json index 415f1dc720b..b4ebecb4ab1 100644 --- a/apps/desktop/src/locales/pl/messages.json +++ b/apps/desktop/src/locales/pl/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Bezpieczna notatka" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Foldery" }, @@ -177,6 +180,48 @@ "address": { "message": "Adres" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Konto Premium jest wymagane" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopiuj hasło" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Nie znaleziono wolnych portów dla logowania SSO." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "Plik zapisany na urządzeniu. Zarządzaj plikiem na swoim urządzeniu." } diff --git a/apps/desktop/src/locales/pt_BR/messages.json b/apps/desktop/src/locales/pt_BR/messages.json index e70618d983f..bc2abfd9b65 100644 --- a/apps/desktop/src/locales/pt_BR/messages.json +++ b/apps/desktop/src/locales/pt_BR/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Nota Segura" }, + "typeSshKey": { + "message": "Chave SSH" + }, "folders": { "message": "Pastas" }, @@ -61,7 +64,7 @@ } }, "welcomeBack": { - "message": "Welcome back" + "message": "Bem vindo de volta" }, "moveToOrgDesc": { "message": "Escolha uma organização para a qual deseja mover este item. Mudar para uma organização transfere a propriedade do item para essa organização. Você não será mais o proprietário direto deste item depois que ele for movido." @@ -177,6 +180,48 @@ "address": { "message": "Endereço" }, + "sshPrivateKey": { + "message": "Chave privada" + }, + "sshPublicKey": { + "message": "Chave pública" + }, + "sshFingerprint": { + "message": "Impressão digital" + }, + "sshKeyAlgorithm": { + "message": "Tipo de chave" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "Uma nova chave SSH foi gerada" + }, + "sshAgentUnlockRequired": { + "message": "Por favor, desbloqueie seu cofre para aprovar a solicitação de chave SSH." + }, + "sshAgentUnlockTimeout": { + "message": "Solicitação de chave SSH expirada." + }, + "enableSshAgent": { + "message": "Habilitar SSH agent" + }, + "enableSshAgentDesc": { + "message": "Permitir que o agente SSH assine solicitações SSH diretamente do seu cofre Bitwarden." + }, + "enableSshAgentHelp": { + "message": "O agente SSH é um serviço direcionado a desenvolvedores que permite que você assine solicitações SSH diretamente do seu cofre do Bitwarden." + }, "premiumRequired": { "message": "Requer Assinatura Premium" }, @@ -263,7 +308,7 @@ "message": "Gerar Senha" }, "generatePassphrase": { - "message": "Generate passphrase" + "message": "Gerar frase secreta" }, "type": { "message": "Tipo" @@ -400,8 +445,14 @@ "copyPassword": { "message": "Copiar Senha" }, + "regenerateSshKey": { + "message": "Regerar chave SSH" + }, + "copySshPrivateKey": { + "message": "Copiar chave SSH privada" + }, "copyPassphrase": { - "message": "Copy passphrase", + "message": "Copiar senha", "description": "Copy passphrase to clipboard" }, "copyUri": { @@ -432,11 +483,11 @@ "message": "Caracteres especiais (!@#$%^&*)" }, "include": { - "message": "Include", + "message": "Incluir", "description": "Card header for password generator include block" }, "uppercaseDescription": { - "message": "Include uppercase characters", + "message": "Incluir caracteres maiúsculos", "description": "Tooltip for the password generator uppercase character checkbox" }, "uppercaseLabel": { @@ -444,7 +495,7 @@ "description": "Label for the password generator uppercase character checkbox" }, "lowercaseDescription": { - "message": "Include lowercase characters", + "message": "Incluir caracteres minúsculos", "description": "Full description for the password generator lowercase character checkbox" }, "lowercaseLabel": { @@ -452,7 +503,7 @@ "description": "Label for the password generator lowercase character checkbox" }, "numbersDescription": { - "message": "Include numbers", + "message": "Incluir números", "description": "Full description for the password generator numbers checkbox" }, "numbersLabel": { @@ -460,7 +511,7 @@ "description": "Label for the password generator numbers checkbox" }, "specialCharactersDescription": { - "message": "Include special characters", + "message": "Incluir caracteres especiais", "description": "Full description for the password generator special characters checkbox" }, "specialCharactersLabel": { @@ -495,11 +546,11 @@ "description": "deprecated. Use avoidAmbiguous instead." }, "avoidAmbiguous": { - "message": "Avoid ambiguous characters", + "message": "Evitar caracteres ambíguos", "description": "Label for the avoid ambiguous characters checkbox." }, "generatorPolicyInEffect": { - "message": "Enterprise policy requirements have been applied to your generator options.", + "message": "Os requisitos de política empresarial foram aplicados às suas opções de gerador.", "description": "Indicates that a policy limits the credential generator screen." }, "searchCollection": { @@ -558,7 +609,7 @@ "message": "Criar Conta" }, "newToBitwarden": { - "message": "New to Bitwarden?" + "message": "Novo no Bitwarden?" }, "setAStrongPassword": { "message": "Defina uma senha forte" @@ -570,16 +621,16 @@ "message": "Iniciar sessão" }, "logInToBitwarden": { - "message": "Log in to Bitwarden" + "message": "Inicie a sessão no Bitwarden" }, "logInWithPasskey": { - "message": "Log in with passkey" + "message": "Iniciar sessão com a chave de acesso" }, "loginWithDevice": { - "message": "Log in with device" + "message": "Fazer login com dispositivo" }, "useSingleSignOn": { - "message": "Use single sign-on" + "message": "Usar login único" }, "submit": { "message": "Enviar" @@ -628,7 +679,7 @@ "message": "Juntar-se à organização" }, "joinOrganizationName": { - "message": "Join $ORGANIZATIONNAME$", + "message": "Entrar em $ORGANIZATIONNAME$", "placeholders": { "organizationName": { "content": "$1", @@ -643,16 +694,16 @@ "message": "Configurações" }, "accountEmail": { - "message": "Account email" + "message": "Email da conta" }, "requestHint": { - "message": "Request hint" + "message": "Pedir dica" }, "requestPasswordHint": { - "message": "Request password hint" + "message": "Dica da senha mestra" }, "enterYourAccountEmailAddressAndYourPasswordHintWillBeSentToYou": { - "message": "Enter your account email address and your password hint will be sent to you" + "message": "Digite o endereço de e-mail da sua conta e sua dica da senha será enviada para você" }, "passwordHint": { "message": "Dica da Senha" @@ -698,10 +749,10 @@ "message": "A sua nova conta foi criada! Agora você pode iniciar a sessão." }, "newAccountCreated2": { - "message": "Your new account has been created!" + "message": "Sua nova conta foi criada!" }, "youHaveBeenLoggedIn": { - "message": "You have been logged in!" + "message": "Você está conectado!" }, "masterPassSent": { "message": "Enviamos um e-mail com a dica da sua senha mestra." @@ -854,7 +905,7 @@ "message": "URL do Servidor" }, "selfHostBaseUrl": { - "message": "Self-host server URL", + "message": "URL do servidor auto-host", "description": "Label for field requesting a self-hosted integration service URL" }, "apiUrl": { @@ -1001,16 +1052,16 @@ "message": "Seu cofre está trancado. Verifique sua identidade para continuar." }, "yourAccountIsLocked": { - "message": "Your account is locked" + "message": "Sua conta está bloqueada" }, "or": { - "message": "or" + "message": "ou" }, "unlockWithBiometrics": { - "message": "Unlock with biometrics" + "message": "Desbloquear com a biometria" }, "unlockWithMasterPassword": { - "message": "Unlock with master password" + "message": "Desbloquear com a senha mestra" }, "unlock": { "message": "Desbloquear" @@ -1041,7 +1092,7 @@ "message": "Tempo Limite do Cofre" }, "vaultTimeout1": { - "message": "Timeout" + "message": "Tempo esgotado" }, "vaultTimeoutDesc": { "message": "Escolha quando o tempo limite do seu cofre irá se esgotar e execute a ação selecionada." @@ -1248,7 +1299,7 @@ "description": "Copy credit card number" }, "copyEmail": { - "message": "Copy email" + "message": "Copiar e-mail" }, "copySecurityCode": { "message": "Copiar Código de Segurança", @@ -1402,7 +1453,7 @@ } }, "copySuccessful": { - "message": "Copy Successful" + "message": "Copiado com sucesso" }, "errorRefreshingAccessToken": { "message": "Erro ao Atualizar Token" @@ -1672,7 +1723,7 @@ "message": "Recomendado para segurança." }, "lockWithMasterPassOnRestart1": { - "message": "Lock with master password on restart" + "message": "Bloquear com senha mestra ao reiniciar" }, "deleteAccount": { "message": "Excluir conta" @@ -1684,10 +1735,10 @@ "message": "A exclusão de sua conta é permanente. Não poderá ser desfeito." }, "cannotDeleteAccount": { - "message": "Cannot delete account" + "message": "Não é possível excluir conta" }, "cannotDeleteAccountDesc": { - "message": "This action cannot be completed because your account is owned by an organization. Contact your organization administrator for additional details." + "message": "Esta ação não pode ser concluída porque sua conta pertence a uma organização. Entre em contato com o administrador da sua organização para obter mais detalhes." }, "accountDeleted": { "message": "Conta excluída" @@ -1800,7 +1851,7 @@ "description": "Used as a card title description on the set password page to explain why the user is there" }, "cardMetrics": { - "message": "out of $TOTAL$", + "message": "fora do $TOTAL$", "placeholders": { "total": { "content": "$1", @@ -1888,7 +1939,7 @@ "message": "Ativar integração com o navegador" }, "enableBrowserIntegrationDesc1": { - "message": "Used to allow biometric unlock in browsers that are not Safari." + "message": "Usado para permitir desbloqueio biométrico em navegadores que não são Safari." }, "enableDuckDuckGoBrowserIntegration": { "message": "Permitir integração ao navegador DuckDuckGo" @@ -2219,7 +2270,7 @@ "message": "Minutos" }, "vaultTimeoutPolicyInEffect1": { - "message": "$HOURS$ hour(s) and $MINUTES$ minute(s) maximum.", + "message": "Máximo de $HOURS$ hora(s) e $MINUTES$ minuto(s).", "placeholders": { "hours": { "content": "$1", @@ -2369,7 +2420,7 @@ "message": "Bloqueado" }, "yourVaultIsLockedV2": { - "message": "Your vault is locked" + "message": "Seu cofre está bloqueado" }, "unlocked": { "message": "Desbloqueado" @@ -2391,7 +2442,7 @@ "message": "Gerar usuário" }, "generateEmail": { - "message": "Generate email" + "message": "Gerar e-mail" }, "generatorBoundariesHint": { "message": "Value must be between $MIN$ and $MAX$", @@ -2451,11 +2502,11 @@ "message": "Gere um alias de e-mail com um serviço externo de encaminhamento." }, "forwarderDomainName": { - "message": "Email domain", + "message": "Domínio de e-mail", "description": "Labels the domain name email forwarder service option" }, "forwarderDomainNameHint": { - "message": "Choose a domain that is supported by the selected service", + "message": "Escolha um domínio que seja suportado pelo serviço selecionado", "description": "Guidance provided for email forwarding services that support multiple email domains." }, "forwarderError": { @@ -2750,7 +2801,7 @@ "message": "Importante:" }, "accessing": { - "message": "Accessing" + "message": "Acessando" }, "accessTokenUnableToBeDecrypted": { "message": "Você foi desconectado porque seu token de acesso não pôde ser descriptografado. Por favor, faça o login novamente para resolver esse problema." @@ -3225,7 +3276,37 @@ "ssoError": { "message": "Nenhuma porta livre foi encontrada para o cliente final." }, + "authorize": { + "message": "Autorizar" + }, + "deny": { + "message": "Negar" + }, + "sshkeyApprovalTitle": { + "message": "Confirmar uso da chave SSH" + }, + "sshkeyApprovalMessageInfix": { + "message": "está solicitando acesso para" + }, + "unknownApplication": { + "message": "Uma aplicação" + }, + "sshKeyPasswordUnsupported": { + "message": "Importar chaves SSH protegidas por senha ainda não é suportado" + }, + "invalidSshKey": { + "message": "A chave SSH é inválida" + }, + "sshKeyTypeUnsupported": { + "message": "O tipo de chave SSH não é suportado" + }, + "importSshKeyFromClipboard": { + "message": "Importar chave da área de transferência" + }, + "sshKeyPasted": { + "message": "Chave SSH importada com sucesso" + }, "fileSavedToDevice": { - "message": "File saved to device. Manage from your device downloads." + "message": "Arquivo salvo no dispositivo. Gerencie a partir das transferências do seu dispositivo." } } diff --git a/apps/desktop/src/locales/pt_PT/messages.json b/apps/desktop/src/locales/pt_PT/messages.json index 6c1d0d98eb1..f25f6c5d110 100644 --- a/apps/desktop/src/locales/pt_PT/messages.json +++ b/apps/desktop/src/locales/pt_PT/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Nota segura" }, + "typeSshKey": { + "message": "Chave SSH" + }, "folders": { "message": "Pastas" }, @@ -177,6 +180,48 @@ "address": { "message": "Endereço" }, + "sshPrivateKey": { + "message": "Chave privada" + }, + "sshPublicKey": { + "message": "Chave pública" + }, + "sshFingerprint": { + "message": "Impressão digital" + }, + "sshKeyAlgorithm": { + "message": "Tipo de chave" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "Foi gerada uma nova chave SSH" + }, + "sshAgentUnlockRequired": { + "message": "Por favor, desbloqueie o seu cofre para aprovar o pedido de chave SSH." + }, + "sshAgentUnlockTimeout": { + "message": "O pedido de chave SSH expirou." + }, + "enableSshAgent": { + "message": "Ativar o agente SSH" + }, + "enableSshAgentDesc": { + "message": "Ative o agente SSH para assinar pedidos SSH diretamente do seu cofre Bitwarden." + }, + "enableSshAgentHelp": { + "message": "O agente SSH é um serviço direcionado a programadores que lhe permite assinar pedidos SSH diretamente do seu cofre Bitwarden." + }, "premiumRequired": { "message": "É necessária uma subscrição Premium" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copiar palavra-passe" }, + "regenerateSshKey": { + "message": "Regenerar chave SSH" + }, + "copySshPrivateKey": { + "message": "Copiar chave privada SSH" + }, "copyPassphrase": { "message": "Copiar frase de acesso", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Não foi possível encontrar portas livres para o início de sessão sso." }, + "authorize": { + "message": "Autorizar" + }, + "deny": { + "message": "Recusar" + }, + "sshkeyApprovalTitle": { + "message": "Confirmar a utilização da chave SSH" + }, + "sshkeyApprovalMessageInfix": { + "message": "está a pedir acesso a" + }, + "unknownApplication": { + "message": "Uma aplicação" + }, + "sshKeyPasswordUnsupported": { + "message": "A importação de chaves SSH protegidas por palavra-passe ainda não é suportada" + }, + "invalidSshKey": { + "message": "A chave SSH é inválida" + }, + "sshKeyTypeUnsupported": { + "message": "O tipo de chave SSH não é suportado" + }, + "importSshKeyFromClipboard": { + "message": "Importar chave da área de transferência" + }, + "sshKeyPasted": { + "message": "Chave SSH importada com sucesso" + }, "fileSavedToDevice": { "message": "Ficheiro guardado no dispositivo. Gira-o a partir das transferências do seu dispositivo." } diff --git a/apps/desktop/src/locales/ro/messages.json b/apps/desktop/src/locales/ro/messages.json index b55cb01662c..f279b4d07fe 100644 --- a/apps/desktop/src/locales/ro/messages.json +++ b/apps/desktop/src/locales/ro/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Notă securizată" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Dosare" }, @@ -177,6 +180,48 @@ "address": { "message": "Adresă" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium necesar" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copiere parolă" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/ru/messages.json b/apps/desktop/src/locales/ru/messages.json index feffc818e4b..d60346087c9 100644 --- a/apps/desktop/src/locales/ru/messages.json +++ b/apps/desktop/src/locales/ru/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Защищенная заметка" }, + "typeSshKey": { + "message": "Ключ SSH" + }, "folders": { "message": "Папки" }, @@ -177,6 +180,48 @@ "address": { "message": "Адрес" }, + "sshPrivateKey": { + "message": "Приватный ключ" + }, + "sshPublicKey": { + "message": "Публичный ключ" + }, + "sshFingerprint": { + "message": "Отпечаток" + }, + "sshKeyAlgorithm": { + "message": "Тип ключа" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "Был создан новый ключ SSH" + }, + "sshAgentUnlockRequired": { + "message": "Пожалуйста, разблокируйте свое хранилище для подтверждения запроса ключа SSH." + }, + "sshAgentUnlockTimeout": { + "message": "Время ожидания запроса ключа SSH истекло." + }, + "enableSshAgent": { + "message": "Включить агент SSH" + }, + "enableSshAgentDesc": { + "message": "Включите агент SSH, чтобы подписывать запросы SSH прямо из вашего хранилища Bitwarden." + }, + "enableSshAgentHelp": { + "message": "Агент SSH - это сервис, ориентированный на разработчиков, позволяющий подписывать запросы SSH непосредственно из вашего хранилища Bitwarden." + }, "premiumRequired": { "message": "Требуется Премиум" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Скопировать пароль" }, + "regenerateSshKey": { + "message": "Пересоздать ключ SSH" + }, + "copySshPrivateKey": { + "message": "Скопировать приватный ключ SSH" + }, "copyPassphrase": { "message": "Скопировать парольную фразу", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Не удалось найти свободные порты для авторизации SSO." }, + "authorize": { + "message": "Разрешить" + }, + "deny": { + "message": "Запретить" + }, + "sshkeyApprovalTitle": { + "message": "Подтвердить использование ключа SSH" + }, + "sshkeyApprovalMessageInfix": { + "message": "запрашивает доступ к" + }, + "unknownApplication": { + "message": "Приложение" + }, + "sshKeyPasswordUnsupported": { + "message": "Импорт защищенных паролем ключей SSH пока не поддерживается" + }, + "invalidSshKey": { + "message": "Ключ SSH недействителен" + }, + "sshKeyTypeUnsupported": { + "message": "Тип ключа SSH не поддерживается" + }, + "importSshKeyFromClipboard": { + "message": "Импорт ключа из буфера обмена" + }, + "sshKeyPasted": { + "message": "Ключ SSH успешно импортирован" + }, "fileSavedToDevice": { "message": "Файл сохранен на устройстве. Управляйте им из загрузок устройства." } diff --git a/apps/desktop/src/locales/si/messages.json b/apps/desktop/src/locales/si/messages.json index a9742d8b5ea..7b73cff3227 100644 --- a/apps/desktop/src/locales/si/messages.json +++ b/apps/desktop/src/locales/si/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "ආරක්ෂිත සටහන" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "බහාලුම්" }, @@ -177,6 +180,48 @@ "address": { "message": "ලිපිනය" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "මුරපදය පිටපත් කරන්න" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/sk/messages.json b/apps/desktop/src/locales/sk/messages.json index 03f4a863fb7..4cf6b7a77e5 100644 --- a/apps/desktop/src/locales/sk/messages.json +++ b/apps/desktop/src/locales/sk/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Zabezpečená poznámka" }, + "typeSshKey": { + "message": "Kľúč SSH" + }, "folders": { "message": "Priečinky" }, @@ -45,7 +48,7 @@ "message": "Zdieľať" }, "moveToOrganization": { - "message": "Presunúť do Organizácie" + "message": "Presunúť do organizácie" }, "movedItemToOrg": { "message": "$ITEMNAME$ presunuté do $ORGNAME$", @@ -177,6 +180,48 @@ "address": { "message": "Adresa" }, + "sshPrivateKey": { + "message": "Súkromný kľúč" + }, + "sshPublicKey": { + "message": "Verejný kľúč" + }, + "sshFingerprint": { + "message": "Odtlačok" + }, + "sshKeyAlgorithm": { + "message": "Typ kľúča" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "Bol vygenerovaný nový kľúč SSH" + }, + "sshAgentUnlockRequired": { + "message": "Prosím, odomknite svoj trezor, aby ste mohli schváliť žiadosť o kľúč SSH." + }, + "sshAgentUnlockTimeout": { + "message": "Požiadavka na kľúč SSH vypršala." + }, + "enableSshAgent": { + "message": "Povoliť agenta SSH" + }, + "enableSshAgentDesc": { + "message": "Povolí agentovi SSH podpisovať požiadavky SSH priamo z vášho trezoru Bitwarden." + }, + "enableSshAgentHelp": { + "message": "Agent SSH je služba určená pre vývojárov, ktorá vám umožňuje podpisovať požiadavky SSH priamo z vášho trezora Bitwarden." + }, "premiumRequired": { "message": "Vyžaduje prémiový účet" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Skopírovať heslo" }, + "regenerateSshKey": { + "message": "Generovať nový kľúč SSH" + }, + "copySshPrivateKey": { + "message": "Kopírovať súkromný kľúč SSH" + }, "copyPassphrase": { "message": "Kopírovať prístupovú frázu", "description": "Copy passphrase to clipboard" @@ -2750,7 +2801,7 @@ "message": "Dôležité:" }, "accessing": { - "message": "Accessing" + "message": "Pristupovanie" }, "accessTokenUnableToBeDecrypted": { "message": "Boli ste odhlásení, pretože váš prístupový token nebolo možné dešifrovať. Na vyriešenie tohto problému sa znova prihláste." @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Pre prihlásenie SSO sa nepodarilo nájsť žiadne voľné porty." }, + "authorize": { + "message": "Autorizovať" + }, + "deny": { + "message": "Odmietnuť" + }, + "sshkeyApprovalTitle": { + "message": "Potvrdiť použitie kľúča SSH" + }, + "sshkeyApprovalMessageInfix": { + "message": "žiada o prístup k" + }, + "unknownApplication": { + "message": "Aplikácia" + }, + "sshKeyPasswordUnsupported": { + "message": "Importovanie kľúčov SSH chránených heslom zatiaľ nie je podporované" + }, + "invalidSshKey": { + "message": "Kľúč SSH je neplatný" + }, + "sshKeyTypeUnsupported": { + "message": "Tento typ kľúča SSH nie je podporovaný" + }, + "importSshKeyFromClipboard": { + "message": "Importovať kľúč zo schránky" + }, + "sshKeyPasted": { + "message": "Kľúč SSH bol úspešne importovaný" + }, "fileSavedToDevice": { "message": "Súbor sa uložil do zariadenia. Spravujte stiahnuté súbory zo zariadenia." } diff --git a/apps/desktop/src/locales/sl/messages.json b/apps/desktop/src/locales/sl/messages.json index 381e34658e9..e9ae08eb91a 100644 --- a/apps/desktop/src/locales/sl/messages.json +++ b/apps/desktop/src/locales/sl/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Varni zapisek" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Mape" }, @@ -177,6 +180,48 @@ "address": { "message": "Naslov" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Potrebno je premium članstvo" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopiraj geslo" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/sr/messages.json b/apps/desktop/src/locales/sr/messages.json index fb1ad8e90f6..1f5be2b05c8 100644 --- a/apps/desktop/src/locales/sr/messages.json +++ b/apps/desktop/src/locales/sr/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Сигурносна белешка" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Фасцикле" }, @@ -177,6 +180,48 @@ "address": { "message": "Адреса" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Потребан Премијум" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Копирај лозинку" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Копирај приступну фразу", "description": "Copy passphrase to clipboard" @@ -558,7 +609,7 @@ "message": "Креирај налог" }, "newToBitwarden": { - "message": "Нови сте у Bitwarden-у?" + "message": "New to Bitwarden?" }, "setAStrongPassword": { "message": "Поставите јаку лозинку" @@ -570,16 +621,16 @@ "message": "Пријавите се" }, "logInToBitwarden": { - "message": "Пријавите се на Bitwarden" + "message": "Log in to Bitwarden" }, "logInWithPasskey": { - "message": "Пријавите се са приступним кључем" + "message": "Log in with passkey" }, "loginWithDevice": { - "message": "Пријавите се са уређајем" + "message": "Log in with device" }, "useSingleSignOn": { - "message": "Употребити једнократну пријаву" + "message": "Use single sign-on" }, "submit": { "message": "Пошаљи" @@ -1684,10 +1735,10 @@ "message": "Брисање налога је трајно. Не може се поништити." }, "cannotDeleteAccount": { - "message": "Није могуће избрисати налог" + "message": "Cannot delete account" }, "cannotDeleteAccountDesc": { - "message": "Ова радња се не може довршити јер је ваш налог у власништву организације. Обратите се администратору своје организације за додатне детаље." + "message": "This action cannot be completed because your account is owned by an organization. Contact your organization administrator for additional details." }, "accountDeleted": { "message": "Налог обрисан" @@ -2394,7 +2445,7 @@ "message": "Генеришите имејл" }, "generatorBoundariesHint": { - "message": "Вредност мора бити између $MIN$ и $MAX$", + "message": "Value must be between $MIN$ and $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Нису пронађени портови за SSO пријаву." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "Датотека је сачувана на уређају. Управљајте преузимањима са свог уређаја." } diff --git a/apps/desktop/src/locales/sv/messages.json b/apps/desktop/src/locales/sv/messages.json index 3ba8e329043..2d53383ef8d 100644 --- a/apps/desktop/src/locales/sv/messages.json +++ b/apps/desktop/src/locales/sv/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Säker anteckning" }, + "typeSshKey": { + "message": "SSH-nyckel" + }, "folders": { "message": "Mappar" }, @@ -98,7 +101,7 @@ "message": "Lösenord" }, "passphrase": { - "message": "Lösenordsfras" + "message": "Lösenfras" }, "editItem": { "message": "Redigera objekt" @@ -177,6 +180,48 @@ "address": { "message": "Adress" }, + "sshPrivateKey": { + "message": "Privat nyckel" + }, + "sshPublicKey": { + "message": "Offentlig nyckel" + }, + "sshFingerprint": { + "message": "Fingeravtryck" + }, + "sshKeyAlgorithm": { + "message": "Nyckeltyp" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "En ny SSH-nyckel har genererats" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Aktivera SSH-agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium krävs" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Kopiera lösenord" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Kopiera privat SSH-nyckel" + }, "copyPassphrase": { "message": "Kopiera lösenfras", "description": "Copy passphrase to clipboard" @@ -432,11 +483,11 @@ "message": "Specialtecken (!@#$%^&*)" }, "include": { - "message": "Include", + "message": "Inkludera", "description": "Card header for password generator include block" }, "uppercaseDescription": { - "message": "Include uppercase characters", + "message": "Inkludera versaler", "description": "Tooltip for the password generator uppercase character checkbox" }, "uppercaseLabel": { @@ -444,7 +495,7 @@ "description": "Label for the password generator uppercase character checkbox" }, "lowercaseDescription": { - "message": "Include lowercase characters", + "message": "Inkludera gemener", "description": "Full description for the password generator lowercase character checkbox" }, "lowercaseLabel": { @@ -452,7 +503,7 @@ "description": "Label for the password generator lowercase character checkbox" }, "numbersDescription": { - "message": "Include numbers", + "message": "Inkludera siffror", "description": "Full description for the password generator numbers checkbox" }, "numbersLabel": { @@ -579,7 +630,7 @@ "message": "Logga in med enhet" }, "useSingleSignOn": { - "message": "Use single sign-on" + "message": "Använd Single Sign-On" }, "submit": { "message": "Skicka" @@ -815,7 +866,7 @@ "message": "E-post" }, "emailDescV2": { - "message": "Enter a code sent to your email." + "message": "Ange en kod som skickas per e-post." }, "loginUnavailable": { "message": "Inloggning ej tillgänglig" @@ -912,7 +963,7 @@ "message": "Please restart registration or try logging in." }, "youMayAlreadyHaveAnAccount": { - "message": "You may already have an account" + "message": "Har du redan skapat ett konto?" }, "logOutConfirmation": { "message": "Är du säker på att du vill logga ut?" @@ -1248,7 +1299,7 @@ "description": "Copy credit card number" }, "copyEmail": { - "message": "Copy email" + "message": "Kopiera e-postadress" }, "copySecurityCode": { "message": "Kopiera säkerhetskod", @@ -1684,7 +1735,7 @@ "message": "Att radera ditt konto är permanent. Det går inte att ångra." }, "cannotDeleteAccount": { - "message": "Cannot delete account" + "message": "Kan inte radera konto" }, "cannotDeleteAccountDesc": { "message": "This action cannot be completed because your account is owned by an organization. Contact your organization administrator for additional details." @@ -1864,13 +1915,13 @@ "message": "Ditt nya huvudlösenord uppfyller inte kraven i policyn." }, "receiveMarketingEmailsV2": { - "message": "Get advice, announcements, and research opportunities from Bitwarden in your inbox." + "message": "Få råd, tillkännagivanden och forskningsmöjligheter från Bitwarden i din inkorg." }, "unsubscribe": { "message": "Unsubscribe" }, "atAnyTime": { - "message": "at any time." + "message": "när som helst." }, "byContinuingYouAgreeToThe": { "message": "By continuing, you agree to the" @@ -2451,7 +2502,7 @@ "message": "Skapa ett e-postalias med en extern vidarebefordranstjänst." }, "forwarderDomainName": { - "message": "Email domain", + "message": "E-postdomän", "description": "Labels the domain name email forwarder service option" }, "forwarderDomainNameHint": { @@ -3118,7 +3169,7 @@ "message": "Godkänn inloggningsbegäran i din autentiseringsapp eller ange en engångskod." }, "passcode": { - "message": "Kod" + "message": "Lösenkod" }, "lastPassMasterPassword": { "message": "LastPass Huvudlösenord" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "begär tillgång till" + }, + "unknownApplication": { + "message": "En applikation" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "SSH-nyckeln är ogiltig" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Importera nyckel från urklipp" + }, + "sshKeyPasted": { + "message": "SSH-nyckel har importerats" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/te/messages.json b/apps/desktop/src/locales/te/messages.json index 811885b464d..e9ab6d58e7d 100644 --- a/apps/desktop/src/locales/te/messages.json +++ b/apps/desktop/src/locales/te/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Secure note" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Folders" }, @@ -177,6 +180,48 @@ "address": { "message": "Address" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Copy password" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/th/messages.json b/apps/desktop/src/locales/th/messages.json index 2f02f780193..d399b2d4bd6 100644 --- a/apps/desktop/src/locales/th/messages.json +++ b/apps/desktop/src/locales/th/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "บันทึกการรักษาปลอดภัย" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "โฟลเดอร์" }, @@ -177,6 +180,48 @@ "address": { "message": "ที่อยู่" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium Required" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "คัดลอกรหัสผ่าน" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/tr/messages.json b/apps/desktop/src/locales/tr/messages.json index 30626fe9dec..667670031b2 100644 --- a/apps/desktop/src/locales/tr/messages.json +++ b/apps/desktop/src/locales/tr/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Güvenli not" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Klasörler" }, @@ -61,7 +64,7 @@ } }, "welcomeBack": { - "message": "Tekrar hoş geldiniz" + "message": "Welcome back" }, "moveToOrgDesc": { "message": "Bu kaydı taşımak istediğiniz kuruluşu seçin. Taşıdığınız kaydın sahipliği seçtiğiniz kuruluşa aktarılacak. Artık bu kaydın doğrudan sahibi olmayacaksınız." @@ -177,6 +180,48 @@ "address": { "message": "Adres" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Premium gerekli" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Parolayı kopyala" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -558,7 +609,7 @@ "message": "Hesap oluştur" }, "newToBitwarden": { - "message": "Bitwarden'da yeni misiniz?" + "message": "New to Bitwarden?" }, "setAStrongPassword": { "message": "Güçlü bir parola belirleyin" @@ -570,16 +621,16 @@ "message": "Giriş yap" }, "logInToBitwarden": { - "message": "Bitwarden'a giriş yapın" + "message": "Log in to Bitwarden" }, "logInWithPasskey": { - "message": "Geçiş anahtarıyla giriş yap" + "message": "Log in with passkey" }, "loginWithDevice": { - "message": "Cihazla giriş yap" + "message": "Log in with device" }, "useSingleSignOn": { - "message": "Çoklu oturum açma kullan" + "message": "Use single sign-on" }, "submit": { "message": "Gönder" @@ -1684,10 +1735,10 @@ "message": "Hesabınızı silmek kalıcıdır. Geri alınamaz." }, "cannotDeleteAccount": { - "message": "Hesap silinemiyor" + "message": "Cannot delete account" }, "cannotDeleteAccountDesc": { - "message": "Hesabınızın sahibi bir kuruluş olduğu için bu işlem tamamlanamadı. Bilgi almak için kuruluş yöneticinizle iletişime geçin." + "message": "This action cannot be completed because your account is owned by an organization. Contact your organization administrator for additional details." }, "accountDeleted": { "message": "Hesap silindi" @@ -2394,7 +2445,7 @@ "message": "E-posta oluştur" }, "generatorBoundariesHint": { - "message": "Değer $MIN$ ile $MAX$ arasında olmalıdır", + "message": "Value must be between $MIN$ and $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -3225,6 +3276,36 @@ "ssoError": { "message": "SSO girişi için açık port bulunamadı." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "Dosya cihaza kaydedildi. Cihazınızın indirilenler klasöründen yönetebilirsiniz." } diff --git a/apps/desktop/src/locales/uk/messages.json b/apps/desktop/src/locales/uk/messages.json index a191b6526da..98391a2a50f 100644 --- a/apps/desktop/src/locales/uk/messages.json +++ b/apps/desktop/src/locales/uk/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Захищена нотатка" }, + "typeSshKey": { + "message": "Ключ SSH" + }, "folders": { "message": "Теки" }, @@ -177,6 +180,48 @@ "address": { "message": "Адреса" }, + "sshPrivateKey": { + "message": "Закритий ключ" + }, + "sshPublicKey": { + "message": "Відкритий ключ" + }, + "sshFingerprint": { + "message": "Цифровий відбиток" + }, + "sshKeyAlgorithm": { + "message": "Тип ключа" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "Згенеровано новий ключ SSH" + }, + "sshAgentUnlockRequired": { + "message": "Розблокуйте своє сховище, щоб затвердити запит ключа SSH." + }, + "sshAgentUnlockTimeout": { + "message": "Вичерпано час очікування запиту ключа SSH." + }, + "enableSshAgent": { + "message": "Увімкнути агента SSH" + }, + "enableSshAgentDesc": { + "message": "Увімкніть агента SSH, щоб підписувати запити SSH безпосередньо зі сховища Bitwarden." + }, + "enableSshAgentHelp": { + "message": "Агент SSH – це служба, призначена для розробників, яка дає можливість підписувати запити SSH безпосередньо зі сховища Bitwarden." + }, "premiumRequired": { "message": "Необхідна передплата преміум" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Копіювати пароль" }, + "regenerateSshKey": { + "message": "Повторно згенерувати ключ SSH" + }, + "copySshPrivateKey": { + "message": "Копіювати закритий ключ SSH" + }, "copyPassphrase": { "message": "Копіювати парольну фразу", "description": "Copy passphrase to clipboard" @@ -579,7 +630,7 @@ "message": "Увійти з пристроєм" }, "useSingleSignOn": { - "message": "Використовувати єдиний вхід" + "message": "Використати єдиний вхід" }, "submit": { "message": "Відправити" @@ -2394,7 +2445,7 @@ "message": "Генерувати е-пошту" }, "generatorBoundariesHint": { - "message": "Значення має бути між $MIN$ та $MAX$", + "message": "Value must be between $MIN$ and $MAX$", "description": "Explains spin box minimum and maximum values to the user", "placeholders": { "min": { @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Не знайдено вільних портів для цього входу SSO." }, + "authorize": { + "message": "Авторизувати" + }, + "deny": { + "message": "Відмовити" + }, + "sshkeyApprovalTitle": { + "message": "Підтвердження використання ключа SSH" + }, + "sshkeyApprovalMessageInfix": { + "message": "запитує доступ до" + }, + "unknownApplication": { + "message": "Програма" + }, + "sshKeyPasswordUnsupported": { + "message": "Імпортування захищених паролем ключів SSH ще не підтримується" + }, + "invalidSshKey": { + "message": "Ключ SSH недійсний" + }, + "sshKeyTypeUnsupported": { + "message": "Тип ключа SSH не підтримується" + }, + "importSshKeyFromClipboard": { + "message": "Імпортувати ключ із буфера обміну" + }, + "sshKeyPasted": { + "message": "Ключ SSH успішно імпортовано" + }, "fileSavedToDevice": { "message": "Файл збережено на пристрої. Ви можете його знайти у теці завантажень." } diff --git a/apps/desktop/src/locales/vi/messages.json b/apps/desktop/src/locales/vi/messages.json index 3f3c680b978..fa7b44b76cc 100644 --- a/apps/desktop/src/locales/vi/messages.json +++ b/apps/desktop/src/locales/vi/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "Ghi chú bảo mật" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "Thư mục" }, @@ -177,6 +180,48 @@ "address": { "message": "Địa chỉ" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "Cần có tài khoản cao cấp" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "Sao chép Mật khẩu" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "Không thể tìm thấy cổng trống để đăng nhập SSO." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/locales/zh_CN/messages.json b/apps/desktop/src/locales/zh_CN/messages.json index 1382becc6da..9ca367526b2 100644 --- a/apps/desktop/src/locales/zh_CN/messages.json +++ b/apps/desktop/src/locales/zh_CN/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "安全笔记" }, + "typeSshKey": { + "message": "SSH 密钥" + }, "folders": { "message": "文件夹" }, @@ -177,6 +180,48 @@ "address": { "message": "地址" }, + "sshPrivateKey": { + "message": "私钥" + }, + "sshPublicKey": { + "message": "公钥" + }, + "sshFingerprint": { + "message": "指纹" + }, + "sshKeyAlgorithm": { + "message": "密钥类型" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "生成了新的 SSH 密钥" + }, + "sshAgentUnlockRequired": { + "message": "请解锁您的密码库以批准 SSH 密钥请求。" + }, + "sshAgentUnlockTimeout": { + "message": "SSH 密钥请求已超时。" + }, + "enableSshAgent": { + "message": "启用 SSH 代理" + }, + "enableSshAgentDesc": { + "message": "启用 SSH 代理以直接从您的 Bitwarden 密码库签署 SSH 请求。" + }, + "enableSshAgentHelp": { + "message": "SSH 代理是一个针对开发者的服务,允许您直接从 Bitwarden 密码库签署 SSH 请求。" + }, "premiumRequired": { "message": "需要高级版" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "复制密码" }, + "regenerateSshKey": { + "message": "重新生成 SSH 密钥" + }, + "copySshPrivateKey": { + "message": "复制 SSH 私钥" + }, "copyPassphrase": { "message": "复制密码短语", "description": "Copy passphrase to clipboard" @@ -558,7 +609,7 @@ "message": "创建账户" }, "newToBitwarden": { - "message": "Bitwarden 新手吗?" + "message": "您是 Bitwarden 新手吗?" }, "setAStrongPassword": { "message": "设置强密码" @@ -2391,7 +2442,7 @@ "message": "生成用户名" }, "generateEmail": { - "message": "生成邮件地址" + "message": "生成电子邮件地址" }, "generatorBoundariesHint": { "message": "值必须在 $MIN$ 和 $MAX$ 之间", @@ -2451,7 +2502,7 @@ "message": "使用外部转发服务生成一个电子邮件别名。" }, "forwarderDomainName": { - "message": "邮件域名", + "message": "电子邮件域名", "description": "Labels the domain name email forwarder service option" }, "forwarderDomainNameHint": { @@ -3225,6 +3276,36 @@ "ssoError": { "message": "找不到用于 SSO 登录的可用端口。" }, + "authorize": { + "message": "批准" + }, + "deny": { + "message": "拒绝" + }, + "sshkeyApprovalTitle": { + "message": "确认 SSH 密钥使用" + }, + "sshkeyApprovalMessageInfix": { + "message": "正在请求访问" + }, + "unknownApplication": { + "message": "某个应用程序" + }, + "sshKeyPasswordUnsupported": { + "message": "尚不支持导入受密码保护的 SSH 密钥" + }, + "invalidSshKey": { + "message": "此 SSH 密钥无效" + }, + "sshKeyTypeUnsupported": { + "message": "不支持此 SSH 密钥类型" + }, + "importSshKeyFromClipboard": { + "message": "从剪贴板导入密钥" + }, + "sshKeyPasted": { + "message": "SSH 密钥导入成功" + }, "fileSavedToDevice": { "message": "文件已保存到设备。可以在设备下载中进行管理。" } diff --git a/apps/desktop/src/locales/zh_TW/messages.json b/apps/desktop/src/locales/zh_TW/messages.json index c1c84ff912e..1b42e57da9c 100644 --- a/apps/desktop/src/locales/zh_TW/messages.json +++ b/apps/desktop/src/locales/zh_TW/messages.json @@ -26,6 +26,9 @@ "typeSecureNote": { "message": "安全筆記" }, + "typeSshKey": { + "message": "SSH key" + }, "folders": { "message": "資料夾" }, @@ -177,6 +180,48 @@ "address": { "message": "地址" }, + "sshPrivateKey": { + "message": "Private key" + }, + "sshPublicKey": { + "message": "Public key" + }, + "sshFingerprint": { + "message": "Fingerprint" + }, + "sshKeyAlgorithm": { + "message": "Key type" + }, + "sshKeyAlgorithmED25519": { + "message": "ED25519" + }, + "sshKeyAlgorithmRSA2048": { + "message": "RSA 2048-Bit" + }, + "sshKeyAlgorithmRSA3072": { + "message": "RSA 3072-Bit" + }, + "sshKeyAlgorithmRSA4096": { + "message": "RSA 4096-Bit" + }, + "sshKeyGenerated": { + "message": "A new SSH key was generated" + }, + "sshAgentUnlockRequired": { + "message": "Please unlock your vault to approve the SSH key request." + }, + "sshAgentUnlockTimeout": { + "message": "SSH key request timed out." + }, + "enableSshAgent": { + "message": "Enable SSH agent" + }, + "enableSshAgentDesc": { + "message": "Enable the SSH agent to sign SSH requests right from your Bitwarden vault." + }, + "enableSshAgentHelp": { + "message": "The SSH agent is a service targeted at developers that allows you to sign SSH requests directly from your Bitwarden vault." + }, "premiumRequired": { "message": "需要進階會員資格" }, @@ -400,6 +445,12 @@ "copyPassword": { "message": "複製密碼" }, + "regenerateSshKey": { + "message": "Regenerate SSH key" + }, + "copySshPrivateKey": { + "message": "Copy SSH private key" + }, "copyPassphrase": { "message": "Copy passphrase", "description": "Copy passphrase to clipboard" @@ -3225,6 +3276,36 @@ "ssoError": { "message": "No free ports could be found for the sso login." }, + "authorize": { + "message": "Authorize" + }, + "deny": { + "message": "Deny" + }, + "sshkeyApprovalTitle": { + "message": "Confirm SSH key usage" + }, + "sshkeyApprovalMessageInfix": { + "message": "is requesting access to" + }, + "unknownApplication": { + "message": "An application" + }, + "sshKeyPasswordUnsupported": { + "message": "Importing password protected SSH keys is not yet supported" + }, + "invalidSshKey": { + "message": "The SSH key is invalid" + }, + "sshKeyTypeUnsupported": { + "message": "The SSH key type is not supported" + }, + "importSshKeyFromClipboard": { + "message": "Import key from clipboard" + }, + "sshKeyPasted": { + "message": "SSH key imported successfully" + }, "fileSavedToDevice": { "message": "File saved to device. Manage from your device downloads." } diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index f869898d57b..bbb5c23513e 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -39,6 +39,7 @@ import { ClipboardMain } from "./platform/main/clipboard.main"; import { DesktopCredentialStorageListener } from "./platform/main/desktop-credential-storage-listener"; import { MainCryptoFunctionService } from "./platform/main/main-crypto-function.service"; import { MainSshAgentService } from "./platform/main/main-ssh-agent.service"; +import { VersionMain } from "./platform/main/version.main"; import { DesktopSettingsService } from "./platform/services/desktop-settings.service"; import { ElectronLogMainService } from "./platform/services/electron-log.main.service"; import { ElectronStorageService } from "./platform/services/electron-storage.service"; @@ -72,6 +73,7 @@ export class Main { nativeMessagingMain: NativeMessagingMain; clipboardMain: ClipboardMain; desktopAutofillSettingsService: DesktopAutofillSettingsService; + versionMain: VersionMain; sshAgentService: MainSshAgentService; constructor() { @@ -199,6 +201,8 @@ export class Main { }); }); + this.versionMain = new VersionMain(this.windowMain); + this.powerMonitorMain = new PowerMonitorMain(this.messagingService, this.logService); this.menuMain = new MenuMain( this.i18nService, @@ -207,6 +211,7 @@ export class Main { this.windowMain, this.updaterMain, this.desktopSettingsService, + this.versionMain, ); this.biometricsService = new BiometricsService( diff --git a/apps/desktop/src/main/menu/menu.about.ts b/apps/desktop/src/main/menu/menu.about.ts index 50e125b3d6c..bd82d73fcb4 100644 --- a/apps/desktop/src/main/menu/menu.about.ts +++ b/apps/desktop/src/main/menu/menu.about.ts @@ -2,6 +2,7 @@ import { BrowserWindow, clipboard, dialog, MenuItemConstructorOptions } from "el import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { VersionMain } from "../../platform/main/version.main"; import { isMacAppStore, isSnapStore, isWindowsStore } from "../../utils"; import { UpdaterMain } from "../updater.main"; @@ -22,17 +23,20 @@ export class AboutMenu implements IMenubarMenu { private readonly _updater: UpdaterMain; private readonly _window: BrowserWindow; private readonly _version: string; + private readonly _versionMain: VersionMain; constructor( i18nService: I18nService, version: string, window: BrowserWindow, updater: UpdaterMain, + versionMain: VersionMain, ) { this._i18nService = i18nService; this._updater = updater; this._version = version; this._window = window; + this._versionMain = versionMain; } private get separator(): MenuItemConstructorOptions { @@ -53,8 +57,11 @@ export class AboutMenu implements IMenubarMenu { id: "aboutBitwarden", label: this.localize("aboutBitwarden"), click: async () => { + const sdkVersion = await this._versionMain.sdkVersion(); const aboutInformation = this.localize("version", this._version) + + "\nSDK " + + sdkVersion + "\nShell " + process.versions.electron + "\nRenderer " + diff --git a/apps/desktop/src/main/menu/menu.main.ts b/apps/desktop/src/main/menu/menu.main.ts index 9a63d389b59..eafadf3bfb5 100644 --- a/apps/desktop/src/main/menu/menu.main.ts +++ b/apps/desktop/src/main/menu/menu.main.ts @@ -5,6 +5,7 @@ import { EnvironmentService } from "@bitwarden/common/platform/abstractions/envi import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; +import { VersionMain } from "../../platform/main/version.main"; import { DesktopSettingsService } from "../../platform/services/desktop-settings.service"; import { UpdaterMain } from "../updater.main"; import { WindowMain } from "../window.main"; @@ -22,6 +23,7 @@ export class MenuMain { private windowMain: WindowMain, private updaterMain: UpdaterMain, private desktopSettingsService: DesktopSettingsService, + private versionMain: VersionMain, ) {} async init() { @@ -44,6 +46,7 @@ export class MenuMain { await this.getWebVaultUrl(), app.getVersion(), await firstValueFrom(this.desktopSettingsService.hardwareAcceleration$), + this.versionMain, updateRequest, ).menu, ); diff --git a/apps/desktop/src/main/menu/menubar.ts b/apps/desktop/src/main/menu/menubar.ts index b71774c5afe..f69174b9a3b 100644 --- a/apps/desktop/src/main/menu/menubar.ts +++ b/apps/desktop/src/main/menu/menubar.ts @@ -3,6 +3,7 @@ import { Menu, MenuItemConstructorOptions } from "electron"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; +import { VersionMain } from "../../platform/main/version.main"; import { DesktopSettingsService } from "../../platform/services/desktop-settings.service"; import { isMac } from "../../utils"; import { UpdaterMain } from "../updater.main"; @@ -54,6 +55,7 @@ export class Menubar { webVaultUrl: string, appVersion: string, hardwareAccelerationEnabled: boolean, + versionMain: VersionMain, updateRequest?: MenuUpdateRequest, ) { let isLocked = true; @@ -96,7 +98,7 @@ export class Menubar { desktopSettingsService, webVaultUrl, hardwareAccelerationEnabled, - new AboutMenu(i18nService, appVersion, windowMain.win, updaterMain), + new AboutMenu(i18nService, appVersion, windowMain.win, updaterMain, versionMain), ), ]; diff --git a/apps/desktop/src/main/native-messaging.main.ts b/apps/desktop/src/main/native-messaging.main.ts index 16594792f71..42be83a303f 100644 --- a/apps/desktop/src/main/native-messaging.main.ts +++ b/apps/desktop/src/main/native-messaging.main.ts @@ -93,11 +93,23 @@ export class NativeMessagingMain { break; } case ipc.IpcMessageType.Message: - this.windowMain.win.webContents.send("nativeMessaging", JSON.parse(msg.message)); + try { + const msgJson = JSON.parse(msg.message); + this.logService.debug("Native messaging message:", msgJson); + this.windowMain.win?.webContents.send("nativeMessaging", msgJson); + } catch (e) { + this.logService.warning("Error processing message:", e, msg.message); + } + break; + + default: + this.logService.warning("Unknown message type:", msg.kind, msg.message); break; } }); + this.logService.info("Native messaging server started at:", this.ipcServer.getPath()); + ipcMain.on("nativeMessagingReply", (event, msg) => { if (msg != null) { this.send(msg); @@ -110,6 +122,7 @@ export class NativeMessagingMain { } send(message: object) { + this.logService.debug("Native messaging reply:", message); this.ipcServer?.send(JSON.stringify(message)); } diff --git a/apps/desktop/src/package-lock.json b/apps/desktop/src/package-lock.json index 21075252981..f47f0f6a281 100644 --- a/apps/desktop/src/package-lock.json +++ b/apps/desktop/src/package-lock.json @@ -1,12 +1,12 @@ { "name": "@bitwarden/desktop", - "version": "2024.11.0", + "version": "2024.11.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@bitwarden/desktop", - "version": "2024.11.0", + "version": "2024.11.1", "license": "GPL-3.0", "dependencies": { "@bitwarden/desktop-napi": "file:../desktop_native/napi", diff --git a/apps/desktop/src/package.json b/apps/desktop/src/package.json index 3f4bb0fc0cf..ca700eff2c6 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": "2024.11.0", + "version": "2024.11.1", "author": "Bitwarden Inc. (https://bitwarden.com)", "homepage": "https://bitwarden.com", "license": "GPL-3.0", diff --git a/apps/desktop/src/platform/main/main-ssh-agent.service.ts b/apps/desktop/src/platform/main/main-ssh-agent.service.ts index c8227e5b6a5..60487aae4da 100644 --- a/apps/desktop/src/platform/main/main-ssh-agent.service.ts +++ b/apps/desktop/src/platform/main/main-ssh-agent.service.ts @@ -79,7 +79,7 @@ export class MainSshAgentService { ipcMain.handle( "sshagent.setkeys", async (event: any, keys: { name: string; privateKey: string; cipherId: string }[]) => { - if (this.agentState != null) { + if (this.agentState != null && (await sshagent.isRunning(this.agentState))) { sshagent.setKeys(this.agentState, keys); } }, @@ -107,7 +107,7 @@ export class MainSshAgentService { ); ipcMain.handle("sshagent.lock", async (event: any) => { - if (this.agentState != null) { + if (this.agentState != null && (await sshagent.isRunning(this.agentState))) { sshagent.lock(this.agentState); } }); diff --git a/apps/desktop/src/platform/main/version.main.ts b/apps/desktop/src/platform/main/version.main.ts new file mode 100644 index 00000000000..1c39b641d27 --- /dev/null +++ b/apps/desktop/src/platform/main/version.main.ts @@ -0,0 +1,17 @@ +import { ipcMain } from "electron"; + +import { WindowMain } from "../../main/window.main"; + +export class VersionMain { + constructor(private windowMain: WindowMain) {} + + sdkVersion() { + const timeout = new Promise((resolve) => setTimeout(() => resolve("Timeout error"), 1000)); + const version = new Promise((resolve) => { + ipcMain.once("sdkVersion", (_, version) => resolve(version)); + this.windowMain.win.webContents.send("sdkVersion"); + }); + + return Promise.race([timeout, version]); + } +} diff --git a/apps/desktop/src/platform/preload.ts b/apps/desktop/src/platform/preload.ts index 35caeff27c8..171e83bbef0 100644 --- a/apps/desktop/src/platform/preload.ts +++ b/apps/desktop/src/platform/preload.ts @@ -122,6 +122,13 @@ const localhostCallbackService = { export default { versions: { app: (): Promise => ipcRenderer.invoke("appVersion"), + registerSdkVersionProvider: (provide: (resolve: (version: string) => void) => void) => { + const resolve = (version: string) => ipcRenderer.send("sdkVersion", version); + + ipcRenderer.on("sdkVersion", () => { + provide(resolve); + }); + }, }, deviceType: deviceType(), isDev: isDev(), diff --git a/apps/desktop/src/platform/services/ssh-agent.service.ts b/apps/desktop/src/platform/services/ssh-agent.service.ts index dd518a943b8..fdd86788ed5 100644 --- a/apps/desktop/src/platform/services/ssh-agent.service.ts +++ b/apps/desktop/src/platform/services/ssh-agent.service.ts @@ -37,7 +37,7 @@ import { DesktopSettingsService } from "./desktop-settings.service"; }) export class SshAgentService implements OnDestroy { SSH_REFRESH_INTERVAL = 1000; - SSH_VAULT_UNLOCK_REQUEST_TIMEOUT = 1000 * 60; + SSH_VAULT_UNLOCK_REQUEST_TIMEOUT = 60_000; SSH_REQUEST_UNLOCK_POLLING_INTERVAL = 100; private destroy$ = new Subject(); @@ -79,7 +79,9 @@ export class SshAgentService implements OnDestroy { }); return this.authService.activeAccountStatus$.pipe( filter((status) => status === AuthenticationStatus.Unlocked), - timeout(this.SSH_VAULT_UNLOCK_REQUEST_TIMEOUT), + timeout({ + first: this.SSH_VAULT_UNLOCK_REQUEST_TIMEOUT, + }), catchError((error: unknown) => { if (error instanceof TimeoutError) { this.toastService.showToast({ diff --git a/apps/desktop/src/platform/services/version.service.ts b/apps/desktop/src/platform/services/version.service.ts new file mode 100644 index 00000000000..2628f83d593 --- /dev/null +++ b/apps/desktop/src/platform/services/version.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from "@angular/core"; +import { firstValueFrom } from "rxjs"; + +import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service"; + +@Injectable({ + providedIn: "root", +}) +export class VersionService { + constructor(private sdkService: SdkService) {} + + init() { + ipc.platform.versions.registerSdkVersionProvider(async (resolve) => { + const version = await firstValueFrom(this.sdkService.version$); + resolve(version); + }); + } +} diff --git a/apps/desktop/src/scss/left-nav.scss b/apps/desktop/src/scss/left-nav.scss index 4404110ba65..d65e60079a5 100644 --- a/apps/desktop/src/scss/left-nav.scss +++ b/apps/desktop/src/scss/left-nav.scss @@ -116,6 +116,7 @@ color: themed("primaryColor"); font-weight: bold; } + max-width: 90%; } .edit-button { diff --git a/apps/desktop/src/scss/variables.scss b/apps/desktop/src/scss/variables.scss index 6f8112b1ca0..23a4644d3da 100644 --- a/apps/desktop/src/scss/variables.scss +++ b/apps/desktop/src/scss/variables.scss @@ -2,7 +2,7 @@ $dark-icon-themes: "theme_dark", "theme_nord"; -$font-family-sans-serif: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +$font-family-sans-serif: "DM Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; $font-size-base: 14px; $font-size-large: 18px; diff --git a/apps/desktop/src/vault/app/vault/add-edit.component.ts b/apps/desktop/src/vault/app/vault/add-edit.component.ts index a3a9c929159..015a7c6b21b 100644 --- a/apps/desktop/src/vault/app/vault/add-edit.component.ts +++ b/apps/desktop/src/vault/app/vault/add-edit.component.ts @@ -111,9 +111,19 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit, On ) { this.cipher = null; } - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - super.load(); + + await super.load(); + + if (!this.editMode || this.cloneMode) { + // Creating an ssh key directly while filtering to the ssh key category + // must force a key to be set. SSH keys must never be created with an empty private key field + if ( + this.cipher.type === CipherType.SshKey && + (this.cipher.sshKey.privateKey == null || this.cipher.sshKey.privateKey === "") + ) { + await this.generateSshKey(false); + } + } } onWindowHidden() { @@ -145,16 +155,19 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit, On ); } - async generateSshKey() { + async generateSshKey(showNotification: boolean = true) { const sshKey = await ipc.platform.sshAgent.generateKey("ed25519"); this.cipher.sshKey.privateKey = sshKey.privateKey; this.cipher.sshKey.publicKey = sshKey.publicKey; this.cipher.sshKey.keyFingerprint = sshKey.keyFingerprint; - this.toastService.showToast({ - variant: "success", - title: "", - message: this.i18nService.t("sshKeyGenerated"), - }); + + if (showNotification) { + this.toastService.showToast({ + variant: "success", + title: "", + message: this.i18nService.t("sshKeyGenerated"), + }); + } } async importSshKeyFromClipboard() { diff --git a/apps/web/config/base.json b/apps/web/config/base.json index cfaf604fb02..e64ef6ebeb2 100644 --- a/apps/web/config/base.json +++ b/apps/web/config/base.json @@ -11,7 +11,6 @@ "allowedHosts": "auto" }, "flags": { - "showPasswordless": false, "sdk": true }, "devFlags": {} diff --git a/apps/web/config/cloud.json b/apps/web/config/cloud.json index 8817142c9ed..600b346893b 100644 --- a/apps/web/config/cloud.json +++ b/apps/web/config/cloud.json @@ -16,7 +16,5 @@ "proxyEvents": "https://events.bitwarden.com", "proxyNotifications": "https://notifications.bitwarden.com" }, - "flags": { - "showPasswordless": true - } + "flags": {} } diff --git a/apps/web/config/development.json b/apps/web/config/development.json index 58dec82a154..f0a15f4f4d6 100644 --- a/apps/web/config/development.json +++ b/apps/web/config/development.json @@ -19,8 +19,6 @@ } } ], - "flags": { - "showPasswordless": true - }, + "flags": {}, "devFlags": {} } diff --git a/apps/web/config/euprd.json b/apps/web/config/euprd.json index 99d98ca09dd..016d7133e5c 100644 --- a/apps/web/config/euprd.json +++ b/apps/web/config/euprd.json @@ -10,7 +10,5 @@ "businessId": "4ZDA7DLUUJGMN", "buttonAction": "https://www.paypal.com/cgi-bin/webscr" }, - "flags": { - "showPasswordless": true - } + "flags": {} } diff --git a/apps/web/config/euqa.json b/apps/web/config/euqa.json index 5f74eb88294..9743654b94c 100644 --- a/apps/web/config/euqa.json +++ b/apps/web/config/euqa.json @@ -20,7 +20,5 @@ } } ], - "flags": { - "showPasswordless": true - } + "flags": {} } diff --git a/apps/web/config/qa.json b/apps/web/config/qa.json index 07e341e6f9f..877506a20dd 100644 --- a/apps/web/config/qa.json +++ b/apps/web/config/qa.json @@ -26,7 +26,5 @@ } } ], - "flags": { - "showPasswordless": true - } + "flags": {} } diff --git a/apps/web/config/selfhosted.json b/apps/web/config/selfhosted.json index 9d8e1cf2685..cd36ab15c5e 100644 --- a/apps/web/config/selfhosted.json +++ b/apps/web/config/selfhosted.json @@ -6,7 +6,5 @@ "proxyNotifications": "http://localhost:61841", "port": 8081 }, - "flags": { - "showPasswordless": true - } + "flags": {} } diff --git a/apps/web/config/usdev.json b/apps/web/config/usdev.json index c19deba27b1..88adaa726ce 100644 --- a/apps/web/config/usdev.json +++ b/apps/web/config/usdev.json @@ -13,7 +13,5 @@ } } ], - "flags": { - "showPasswordless": true - } + "flags": {} } diff --git a/apps/web/src/404.html b/apps/web/src/404.html index 817bfe30985..1a01aee40c7 100644 --- a/apps/web/src/404.html +++ b/apps/web/src/404.html @@ -30,7 +30,7 @@ Go to your web vault -
+
diff --git a/apps/web/src/app/admin-console/organizations/guards/is-enterprise-org.guard.ts b/apps/web/src/app/admin-console/organizations/guards/is-enterprise-org.guard.ts index 3373f0cfd53..8a0d374997d 100644 --- a/apps/web/src/app/admin-console/organizations/guards/is-enterprise-org.guard.ts +++ b/apps/web/src/app/admin-console/organizations/guards/is-enterprise-org.guard.ts @@ -6,10 +6,8 @@ import { RouterStateSnapshot, } from "@angular/router"; -import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { ProductTierType } from "@bitwarden/common/billing/enums"; -import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { DialogService } from "@bitwarden/components"; /** @@ -31,11 +29,6 @@ export function isEnterpriseOrgGuard(): CanActivateFn { return router.createUrlTree(["/"]); } - // TODO: Remove on "MemberAccessReport" feature flag cleanup - if (!canAccessFeature(FeatureFlag.MemberAccessReport)) { - return router.createUrlTree(["/"]); - } - if (org.productTierType != ProductTierType.Enterprise) { // Users without billing permission can't access billing if (!org.canEditSubscription) { diff --git a/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.html b/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.html index 9cd94c5208c..aaba492dff8 100644 --- a/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.html +++ b/apps/web/src/app/admin-console/organizations/layouts/organization-layout.component.html @@ -2,7 +2,16 @@ - + + + - ; hideNewOrgButton$: Observable; organizationIsUnmanaged$: Observable; - isRiskInsightsFeatureEnabled = false; + isAccessIntelligenceFeatureEnabled = false; private _destroy = new Subject(); @@ -67,7 +67,7 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy { async ngOnInit() { document.body.classList.remove("layout_frontend"); - this.isRiskInsightsFeatureEnabled = await this.configService.getFeatureFlag( + this.isAccessIntelligenceFeatureEnabled = await this.configService.getFeatureFlag( FeatureFlag.AccessIntelligence, ); diff --git a/apps/web/src/app/admin-console/organizations/manage/groups.component.ts b/apps/web/src/app/admin-console/organizations/manage/groups.component.ts index dd0cde70e67..4525d87706d 100644 --- a/apps/web/src/app/admin-console/organizations/manage/groups.component.ts +++ b/apps/web/src/app/admin-console/organizations/manage/groups.component.ts @@ -59,6 +59,7 @@ type GroupDetailsRow = { * with members' names (who are assigned to the group) or collection names (which the group has access to). */ const groupsFilter = (filter: string) => { + filter ??= ""; const transformedFilter = filter.trim().toLowerCase(); return (data: GroupDetailsRow) => { const group = data.details; @@ -81,8 +82,8 @@ export class GroupsComponent { protected searchControl = new FormControl(""); // Fixed sizes used for cdkVirtualScroll - protected rowHeight = 46; - protected rowHeightClass = `tw-h-[46px]`; + protected rowHeight = 52; + protected rowHeightClass = `tw-h-[52px]`; protected ModalTabType = GroupAddEditTabType; private refreshGroups$ = new BehaviorSubject(null); diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-delete-dialog.component.html b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-delete-dialog.component.html new file mode 100644 index 00000000000..9a4ce89671e --- /dev/null +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-delete-dialog.component.html @@ -0,0 +1,85 @@ + + + + {{ "noSelectedMembersApplicable" | i18n }} + + + {{ error }} + + + +

{{ "deleteOrganizationUserWarning" | i18n }}

+
+ + + + {{ "member" | i18n }} + + + + + + + + +
+ {{ user.email }} + + {{ "invited" | i18n }} + +
+ {{ user.name }} + + +
+
+
+ + + + + {{ "member" | i18n }} + {{ "status" | i18n }} + + + + + + + + + {{ user.email }} + {{ user.name }} + + + {{ statuses.get(user.id) }} + + + {{ "bulkFilteredMessage" | i18n }} + + + + + +
+ + + + +
diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-delete-dialog.component.ts b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-delete-dialog.component.ts new file mode 100644 index 00000000000..1755b0b0b91 --- /dev/null +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-delete-dialog.component.ts @@ -0,0 +1,65 @@ +import { DIALOG_DATA, DialogConfig } from "@angular/cdk/dialog"; +import { Component, Inject } from "@angular/core"; + +import { OrganizationUserApiService } from "@bitwarden/admin-console/common"; +import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enums"; +import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { DialogService } from "@bitwarden/components"; + +import { BulkUserDetails } from "./bulk-status.component"; + +type BulkDeleteDialogParams = { + organizationId: string; + users: BulkUserDetails[]; +}; + +@Component({ + templateUrl: "bulk-delete-dialog.component.html", +}) +export class BulkDeleteDialogComponent { + organizationId: string; + users: BulkUserDetails[]; + loading = false; + done = false; + error: string = null; + statuses = new Map(); + userStatusType = OrganizationUserStatusType; + + constructor( + @Inject(DIALOG_DATA) protected dialogParams: BulkDeleteDialogParams, + protected i18nService: I18nService, + private organizationUserApiService: OrganizationUserApiService, + ) { + this.organizationId = dialogParams.organizationId; + this.users = dialogParams.users; + } + + async submit() { + try { + this.loading = true; + this.error = null; + + const response = await this.organizationUserApiService.deleteManyOrganizationUsers( + this.organizationId, + this.users.map((user) => user.id), + ); + + response.data.forEach((entry) => { + this.statuses.set( + entry.id, + entry.error ? entry.error : this.i18nService.t("deletedSuccessfully"), + ); + }); + + this.done = true; + } catch (e) { + this.error = e.message; + } finally { + this.loading = false; + } + } + + static open(dialogService: DialogService, config: DialogConfig) { + return dialogService.open(BulkDeleteDialogComponent, config); + } +} diff --git a/apps/web/src/app/admin-console/organizations/members/members.component.html b/apps/web/src/app/admin-console/organizations/members/members.component.html index f87934dbe81..a9c5ab3e4a8 100644 --- a/apps/web/src/app/admin-console/organizations/members/members.component.html +++ b/apps/web/src/app/admin-console/organizations/members/members.component.html @@ -137,6 +137,17 @@ {{ "remove" | i18n }} + diff --git a/apps/web/src/app/admin-console/organizations/members/members.component.ts b/apps/web/src/app/admin-console/organizations/members/members.component.ts index f1cd505de0a..aff33414e6f 100644 --- a/apps/web/src/app/admin-console/organizations/members/members.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/members.component.ts @@ -61,6 +61,7 @@ import { OrganizationUserView } from "../core/views/organization-user.view"; import { openEntityEventsDialog } from "../manage/entity-events.component"; import { BulkConfirmDialogComponent } from "./components/bulk/bulk-confirm-dialog.component"; +import { BulkDeleteDialogComponent } from "./components/bulk/bulk-delete-dialog.component"; import { BulkEnableSecretsManagerDialogComponent } from "./components/bulk/bulk-enable-sm-dialog.component"; import { BulkRemoveDialogComponent } from "./components/bulk/bulk-remove-dialog.component"; import { BulkRestoreRevokeComponent } from "./components/bulk/bulk-restore-revoke.component"; @@ -98,17 +99,13 @@ export class MembersComponent extends BaseMembersComponent protected canUseSecretsManager$: Observable; - protected enableUpgradePasswordManagerSub$ = this.configService.getFeatureFlag$( - FeatureFlag.EnableUpgradePasswordManagerSub, - ); - protected accountDeprovisioningEnabled$: Observable = this.configService.getFeatureFlag$( FeatureFlag.AccountDeprovisioning, ); // Fixed sizes used for cdkVirtualScroll - protected rowHeight = 62; - protected rowHeightClass = `tw-h-[62px]`; + protected rowHeight = 69; + protected rowHeightClass = `tw-h-[69px]`; constructor( apiService: ApiService, @@ -487,29 +484,20 @@ export class MembersComponent extends BaseMembersComponent this.organization.productTierType === ProductTierType.TeamsStarter || this.organization.productTierType === ProductTierType.Families) ) { - const enableUpgradePasswordManagerSub = await firstValueFrom( - this.enableUpgradePasswordManagerSub$, - ); - if (enableUpgradePasswordManagerSub && this.organization.canEditSubscription) { - const reference = openChangePlanDialog(this.dialogService, { - data: { - organizationId: this.organization.id, - subscription: null, - productTierType: this.organization.productTierType, - }, - }); + const reference = openChangePlanDialog(this.dialogService, { + data: { + organizationId: this.organization.id, + subscription: null, + productTierType: this.organization.productTierType, + }, + }); - const result = await lastValueFrom(reference.closed); + const result = await lastValueFrom(reference.closed); - if (result === ChangePlanDialogResultType.Submitted) { - await this.load(); - } - return; - } else { - // Show org upgrade modal - await this.showSeatLimitReachedDialog(); - return; + if (result === ChangePlanDialogResultType.Submitted) { + await this.load(); } + return; } const dialog = openUserAddEditDialog(this.dialogService, { @@ -556,6 +544,21 @@ export class MembersComponent extends BaseMembersComponent await this.load(); } + async bulkDelete() { + if (this.actionPromise != null) { + return; + } + + const dialogRef = BulkDeleteDialogComponent.open(this.dialogService, { + data: { + organizationId: this.organization.id, + users: this.dataSource.getCheckedUsers(), + }, + }); + await lastValueFrom(dialogRef.closed); + await this.load(); + } + async bulkRevoke() { await this.bulkRevokeOrRestore(true); } diff --git a/apps/web/src/app/admin-console/organizations/members/members.module.ts b/apps/web/src/app/admin-console/organizations/members/members.module.ts index d7c5a9bf1df..81697f8c845 100644 --- a/apps/web/src/app/admin-console/organizations/members/members.module.ts +++ b/apps/web/src/app/admin-console/organizations/members/members.module.ts @@ -8,6 +8,7 @@ import { LooseComponentsModule } from "../../../shared"; import { SharedOrganizationModule } from "../shared"; import { BulkConfirmDialogComponent } from "./components/bulk/bulk-confirm-dialog.component"; +import { BulkDeleteDialogComponent } from "./components/bulk/bulk-delete-dialog.component"; import { BulkEnableSecretsManagerDialogComponent } from "./components/bulk/bulk-enable-sm-dialog.component"; import { BulkRemoveDialogComponent } from "./components/bulk/bulk-remove-dialog.component"; import { BulkRestoreRevokeComponent } from "./components/bulk/bulk-restore-revoke.component"; @@ -35,6 +36,7 @@ import { MembersComponent } from "./members.component"; BulkStatusComponent, MembersComponent, ResetPasswordComponent, + BulkDeleteDialogComponent, ], }) export class MembersModule {} diff --git a/apps/web/src/app/admin-console/organizations/organization-routing.module.ts b/apps/web/src/app/admin-console/organizations/organization-routing.module.ts index 1725148d477..a36b267e2fe 100644 --- a/apps/web/src/app/admin-console/organizations/organization-routing.module.ts +++ b/apps/web/src/app/admin-console/organizations/organization-routing.module.ts @@ -63,10 +63,10 @@ const routes: Routes = [ ), }, { - path: "risk-insights", + path: "access-intelligence", loadChildren: () => - import("../../tools/risk-insights/risk-insights.module").then( - (m) => m.RiskInsightsModule, + import("../../tools/access-intelligence/access-intelligence.module").then( + (m) => m.AccessIntelligenceModule, ), }, { diff --git a/apps/web/src/app/admin-console/organizations/policies/password-generator.component.html b/apps/web/src/app/admin-console/organizations/policies/password-generator.component.html index a31679ce484..fcf03d27acc 100644 --- a/apps/web/src/app/admin-console/organizations/policies/password-generator.component.html +++ b/apps/web/src/app/admin-console/organizations/policies/password-generator.component.html @@ -23,34 +23,52 @@
{{ "minLength" | i18n }} - +
{{ "minNumbers" | i18n }} - + {{ "minSpecial" | i18n }} - +
- A-Z + {{ "uppercaseLabel" | i18n }} - a-z + {{ "lowercaseLabel" | i18n }} - 0-9 + {{ "numbersLabel" | i18n }} - !@#$%^&* + {{ "specialCharactersLabel" | i18n }}
@@ -60,7 +78,13 @@
{{ "minimumNumberOfWords" | i18n }} - +
diff --git a/apps/web/src/app/admin-console/organizations/policies/password-generator.component.ts b/apps/web/src/app/admin-console/organizations/policies/password-generator.component.ts index e1568da0487..818a0853ad3 100644 --- a/apps/web/src/app/admin-console/organizations/policies/password-generator.component.ts +++ b/apps/web/src/app/admin-console/organizations/policies/password-generator.component.ts @@ -5,7 +5,7 @@ import { BehaviorSubject, map } from "rxjs"; import { PolicyType } from "@bitwarden/common/admin-console/enums"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { DefaultPassphraseBoundaries, DefaultPasswordBoundaries } from "@bitwarden/generator-core"; +import { Generators } from "@bitwarden/generator-core"; import { BasePolicy, BasePolicyComponent } from "./base-policy.component"; @@ -21,39 +21,29 @@ export class PasswordGeneratorPolicy extends BasePolicy { templateUrl: "password-generator.component.html", }) export class PasswordGeneratorPolicyComponent extends BasePolicyComponent { + // these properties forward the application default settings to the UI + // for HTML attribute bindings + protected readonly minLengthMin = Generators.password.settings.constraints.length.min; + protected readonly minLengthMax = Generators.password.settings.constraints.length.max; + protected readonly minNumbersMin = Generators.password.settings.constraints.minNumber.min; + protected readonly minNumbersMax = Generators.password.settings.constraints.minNumber.max; + protected readonly minSpecialMin = Generators.password.settings.constraints.minSpecial.min; + protected readonly minSpecialMax = Generators.password.settings.constraints.minSpecial.max; + protected readonly minNumberWordsMin = Generators.passphrase.settings.constraints.numWords.min; + protected readonly minNumberWordsMax = Generators.passphrase.settings.constraints.numWords.max; + data = this.formBuilder.group({ overridePasswordType: [null], - minLength: [ - null, - [ - Validators.min(DefaultPasswordBoundaries.length.min), - Validators.max(DefaultPasswordBoundaries.length.max), - ], - ], + minLength: [null, [Validators.min(this.minLengthMin), Validators.max(this.minLengthMax)]], useUpper: [null], useLower: [null], useNumbers: [null], useSpecial: [null], - minNumbers: [ - null, - [ - Validators.min(DefaultPasswordBoundaries.minDigits.min), - Validators.max(DefaultPasswordBoundaries.minDigits.max), - ], - ], - minSpecial: [ - null, - [ - Validators.min(DefaultPasswordBoundaries.minSpecialCharacters.min), - Validators.max(DefaultPasswordBoundaries.minSpecialCharacters.max), - ], - ], + minNumbers: [null, [Validators.min(this.minNumbersMin), Validators.max(this.minNumbersMax)]], + minSpecial: [null, [Validators.min(this.minSpecialMin), Validators.max(this.minSpecialMax)]], minNumberWords: [ null, - [ - Validators.min(DefaultPassphraseBoundaries.numWords.min), - Validators.max(DefaultPassphraseBoundaries.numWords.max), - ], + [Validators.min(this.minNumberWordsMin), Validators.max(this.minNumberWordsMax)], ], capitalize: [null], includeNumber: [null], diff --git a/apps/web/src/app/admin-console/organizations/reporting/reports-home.component.ts b/apps/web/src/app/admin-console/organizations/reporting/reports-home.component.ts index c89ff280dd3..2007b5c9a63 100644 --- a/apps/web/src/app/admin-console/organizations/reporting/reports-home.component.ts +++ b/apps/web/src/app/admin-console/organizations/reporting/reports-home.component.ts @@ -1,11 +1,9 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, NavigationEnd, Router } from "@angular/router"; -import { filter, map, Observable, startWith, concatMap, firstValueFrom } from "rxjs"; +import { filter, map, Observable, startWith, concatMap } from "rxjs"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { ProductTierType } from "@bitwarden/common/billing/enums"; -import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; -import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { ReportVariant, reports, ReportType, ReportEntry } from "../../../tools/reports"; @@ -17,21 +15,13 @@ export class ReportsHomeComponent implements OnInit { reports$: Observable; homepage$: Observable; - private isMemberAccessReportEnabled: boolean; - constructor( private route: ActivatedRoute, private organizationService: OrganizationService, private router: Router, - private configService: ConfigService, ) {} async ngOnInit() { - // TODO: Remove on "MemberAccessReport" feature flag cleanup - this.isMemberAccessReportEnabled = await firstValueFrom( - this.configService.getFeatureFlag$(FeatureFlag.MemberAccessReport), - ); - this.homepage$ = this.router.events.pipe( filter((event) => event instanceof NavigationEnd), map((event) => this.isReportsHomepageRouteUrl((event as NavigationEnd).urlAfterRedirects)), @@ -69,17 +59,14 @@ export class ReportsHomeComponent implements OnInit { ...reports[ReportType.Inactive2fa], variant: reportRequiresUpgrade, }, - ]; - - if (this.isMemberAccessReportEnabled) { - reportsArray.push({ + { ...reports[ReportType.MemberAccessReport], variant: productType == ProductTierType.Enterprise ? ReportVariant.Enabled : ReportVariant.RequiresEnterprise, - }); - } + }, + ]; return reportsArray; } diff --git a/apps/web/src/app/admin-console/organizations/shared/components/access-selector/access-selector.component.html b/apps/web/src/app/admin-console/organizations/shared/components/access-selector/access-selector.component.html index aff5d25ee08..4226862fde7 100644 --- a/apps/web/src/app/admin-console/organizations/shared/components/access-selector/access-selector.component.html +++ b/apps/web/src/app/admin-console/organizations/shared/components/access-selector/access-selector.component.html @@ -3,13 +3,7 @@
{{ "permission" | i18n }} - + > + +
+ {{ "needAnotherOptionV1" | i18n }} + {{ + "viewAllLogInOptions" | i18n + }} +
+ + + +

{{ "youWillBeNotifiedOnceTheRequestIsApproved" | i18n }}

+ +
{{ "fingerprintPhraseHeader" | i18n }}
+ {{ fingerprintPhrase }} + +
+ {{ "troubleLoggingIn" | i18n }} + {{ + "viewAllLogInOptions" | i18n + }} +
+
+
diff --git a/libs/auth/src/angular/login-via-auth-request/login-via-auth-request.component.ts b/libs/auth/src/angular/login-via-auth-request/login-via-auth-request.component.ts new file mode 100644 index 00000000000..38614a9046a --- /dev/null +++ b/libs/auth/src/angular/login-via-auth-request/login-via-auth-request.component.ts @@ -0,0 +1,569 @@ +import { CommonModule } from "@angular/common"; +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; +import { IsActiveMatchOptions, Router, RouterModule } from "@angular/router"; +import { firstValueFrom, map } from "rxjs"; + +import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { + AuthRequestLoginCredentials, + AuthRequestServiceAbstraction, + LoginEmailServiceAbstraction, + LoginStrategyServiceAbstraction, +} from "@bitwarden/auth/common"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service"; +import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; +import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction"; +import { AuthRequestType } from "@bitwarden/common/auth/enums/auth-request-type"; +import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; +import { AdminAuthRequestStorable } from "@bitwarden/common/auth/models/domain/admin-auth-req-storable"; +import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; +import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason"; +import { AuthRequest } from "@bitwarden/common/auth/models/request/auth.request"; +import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response"; +import { ClientType, HttpStatusCode } from "@bitwarden/common/enums"; +import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; +import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; +import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; +import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; +import { Utils } from "@bitwarden/common/platform/misc/utils"; +import { UserId } from "@bitwarden/common/types/guid"; +import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; +import { ButtonModule, LinkModule, ToastService } from "@bitwarden/components"; +import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; + +import { AuthRequestApiService } from "../../common/abstractions/auth-request-api.service"; + +enum Flow { + StandardAuthRequest, // when user clicks "Login with device" from /login or "Approve from your other device" from /login-initiated + AdminAuthRequest, // when user clicks "Request admin approval" from /login-initiated +} + +const matchOptions: IsActiveMatchOptions = { + paths: "exact", + queryParams: "ignored", + fragment: "ignored", + matrixParams: "ignored", +}; + +@Component({ + standalone: true, + templateUrl: "./login-via-auth-request.component.html", + imports: [ButtonModule, CommonModule, JslibModule, LinkModule, RouterModule], +}) +export class LoginViaAuthRequestComponent implements OnInit, OnDestroy { + private authRequest: AuthRequest; + private authRequestKeyPair: { publicKey: Uint8Array; privateKey: Uint8Array }; + private authStatus: AuthenticationStatus; + private showResendNotificationTimeoutSeconds = 12; + + protected backToRoute = "/login"; + protected clientType: ClientType; + protected ClientType = ClientType; + protected email: string; + protected fingerprintPhrase: string; + protected showResendNotification = false; + protected Flow = Flow; + protected flow = Flow.StandardAuthRequest; + + constructor( + private accountService: AccountService, + private anonymousHubService: AnonymousHubService, + private appIdService: AppIdService, + private authRequestApiService: AuthRequestApiService, + private authRequestService: AuthRequestServiceAbstraction, + private authService: AuthService, + private cryptoFunctionService: CryptoFunctionService, + private deviceTrustService: DeviceTrustServiceAbstraction, + private i18nService: I18nService, + private logService: LogService, + private loginEmailService: LoginEmailServiceAbstraction, + private loginStrategyService: LoginStrategyServiceAbstraction, + private passwordGenerationService: PasswordGenerationServiceAbstraction, + private platformUtilsService: PlatformUtilsService, + private router: Router, + private syncService: SyncService, + private toastService: ToastService, + private validationService: ValidationService, + ) { + this.clientType = this.platformUtilsService.getClientType(); + + // Gets SignalR push notification + // Only fires on approval to prevent enumeration + this.authRequestService.authRequestPushNotification$ + .pipe(takeUntilDestroyed()) + .subscribe((requestId) => { + this.verifyAndHandleApprovedAuthReq(requestId).catch((e: Error) => { + this.toastService.showToast({ + variant: "error", + title: this.i18nService.t("error"), + message: e.message, + }); + + this.logService.error("Failed to use approved auth request: " + e.message); + }); + }); + } + + async ngOnInit(): Promise { + // Get the authStatus early because we use it in both flows + this.authStatus = await firstValueFrom(this.authService.activeAccountStatus$); + + const userHasAuthenticatedViaSSO = this.authStatus === AuthenticationStatus.Locked; + + if (userHasAuthenticatedViaSSO) { + this.backToRoute = "/login-initiated"; + } + + /** + * The LoginViaAuthRequestComponent handles both the `login-with-device` and + * the `admin-approval-requested` routes. Therefore we check the route to determine + * which flow to initialize. + */ + if (this.router.isActive("admin-approval-requested", matchOptions)) { + await this.initAdminAuthRequestFlow(); + } else { + await this.initStandardAuthRequestFlow(); + } + } + + private async initAdminAuthRequestFlow(): Promise { + this.flow = Flow.AdminAuthRequest; + + // Get email from state for admin auth requests because it is available and also + // prevents it from being lost on refresh as the loginEmailService email does not persist. + this.email = await firstValueFrom( + this.accountService.activeAccount$.pipe(map((a) => a?.email)), + ); + + if (!this.email) { + await this.handleMissingEmail(); + return; + } + + // We only allow a single admin approval request to be active at a time + // so we must check state to see if we have an existing one or not + const userId = (await firstValueFrom(this.accountService.activeAccount$)).id; + const existingAdminAuthRequest = await this.authRequestService.getAdminAuthRequest(userId); + + if (existingAdminAuthRequest) { + await this.handleExistingAdminAuthRequest(existingAdminAuthRequest, userId); + } else { + await this.startAdminAuthRequestLogin(); + } + } + + private async initStandardAuthRequestFlow(): Promise { + this.flow = Flow.StandardAuthRequest; + + this.email = await firstValueFrom(this.loginEmailService.loginEmail$); + + if (!this.email) { + await this.handleMissingEmail(); + return; + } + + await this.startStandardAuthRequestLogin(); + } + + private async handleMissingEmail(): Promise { + this.toastService.showToast({ + variant: "error", + title: null, + message: this.i18nService.t("userEmailMissing"), + }); + + await this.router.navigate([this.backToRoute]); + } + + async ngOnDestroy(): Promise { + await this.anonymousHubService.stopHubConnection(); + } + + private async startAdminAuthRequestLogin(): Promise { + try { + await this.buildAuthRequest(AuthRequestType.AdminApproval); + + const authRequestResponse = await this.authRequestApiService.postAdminAuthRequest( + this.authRequest, + ); + const adminAuthReqStorable = new AdminAuthRequestStorable({ + id: authRequestResponse.id, + privateKey: this.authRequestKeyPair.privateKey, + }); + + const userId = (await firstValueFrom(this.accountService.activeAccount$)).id; + await this.authRequestService.setAdminAuthRequest(adminAuthReqStorable, userId); + + if (authRequestResponse.id) { + await this.anonymousHubService.createHubConnection(authRequestResponse.id); + } + } catch (e) { + this.logService.error(e); + } + } + + protected async startStandardAuthRequestLogin(): Promise { + this.showResendNotification = false; + + try { + await this.buildAuthRequest(AuthRequestType.AuthenticateAndUnlock); + + const authRequestResponse = await this.authRequestApiService.postAuthRequest( + this.authRequest, + ); + + if (authRequestResponse.id) { + await this.anonymousHubService.createHubConnection(authRequestResponse.id); + } + } catch (e) { + this.logService.error(e); + } + + setTimeout(() => { + this.showResendNotification = true; + }, this.showResendNotificationTimeoutSeconds * 1000); + } + + private async buildAuthRequest(authRequestType: AuthRequestType): Promise { + const authRequestKeyPairArray = await this.cryptoFunctionService.rsaGenerateKeyPair(2048); + + this.authRequestKeyPair = { + publicKey: authRequestKeyPairArray[0], + privateKey: authRequestKeyPairArray[1], + }; + + const deviceIdentifier = await this.appIdService.getAppId(); + const publicKey = Utils.fromBufferToB64(this.authRequestKeyPair.publicKey); + const accessCode = await this.passwordGenerationService.generatePassword({ + type: "password", + length: 25, + }); + + this.fingerprintPhrase = await this.authRequestService.getFingerprintPhrase( + this.email, + this.authRequestKeyPair.publicKey, + ); + + this.authRequest = new AuthRequest( + this.email, + deviceIdentifier, + publicKey, + authRequestType, + accessCode, + ); + } + + private async handleExistingAdminAuthRequest( + adminAuthRequestStorable: AdminAuthRequestStorable, + userId: UserId, + ): Promise { + // Note: on login, the SSOLoginStrategy will also call to see if an existing admin auth req + // has been approved and handle it if so. + + // Regardless, we always retrieve the auth request from the server and verify and handle status changes here as well + let adminAuthRequestResponse: AuthRequestResponse; + + try { + adminAuthRequestResponse = await this.authRequestApiService.getAuthRequest( + adminAuthRequestStorable.id, + ); + } catch (error) { + if (error instanceof ErrorResponse && error.statusCode === HttpStatusCode.NotFound) { + return await this.handleExistingAdminAuthReqDeletedOrDenied(userId); + } + } + + // Request doesn't exist anymore + if (!adminAuthRequestResponse) { + return await this.handleExistingAdminAuthReqDeletedOrDenied(userId); + } + + // Re-derive the user's fingerprint phrase + // It is important to not use the server's public key here as it could have been compromised via MITM + const derivedPublicKeyArrayBuffer = await this.cryptoFunctionService.rsaExtractPublicKey( + adminAuthRequestStorable.privateKey, + ); + this.fingerprintPhrase = await this.authRequestService.getFingerprintPhrase( + this.email, + derivedPublicKeyArrayBuffer, + ); + + // Request denied + if (adminAuthRequestResponse.isAnswered && !adminAuthRequestResponse.requestApproved) { + return await this.handleExistingAdminAuthReqDeletedOrDenied(userId); + } + + // Request approved + if (adminAuthRequestResponse.requestApproved) { + return await this.decryptViaApprovedAuthRequest( + adminAuthRequestResponse, + adminAuthRequestStorable.privateKey, + userId, + ); + } + + // Request still pending response from admin + // set keypair and create hub connection so that any approvals will be received via push notification + this.authRequestKeyPair = { privateKey: adminAuthRequestStorable.privateKey, publicKey: null }; + await this.anonymousHubService.createHubConnection(adminAuthRequestStorable.id); + } + + private async verifyAndHandleApprovedAuthReq(requestId: string): Promise { + /** + * *********************************** + * Standard Auth Request Flows + * *********************************** + * + * Flow 1: Unauthed user requests approval from device; Approving device has a masterKey in memory. + * + * Unauthed user clicks "Login with device" > navigates to /login-with-device which creates a StandardAuthRequest + * > receives approval from a device with authRequestPublicKey(masterKey) > decrypts masterKey > decrypts userKey > proceed to vault + * + * Flow 2: Unauthed user requests approval from device; Approving device does NOT have a masterKey in memory. + * + * Unauthed user clicks "Login with device" > navigates to /login-with-device which creates a StandardAuthRequest + * > receives approval from a device with authRequestPublicKey(userKey) > decrypts userKey > proceeds to vault + * + * Note: this flow is an uncommon scenario and relates to TDE off-boarding. The following describes how a user could get into this flow: + * 1) An SSO TD user logs into a device via an Admin auth request approval, therefore this device does NOT have a masterKey in memory. + * 2) The org admin... + * (2a) Changes the member decryption options from "Trusted devices" to "Master password" AND + * (2b) Turns off the "Require single sign-on authentication" policy + * 3) On another device, the user clicks "Login with device", which they can do because the org no longer requires SSO. + * 4) The user approves from the device they had previously logged into with SSO TD, which does NOT have a masterKey in memory (see step 1 above). + * + * Flow 3: Authed SSO TD user requests approval from device; Approving device has a masterKey in memory. + * + * SSO TD user authenticates via SSO > navigates to /login-initiated > clicks "Approve from your other device" + * > navigates to /login-with-device which creates a StandardAuthRequest > receives approval from device with authRequestPublicKey(masterKey) + * > decrypts masterKey > decrypts userKey > establishes trust (if required) > proceeds to vault + * + * Flow 4: Authed SSO TD user requests approval from device; Approving device does NOT have a masterKey in memory. + * + * SSO TD user authenticates via SSO > navigates to /login-initiated > clicks "Approve from your other device" + * > navigates to /login-with-device which creates a StandardAuthRequest > receives approval from device with authRequestPublicKey(userKey) + * > decrypts userKey > establishes trust (if required) > proceeds to vault + * + * *********************************** + * Admin Auth Request Flow + * *********************************** + * + * Flow: Authed SSO TD user requests admin approval. + * + * SSO TD user authenticates via SSO > navigates to /login-initiated > clicks "Request admin approval" + * > navigates to /admin-approval-requested which creates an AdminAuthRequest > receives approval from device with authRequestPublicKey(userKey) + * > decrypts userKey > establishes trust (if required) > proceeds to vault + * + * Note: TDE users are required to be enrolled in admin password reset, which gives the admin access to the user's userKey. + * This is how admins are able to send over the authRequestPublicKey(userKey) to the user to allow them to unlock. + * + * + * Summary Table + * |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| + * | Flow | Auth Status | Clicks Button [active route] | Navigates to | Approving device has masterKey in memory (see note 1) | + * |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| + * | Standard Flow 1 | unauthed | "Login with device" [/login] | /login-with-device | yes | + * | Standard Flow 2 | unauthed | "Login with device" [/login] | /login-with-device | no | + * | Standard Flow 3 | authed | "Approve from your other device" [/login-initiated] | /login-with-device | yes | + * | Standard Flow 4 | authed | "Approve from your other device" [/login-initiated] | /login-with-device | no | | + * | Admin Flow | authed | "Request admin approval" [/login-initiated] | /admin-approval-requested | NA - admin requests always send encrypted userKey | + * |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| + * * Note 1: The phrase "in memory" here is important. It is possible for a user to have a master password for their account, but not have a masterKey IN MEMORY for + * a specific device. For example, if a user registers an account with a master password, then joins an SSO TD org, then logs in to a device via SSO and + * admin auth request, they are now logged into that device but that device does not have masterKey IN MEMORY. + */ + + try { + const userHasAuthenticatedViaSSO = this.authStatus === AuthenticationStatus.Locked; + + if (userHasAuthenticatedViaSSO) { + // Get the auth request from the server + // User is authenticated, therefore the endpoint does not require an access code. + const authRequestResponse = await this.authRequestApiService.getAuthRequest(requestId); + + if (authRequestResponse.requestApproved) { + // Handles Standard Flows 3-4 and Admin Flow + await this.handleAuthenticatedFlows(authRequestResponse); + } + } else { + // Get the auth request from the server + // User is unauthenticated, therefore the endpoint requires an access code for user verification. + const authRequestResponse = await this.authRequestApiService.getAuthResponse( + requestId, + this.authRequest.accessCode, + ); + + if (authRequestResponse.requestApproved) { + // Handles Standard Flows 1-2 + await this.handleUnauthenticatedFlows(authRequestResponse, requestId); + } + } + } catch (error) { + if (error instanceof ErrorResponse) { + await this.router.navigate([this.backToRoute]); + this.validationService.showError(error); + return; + } + + this.logService.error(error); + } + } + + private async handleAuthenticatedFlows(authRequestResponse: AuthRequestResponse) { + const userId = (await firstValueFrom(this.accountService.activeAccount$)).id; + + await this.decryptViaApprovedAuthRequest( + authRequestResponse, + this.authRequestKeyPair.privateKey, + userId, + ); + } + + private async handleUnauthenticatedFlows( + authRequestResponse: AuthRequestResponse, + requestId: string, + ) { + const authRequestLoginCredentials = await this.buildAuthRequestLoginCredentials( + requestId, + authRequestResponse, + ); + + // Note: keys are set by AuthRequestLoginStrategy success handling + const authResult = await this.loginStrategyService.logIn(authRequestLoginCredentials); + + await this.handlePostLoginNavigation(authResult); + } + + private async decryptViaApprovedAuthRequest( + authRequestResponse: AuthRequestResponse, + privateKey: ArrayBuffer, + userId: UserId, + ): Promise { + /** + * See verifyAndHandleApprovedAuthReq() for flow details. + * + * We determine the type of `key` based on the presence or absence of `masterPasswordHash`: + * - If `masterPasswordHash` has a value, we receive the `key` as an authRequestPublicKey(masterKey) [plus we have authRequestPublicKey(masterPasswordHash)] + * - If `masterPasswordHash` does not have a value, we receive the `key` as an authRequestPublicKey(userKey) + */ + + if (authRequestResponse.masterPasswordHash) { + // ...in Standard Auth Request Flow 3 + await this.authRequestService.setKeysAfterDecryptingSharedMasterKeyAndHash( + authRequestResponse, + privateKey, + userId, + ); + } else { + // ...in Standard Auth Request Flow 4 or Admin Auth Request Flow + await this.authRequestService.setUserKeyAfterDecryptingSharedUserKey( + authRequestResponse, + privateKey, + userId, + ); + } + + // clear the admin auth request from state so it cannot be used again (it's a one time use) + // TODO: this should eventually be enforced via deleting this on the server once it is used + await this.authRequestService.clearAdminAuthRequest(userId); + + this.toastService.showToast({ + variant: "success", + title: null, + message: this.i18nService.t("loginApproved"), + }); + + // Now that we have a decrypted user key in memory, we can check if we + // need to establish trust on the current device + const activeAccount = await firstValueFrom(this.accountService.activeAccount$); + await this.deviceTrustService.trustDeviceIfRequired(activeAccount.id); + + await this.handleSuccessfulLoginNavigation(); + } + + /** + * Takes an `AuthRequestResponse` and decrypts the `key` to build an `AuthRequestLoginCredentials` + * object for use in the `AuthRequestLoginStrategy`. + * + * The credentials object that gets built is affected by whether the `authRequestResponse.key` + * is an encrypted MasterKey or an encrypted UserKey. + */ + private async buildAuthRequestLoginCredentials( + requestId: string, + authRequestResponse: AuthRequestResponse, + ): Promise { + /** + * See verifyAndHandleApprovedAuthReq() for flow details. + * + * We determine the type of `key` based on the presence or absence of `masterPasswordHash`: + * - If `masterPasswordHash` has a value, we receive the `key` as an authRequestPublicKey(masterKey) [plus we have authRequestPublicKey(masterPasswordHash)] + * - If `masterPasswordHash` does not have a value, we receive the `key` as an authRequestPublicKey(userKey) + */ + + if (authRequestResponse.masterPasswordHash) { + // ...in Standard Auth Request Flow 1 + const { masterKey, masterKeyHash } = + await this.authRequestService.decryptPubKeyEncryptedMasterKeyAndHash( + authRequestResponse.key, + authRequestResponse.masterPasswordHash, + this.authRequestKeyPair.privateKey, + ); + + return new AuthRequestLoginCredentials( + this.email, + this.authRequest.accessCode, + requestId, + null, // no userKey + masterKey, + masterKeyHash, + ); + } else { + // ...in Standard Auth Request Flow 2 + const userKey = await this.authRequestService.decryptPubKeyEncryptedUserKey( + authRequestResponse.key, + this.authRequestKeyPair.privateKey, + ); + return new AuthRequestLoginCredentials( + this.email, + this.authRequest.accessCode, + requestId, + userKey, + null, // no masterKey + null, // no masterKeyHash + ); + } + } + + private async handleExistingAdminAuthReqDeletedOrDenied(userId: UserId) { + // clear the admin auth request from state + await this.authRequestService.clearAdminAuthRequest(userId); + + // start new auth request + await this.startAdminAuthRequestLogin(); + } + + private async handlePostLoginNavigation(loginResponse: AuthResult) { + if (loginResponse.requiresTwoFactor) { + await this.router.navigate(["2fa"]); + } else if (loginResponse.forcePasswordReset != ForceSetPasswordReason.None) { + await this.router.navigate(["update-temp-password"]); + } else { + await this.handleSuccessfulLoginNavigation(); + } + } + + private async handleSuccessfulLoginNavigation() { + if (this.flow === Flow.StandardAuthRequest) { + // Only need to set remembered email on standard login with auth req flow + await this.loginEmailService.saveEmailSettings(); + } + + await this.syncService.fullSync(true); + await this.router.navigate(["vault"]); + } +} diff --git a/libs/auth/src/angular/login/default-login-component.service.spec.ts b/libs/auth/src/angular/login/default-login-component.service.spec.ts index 9878372801b..05b24da56cc 100644 --- a/libs/auth/src/angular/login/default-login-component.service.spec.ts +++ b/libs/auth/src/angular/login/default-login-component.service.spec.ts @@ -63,12 +63,6 @@ describe("DefaultLoginComponentService", () => { }); }); - describe("isLoginViaAuthRequestSupported", () => { - it("returns false by default", () => { - expect(service.isLoginViaAuthRequestSupported()).toBe(false); - }); - }); - describe("isLoginWithPasskeySupported", () => { it("returns true when clientType is Web", () => { service["clientType"] = ClientType.Web; diff --git a/libs/auth/src/angular/login/default-login-component.service.ts b/libs/auth/src/angular/login/default-login-component.service.ts index a06ad1e6539..b6d80ae1617 100644 --- a/libs/auth/src/angular/login/default-login-component.service.ts +++ b/libs/auth/src/angular/login/default-login-component.service.ts @@ -25,10 +25,6 @@ export class DefaultLoginComponentService implements LoginComponentService { return null; } - isLoginViaAuthRequestSupported(): boolean { - return false; - } - isLoginWithPasskeySupported(): boolean { return this.clientType === ClientType.Web; } diff --git a/libs/auth/src/angular/login/login-component.service.ts b/libs/auth/src/angular/login/login-component.service.ts index 213e09e3520..02fcbe02f3d 100644 --- a/libs/auth/src/angular/login/login-component.service.ts +++ b/libs/auth/src/angular/login/login-component.service.ts @@ -23,11 +23,6 @@ export abstract class LoginComponentService { */ getOrgPolicies: () => Promise; - /** - * Indicates whether login with device (auth request) is supported on the given client - */ - isLoginViaAuthRequestSupported: () => boolean; - /** * Indicates whether login with passkey is supported on the given client */ diff --git a/libs/auth/src/angular/login/login.component.html b/libs/auth/src/angular/login/login.component.html index 0afc4659db3..0629e70a6ac 100644 --- a/libs/auth/src/angular/login/login.component.html +++ b/libs/auth/src/angular/login/login.component.html @@ -112,7 +112,7 @@ - +
{{ "or" | i18n }}
+ + + + + +

+ Hover + + + + + + +

+ Focus Visible + + + + + + +

+ Disabled + + + + + + + `, + }), +}; + export const Primary: Story = { render: (args) => ({ props: args, - template: ` + template: /*html*/ ` Span Badge containing lengthy text

Link
Badge diff --git a/libs/components/src/banner/banner.component.html b/libs/components/src/banner/banner.component.html index 865aacd410a..566494eb64a 100644 --- a/libs/components/src/banner/banner.component.html +++ b/libs/components/src/banner/banner.component.html @@ -1,18 +1,21 @@
- + + + + `, }), diff --git a/libs/components/src/button/button.component.spec.ts b/libs/components/src/button/button.component.spec.ts index a75ac400a96..f3c3aa3175c 100644 --- a/libs/components/src/button/button.component.spec.ts +++ b/libs/components/src/button/button.component.spec.ts @@ -27,57 +27,6 @@ describe("Button", () => { linkDebugElement = fixture.debugElement.query(By.css("a")); })); - it("should apply classes based on type", () => { - testAppComponent.buttonType = "primary"; - fixture.detectChanges(); - expect(buttonDebugElement.nativeElement.classList.contains("tw-bg-primary-600")).toBe(true); - expect(linkDebugElement.nativeElement.classList.contains("tw-bg-primary-600")).toBe(true); - - testAppComponent.buttonType = "secondary"; - fixture.detectChanges(); - expect(buttonDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true); - expect(linkDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true); - - testAppComponent.buttonType = "danger"; - fixture.detectChanges(); - expect(buttonDebugElement.nativeElement.classList.contains("tw-border-danger-600")).toBe(true); - expect(linkDebugElement.nativeElement.classList.contains("tw-border-danger-600")).toBe(true); - - testAppComponent.buttonType = "unstyled"; - fixture.detectChanges(); - expect( - Array.from(buttonDebugElement.nativeElement.classList).some((klass: string) => - klass.startsWith("tw-bg"), - ), - ).toBe(false); - expect( - Array.from(linkDebugElement.nativeElement.classList).some((klass: string) => - klass.startsWith("tw-bg"), - ), - ).toBe(false); - - testAppComponent.buttonType = null; - fixture.detectChanges(); - expect(buttonDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true); - expect(linkDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true); - }); - - it("should apply block when true and inline-block when false", () => { - testAppComponent.block = true; - fixture.detectChanges(); - expect(buttonDebugElement.nativeElement.classList.contains("tw-block")).toBe(true); - expect(linkDebugElement.nativeElement.classList.contains("tw-block")).toBe(true); - expect(buttonDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(false); - expect(linkDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(false); - - testAppComponent.block = false; - fixture.detectChanges(); - expect(buttonDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(true); - expect(linkDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(true); - expect(buttonDebugElement.nativeElement.classList.contains("tw-block")).toBe(false); - expect(linkDebugElement.nativeElement.classList.contains("tw-block")).toBe(false); - }); - it("should not be disabled when loading and disabled are false", () => { testAppComponent.loading = false; testAppComponent.disabled = false; diff --git a/libs/components/src/button/button.component.ts b/libs/components/src/button/button.component.ts index d8787c994f4..115347d3163 100644 --- a/libs/components/src/button/button.component.ts +++ b/libs/components/src/button/button.component.ts @@ -4,9 +4,9 @@ import { Input, HostBinding, Component } from "@angular/core"; import { ButtonLikeAbstraction, ButtonType } from "../shared/button-like.abstraction"; const focusRing = [ - "focus-visible:tw-ring", + "focus-visible:tw-ring-2", "focus-visible:tw-ring-offset-2", - "focus-visible:tw-ring-primary-700", + "focus-visible:tw-ring-primary-600", "focus-visible:tw-z-10", ]; @@ -17,24 +17,15 @@ const buttonStyles: Record = { "!tw-text-contrast", "hover:tw-bg-primary-700", "hover:tw-border-primary-700", - "disabled:tw-bg-primary-600/60", - "disabled:tw-border-primary-600/60", - "disabled:!tw-text-contrast/60", - "disabled:tw-bg-clip-padding", - "disabled:tw-cursor-not-allowed", ...focusRing, ], secondary: [ "tw-bg-transparent", - "tw-border-text-muted", - "!tw-text-muted", - "hover:tw-bg-text-muted", - "hover:tw-border-text-muted", + "tw-border-primary-600", + "!tw-text-primary-600", + "hover:tw-bg-primary-600", + "hover:tw-border-primary-600", "hover:!tw-text-contrast", - "disabled:tw-bg-transparent", - "disabled:tw-border-text-muted/60", - "disabled:!tw-text-muted/60", - "disabled:tw-cursor-not-allowed", ...focusRing, ], danger: [ @@ -44,10 +35,6 @@ const buttonStyles: Record = { "hover:tw-bg-danger-600", "hover:tw-border-danger-600", "hover:!tw-text-contrast", - "disabled:tw-bg-transparent", - "disabled:tw-border-danger-600/60", - "disabled:!tw-text-danger/60", - "disabled:tw-cursor-not-allowed", ...focusRing, ], unstyled: [], @@ -64,14 +51,22 @@ export class ButtonComponent implements ButtonLikeAbstraction { "tw-font-semibold", "tw-py-1.5", "tw-px-3", - "tw-rounded", + "tw-rounded-full", "tw-transition", - "tw-border", + "tw-border-2", "tw-border-solid", "tw-text-center", "tw-no-underline", "hover:tw-no-underline", "focus:tw-outline-none", + "disabled:tw-bg-secondary-300", + "disabled:hover:tw-bg-secondary-300", + "disabled:tw-border-secondary-300", + "disabled:hover:tw-border-secondary-300", + "disabled:!tw-text-muted", + "disabled:hover:!tw-text-muted", + "disabled:tw-cursor-not-allowed", + "disabled:hover:tw-no-underline", ] .concat(this.block ? ["tw-w-full", "tw-block"] : ["tw-inline-block"]) .concat(buttonStyles[this.buttonType ?? "secondary"]); @@ -99,8 +94,4 @@ export class ButtonComponent implements ButtonLikeAbstraction { @Input() loading = false; @Input() disabled = false; - - setButtonType(value: "primary" | "secondary" | "danger" | "unstyled") { - this.buttonType = value; - } } diff --git a/libs/components/src/button/button.mdx b/libs/components/src/button/button.mdx index 5ee709093e3..33e4aed19f7 100644 --- a/libs/components/src/button/button.mdx +++ b/libs/components/src/button/button.mdx @@ -64,9 +64,6 @@ Use the danger styling only in settings when the user may preform a permanent ac ## Disabled UI -Both the disabled and loading states use the default state’s color with a 60% opacity or -`tw-opacity-60`. - ## Block diff --git a/libs/components/src/button/button.stories.ts b/libs/components/src/button/button.stories.ts index 6923878b353..260d5565c0c 100644 --- a/libs/components/src/button/button.stories.ts +++ b/libs/components/src/button/button.stories.ts @@ -23,9 +23,21 @@ type Story = StoryObj; export const Primary: Story = { render: (args) => ({ props: args, - template: ` + template: /*html*/ ` +
- Link + + + + +
+ `, }), args: { diff --git a/libs/components/src/callout/callout.component.html b/libs/components/src/callout/callout.component.html index 57da850d8bb..f64e197b9ef 100644 --- a/libs/components/src/callout/callout.component.html +++ b/libs/components/src/callout/callout.component.html @@ -1,16 +1,13 @@ diff --git a/libs/components/src/callout/callout.component.spec.ts b/libs/components/src/callout/callout.component.spec.ts index 36abae437d5..b7388da3492 100644 --- a/libs/components/src/callout/callout.component.spec.ts +++ b/libs/components/src/callout/callout.component.spec.ts @@ -12,7 +12,7 @@ describe("Callout", () => { beforeEach(() => { TestBed.configureTestingModule({ - declarations: [CalloutComponent], + imports: [CalloutComponent], providers: [ { provide: I18nService, diff --git a/libs/components/src/callout/callout.component.ts b/libs/components/src/callout/callout.component.ts index bfeae17b359..0fa1c130504 100644 --- a/libs/components/src/callout/callout.component.ts +++ b/libs/components/src/callout/callout.component.ts @@ -2,6 +2,9 @@ import { Component, Input, OnInit } from "@angular/core"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { SharedModule } from "../shared"; +import { TypographyModule } from "../typography"; + export type CalloutTypes = "success" | "info" | "warning" | "danger"; const defaultIcon: Record = { @@ -22,6 +25,8 @@ let nextId = 0; @Component({ selector: "bit-callout", templateUrl: "callout.component.html", + standalone: true, + imports: [SharedModule, TypographyModule], }) export class CalloutComponent implements OnInit { @Input() type: CalloutTypes = "info"; @@ -42,13 +47,13 @@ export class CalloutComponent implements OnInit { get calloutClass() { switch (this.type) { case "danger": - return "tw-border-l-danger-600"; + return "tw-border-danger-600"; case "info": - return "tw-border-l-info-600"; + return "tw-border-info-600"; case "success": - return "tw-border-l-success-600"; + return "tw-border-success-600"; case "warning": - return "tw-border-l-warning-600"; + return "tw-border-warning-600"; } } diff --git a/libs/components/src/callout/callout.mdx b/libs/components/src/callout/callout.mdx index a40a970f895..3fdb53943b4 100644 --- a/libs/components/src/callout/callout.mdx +++ b/libs/components/src/callout/callout.mdx @@ -2,6 +2,10 @@ import { Meta, Story, Primary, Controls } from "@storybook/addon-docs"; import * as stories from "./callout.stories"; +```ts +import { CalloutModule } from "@bitwarden/components"; +``` + # Callouts diff --git a/libs/components/src/callout/callout.module.ts b/libs/components/src/callout/callout.module.ts index fac89dfbcf9..ad7e083fec7 100644 --- a/libs/components/src/callout/callout.module.ts +++ b/libs/components/src/callout/callout.module.ts @@ -1,11 +1,9 @@ -import { CommonModule } from "@angular/common"; import { NgModule } from "@angular/core"; import { CalloutComponent } from "./callout.component"; @NgModule({ - imports: [CommonModule], + imports: [CalloutComponent], exports: [CalloutComponent], - declarations: [CalloutComponent], }) export class CalloutModule {} diff --git a/libs/components/src/card/card.component.ts b/libs/components/src/card/card.component.ts index 3aaed26d8d0..37756088e0d 100644 --- a/libs/components/src/card/card.component.ts +++ b/libs/components/src/card/card.component.ts @@ -9,7 +9,7 @@ import { ChangeDetectionStrategy, Component } from "@angular/core"; changeDetection: ChangeDetectionStrategy.OnPush, host: { class: - "tw-box-border tw-block tw-bg-background tw-text-main tw-border-solid tw-border-b tw-border-0 tw-border-b-secondary-300 [&:not(bit-layout_*)]:tw-rounded-lg tw-py-4 tw-px-3", + "tw-box-border tw-block tw-bg-background tw-text-main tw-border-solid tw-border-b tw-border-0 tw-border-b-secondary-300 [&:not(bit-layout_*)]:tw-rounded-lg [&:not(bit-layout_*)]:tw-border-b-shadow tw-py-4 bit-compact:tw-py-3 tw-px-3 bit-compact:tw-px-2", }, }) export class CardComponent {} diff --git a/libs/components/src/checkbox/checkbox.component.ts b/libs/components/src/checkbox/checkbox.component.ts index d8fd3f76eaa..ef57d3d5cd3 100644 --- a/libs/components/src/checkbox/checkbox.component.ts +++ b/libs/components/src/checkbox/checkbox.component.ts @@ -17,12 +17,13 @@ export class CheckboxComponent implements BitFormControlAbstraction { "tw-transition", "tw-cursor-pointer", "tw-inline-block", + "tw-align-sub", "tw-rounded", "tw-border", "tw-border-solid", - "tw-border-secondary-600", - "tw-h-3.5", - "tw-w-3.5", + "tw-border-secondary-500", + "tw-h-5", + "tw-w-5", "tw-mr-1.5", "tw-bottom-[-1px]", // Fix checkbox looking off-center "tw-flex-none", // Flexbox fix for bit-form-control @@ -35,13 +36,16 @@ export class CheckboxComponent implements BitFormControlAbstraction { "hover:tw-border-2", "[&>label]:tw-border-2", - "focus-visible:tw-ring-2", - "focus-visible:tw-ring-offset-2", - "focus-visible:tw-ring-primary-700", + // if it exists, the parent form control handles focus + "[&:not(bit-form-control_*)]:focus-visible:tw-ring-2", + "[&:not(bit-form-control_*)]:focus-visible:tw-ring-offset-2", + "[&:not(bit-form-control_*)]:focus-visible:tw-ring-primary-600", "disabled:tw-cursor-auto", "disabled:tw-border", + "disabled:hover:tw-border", "disabled:tw-bg-secondary-100", + "disabled:hover:tw-bg-secondary-100", "checked:tw-bg-primary-600", "checked:tw-border-primary-600", @@ -53,6 +57,7 @@ export class CheckboxComponent implements BitFormControlAbstraction { "checked:before:tw-mask-position-[center]", "checked:before:tw-mask-repeat-[no-repeat]", "checked:disabled:tw-border-secondary-100", + "checked:disabled:hover:tw-border-secondary-100", "checked:disabled:tw-bg-secondary-100", "checked:disabled:before:tw-bg-text-muted", @@ -78,11 +83,11 @@ export class CheckboxComponent implements BitFormControlAbstraction { @HostBinding("style.--mask-image") protected maskImage = - `url('data:image/svg+xml,%3Csvg class="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="8" height="8" viewBox="0 0 10 10"%3E%3Cpath d="M0.5 6.2L2.9 8.6L9.5 1.4" fill="none" stroke="white" stroke-width="2"%3E%3C/path%3E%3C/svg%3E')`; + `url('data:image/svg+xml,%3Csvg class="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 10 10"%3E%3Cpath d="M0.5 6.2L2.9 8.6L9.5 1.4" fill="none" stroke="white" stroke-width="2"%3E%3C/path%3E%3C/svg%3E')`; @HostBinding("style.--indeterminate-mask-image") protected indeterminateImage = - `url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="13" height="13" fill="none" viewBox="0 0 13 13"%3E%3Cpath stroke="%23fff" stroke-width="2" d="M2.5 6.5h8"/%3E%3C/svg%3E%0A')`; + `url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 13 13"%3E%3Cpath stroke="%23fff" stroke-width="2" d="M2.5 6.5h8"/%3E%3C/svg%3E%0A')`; @HostBinding() @Input() diff --git a/libs/components/src/checkbox/checkbox.stories.ts b/libs/components/src/checkbox/checkbox.stories.ts index 0d649eb433d..c322f29b957 100644 --- a/libs/components/src/checkbox/checkbox.stories.ts +++ b/libs/components/src/checkbox/checkbox.stories.ts @@ -11,12 +11,14 @@ import { Meta, StoryObj, moduleMetadata } from "@storybook/angular"; import { I18nService } from "@bitwarden/common/src/platform/abstractions/i18n.service"; +import { BadgeModule } from "../badge"; import { FormControlModule } from "../form-control"; +import { TableModule } from "../table"; import { I18nMockService } from "../utils/i18n-mock.service"; import { CheckboxModule } from "./checkbox.module"; -const template = ` +const template = /*html*/ ` @@ -54,7 +56,14 @@ export default { decorators: [ moduleMetadata({ declarations: [ExampleComponent], - imports: [FormsModule, ReactiveFormsModule, FormControlModule, CheckboxModule], + imports: [ + FormsModule, + ReactiveFormsModule, + FormControlModule, + CheckboxModule, + TableModule, + BadgeModule, + ], providers: [ { provide: I18nService, @@ -82,7 +91,10 @@ type Story = StoryObj; export const Default: Story = { render: (args) => ({ props: args, - template: ``, + template: /*html*/ ` + + + `, }), parameters: { docs: { @@ -91,9 +103,39 @@ export const Default: Story = { }, }, }, - args: { - checked: false, - disabled: false, +}; + +export const LongLabel: Story = { + render: () => ({ + props: { + formObj: new FormGroup({ + checkbox: new FormControl(false), + }), + }, + template: /*html*/ ` + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur iaculis consequat enim vitae elementum. + Ut non odio est. + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur iaculis consequat enim vitae elementum. + Ut non odio est. + Premium + + + + `, + }), + parameters: { + docs: { + source: { + code: template, + }, + }, }, }; @@ -104,7 +146,7 @@ export const Hint: Story = { checkbox: new FormControl(false), }), }, - template: ` + template: /*html*/ `
@@ -131,20 +173,37 @@ export const Hint: Story = { }, }; +export const Disabled: Story = { + render: (args) => ({ + props: args, + template: /*html*/ ` + + + `, + }), + parameters: { + docs: { + source: { + code: template, + }, + }, + }, +}; + export const Custom: Story = { render: (args) => ({ props: args, - template: ` + template: /*html*/ `
-