1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-10-30 08:10:34 +01:00

[PM-6426] Merging main into branch and fixing merge conflicts

This commit is contained in:
Cesar Gonzalez 2024-04-29 10:38:34 -05:00
commit 5032d6d913
No known key found for this signature in database
GPG Key ID: 3381A5457F8CCECF
430 changed files with 4503 additions and 2935 deletions

View File

@ -164,6 +164,10 @@ jobs:
run: npm run dist:mv3 run: npm run dist:mv3
working-directory: browser-source/apps/browser working-directory: browser-source/apps/browser
- name: Build Chrome Manifest v3 Beta
run: npm run dist:chrome:beta
working-directory: browser-source/apps/browser
- name: Gulp - name: Gulp
run: gulp ci run: gulp ci
working-directory: browser-source/apps/browser working-directory: browser-source/apps/browser
@ -196,6 +200,13 @@ jobs:
path: browser-source/apps/browser/dist/dist-chrome-mv3.zip path: browser-source/apps/browser/dist/dist-chrome-mv3.zip
if-no-files-found: error if-no-files-found: error
- name: Upload Chrome MV3 Beta artifact (DO NOT USE FOR PROD)
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: DO-NOT-USE-FOR-PROD-dist-chrome-MV3-beta-${{ env._BUILD_NUMBER }}.zip
path: browser-source/apps/browser/dist/dist-chrome-mv3-beta.zip
if-no-files-found: error
- name: Upload Firefox artifact - name: Upload Firefox artifact
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:

View File

@ -230,6 +230,17 @@ jobs:
url: https://github.com/bitwarden/clients/actions/runs/${{ github.run_id }} url: https://github.com/bitwarden/clients/actions/runs/${{ github.run_id }}
AZURE_KV_CI_SERVICE_PRINCIPAL: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} AZURE_KV_CI_SERVICE_PRINCIPAL: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
update-summary:
name: Display commit
needs: artifact-check
runs-on: ubuntu-22.04
steps:
- name: Display commit SHA
run: |
REPO_URL="https://github.com/bitwarden/clients/commit"
COMMIT_SHA="${{ needs.artifact-check.outputs.artifact-build-commit }}"
echo ":steam_locomotive: View [commit]($REPO_URL/$COMMIT_SHA)" >> $GITHUB_STEP_SUMMARY
azure-deploy: azure-deploy:
name: Deploy Web Vault to ${{ inputs.environment }} Storage Account name: Deploy Web Vault to ${{ inputs.environment }} Storage Account
needs: needs:

View File

@ -955,11 +955,7 @@ jobs:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "aws-electron-access-id, secrets: "aws-electron-access-id,
aws-electron-access-key, aws-electron-access-key,
aws-electron-bucket-name, aws-electron-bucket-name"
r2-electron-access-id,
r2-electron-access-key,
r2-electron-bucket-name,
cf-prod-account"
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
@ -985,20 +981,6 @@ jobs:
--recursive \ --recursive \
--quiet --quiet
- name: Publish artifacts to R2
env:
AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.r2-electron-access-id }}
AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.r2-electron-access-key }}
AWS_DEFAULT_REGION: 'us-east-1'
AWS_S3_BUCKET_NAME: ${{ steps.retrieve-secrets.outputs.r2-electron-bucket-name }}
CF_ACCOUNT: ${{ steps.retrieve-secrets.outputs.cf-prod-account }}
working-directory: apps/desktop/artifacts
run: |
aws s3 cp ./ $AWS_S3_BUCKET_NAME/desktop/ \
--recursive \
--quiet \
--endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com
- name: Update deployment status to Success - name: Update deployment status to Success
if: ${{ success() }} if: ${{ success() }}
uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3

View File

@ -115,11 +115,7 @@ jobs:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "aws-electron-access-id, secrets: "aws-electron-access-id,
aws-electron-access-key, aws-electron-access-key,
aws-electron-bucket-name, aws-electron-bucket-name"
r2-electron-access-id,
r2-electron-access-key,
r2-electron-bucket-name,
cf-prod-account"
- name: Download all artifacts - name: Download all artifacts
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
@ -169,21 +165,6 @@ jobs:
--recursive \ --recursive \
--quiet --quiet
- name: Publish artifacts to R2
if: ${{ github.event.inputs.release_type != 'Dry Run' && github.event.inputs.electron_publish == 'true' }}
env:
AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.r2-electron-access-id }}
AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.r2-electron-access-key }}
AWS_DEFAULT_REGION: 'us-east-1'
AWS_S3_BUCKET_NAME: ${{ steps.retrieve-secrets.outputs.r2-electron-bucket-name }}
CF_ACCOUNT: ${{ steps.retrieve-secrets.outputs.cf-prod-account }}
working-directory: apps/desktop/artifacts
run: |
aws s3 cp ./ $AWS_S3_BUCKET_NAME/desktop/ \
--recursive \
--quiet \
--endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com
- name: Get checksum files - name: Get checksum files
uses: bitwarden/gh-actions/get-checksum@main uses: bitwarden/gh-actions/get-checksum@main
with: with:

View File

@ -31,29 +31,21 @@ jobs:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "aws-electron-access-id, secrets: "aws-electron-access-id,
aws-electron-access-key, aws-electron-access-key,
aws-electron-bucket-name, aws-electron-bucket-name"
r2-electron-access-id,
r2-electron-access-key,
r2-electron-bucket-name,
cf-prod-account"
- name: Download channel update info files from R2 - name: Download channel update info files from S3
env: env:
AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.r2-electron-access-id }} AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.aws-electron-access-id }}
AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.r2-electron-access-key }} AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.aws-electron-access-key }}
AWS_DEFAULT_REGION: 'us-east-1' AWS_DEFAULT_REGION: 'us-west-2'
AWS_S3_BUCKET_NAME: ${{ steps.retrieve-secrets.outputs.r2-electron-bucket-name }} AWS_S3_BUCKET_NAME: ${{ steps.retrieve-secrets.outputs.aws-electron-bucket-name }}
CF_ACCOUNT: ${{ steps.retrieve-secrets.outputs.cf-prod-account }}
run: | run: |
aws s3 cp $AWS_S3_BUCKET_NAME/desktop/latest.yml . \ aws s3 cp $AWS_S3_BUCKET_NAME/desktop/latest.yml . \
--quiet \ --quiet \
--endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com
aws s3 cp $AWS_S3_BUCKET_NAME/desktop/latest-linux.yml . \ aws s3 cp $AWS_S3_BUCKET_NAME/desktop/latest-linux.yml . \
--quiet \ --quiet \
--endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com
aws s3 cp $AWS_S3_BUCKET_NAME/desktop/latest-mac.yml . \ aws s3 cp $AWS_S3_BUCKET_NAME/desktop/latest-mac.yml . \
--quiet \ --quiet \
--endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com
- name: Check new rollout percentage - name: Check new rollout percentage
env: env:
@ -95,20 +87,3 @@ jobs:
aws s3 cp latest-mac.yml $AWS_S3_BUCKET_NAME/desktop/ \ aws s3 cp latest-mac.yml $AWS_S3_BUCKET_NAME/desktop/ \
--acl "public-read" --acl "public-read"
- name: Publish channel update info files to R2
env:
AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.r2-electron-access-id }}
AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.r2-electron-access-key }}
AWS_DEFAULT_REGION: 'us-east-1'
AWS_S3_BUCKET_NAME: ${{ steps.retrieve-secrets.outputs.r2-electron-bucket-name }}
CF_ACCOUNT: ${{ steps.retrieve-secrets.outputs.cf-prod-account }}
run: |
aws s3 cp latest.yml $AWS_S3_BUCKET_NAME/desktop/ \
--endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com
aws s3 cp latest-linux.yml $AWS_S3_BUCKET_NAME/desktop/ \
--endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com
aws s3 cp latest-mac.yml $AWS_S3_BUCKET_NAME/desktop/ \
--endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com

View File

@ -9,6 +9,8 @@ const config: StorybookConfig = {
"../libs/components/src/**/*.stories.@(js|jsx|ts|tsx)", "../libs/components/src/**/*.stories.@(js|jsx|ts|tsx)",
"../apps/web/src/**/*.mdx", "../apps/web/src/**/*.mdx",
"../apps/web/src/**/*.stories.@(js|jsx|ts|tsx)", "../apps/web/src/**/*.stories.@(js|jsx|ts|tsx)",
"../apps/browser/src/**/*.mdx",
"../apps/browser/src/**/*.stories.@(js|jsx|ts|tsx)",
"../bitwarden_license/bit-web/src/**/*.mdx", "../bitwarden_license/bit-web/src/**/*.mdx",
"../bitwarden_license/bit-web/src/**/*.stories.@(js|jsx|ts|tsx)", "../bitwarden_license/bit-web/src/**/*.stories.@(js|jsx|ts|tsx)",
], ],

View File

@ -1,12 +1,10 @@
{ {
"extends": "../tsconfig", "extends": "../tsconfig",
"compilerOptions": { "compilerOptions": {
"types": ["node", "jest", "chrome"],
"allowSyntheticDefaultImports": true "allowSyntheticDefaultImports": true
}, },
"exclude": ["../src/test.setup.ts", "../apps/src/**/*.spec.ts", "../libs/**/*.spec.ts"], "exclude": ["../src/test.setup.ts", "../apps/**/*.spec.ts", "../libs/**/*.spec.ts"],
"files": [ "files": [
"./typings.d.ts",
"./preview.tsx", "./preview.tsx",
"../libs/components/src/main.ts", "../libs/components/src/main.ts",
"../libs/components/src/polyfills.ts" "../libs/components/src/polyfills.ts"

View File

@ -1,4 +0,0 @@
declare module "*.md" {
const content: string;
export default content;
}

View File

@ -35,6 +35,9 @@ function buildString() {
if (process.env.MANIFEST_VERSION) { if (process.env.MANIFEST_VERSION) {
build = `-mv${process.env.MANIFEST_VERSION}`; build = `-mv${process.env.MANIFEST_VERSION}`;
} }
if (process.env.BETA_BUILD === "1") {
build += "-beta";
}
if (process.env.BUILD_NUMBER && process.env.BUILD_NUMBER !== "") { if (process.env.BUILD_NUMBER && process.env.BUILD_NUMBER !== "") {
build = `-${process.env.BUILD_NUMBER}`; build = `-${process.env.BUILD_NUMBER}`;
} }
@ -65,6 +68,9 @@ function distFirefox() {
manifest.optional_permissions = manifest.optional_permissions.filter( manifest.optional_permissions = manifest.optional_permissions.filter(
(permission) => permission !== "privacy", (permission) => permission !== "privacy",
); );
if (process.env.BETA_BUILD === "1") {
manifest = applyBetaLabels(manifest);
}
return manifest; return manifest;
}); });
} }
@ -72,6 +78,9 @@ function distFirefox() {
function distOpera() { function distOpera() {
return dist("opera", (manifest) => { return dist("opera", (manifest) => {
delete manifest.applications; delete manifest.applications;
if (process.env.BETA_BUILD === "1") {
manifest = applyBetaLabels(manifest);
}
return manifest; return manifest;
}); });
} }
@ -81,6 +90,9 @@ function distChrome() {
delete manifest.applications; delete manifest.applications;
delete manifest.sidebar_action; delete manifest.sidebar_action;
delete manifest.commands._execute_sidebar_action; delete manifest.commands._execute_sidebar_action;
if (process.env.BETA_BUILD === "1") {
manifest = applyBetaLabels(manifest);
}
return manifest; return manifest;
}); });
} }
@ -90,6 +102,9 @@ function distEdge() {
delete manifest.applications; delete manifest.applications;
delete manifest.sidebar_action; delete manifest.sidebar_action;
delete manifest.commands._execute_sidebar_action; delete manifest.commands._execute_sidebar_action;
if (process.env.BETA_BUILD === "1") {
manifest = applyBetaLabels(manifest);
}
return manifest; return manifest;
}); });
} }
@ -210,6 +225,9 @@ async function safariCopyBuild(source, dest) {
delete manifest.commands._execute_sidebar_action; delete manifest.commands._execute_sidebar_action;
delete manifest.optional_permissions; delete manifest.optional_permissions;
manifest.permissions.push("nativeMessaging"); manifest.permissions.push("nativeMessaging");
if (process.env.BETA_BUILD === "1") {
manifest = applyBetaLabels(manifest);
}
return manifest; return manifest;
}), }),
), ),
@ -235,6 +253,19 @@ async function ciCoverage(cb) {
.pipe(gulp.dest(paths.coverage)); .pipe(gulp.dest(paths.coverage));
} }
function applyBetaLabels(manifest) {
manifest.name = "Bitwarden Password Manager BETA";
manifest.short_name = "Bitwarden BETA";
manifest.description = "THIS EXTENSION IS FOR BETA TESTING BITWARDEN.";
if (process.env.GITHUB_RUN_ID) {
manifest.version_name = `${manifest.version} beta - ${process.env.GITHUB_SHA.slice(0, 8)}`;
manifest.version = `${manifest.version}.${parseInt(process.env.GITHUB_RUN_ID.slice(-4))}`;
} else {
manifest.version = `${manifest.version}.0`;
}
return manifest;
}
exports["dist:firefox"] = distFirefox; exports["dist:firefox"] = distFirefox;
exports["dist:chrome"] = distChrome; exports["dist:chrome"] = distChrome;
exports["dist:opera"] = distOpera; exports["dist:opera"] = distOpera;

View File

@ -7,10 +7,14 @@
"build:watch": "webpack --watch", "build:watch": "webpack --watch",
"build:watch:mv3": "cross-env MANIFEST_VERSION=3 webpack --watch", "build:watch:mv3": "cross-env MANIFEST_VERSION=3 webpack --watch",
"build:prod": "cross-env NODE_ENV=production webpack", "build:prod": "cross-env NODE_ENV=production webpack",
"build:prod:beta": "cross-env BETA_BUILD=1 NODE_ENV=production webpack",
"build:prod:watch": "cross-env NODE_ENV=production webpack --watch", "build:prod:watch": "cross-env NODE_ENV=production webpack --watch",
"dist": "npm run build:prod && gulp dist", "dist": "npm run build:prod && gulp dist",
"dist:beta": "npm run build:prod:beta && cross-env BETA_BUILD=1 gulp dist",
"dist:mv3": "cross-env MANIFEST_VERSION=3 npm run build:prod && cross-env MANIFEST_VERSION=3 gulp dist", "dist:mv3": "cross-env MANIFEST_VERSION=3 npm run build:prod && cross-env MANIFEST_VERSION=3 gulp dist",
"dist:mv3:beta": "cross-env MANIFEST_VERSION=3 npm run build:prod:beta && cross-env MANIFEST_VERSION=3 BETA_BUILD=1 gulp dist",
"dist:chrome": "npm run build:prod && gulp dist:chrome", "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:firefox": "npm run build:prod && gulp dist:firefox",
"dist:opera": "npm run build:prod && gulp dist:opera", "dist:opera": "npm run build:prod && gulp dist:opera",
"dist:safari": "npm run build:prod && gulp dist:safari", "dist:safari": "npm run build:prod && gulp dist:safari",

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "قم بالتسجيل أو إنشاء حساب جديد للوصول إلى خزنتك الآمنة." "message": "قم بالتسجيل أو إنشاء حساب جديد للوصول إلى خزنتك الآمنة."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Güvənli anbarınıza müraciət etmək üçün giriş edin və ya yeni bir hesab yaradın." "message": "Güvənli anbarınıza müraciət etmək üçün giriş edin və ya yeni bir hesab yaradın."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Увайдзіце або стварыце новы ўліковы запіс для доступу да бяспечнага сховішча." "message": "Увайдзіце або стварыце новы ўліковы запіс для доступу да бяспечнага сховішча."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Впишете се или създайте нов абонамент, за да достъпите защитен трезор." "message": "Впишете се или създайте нов абонамент, за да достъпите защитен трезор."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "আপনার সুরক্ষিত ভল্টে প্রবেশ করতে লগ ইন করুন অথবা একটি নতুন অ্যাকাউন্ট তৈরি করুন।" "message": "আপনার সুরক্ষিত ভল্টে প্রবেশ করতে লগ ইন করুন অথবা একটি নতুন অ্যাকাউন্ট তৈরি করুন।"

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Prijavite se ili napravite novi račun da biste pristupili svom sigurnom trezoru." "message": "Prijavite se ili napravite novi račun da biste pristupili svom sigurnom trezoru."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Inicieu sessió o creeu un compte nou per accedir a la caixa forta." "message": "Inicieu sessió o creeu un compte nou per accedir a la caixa forta."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Pro přístup do Vašeho bezpečného trezoru se přihlaste nebo si vytvořte nový účet." "message": "Pro přístup do Vašeho bezpečného trezoru se přihlaste nebo si vytvořte nový účet."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Mewngofnodwch neu crëwch gyfrif newydd i gael mynediad i'ch cell ddiogel." "message": "Mewngofnodwch neu crëwch gyfrif newydd i gael mynediad i'ch cell ddiogel."
@ -23,7 +23,7 @@
"message": "Enterprise single sign-on" "message": "Enterprise single sign-on"
}, },
"cancel": { "cancel": {
"message": "Cancel" "message": "Canslo"
}, },
"close": { "close": {
"message": "Cau" "message": "Cau"
@ -318,7 +318,7 @@
"message": "Golygu" "message": "Golygu"
}, },
"view": { "view": {
"message": "View" "message": "Gweld"
}, },
"noItemsInList": { "noItemsInList": {
"message": "Does dim eitemau i'w rhestru." "message": "Does dim eitemau i'w rhestru."
@ -549,10 +549,10 @@
"message": "Ydych chi'n siŵr eich bod am allgofnodi?" "message": "Ydych chi'n siŵr eich bod am allgofnodi?"
}, },
"yes": { "yes": {
"message": "Yes" "message": "Ydw"
}, },
"no": { "no": {
"message": "No" "message": "Na"
}, },
"unexpectedError": { "unexpectedError": {
"message": "An unexpected error has occurred." "message": "An unexpected error has occurred."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log ind eller opret en ny konto for at få adgang til din sikre boks." "message": "Log ind eller opret en ny konto for at få adgang til din sikre boks."

View File

@ -3,12 +3,12 @@
"message": "Bitwarden" "message": "Bitwarden"
}, },
"extName": { "extName": {
"message": "Bitwarden Password Manager", "message": "Bitwarden Passwortmanager",
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Melde dich an oder erstelle ein neues Konto, um auf deinen Tresor zuzugreifen." "message": "Melde dich an oder erstelle ein neues Konto, um auf deinen Tresor zuzugreifen."
@ -173,10 +173,10 @@
"message": "Master-Passwort ändern" "message": "Master-Passwort ändern"
}, },
"continueToWebApp": { "continueToWebApp": {
"message": "Continue to web app?" "message": "Weiter zur Web-App?"
}, },
"changeMasterPasswordOnWebConfirmation": { "changeMasterPasswordOnWebConfirmation": {
"message": "You can change your master password on the Bitwarden web app." "message": "Du kannst dein Master-Passwort in der Bitwarden Web-App ändern."
}, },
"fingerprintPhrase": { "fingerprintPhrase": {
"message": "Fingerabdruck-Phrase", "message": "Fingerabdruck-Phrase",
@ -3001,7 +3001,7 @@
"description": "Notification message for when saving credentials has failed." "description": "Notification message for when saving credentials has failed."
}, },
"success": { "success": {
"message": "Success" "message": "Erfolg"
}, },
"removePasskey": { "removePasskey": {
"message": "Passkey entfernen" "message": "Passkey entfernen"
@ -3010,21 +3010,21 @@
"message": "Passkey entfernt" "message": "Passkey entfernt"
}, },
"unassignedItemsBannerNotice": { "unassignedItemsBannerNotice": {
"message": "Notice: Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console." "message": "Hinweis: Nicht zugeordnete Organisationseinträge sind nicht mehr in der Ansicht aller Tresore sichtbar und nur über die Administrator-Konsole zugänglich."
}, },
"unassignedItemsBannerSelfHostNotice": { "unassignedItemsBannerSelfHostNotice": {
"message": "Notice: On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and will only be accessible via the Admin Console." "message": "Hinweis: Ab dem 16. Mai 2024 sind nicht zugewiesene Organisationselemente nicht mehr in der Ansicht aller Tresore sichtbar und nur über die Administrator-Konsole zugänglich."
}, },
"unassignedItemsBannerCTAPartOne": { "unassignedItemsBannerCTAPartOne": {
"message": "Assign these items to a collection from the", "message": "Weise diese Einträge einer Sammlung aus der",
"description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible." "description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible."
}, },
"unassignedItemsBannerCTAPartTwo": { "unassignedItemsBannerCTAPartTwo": {
"message": "to make them visible.", "message": "zu, um sie sichtbar zu machen.",
"description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible." "description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible."
}, },
"adminConsole": { "adminConsole": {
"message": "Admin Console" "message": "Administrator-Konsole"
}, },
"errorAssigningTargetCollection": { "errorAssigningTargetCollection": {
"message": "Fehler beim Zuweisen der Ziel-Sammlung." "message": "Fehler beim Zuweisen der Ziel-Sammlung."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Συνδεθείτε ή δημιουργήστε ένα νέο λογαριασμό για να αποκτήσετε πρόσβαση στο ασφαλές vault σας." "message": "Συνδεθείτε ή δημιουργήστε ένα νέο λογαριασμό για να αποκτήσετε πρόσβαση στο ασφαλές vault σας."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in or create a new account to access your secure vault." "message": "Log in or create a new account to access your secure vault."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in or create a new account to access your secure vault." "message": "Log in or create a new account to access your secure vault."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in or create a new account to access your secure vault." "message": "Log in or create a new account to access your secure vault."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Identifícate o crea una nueva cuenta para acceder a tu caja fuerte." "message": "Identifícate o crea una nueva cuenta para acceder a tu caja fuerte."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Logi oma olemasolevasse kontosse sisse või loo uus konto." "message": "Logi oma olemasolevasse kontosse sisse või loo uus konto."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Saioa hasi edo sortu kontu berri bat zure kutxa gotorrera sartzeko." "message": "Saioa hasi edo sortu kontu berri bat zure kutxa gotorrera sartzeko."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "وارد شوید یا یک حساب کاربری بسازید تا به گاوصندوق امن‌تان دسترسی یابید." "message": "وارد شوید یا یک حساب کاربری بسازید تا به گاوصندوق امن‌تان دسترسی یابید."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "Kotona, töissä tai reissussa, Bitwarden suojaa helposti kaikki salasanasi, avainkoodisi ja arkaluonteiset tietosi.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Käytä salattua holviasi kirjautumalla sisään tai luo uusi tili." "message": "Käytä salattua holviasi kirjautumalla sisään tai luo uusi tili."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Maglog-in o gumawa ng bagong account para ma-access ang iyong ligtas na kahadeyero." "message": "Maglog-in o gumawa ng bagong account para ma-access ang iyong ligtas na kahadeyero."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Identifiez-vous ou créez un nouveau compte pour accéder à votre coffre sécurisé." "message": "Identifiez-vous ou créez un nouveau compte pour accéder à votre coffre sécurisé."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in or create a new account to access your secure vault." "message": "Log in or create a new account to access your secure vault."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "צור חשבון חדש או התחבר כדי לגשת לכספת המאובטחת שלך." "message": "צור חשבון חדש או התחבר כדי לגשת לכספת המאובטחת שלך."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "अपनी सुरक्षित तिजोरी में प्रवेश करने के लिए नया खाता बनाएं या लॉग इन करें।" "message": "अपनी सुरक्षित तिजोरी में प्रवेश करने के लिए नया खाता बनाएं या लॉग इन करें।"

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Prijavi se ili stvori novi račun za pristup svojem sigurnom trezoru." "message": "Prijavi se ili stvori novi račun za pristup svojem sigurnom trezoru."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Bejelentkezés vagy új fiók létrehozása a biztonsági széf eléréséhez." "message": "Bejelentkezés vagy új fiók létrehozása a biztonsági széf eléréséhez."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Masuk atau buat akun baru untuk mengakses brankas Anda." "message": "Masuk atau buat akun baru untuk mengakses brankas Anda."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Accedi o crea un nuovo account per accedere alla tua cassaforte." "message": "Accedi o crea un nuovo account per accedere alla tua cassaforte."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "安全なデータ保管庫へアクセスするためにログインまたはアカウントを作成してください。" "message": "安全なデータ保管庫へアクセスするためにログインまたはアカウントを作成してください。"

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in or create a new account to access your secure vault." "message": "Log in or create a new account to access your secure vault."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in or create a new account to access your secure vault." "message": "Log in or create a new account to access your secure vault."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "ನಿಮ್ಮ ಸುರಕ್ಷಿತ ವಾಲ್ಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಲಾಗ್ ಇನ್ ಮಾಡಿ ಅಥವಾ ಹೊಸ ಖಾತೆಯನ್ನು ರಚಿಸಿ." "message": "ನಿಮ್ಮ ಸುರಕ್ಷಿತ ವಾಲ್ಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಲಾಗ್ ಇನ್ ಮಾಡಿ ಅಥವಾ ಹೊಸ ಖಾತೆಯನ್ನು ರಚಿಸಿ."

View File

@ -3,12 +3,12 @@
"message": "Bitwarden" "message": "Bitwarden"
}, },
"extName": { "extName": {
"message": "Bitwarden Password Manager", "message": "Bitwarden 비밀번호 관리자",
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "집에서도, 직장에서도, 이동 중에도 Bitwarden은 비밀번호, 패스키, 민감 정보를 쉽게 보호합니다.",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "안전 보관함에 접근하려면 로그인하거나 새 계정을 만드세요." "message": "안전 보관함에 접근하려면 로그인하거나 새 계정을 만드세요."
@ -173,7 +173,7 @@
"message": "마스터 비밀번호 변경" "message": "마스터 비밀번호 변경"
}, },
"continueToWebApp": { "continueToWebApp": {
"message": "Continue to web app?" "message": "웹 앱에서 계속하시겠용?"
}, },
"changeMasterPasswordOnWebConfirmation": { "changeMasterPasswordOnWebConfirmation": {
"message": "You can change your master password on the Bitwarden web app." "message": "You can change your master password on the Bitwarden web app."
@ -688,10 +688,10 @@
"message": "Ask to update a login's password when a change is detected on a website. Applies to all logged in accounts." "message": "Ask to update a login's password when a change is detected on a website. Applies to all logged in accounts."
}, },
"enableUsePasskeys": { "enableUsePasskeys": {
"message": "Ask to save and use passkeys" "message": "패스키를 저장 및 사용할지 묻기"
}, },
"usePasskeysDesc": { "usePasskeysDesc": {
"message": "Ask to save new passkeys or log in with passkeys stored in your vault. Applies to all logged in accounts." "message": "보관함에 새 패스키를 저장하거나 로그인할지 물어봅니다. 모든 로그인된 계정에 적용됩니다."
}, },
"notificationChangeDesc": { "notificationChangeDesc": {
"message": "Bitwarden에 저장되어 있는 비밀번호를 이 비밀번호로 변경하시겠습니까?" "message": "Bitwarden에 저장되어 있는 비밀번호를 이 비밀번호로 변경하시겠습니까?"
@ -2786,55 +2786,55 @@
"message": "Confirm file password" "message": "Confirm file password"
}, },
"typePasskey": { "typePasskey": {
"message": "Passkey" "message": "패스키"
}, },
"passkeyNotCopied": { "passkeyNotCopied": {
"message": "Passkey will not be copied" "message": "패스키가 복사되지 않습니다"
}, },
"passkeyNotCopiedAlert": { "passkeyNotCopiedAlert": {
"message": "The passkey will not be copied to the cloned item. Do you want to continue cloning this item?" "message": "패스키는 복제된 아이템에 복사되지 않습니다. 계속 이 항목을 복제하시겠어요?"
}, },
"passkeyFeatureIsNotImplementedForAccountsWithoutMasterPassword": { "passkeyFeatureIsNotImplementedForAccountsWithoutMasterPassword": {
"message": "Verification required by the initiating site. This feature is not yet implemented for accounts without master password." "message": "사이트에서 인증을 요구합니다. 이 기능은 비밀번호가 없는 계정에서는 아직 지원하지 않습니다."
}, },
"logInWithPasskey": { "logInWithPasskey": {
"message": "Log in with passkey?" "message": "패스키로 로그인하시겠어요?"
}, },
"passkeyAlreadyExists": { "passkeyAlreadyExists": {
"message": "A passkey already exists for this application." "message": "이미 이 애플리케이션에 해당하는 패스키가 있습니다."
}, },
"noPasskeysFoundForThisApplication": { "noPasskeysFoundForThisApplication": {
"message": "No passkeys found for this application." "message": "이 애플리케이션에 대한 패스키를 찾을 수 없습니다."
}, },
"noMatchingPasskeyLogin": { "noMatchingPasskeyLogin": {
"message": "You do not have a matching login for this site." "message": "사이트와 일치하는 로그인이 없습니다."
}, },
"confirm": { "confirm": {
"message": "Confirm" "message": "Confirm"
}, },
"savePasskey": { "savePasskey": {
"message": "Save passkey" "message": "패스키 저장"
}, },
"savePasskeyNewLogin": { "savePasskeyNewLogin": {
"message": "Save passkey as new login" "message": "새 로그인으로 패스키 저장"
}, },
"choosePasskey": { "choosePasskey": {
"message": "Choose a login to save this passkey to" "message": "패스키를 저장할 로그인 선택하기"
}, },
"passkeyItem": { "passkeyItem": {
"message": "Passkey Item" "message": "패스키 항목"
}, },
"overwritePasskey": { "overwritePasskey": {
"message": "Overwrite passkey?" "message": "비밀번호를 덮어쓰시겠어요?"
}, },
"overwritePasskeyAlert": { "overwritePasskeyAlert": {
"message": "This item already contains a passkey. Are you sure you want to overwrite the current passkey?" "message": "이 항목은 이미 패스키가 있습니다. 정말로 현재 패스키를 덮어쓰시겠어요?"
}, },
"featureNotSupported": { "featureNotSupported": {
"message": "Feature not yet supported" "message": "Feature not yet supported"
}, },
"yourPasskeyIsLocked": { "yourPasskeyIsLocked": {
"message": "Authentication required to use passkey. Verify your identity to continue." "message": "패스키를 사용하려면 인증이 필요합니다. 인증을 진행해주세요."
}, },
"multifactorAuthenticationCancelled": { "multifactorAuthenticationCancelled": {
"message": "Multifactor authentication cancelled" "message": "Multifactor authentication cancelled"
@ -3004,10 +3004,10 @@
"message": "Success" "message": "Success"
}, },
"removePasskey": { "removePasskey": {
"message": "Remove passkey" "message": "패스키 제거"
}, },
"passkeyRemoved": { "passkeyRemoved": {
"message": "Passkey removed" "message": "패스키 제거됨"
}, },
"unassignedItemsBannerNotice": { "unassignedItemsBannerNotice": {
"message": "Notice: Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console." "message": "Notice: Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Prisijunkite arba sukurkite naują paskyrą, kad galėtumėte pasiekti saugyklą." "message": "Prisijunkite arba sukurkite naują paskyrą, kad galėtumėte pasiekti saugyklą."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Jāpiesakās vai jāizveido jauns konts, lai piekļūtu drošajai glabātavai." "message": "Jāpiesakās vai jāizveido jauns konts, lai piekļūtu drošajai glabātavai."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "നിങ്ങളുടെ സുരക്ഷിത വാൾട്ടിലേക്കു പ്രവേശിക്കാൻ ലോഗിൻ ചെയ്യുക അല്ലെങ്കിൽ ഒരു പുതിയ അക്കൗണ്ട് സൃഷ്ടിക്കുക." "message": "നിങ്ങളുടെ സുരക്ഷിത വാൾട്ടിലേക്കു പ്രവേശിക്കാൻ ലോഗിൻ ചെയ്യുക അല്ലെങ്കിൽ ഒരു പുതിയ അക്കൗണ്ട് സൃഷ്ടിക്കുക."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "तुमच्या सुरक्षित तिजोरीत पोहचण्यासाठी लॉग इन करा किंवा नवीन खाते उघडा." "message": "तुमच्या सुरक्षित तिजोरीत पोहचण्यासाठी लॉग इन करा किंवा नवीन खाते उघडा."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in or create a new account to access your secure vault." "message": "Log in or create a new account to access your secure vault."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Logg på eller opprett en ny konto for å få tilgang til ditt sikre hvelv." "message": "Logg på eller opprett en ny konto for å få tilgang til ditt sikre hvelv."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in or create a new account to access your secure vault." "message": "Log in or create a new account to access your secure vault."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in of maak een nieuw account aan om toegang te krijgen tot je beveiligde kluis." "message": "Log in of maak een nieuw account aan om toegang te krijgen tot je beveiligde kluis."
@ -531,7 +531,7 @@
"message": "Kan de QR-code van de huidige webpagina niet scannen" "message": "Kan de QR-code van de huidige webpagina niet scannen"
}, },
"totpCaptureSuccess": { "totpCaptureSuccess": {
"message": "Authenticatie-sleutel toegevoegd" "message": "Authenticatiesleutel toegevoegd"
}, },
"totpCapture": { "totpCapture": {
"message": "Scan de authenticatie-QR-code van de huidige webpagina" "message": "Scan de authenticatie-QR-code van de huidige webpagina"
@ -1673,10 +1673,10 @@
"message": "Browserintegratie is niet ingeschakeld in de Bitwarden-desktopapplicatie. Schakel deze optie in de instellingen binnen de desktop-applicatie in." "message": "Browserintegratie is niet ingeschakeld in de Bitwarden-desktopapplicatie. Schakel deze optie in de instellingen binnen de desktop-applicatie in."
}, },
"startDesktopTitle": { "startDesktopTitle": {
"message": "Bitwarden-desktopapplicatie opstarten" "message": "Bitwarden desktopapplicatie opstarten"
}, },
"startDesktopDesc": { "startDesktopDesc": {
"message": "Je moet de Bitwarden-desktopapplicatie starten om deze functie te gebruiken." "message": "Je moet de Bitwarden desktopapplicatie starten om deze functie te gebruiken."
}, },
"errorEnableBiometricTitle": { "errorEnableBiometricTitle": {
"message": "Kon biometrie niet inschakelen" "message": "Kon biometrie niet inschakelen"

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in or create a new account to access your secure vault." "message": "Log in or create a new account to access your secure vault."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in or create a new account to access your secure vault." "message": "Log in or create a new account to access your secure vault."

View File

@ -3,12 +3,12 @@
"message": "Bitwarden" "message": "Bitwarden"
}, },
"extName": { "extName": {
"message": "Bitwarden Password Manager", "message": "Menedżer Haseł Bitwarden",
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "W domu, w pracy, lub w ruchu, Bitwarden z łatwością zabezpiecza Twoje hasła, passkeys i poufne informacje",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Zaloguj się lub utwórz nowe konto, aby uzyskać dostęp do Twojego bezpiecznego sejfu." "message": "Zaloguj się lub utwórz nowe konto, aby uzyskać dostęp do Twojego bezpiecznego sejfu."

View File

@ -3,12 +3,12 @@
"message": "Bitwarden" "message": "Bitwarden"
}, },
"extName": { "extName": {
"message": "Bitwarden Password Manager", "message": "Bitwarden Gerenciador de Senhas",
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "Em qual lugar for, o Bitwarden protege suas senhas, chaves de acesso, e informações confidenciais",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Inicie a sessão ou crie uma nova conta para acessar seu cofre seguro." "message": "Inicie a sessão ou crie uma nova conta para acessar seu cofre seguro."
@ -173,10 +173,10 @@
"message": "Alterar Senha Mestra" "message": "Alterar Senha Mestra"
}, },
"continueToWebApp": { "continueToWebApp": {
"message": "Continue to web app?" "message": "Continuar no aplicativo web?"
}, },
"changeMasterPasswordOnWebConfirmation": { "changeMasterPasswordOnWebConfirmation": {
"message": "You can change your master password on the Bitwarden web app." "message": "Você pode alterar a sua senha mestra no aplicativo web Bitwarden."
}, },
"fingerprintPhrase": { "fingerprintPhrase": {
"message": "Frase Biométrica", "message": "Frase Biométrica",
@ -500,10 +500,10 @@
"message": "A sua nova conta foi criada! Agora você pode iniciar a sessão." "message": "A sua nova conta foi criada! Agora você pode iniciar a sessão."
}, },
"youSuccessfullyLoggedIn": { "youSuccessfullyLoggedIn": {
"message": "You successfully logged in" "message": "Você logou na sua conta com sucesso"
}, },
"youMayCloseThisWindow": { "youMayCloseThisWindow": {
"message": "You may close this window" "message": "Você pode fechar esta janela"
}, },
"masterPassSent": { "masterPassSent": {
"message": "Enviamos um e-mail com a dica da sua senha mestra." "message": "Enviamos um e-mail com a dica da sua senha mestra."
@ -1500,7 +1500,7 @@
"message": "Código PIN inválido." "message": "Código PIN inválido."
}, },
"tooManyInvalidPinEntryAttemptsLoggingOut": { "tooManyInvalidPinEntryAttemptsLoggingOut": {
"message": "Too many invalid PIN entry attempts. Logging out." "message": "Muitas tentativas de entrada de PIN inválidas. Desconectando."
}, },
"unlockWithBiometrics": { "unlockWithBiometrics": {
"message": "Desbloquear com a biometria" "message": "Desbloquear com a biometria"
@ -2005,7 +2005,7 @@
"message": "Selecionar pasta..." "message": "Selecionar pasta..."
}, },
"noFoldersFound": { "noFoldersFound": {
"message": "No folders found", "message": "Nenhuma pasta encontrada",
"description": "Used as a message within the notification bar when no folders are found" "description": "Used as a message within the notification bar when no folders are found"
}, },
"orgPermissionsUpdatedMustSetPassword": { "orgPermissionsUpdatedMustSetPassword": {
@ -2017,7 +2017,7 @@
"description": "Used as a card title description on the set password page to explain why the user is there" "description": "Used as a card title description on the set password page to explain why the user is there"
}, },
"verificationRequired": { "verificationRequired": {
"message": "Verification required", "message": "Verificação necessária",
"description": "Default title for the user verification dialog." "description": "Default title for the user verification dialog."
}, },
"hours": { "hours": {
@ -2652,40 +2652,40 @@
} }
}, },
"tryAgain": { "tryAgain": {
"message": "Try again" "message": "Tentar novamente"
}, },
"verificationRequiredForActionSetPinToContinue": { "verificationRequiredForActionSetPinToContinue": {
"message": "Verification required for this action. Set a PIN to continue." "message": "Verificação necessária para esta ação. Defina um PIN para continuar."
}, },
"setPin": { "setPin": {
"message": "Set PIN" "message": "Definir PIN"
}, },
"verifyWithBiometrics": { "verifyWithBiometrics": {
"message": "Verify with biometrics" "message": "Verificiar com biometria"
}, },
"awaitingConfirmation": { "awaitingConfirmation": {
"message": "Awaiting confirmation" "message": "Aguardando confirmação"
}, },
"couldNotCompleteBiometrics": { "couldNotCompleteBiometrics": {
"message": "Could not complete biometrics." "message": "Não foi possível completar a biometria."
}, },
"needADifferentMethod": { "needADifferentMethod": {
"message": "Need a different method?" "message": "Precisa de um método diferente?"
}, },
"useMasterPassword": { "useMasterPassword": {
"message": "Use master password" "message": "Usar a senha mestra"
}, },
"usePin": { "usePin": {
"message": "Use PIN" "message": "Usar PIN"
}, },
"useBiometrics": { "useBiometrics": {
"message": "Use biometrics" "message": "Usar biometria"
}, },
"enterVerificationCodeSentToEmail": { "enterVerificationCodeSentToEmail": {
"message": "Enter the verification code that was sent to your email." "message": "Digite o código de verificação que foi enviado para o seu e-mail."
}, },
"resendCode": { "resendCode": {
"message": "Resend code" "message": "Reenviar código"
}, },
"total": { "total": {
"message": "Total" "message": "Total"
@ -2700,19 +2700,19 @@
} }
}, },
"launchDuoAndFollowStepsToFinishLoggingIn": { "launchDuoAndFollowStepsToFinishLoggingIn": {
"message": "Launch Duo and follow the steps to finish logging in." "message": "Inicie o Duo e siga os passos para finalizar o login."
}, },
"duoRequiredForAccount": { "duoRequiredForAccount": {
"message": "Duo two-step login is required for your account." "message": "A autenticação em duas etapas do Duo é necessária para sua conta."
}, },
"popoutTheExtensionToCompleteLogin": { "popoutTheExtensionToCompleteLogin": {
"message": "Popout the extension to complete login." "message": "Abra a extensão para concluir o login."
}, },
"popoutExtension": { "popoutExtension": {
"message": "Popout extension" "message": "Extensão pop-out"
}, },
"launchDuo": { "launchDuo": {
"message": "Launch Duo" "message": "Abrir o Duo"
}, },
"importFormatError": { "importFormatError": {
"message": "Os dados não estão formatados corretamente. Por favor, verifique o seu arquivo de importação e tente novamente." "message": "Os dados não estão formatados corretamente. Por favor, verifique o seu arquivo de importação e tente novamente."
@ -2846,13 +2846,13 @@
"message": "Nome de usuário ou senha incorretos" "message": "Nome de usuário ou senha incorretos"
}, },
"incorrectPassword": { "incorrectPassword": {
"message": "Incorrect password" "message": "Senha incorreta"
}, },
"incorrectCode": { "incorrectCode": {
"message": "Incorrect code" "message": "Código incorreto"
}, },
"incorrectPin": { "incorrectPin": {
"message": "Incorrect PIN" "message": "PIN incorreto"
}, },
"multifactorAuthenticationFailed": { "multifactorAuthenticationFailed": {
"message": "Falha na autenticação de múltiplos fatores" "message": "Falha na autenticação de múltiplos fatores"
@ -2965,71 +2965,71 @@
"description": "Label indicating the most common import formats" "description": "Label indicating the most common import formats"
}, },
"overrideDefaultBrowserAutofillTitle": { "overrideDefaultBrowserAutofillTitle": {
"message": "Make Bitwarden your default password manager?", "message": "Tornar o Bitwarden seu gerenciador de senhas padrão?",
"description": "Dialog title facilitating the ability to override a chrome browser's default autofill behavior" "description": "Dialog title facilitating the ability to override a chrome browser's default autofill behavior"
}, },
"overrideDefaultBrowserAutofillDescription": { "overrideDefaultBrowserAutofillDescription": {
"message": "Ignoring this option may cause conflicts between the Bitwarden auto-fill menu and your browser's.", "message": "Ignorar esta opção pode causar conflitos entre o menu de autopreenchimento do Bitwarden e o do seu navegador.",
"description": "Dialog message facilitating the ability to override a chrome browser's default autofill behavior" "description": "Dialog message facilitating the ability to override a chrome browser's default autofill behavior"
}, },
"overrideDefaultBrowserAutoFillSettings": { "overrideDefaultBrowserAutoFillSettings": {
"message": "Make Bitwarden your default password manager", "message": "Faça do Bitwarden seu gerenciador de senhas padrão",
"description": "Label for the setting that allows overriding the default browser autofill settings" "description": "Label for the setting that allows overriding the default browser autofill settings"
}, },
"privacyPermissionAdditionNotGrantedTitle": { "privacyPermissionAdditionNotGrantedTitle": {
"message": "Unable to set Bitwarden as the default password manager", "message": "Não é possível definir o Bitwarden como o gerenciador de senhas padrão",
"description": "Title for the dialog that appears when the user has not granted the extension permission to set privacy settings" "description": "Title for the dialog that appears when the user has not granted the extension permission to set privacy settings"
}, },
"privacyPermissionAdditionNotGrantedDescription": { "privacyPermissionAdditionNotGrantedDescription": {
"message": "You must grant browser privacy permissions to Bitwarden to set it as the default password manager.", "message": "Você deve conceder permissões de privacidade do navegador ao Bitwarden para defini-lo como o Gerenciador de Senhas padrão.",
"description": "Description for the dialog that appears when the user has not granted the extension permission to set privacy settings" "description": "Description for the dialog that appears when the user has not granted the extension permission to set privacy settings"
}, },
"makeDefault": { "makeDefault": {
"message": "Make default", "message": "Tornar padrão",
"description": "Button text for the setting that allows overriding the default browser autofill settings" "description": "Button text for the setting that allows overriding the default browser autofill settings"
}, },
"saveCipherAttemptSuccess": { "saveCipherAttemptSuccess": {
"message": "Credentials saved successfully!", "message": "Credenciais salvas com sucesso!",
"description": "Notification message for when saving credentials has succeeded." "description": "Notification message for when saving credentials has succeeded."
}, },
"updateCipherAttemptSuccess": { "updateCipherAttemptSuccess": {
"message": "Credentials updated successfully!", "message": "Credenciais atualizadas com sucesso!",
"description": "Notification message for when updating credentials has succeeded." "description": "Notification message for when updating credentials has succeeded."
}, },
"saveCipherAttemptFailed": { "saveCipherAttemptFailed": {
"message": "Error saving credentials. Check console for details.", "message": "Erro ao salvar credenciais. Verifique o console para detalhes.",
"description": "Notification message for when saving credentials has failed." "description": "Notification message for when saving credentials has failed."
}, },
"success": { "success": {
"message": "Success" "message": "Sucesso"
}, },
"removePasskey": { "removePasskey": {
"message": "Remove passkey" "message": "Remover senha"
}, },
"passkeyRemoved": { "passkeyRemoved": {
"message": "Passkey removed" "message": "Chave de acesso removida"
}, },
"unassignedItemsBannerNotice": { "unassignedItemsBannerNotice": {
"message": "Notice: Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console." "message": "Aviso: Itens da organização não atribuídos não estão mais visíveis na visualização Todos os Cofres e só são acessíveis por meio do painel de administração."
}, },
"unassignedItemsBannerSelfHostNotice": { "unassignedItemsBannerSelfHostNotice": {
"message": "Notice: On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and will only be accessible via the Admin Console." "message": "Aviso: Em 16 de maio, 2024, itens da organização não serão mais visíveis na visualização Todos os Cofres e só serão acessíveis por meio do painel de administração."
}, },
"unassignedItemsBannerCTAPartOne": { "unassignedItemsBannerCTAPartOne": {
"message": "Assign these items to a collection from the", "message": "Atribua estes itens a uma coleção da",
"description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible." "description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible."
}, },
"unassignedItemsBannerCTAPartTwo": { "unassignedItemsBannerCTAPartTwo": {
"message": "to make them visible.", "message": "para torná-los visíveis.",
"description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible." "description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible."
}, },
"adminConsole": { "adminConsole": {
"message": "Admin Console" "message": "Painel de administração"
}, },
"errorAssigningTargetCollection": { "errorAssigningTargetCollection": {
"message": "Error assigning target collection." "message": "Erro ao atribuir coleção de destino."
}, },
"errorAssigningTargetFolder": { "errorAssigningTargetFolder": {
"message": "Error assigning target folder." "message": "Erro ao atribuir pasta de destino."
} }
} }

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Inicie sessão ou crie uma nova conta para aceder ao seu cofre seguro." "message": "Inicie sessão ou crie uma nova conta para aceder ao seu cofre seguro."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Autentificați-vă sau creați un cont nou pentru a accesa seiful dvs. securizat." "message": "Autentificați-vă sau creați un cont nou pentru a accesa seiful dvs. securizat."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Войдите или создайте новый аккаунт для доступа к вашему защищенному хранилищу." "message": "Войдите или создайте новый аккаунт для доступа к вашему защищенному хранилищу."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "ඔබගේ ආරක්ෂිත සුරක්ෂිතාගාරය වෙත පිවිසීමට හෝ නව ගිණුමක් නිර්මාණය කරන්න." "message": "ඔබගේ ආරක්ෂිත සුරක්ෂිතාගාරය වෙත පිවිසීමට හෝ නව ගිණුමක් නිර්මාණය කරන්න."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Prihláste sa, alebo vytvorte nový účet pre prístup k vášmu bezpečnému trezoru." "message": "Prihláste sa, alebo vytvorte nový účet pre prístup k vášmu bezpečnému trezoru."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Prijavite se ali ustvarite nov račun za dostop do svojega varnega trezorja." "message": "Prijavite se ali ustvarite nov račun za dostop do svojega varnega trezorja."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Пријавите се или креирајте нови налог за приступ сефу." "message": "Пријавите се или креирајте нови налог за приступ сефу."
@ -173,10 +173,10 @@
"message": "Промени главну лозинку" "message": "Промени главну лозинку"
}, },
"continueToWebApp": { "continueToWebApp": {
"message": "Continue to web app?" "message": "Ићи на веб апликацију?"
}, },
"changeMasterPasswordOnWebConfirmation": { "changeMasterPasswordOnWebConfirmation": {
"message": "You can change your master password on the Bitwarden web app." "message": "Можете променити главну лозинку на Bitwarden веб апликацији."
}, },
"fingerprintPhrase": { "fingerprintPhrase": {
"message": "Сигурносна Фраза Сефа", "message": "Сигурносна Фраза Сефа",
@ -3001,7 +3001,7 @@
"description": "Notification message for when saving credentials has failed." "description": "Notification message for when saving credentials has failed."
}, },
"success": { "success": {
"message": "Success" "message": "Успех"
}, },
"removePasskey": { "removePasskey": {
"message": "Уклонити приступачни кључ" "message": "Уклонити приступачни кључ"
@ -3010,10 +3010,10 @@
"message": "Приступачни кључ је уклоњен" "message": "Приступачни кључ је уклоњен"
}, },
"unassignedItemsBannerNotice": { "unassignedItemsBannerNotice": {
"message": "Notice: Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console." "message": "Напомена: Недодељене ставке организације више нису видљиве у приказу Сви сефови и доступне су само преко Админ конзоле."
}, },
"unassignedItemsBannerSelfHostNotice": { "unassignedItemsBannerSelfHostNotice": {
"message": "Notice: On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and will only be accessible via the Admin Console." "message": "Напомена: од 16 Маја 2024м недодељене ставке организације више нису видљиве у приказу Сви сефови и доступне су само преко Админ конзоле."
}, },
"unassignedItemsBannerCTAPartOne": { "unassignedItemsBannerCTAPartOne": {
"message": "Assign these items to a collection from the", "message": "Assign these items to a collection from the",
@ -3024,12 +3024,12 @@
"description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible." "description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible."
}, },
"adminConsole": { "adminConsole": {
"message": "Admin Console" "message": "Администраторска конзола"
}, },
"errorAssigningTargetCollection": { "errorAssigningTargetCollection": {
"message": "Error assigning target collection." "message": "Грешка при додељивању циљне колекције."
}, },
"errorAssigningTargetFolder": { "errorAssigningTargetFolder": {
"message": "Error assigning target folder." "message": "Грешка при додељивању циљне фасцикле."
} }
} }

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Logga in eller skapa ett nytt konto för att komma åt ditt säkra valv." "message": "Logga in eller skapa ett nytt konto för att komma åt ditt säkra valv."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Log in or create a new account to access your secure vault." "message": "Log in or create a new account to access your secure vault."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "ล็อกอิน หรือ สร้างบัญชีใหม่ เพื่อใช้งานตู้นิรภัยของคุณ" "message": "ล็อกอิน หรือ สร้างบัญชีใหม่ เพื่อใช้งานตู้นิรภัยของคุณ"

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Güvenli kasanıza ulaşmak için giriş yapın veya yeni bir hesap oluşturun." "message": "Güvenli kasanıza ulaşmak için giriş yapın veya yeni bir hesap oluşturun."

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Для доступу до сховища увійдіть в обліковий запис, або створіть новий." "message": "Для доступу до сховища увійдіть в обліковий запис, або створіть новий."

View File

@ -3,12 +3,12 @@
"message": "Bitwarden" "message": "Bitwarden"
}, },
"extName": { "extName": {
"message": "Bitwarden Password Manager", "message": "Bitwarden - Trình Quản lý Mật khẩu",
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "Ở nhà, ở cơ quan, hay trên đường đi, Bitwarden sẽ bảo mật tất cả mật khẩu, passkey, và thông tin cá nhân của bạn",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "Đăng nhập hoặc tạo tài khoản mới để truy cập kho lưu trữ của bạn." "message": "Đăng nhập hoặc tạo tài khoản mới để truy cập kho lưu trữ của bạn."
@ -650,7 +650,7 @@
"message": "'Thông báo Thêm đăng nhập' sẽ tự động nhắc bạn lưu các đăng nhập mới vào hầm an toàn của bạn bất cứ khi nào bạn đăng nhập trang web lần đầu tiên." "message": "'Thông báo Thêm đăng nhập' sẽ tự động nhắc bạn lưu các đăng nhập mới vào hầm an toàn của bạn bất cứ khi nào bạn đăng nhập trang web lần đầu tiên."
}, },
"addLoginNotificationDescAlt": { "addLoginNotificationDescAlt": {
"message": "Ask to add an item if one isn't found in your vault. Applies to all logged in accounts." "message": "Đưa ra lựa chọn để thêm một mục nếu không tìm thấy mục đó trong hòm của bạn. Áp dụng với mọi tài khoản đăng nhập trên thiết bị."
}, },
"showCardsCurrentTab": { "showCardsCurrentTab": {
"message": "Hiển thị thẻ trên trang Tab" "message": "Hiển thị thẻ trên trang Tab"
@ -685,13 +685,13 @@
"message": "Yêu cầu cập nhật mật khẩu đăng nhập khi phát hiện thay đổi trên trang web." "message": "Yêu cầu cập nhật mật khẩu đăng nhập khi phát hiện thay đổi trên trang web."
}, },
"changedPasswordNotificationDescAlt": { "changedPasswordNotificationDescAlt": {
"message": "Ask to update a login's password when a change is detected on a website. Applies to all logged in accounts." "message": "Đưa ra lựa chọn để cập nhật mật khẩu khi phát hiện có sự thay đổi trên trang web. Áp dụng với mọi tài khoản đăng nhập trên thiết bị."
}, },
"enableUsePasskeys": { "enableUsePasskeys": {
"message": "Ask to save and use passkeys" "message": "Đưa ra lựa chọn để lưu và sử dụng passkey"
}, },
"usePasskeysDesc": { "usePasskeysDesc": {
"message": "Ask to save new passkeys or log in with passkeys stored in your vault. Applies to all logged in accounts." "message": "Đưa ra lựa chọn để lưu passkey mới hoặc đăng nhập bằng passkey đã lưu trong hòm. Áp dụng với mọi tài khoản đăng nhập trên thiết bị."
}, },
"notificationChangeDesc": { "notificationChangeDesc": {
"message": "Bạn có muốn cập nhật mật khẩu này trên Bitwarden không?" "message": "Bạn có muốn cập nhật mật khẩu này trên Bitwarden không?"
@ -712,7 +712,7 @@
"message": "Sử dụng một đúp chuột để truy cập vào việc tạo mật khẩu và thông tin đăng nhập phù hợp cho trang web. " "message": "Sử dụng một đúp chuột để truy cập vào việc tạo mật khẩu và thông tin đăng nhập phù hợp cho trang web. "
}, },
"contextMenuItemDescAlt": { "contextMenuItemDescAlt": {
"message": "Use a secondary click to access password generation and matching logins for the website. Applies to all logged in accounts." "message": "Truy cập trình khởi tạo mật khẩu và các mục đăng nhập đã lưu của trang web bằng cách nhấn đúp chuột. Áp dụng với mọi tài khoản đăng nhập trên thiết bị."
}, },
"defaultUriMatchDetection": { "defaultUriMatchDetection": {
"message": "Phương thức kiểm tra URI mặc định", "message": "Phương thức kiểm tra URI mặc định",
@ -728,7 +728,7 @@
"message": "Thay đổi màu sắc ứng dụng." "message": "Thay đổi màu sắc ứng dụng."
}, },
"themeDescAlt": { "themeDescAlt": {
"message": "Change the application's color theme. Applies to all logged in accounts." "message": "Thay đổi tông màu giao diện của ứng dụng. Áp dụng với mọi tài khoản đăng nhập trên thiết bị."
}, },
"dark": { "dark": {
"message": "Tối", "message": "Tối",
@ -1061,10 +1061,10 @@
"message": "Tắt cài đặt trình quản lý mật khẩu tích hợp trong trình duyệt của bạn để tránh xung đột." "message": "Tắt cài đặt trình quản lý mật khẩu tích hợp trong trình duyệt của bạn để tránh xung đột."
}, },
"turnOffBrowserBuiltInPasswordManagerSettingsLink": { "turnOffBrowserBuiltInPasswordManagerSettingsLink": {
"message": "Edit browser settings." "message": "Thay đổi cài đặt của trình duyệt."
}, },
"autofillOverlayVisibilityOff": { "autofillOverlayVisibilityOff": {
"message": "Off", "message": "Tắt",
"description": "Overlay setting select option for disabling autofill overlay" "description": "Overlay setting select option for disabling autofill overlay"
}, },
"autofillOverlayVisibilityOnFieldFocus": { "autofillOverlayVisibilityOnFieldFocus": {
@ -1168,7 +1168,7 @@
"message": "Hiển thị một ảnh nhận dạng bên cạnh mỗi lần đăng nhập." "message": "Hiển thị một ảnh nhận dạng bên cạnh mỗi lần đăng nhập."
}, },
"faviconDescAlt": { "faviconDescAlt": {
"message": "Show a recognizable image next to each login. Applies to all logged in accounts." "message": "Hiển thị một biểu tượng dễ nhận dạng bên cạnh mỗi mục đăng nhập. Áp dụng với mọi tài khoản đăng nhập trên thiết bị."
}, },
"enableBadgeCounter": { "enableBadgeCounter": {
"message": "Hiển thị biểu tượng bộ đếm" "message": "Hiển thị biểu tượng bộ đếm"
@ -1500,7 +1500,7 @@
"message": "Mã PIN không hợp lệ." "message": "Mã PIN không hợp lệ."
}, },
"tooManyInvalidPinEntryAttemptsLoggingOut": { "tooManyInvalidPinEntryAttemptsLoggingOut": {
"message": "Too many invalid PIN entry attempts. Logging out." "message": "Mã PIN bị gõ sai quá nhiều lần. Đang đăng xuất."
}, },
"unlockWithBiometrics": { "unlockWithBiometrics": {
"message": "Mở khóa bằng sinh trắc học" "message": "Mở khóa bằng sinh trắc học"

View File

@ -3,12 +3,12 @@
"message": "Bitwarden" "message": "Bitwarden"
}, },
"extName": { "extName": {
"message": "Bitwarden Password Manager", "message": "Bitwarden 密码管理器",
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "无论是在家里、工作中还是在外出时Bitwarden 都可以轻松地保护您的所有密码、通行密钥和敏感信息。",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "登录或者创建一个账户来访问您的安全密码库。" "message": "登录或者创建一个账户来访问您的安全密码库。"
@ -176,7 +176,7 @@
"message": "前往网页 App 吗?" "message": "前往网页 App 吗?"
}, },
"changeMasterPasswordOnWebConfirmation": { "changeMasterPasswordOnWebConfirmation": {
"message": "You can change your master password on the Bitwarden web app." "message": "您可以在 Bitwarden 网页应用上更改您的主密码。"
}, },
"fingerprintPhrase": { "fingerprintPhrase": {
"message": "指纹短语", "message": "指纹短语",
@ -3010,17 +3010,17 @@
"message": "通行密钥已移除" "message": "通行密钥已移除"
}, },
"unassignedItemsBannerNotice": { "unassignedItemsBannerNotice": {
"message": "Notice: Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console." "message": "注意:未分配的组织项目在「所有密码库」视图中不再可见,只能通过管理控制台访问。"
}, },
"unassignedItemsBannerSelfHostNotice": { "unassignedItemsBannerSelfHostNotice": {
"message": "Notice: On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and will only be accessible via the Admin Console." "message": "注意:从 2024 年 5 月 16 日起,未分配的组织项目在「所有密码库」视图中将不再可见,只能通过管理控制台访问。"
}, },
"unassignedItemsBannerCTAPartOne": { "unassignedItemsBannerCTAPartOne": {
"message": "Assign these items to a collection from the", "message": "Assign these items to a collection from the",
"description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible." "description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible."
}, },
"unassignedItemsBannerCTAPartTwo": { "unassignedItemsBannerCTAPartTwo": {
"message": "to make them visible.", "message": "以使其可见。",
"description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible." "description": "This will be part of a larger sentence, which will read like so: Assign these items to a collection from the Admin Console to make them visible."
}, },
"adminConsole": { "adminConsole": {

View File

@ -7,8 +7,8 @@
"description": "Extension name, MUST be less than 40 characters (Safari restriction)" "description": "Extension name, MUST be less than 40 characters (Safari restriction)"
}, },
"extDesc": { "extDesc": {
"message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information.", "message": "At home, at work, or on the go, Bitwarden easily secures all your passwords, passkeys, and sensitive information",
"description": "Extension description" "description": "Extension description, MUST be less than 112 characters (Safari restriction)"
}, },
"loginOrCreateNewAccount": { "loginOrCreateNewAccount": {
"message": "登入或建立帳戶以存取您的安全密碼庫。" "message": "登入或建立帳戶以存取您的安全密碼庫。"

View File

@ -1,5 +1,5 @@
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction"; import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation"; import { DeviceTrustService } from "@bitwarden/common/auth/services/device-trust.service.implementation";
import { import {
DevicesApiServiceInitOptions, DevicesApiServiceInitOptions,
@ -52,9 +52,9 @@ import {
userDecryptionOptionsServiceFactory, userDecryptionOptionsServiceFactory,
} from "./user-decryption-options-service.factory"; } from "./user-decryption-options-service.factory";
type DeviceTrustCryptoServiceFactoryOptions = FactoryOptions; type DeviceTrustServiceFactoryOptions = FactoryOptions;
export type DeviceTrustCryptoServiceInitOptions = DeviceTrustCryptoServiceFactoryOptions & export type DeviceTrustServiceInitOptions = DeviceTrustServiceFactoryOptions &
KeyGenerationServiceInitOptions & KeyGenerationServiceInitOptions &
CryptoFunctionServiceInitOptions & CryptoFunctionServiceInitOptions &
CryptoServiceInitOptions & CryptoServiceInitOptions &
@ -67,16 +67,16 @@ export type DeviceTrustCryptoServiceInitOptions = DeviceTrustCryptoServiceFactor
SecureStorageServiceInitOptions & SecureStorageServiceInitOptions &
UserDecryptionOptionsServiceInitOptions; UserDecryptionOptionsServiceInitOptions;
export function deviceTrustCryptoServiceFactory( export function deviceTrustServiceFactory(
cache: { deviceTrustCryptoService?: DeviceTrustCryptoServiceAbstraction } & CachedServices, cache: { deviceTrustService?: DeviceTrustServiceAbstraction } & CachedServices,
opts: DeviceTrustCryptoServiceInitOptions, opts: DeviceTrustServiceInitOptions,
): Promise<DeviceTrustCryptoServiceAbstraction> { ): Promise<DeviceTrustServiceAbstraction> {
return factory( return factory(
cache, cache,
"deviceTrustCryptoService", "deviceTrustService",
opts, opts,
async () => async () =>
new DeviceTrustCryptoService( new DeviceTrustService(
await keyGenerationServiceFactory(cache, opts), await keyGenerationServiceFactory(cache, opts),
await cryptoFunctionServiceFactory(cache, opts), await cryptoFunctionServiceFactory(cache, opts),
await cryptoServiceFactory(cache, opts), await cryptoServiceFactory(cache, opts),

View File

@ -0,0 +1,28 @@
import { KdfConfigService as AbstractKdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { KdfConfigService } from "@bitwarden/common/auth/services/kdf-config.service";
import {
FactoryOptions,
CachedServices,
factory,
} from "../../../platform/background/service-factories/factory-options";
import {
StateProviderInitOptions,
stateProviderFactory,
} from "../../../platform/background/service-factories/state-provider.factory";
type KdfConfigServiceFactoryOptions = FactoryOptions;
export type KdfConfigServiceInitOptions = KdfConfigServiceFactoryOptions & StateProviderInitOptions;
export function kdfConfigServiceFactory(
cache: { kdfConfigService?: AbstractKdfConfigService } & CachedServices,
opts: KdfConfigServiceInitOptions,
): Promise<AbstractKdfConfigService> {
return factory(
cache,
"kdfConfigService",
opts,
async () => new KdfConfigService(await stateProviderFactory(cache, opts)),
);
}

View File

@ -69,9 +69,10 @@ import {
AuthRequestServiceInitOptions, AuthRequestServiceInitOptions,
} from "./auth-request-service.factory"; } from "./auth-request-service.factory";
import { import {
deviceTrustCryptoServiceFactory, deviceTrustServiceFactory,
DeviceTrustCryptoServiceInitOptions, DeviceTrustServiceInitOptions,
} from "./device-trust-crypto-service.factory"; } from "./device-trust-service.factory";
import { kdfConfigServiceFactory, KdfConfigServiceInitOptions } from "./kdf-config-service.factory";
import { import {
keyConnectorServiceFactory, keyConnectorServiceFactory,
KeyConnectorServiceInitOptions, KeyConnectorServiceInitOptions,
@ -106,11 +107,12 @@ export type LoginStrategyServiceInitOptions = LoginStrategyServiceFactoryOptions
EncryptServiceInitOptions & EncryptServiceInitOptions &
PolicyServiceInitOptions & PolicyServiceInitOptions &
PasswordStrengthServiceInitOptions & PasswordStrengthServiceInitOptions &
DeviceTrustCryptoServiceInitOptions & DeviceTrustServiceInitOptions &
AuthRequestServiceInitOptions & AuthRequestServiceInitOptions &
UserDecryptionOptionsServiceInitOptions & UserDecryptionOptionsServiceInitOptions &
GlobalStateProviderInitOptions & GlobalStateProviderInitOptions &
BillingAccountProfileStateServiceInitOptions & BillingAccountProfileStateServiceInitOptions &
KdfConfigServiceInitOptions &
TaskSchedulerServiceInitOptions; TaskSchedulerServiceInitOptions;
export function loginStrategyServiceFactory( export function loginStrategyServiceFactory(
@ -140,11 +142,12 @@ export function loginStrategyServiceFactory(
await encryptServiceFactory(cache, opts), await encryptServiceFactory(cache, opts),
await passwordStrengthServiceFactory(cache, opts), await passwordStrengthServiceFactory(cache, opts),
await policyServiceFactory(cache, opts), await policyServiceFactory(cache, opts),
await deviceTrustCryptoServiceFactory(cache, opts), await deviceTrustServiceFactory(cache, opts),
await authRequestServiceFactory(cache, opts), await authRequestServiceFactory(cache, opts),
await internalUserDecryptionOptionServiceFactory(cache, opts), await internalUserDecryptionOptionServiceFactory(cache, opts),
await globalStateProviderFactory(cache, opts), await globalStateProviderFactory(cache, opts),
await billingAccountProfileStateServiceFactory(cache, opts), await billingAccountProfileStateServiceFactory(cache, opts),
await kdfConfigServiceFactory(cache, opts),
await taskSchedulerServiceFactory(cache, opts), await taskSchedulerServiceFactory(cache, opts),
), ),
); );

View File

@ -22,13 +22,16 @@ import {
stateServiceFactory, stateServiceFactory,
} from "../../../platform/background/service-factories/state-service.factory"; } from "../../../platform/background/service-factories/state-service.factory";
import { KdfConfigServiceInitOptions, kdfConfigServiceFactory } from "./kdf-config-service.factory";
type PinCryptoServiceFactoryOptions = FactoryOptions; type PinCryptoServiceFactoryOptions = FactoryOptions;
export type PinCryptoServiceInitOptions = PinCryptoServiceFactoryOptions & export type PinCryptoServiceInitOptions = PinCryptoServiceFactoryOptions &
StateServiceInitOptions & StateServiceInitOptions &
CryptoServiceInitOptions & CryptoServiceInitOptions &
VaultTimeoutSettingsServiceInitOptions & VaultTimeoutSettingsServiceInitOptions &
LogServiceInitOptions; LogServiceInitOptions &
KdfConfigServiceInitOptions;
export function pinCryptoServiceFactory( export function pinCryptoServiceFactory(
cache: { pinCryptoService?: PinCryptoServiceAbstraction } & CachedServices, cache: { pinCryptoService?: PinCryptoServiceAbstraction } & CachedServices,
@ -44,6 +47,7 @@ export function pinCryptoServiceFactory(
await cryptoServiceFactory(cache, opts), await cryptoServiceFactory(cache, opts),
await vaultTimeoutSettingsServiceFactory(cache, opts), await vaultTimeoutSettingsServiceFactory(cache, opts),
await logServiceFactory(cache, opts), await logServiceFactory(cache, opts),
await kdfConfigServiceFactory(cache, opts),
), ),
); );
} }

View File

@ -1,11 +1,13 @@
import { TwoFactorService as AbstractTwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service"; import { TwoFactorService as AbstractTwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service"; import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service";
import { GlobalStateProvider } from "@bitwarden/common/platform/state";
import { import {
FactoryOptions, FactoryOptions,
CachedServices, CachedServices,
factory, factory,
} from "../../../platform/background/service-factories/factory-options"; } from "../../../platform/background/service-factories/factory-options";
import { globalStateProviderFactory } from "../../../platform/background/service-factories/global-state-provider.factory";
import { import {
I18nServiceInitOptions, I18nServiceInitOptions,
i18nServiceFactory, i18nServiceFactory,
@ -19,7 +21,8 @@ type TwoFactorServiceFactoryOptions = FactoryOptions;
export type TwoFactorServiceInitOptions = TwoFactorServiceFactoryOptions & export type TwoFactorServiceInitOptions = TwoFactorServiceFactoryOptions &
I18nServiceInitOptions & I18nServiceInitOptions &
PlatformUtilsServiceInitOptions; PlatformUtilsServiceInitOptions &
GlobalStateProvider;
export async function twoFactorServiceFactory( export async function twoFactorServiceFactory(
cache: { twoFactorService?: AbstractTwoFactorService } & CachedServices, cache: { twoFactorService?: AbstractTwoFactorService } & CachedServices,
@ -33,6 +36,7 @@ export async function twoFactorServiceFactory(
new TwoFactorService( new TwoFactorService(
await i18nServiceFactory(cache, opts), await i18nServiceFactory(cache, opts),
await platformUtilsServiceFactory(cache, opts), await platformUtilsServiceFactory(cache, opts),
await globalStateProviderFactory(cache, opts),
), ),
); );
service.init(); service.init();

View File

@ -32,6 +32,7 @@ import {
} from "../../../platform/background/service-factories/state-service.factory"; } from "../../../platform/background/service-factories/state-service.factory";
import { accountServiceFactory, AccountServiceInitOptions } from "./account-service.factory"; import { accountServiceFactory, AccountServiceInitOptions } from "./account-service.factory";
import { KdfConfigServiceInitOptions, kdfConfigServiceFactory } from "./kdf-config-service.factory";
import { import {
internalMasterPasswordServiceFactory, internalMasterPasswordServiceFactory,
MasterPasswordServiceInitOptions, MasterPasswordServiceInitOptions,
@ -59,7 +60,8 @@ export type UserVerificationServiceInitOptions = UserVerificationServiceFactoryO
PinCryptoServiceInitOptions & PinCryptoServiceInitOptions &
LogServiceInitOptions & LogServiceInitOptions &
VaultTimeoutSettingsServiceInitOptions & VaultTimeoutSettingsServiceInitOptions &
PlatformUtilsServiceInitOptions; PlatformUtilsServiceInitOptions &
KdfConfigServiceInitOptions;
export function userVerificationServiceFactory( export function userVerificationServiceFactory(
cache: { userVerificationService?: AbstractUserVerificationService } & CachedServices, cache: { userVerificationService?: AbstractUserVerificationService } & CachedServices,
@ -82,6 +84,7 @@ export function userVerificationServiceFactory(
await logServiceFactory(cache, opts), await logServiceFactory(cache, opts),
await vaultTimeoutSettingsServiceFactory(cache, opts), await vaultTimeoutSettingsServiceFactory(cache, opts),
await platformUtilsServiceFactory(cache, opts), await platformUtilsServiceFactory(cache, opts),
await kdfConfigServiceFactory(cache, opts),
), ),
); );
} }

View File

@ -110,7 +110,7 @@ export class AccountSwitcherService {
}), }),
); );
// Create a reusable observable that listens to the the switchAccountFinish message and returns the userId from the message // Create a reusable observable that listens to the switchAccountFinish message and returns the userId from the message
this.switchAccountFinished$ = fromChromeEvent<[message: { command: string; userId: string }]>( this.switchAccountFinished$ = fromChromeEvent<[message: { command: string; userId: string }]>(
chrome.runtime.onMessage, chrome.runtime.onMessage,
).pipe( ).pipe(

View File

@ -11,7 +11,8 @@ import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abs
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction"; import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction"; import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
@ -60,12 +61,13 @@ export class LockComponent extends BaseLockComponent {
passwordStrengthService: PasswordStrengthServiceAbstraction, passwordStrengthService: PasswordStrengthServiceAbstraction,
private authService: AuthService, private authService: AuthService,
dialogService: DialogService, dialogService: DialogService,
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction, deviceTrustService: DeviceTrustServiceAbstraction,
userVerificationService: UserVerificationService, userVerificationService: UserVerificationService,
pinCryptoService: PinCryptoServiceAbstraction, pinCryptoService: PinCryptoServiceAbstraction,
private routerService: BrowserRouterService, private routerService: BrowserRouterService,
biometricStateService: BiometricStateService, biometricStateService: BiometricStateService,
accountService: AccountService, accountService: AccountService,
kdfConfigService: KdfConfigService,
) { ) {
super( super(
masterPasswordService, masterPasswordService,
@ -85,11 +87,12 @@ export class LockComponent extends BaseLockComponent {
policyService, policyService,
passwordStrengthService, passwordStrengthService,
dialogService, dialogService,
deviceTrustCryptoService, deviceTrustService,
userVerificationService, userVerificationService,
pinCryptoService, pinCryptoService,
biometricStateService, biometricStateService,
accountService, accountService,
kdfConfigService,
); );
this.successRoute = "/tabs/current"; this.successRoute = "/tabs/current";
this.isInitialLockScreen = (window as any).previousPopupUrl == null; this.isInitialLockScreen = (window as any).previousPopupUrl == null;

View File

@ -12,7 +12,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service"; import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction"; import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
@ -47,7 +47,7 @@ export class LoginViaAuthRequestComponent extends BaseLoginWithDeviceComponent {
stateService: StateService, stateService: StateService,
loginEmailService: LoginEmailServiceAbstraction, loginEmailService: LoginEmailServiceAbstraction,
syncService: SyncService, syncService: SyncService,
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction, deviceTrustService: DeviceTrustServiceAbstraction,
authRequestService: AuthRequestServiceAbstraction, authRequestService: AuthRequestServiceAbstraction,
loginStrategyService: LoginStrategyServiceAbstraction, loginStrategyService: LoginStrategyServiceAbstraction,
accountService: AccountService, accountService: AccountService,
@ -69,7 +69,7 @@ export class LoginViaAuthRequestComponent extends BaseLoginWithDeviceComponent {
validationService, validationService,
stateService, stateService,
loginEmailService, loginEmailService,
deviceTrustCryptoService, deviceTrustService,
authRequestService, authRequestService,
loginStrategyService, loginStrategyService,
accountService, accountService,

View File

@ -2,7 +2,10 @@ import { Component } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router"; import { ActivatedRoute, Router } from "@angular/router";
import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "@bitwarden/angular/auth/components/two-factor-options.component"; import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "@bitwarden/angular/auth/components/two-factor-options.component";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service"; import {
TwoFactorProviderDetails,
TwoFactorService,
} from "@bitwarden/common/auth/abstractions/two-factor.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -27,9 +30,9 @@ export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent {
this.navigateTo2FA(); this.navigateTo2FA();
} }
choose(p: any) { override async choose(p: TwoFactorProviderDetails) {
super.choose(p); await super.choose(p);
this.twoFactorService.setSelectedProvider(p.type); await this.twoFactorService.setSelectedProvider(p.type);
this.navigateTo2FA(); this.navigateTo2FA();
} }

View File

@ -130,7 +130,9 @@ export default class AutofillService implements AutofillServiceInterface {
if (triggeringOnPageLoad && autoFillOnPageLoadIsEnabled) { if (triggeringOnPageLoad && autoFillOnPageLoadIsEnabled) {
injectedScripts.push("autofiller.js"); injectedScripts.push("autofiller.js");
} else { }
if (!triggeringOnPageLoad) {
await this.scriptInjectorService.inject({ await this.scriptInjectorService.inject({
tabId: tab.id, tabId: tab.id,
injectDetails: { file: "content/content-message-handler.js", runAt: "document_start" }, injectDetails: { file: "content/content-message-handler.js", runAt: "document_start" },

View File

@ -1,10 +1,8 @@
import { Subject, firstValueFrom, merge } from "rxjs"; import { Subject, firstValueFrom, merge, timeout } from "rxjs";
import { import {
PinCryptoServiceAbstraction, PinCryptoServiceAbstraction,
PinCryptoService, PinCryptoService,
LoginStrategyServiceAbstraction,
LoginStrategyService,
InternalUserDecryptionOptionsServiceAbstraction, InternalUserDecryptionOptionsServiceAbstraction,
UserDecryptionOptionsService, UserDecryptionOptionsService,
AuthRequestServiceAbstraction, AuthRequestServiceAbstraction,
@ -30,14 +28,14 @@ import { ProviderService } from "@bitwarden/common/admin-console/services/provid
import { AccountService as AccountServiceAbstraction } from "@bitwarden/common/auth/abstractions/account.service"; import { AccountService as AccountServiceAbstraction } from "@bitwarden/common/auth/abstractions/account.service";
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service"; import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/auth/abstractions/avatar.service"; import { AvatarService as AvatarServiceAbstraction } from "@bitwarden/common/auth/abstractions/avatar.service";
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction"; import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction"; import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction"; import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { KdfConfigService as kdfConfigServiceAbstraction } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarden/common/auth/abstractions/key-connector.service"; import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarden/common/auth/abstractions/key-connector.service";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction"; import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/auth/abstractions/token.service"; import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/auth/abstractions/token.service";
import { TwoFactorService as TwoFactorServiceAbstraction } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { UserVerificationApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification-api.service.abstraction"; import { UserVerificationApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification-api.service.abstraction";
import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
@ -45,14 +43,14 @@ import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/for
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service"; import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
import { AuthService } from "@bitwarden/common/auth/services/auth.service"; import { AuthService } from "@bitwarden/common/auth/services/auth.service";
import { AvatarService } from "@bitwarden/common/auth/services/avatar.service"; import { AvatarService } from "@bitwarden/common/auth/services/avatar.service";
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation"; import { DeviceTrustService } from "@bitwarden/common/auth/services/device-trust.service.implementation";
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation"; import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation"; import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
import { KdfConfigService } from "@bitwarden/common/auth/services/kdf-config.service";
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service"; import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
import { MasterPasswordService } from "@bitwarden/common/auth/services/master-password/master-password.service"; import { MasterPasswordService } from "@bitwarden/common/auth/services/master-password/master-password.service";
import { SsoLoginService } from "@bitwarden/common/auth/services/sso-login.service"; import { SsoLoginService } from "@bitwarden/common/auth/services/sso-login.service";
import { TokenService } from "@bitwarden/common/auth/services/token.service"; import { TokenService } from "@bitwarden/common/auth/services/token.service";
import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service";
import { UserVerificationApiService } from "@bitwarden/common/auth/services/user-verification/user-verification-api.service"; import { UserVerificationApiService } from "@bitwarden/common/auth/services/user-verification/user-verification-api.service";
import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service"; import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service";
import { import {
@ -73,6 +71,7 @@ import {
} from "@bitwarden/common/autofill/services/user-notification-settings.service"; } from "@bitwarden/common/autofill/services/user-notification-settings.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service"; import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service";
import { ClientType } from "@bitwarden/common/enums";
import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service"; import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service";
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction"; import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
@ -277,7 +276,6 @@ export default class MainBackground {
containerService: ContainerService; containerService: ContainerService;
auditService: AuditServiceAbstraction; auditService: AuditServiceAbstraction;
authService: AuthServiceAbstraction; authService: AuthServiceAbstraction;
loginStrategyService: LoginStrategyServiceAbstraction;
loginEmailService: LoginEmailServiceAbstraction; loginEmailService: LoginEmailServiceAbstraction;
importApiService: ImportApiServiceAbstraction; importApiService: ImportApiServiceAbstraction;
importService: ImportServiceAbstraction; importService: ImportServiceAbstraction;
@ -301,7 +299,6 @@ export default class MainBackground {
providerService: ProviderServiceAbstraction; providerService: ProviderServiceAbstraction;
keyConnectorService: KeyConnectorServiceAbstraction; keyConnectorService: KeyConnectorServiceAbstraction;
userVerificationService: UserVerificationServiceAbstraction; userVerificationService: UserVerificationServiceAbstraction;
twoFactorService: TwoFactorServiceAbstraction;
vaultFilterService: VaultFilterService; vaultFilterService: VaultFilterService;
usernameGenerationService: UsernameGenerationServiceAbstraction; usernameGenerationService: UsernameGenerationServiceAbstraction;
encryptService: EncryptService; encryptService: EncryptService;
@ -320,7 +317,7 @@ export default class MainBackground {
configApiService: ConfigApiServiceAbstraction; configApiService: ConfigApiServiceAbstraction;
devicesApiService: DevicesApiServiceAbstraction; devicesApiService: DevicesApiServiceAbstraction;
devicesService: DevicesServiceAbstraction; devicesService: DevicesServiceAbstraction;
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction; deviceTrustService: DeviceTrustServiceAbstraction;
authRequestService: AuthRequestServiceAbstraction; authRequestService: AuthRequestServiceAbstraction;
accountService: AccountServiceAbstraction; accountService: AccountServiceAbstraction;
globalStateProvider: GlobalStateProvider; globalStateProvider: GlobalStateProvider;
@ -342,6 +339,7 @@ export default class MainBackground {
intraprocessMessagingSubject: Subject<Message<object>>; intraprocessMessagingSubject: Subject<Message<object>>;
userKeyInitService: UserKeyInitService; userKeyInitService: UserKeyInitService;
scriptInjectorService: BrowserScriptInjectorService; scriptInjectorService: BrowserScriptInjectorService;
kdfConfigService: kdfConfigServiceAbstraction;
onUpdatedRan: boolean; onUpdatedRan: boolean;
onReplacedRan: boolean; onReplacedRan: boolean;
@ -496,7 +494,7 @@ export default class MainBackground {
this.accountService, this.accountService,
this.singleUserStateProvider, this.singleUserStateProvider,
); );
this.derivedStateProvider = new BackgroundDerivedStateProvider(storageServiceProvider); this.derivedStateProvider = new BackgroundDerivedStateProvider();
this.stateProvider = new DefaultStateProvider( this.stateProvider = new DefaultStateProvider(
this.activeUserStateProvider, this.activeUserStateProvider,
this.singleUserStateProvider, this.singleUserStateProvider,
@ -540,6 +538,7 @@ export default class MainBackground {
this.storageService, this.storageService,
this.logService, this.logService,
new MigrationBuilderService(), new MigrationBuilderService(),
ClientType.Browser,
); );
this.stateService = new DefaultBrowserStateService( this.stateService = new DefaultBrowserStateService(
@ -559,6 +558,9 @@ export default class MainBackground {
this.masterPasswordService = new MasterPasswordService(this.stateProvider); this.masterPasswordService = new MasterPasswordService(this.stateProvider);
this.i18nService = new I18nService(BrowserApi.getUILanguage(), this.globalStateProvider); this.i18nService = new I18nService(BrowserApi.getUILanguage(), this.globalStateProvider);
this.kdfConfigService = new KdfConfigService(this.stateProvider);
this.cryptoService = new BrowserCryptoService( this.cryptoService = new BrowserCryptoService(
this.masterPasswordService, this.masterPasswordService,
this.keyGenerationService, this.keyGenerationService,
@ -570,6 +572,7 @@ export default class MainBackground {
this.accountService, this.accountService,
this.stateProvider, this.stateProvider,
this.biometricStateService, this.biometricStateService,
this.kdfConfigService,
); );
this.appIdService = new AppIdService(this.globalStateProvider); this.appIdService = new AppIdService(this.globalStateProvider);
@ -624,12 +627,10 @@ export default class MainBackground {
this.stateService, this.stateService,
); );
this.twoFactorService = new TwoFactorService(this.i18nService, this.platformUtilsService);
this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider); this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider);
this.devicesApiService = new DevicesApiServiceImplementation(this.apiService); this.devicesApiService = new DevicesApiServiceImplementation(this.apiService);
this.deviceTrustCryptoService = new DeviceTrustCryptoService( this.deviceTrustService = new DeviceTrustService(
this.keyGenerationService, this.keyGenerationService,
this.cryptoFunctionService, this.cryptoFunctionService,
this.cryptoService, this.cryptoService,
@ -669,32 +670,6 @@ export default class MainBackground {
this.loginEmailService = new LoginEmailService(this.stateProvider); this.loginEmailService = new LoginEmailService(this.stateProvider);
this.loginStrategyService = new LoginStrategyService(
this.accountService,
this.masterPasswordService,
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.keyConnectorService,
this.environmentService,
this.stateService,
this.twoFactorService,
this.i18nService,
this.encryptService,
this.passwordStrengthService,
this.policyService,
this.deviceTrustCryptoService,
this.authRequestService,
this.userDecryptionOptionsService,
this.globalStateProvider,
this.billingAccountProfileStateService,
this.taskSchedulerService,
);
this.ssoLoginService = new SsoLoginService(this.stateProvider); this.ssoLoginService = new SsoLoginService(this.stateProvider);
this.userVerificationApiService = new UserVerificationApiService(this.apiService); this.userVerificationApiService = new UserVerificationApiService(this.apiService);
@ -743,6 +718,7 @@ export default class MainBackground {
this.cryptoService, this.cryptoService,
this.vaultTimeoutSettingsService, this.vaultTimeoutSettingsService,
this.logService, this.logService,
this.kdfConfigService,
); );
this.userVerificationService = new UserVerificationService( this.userVerificationService = new UserVerificationService(
@ -757,6 +733,7 @@ export default class MainBackground {
this.logService, this.logService,
this.vaultTimeoutSettingsService, this.vaultTimeoutSettingsService,
this.platformUtilsService, this.platformUtilsService,
this.kdfConfigService,
); );
this.vaultFilterService = new VaultFilterService( this.vaultFilterService = new VaultFilterService(
@ -831,6 +808,7 @@ export default class MainBackground {
this.avatarService, this.avatarService,
logoutCallback, logoutCallback,
this.billingAccountProfileStateService, this.billingAccountProfileStateService,
this.tokenService,
); );
this.eventUploadService = new EventUploadService( this.eventUploadService = new EventUploadService(
this.apiService, this.apiService,
@ -879,7 +857,7 @@ export default class MainBackground {
this.cipherService, this.cipherService,
this.cryptoService, this.cryptoService,
this.cryptoFunctionService, this.cryptoFunctionService,
this.stateService, this.kdfConfigService,
); );
this.organizationVaultExportService = new OrganizationVaultExportService( this.organizationVaultExportService = new OrganizationVaultExportService(
@ -887,8 +865,8 @@ export default class MainBackground {
this.apiService, this.apiService,
this.cryptoService, this.cryptoService,
this.cryptoFunctionService, this.cryptoFunctionService,
this.stateService,
this.collectionService, this.collectionService,
this.kdfConfigService,
); );
this.exportService = new VaultExportService( this.exportService = new VaultExportService(
@ -1117,15 +1095,15 @@ export default class MainBackground {
async bootstrap() { async bootstrap() {
this.containerService.attachToGlobal(self); this.containerService.attachToGlobal(self);
await this.stateService.init({ runMigrations: !this.isPrivateMode }); // Only the "true" background should run migrations
await this.stateService.init({ runMigrations: !this.popupOnlyContext });
// This is here instead of in in the InitService b/c we don't plan for // This is here instead of in in the InitService b/c we don't plan for
// side effects to run in the Browser InitService. // side effects to run in the Browser InitService.
this.userKeyInitService.listenForActiveUserChangesToSetUserKey(); this.userKeyInitService.listenForActiveUserChangesToSetUserKey();
await (this.i18nService as I18nService).init(); await (this.i18nService as I18nService).init();
await (this.eventUploadService as EventUploadService).init(true); (this.eventUploadService as EventUploadService).init(true);
this.twoFactorService.init();
if (this.popupOnlyContext) { if (this.popupOnlyContext) {
return; return;
@ -1247,7 +1225,18 @@ export default class MainBackground {
} }
async logout(expired: boolean, userId?: UserId) { async logout(expired: boolean, userId?: UserId) {
userId ??= (await firstValueFrom(this.accountService.activeAccount$))?.id; userId ??= (
await firstValueFrom(
this.accountService.activeAccount$.pipe(
timeout({
first: 2000,
with: () => {
throw new Error("No active account found to logout");
},
}),
),
)
)?.id;
await this.eventUploadService.uploadEvents(userId as UserId); await this.eventUploadService.uploadEvents(userId as UserId);

View File

@ -10,7 +10,7 @@ import { SystemService } from "@bitwarden/common/platform/abstractions/system.se
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherType } from "@bitwarden/common/vault/enums"; import { CipherType } from "@bitwarden/common/vault/enums";
import { MessageListener } from "../../../../libs/common/src/platform/messaging"; import { MessageListener, isExternalMessage } from "../../../../libs/common/src/platform/messaging";
import { import {
closeUnlockPopout, closeUnlockPopout,
openSsoAuthResultPopout, openSsoAuthResultPopout,
@ -85,7 +85,11 @@ export default class RuntimeBackground {
this.messageListener.allMessages$ this.messageListener.allMessages$
.pipe( .pipe(
mergeMap(async (message: any) => { mergeMap(async (message: any) => {
try {
await this.processMessage(message); await this.processMessage(message);
} catch (err) {
this.logService.error(err);
}
}), }),
) )
.subscribe(); .subscribe();
@ -266,7 +270,9 @@ export default class RuntimeBackground {
break; break;
} }
case "reloadPopup": case "reloadPopup":
if (isExternalMessage(msg)) {
this.messagingService.send("reloadPopup"); this.messagingService.send("reloadPopup");
}
break; break;
case "emailVerificationRequired": case "emailVerificationRequired":
this.messagingService.send("showDialog", { this.messagingService.send("showDialog", {

View File

@ -4,6 +4,10 @@ import {
AccountServiceInitOptions, AccountServiceInitOptions,
accountServiceFactory, accountServiceFactory,
} from "../../../auth/background/service-factories/account-service.factory"; } from "../../../auth/background/service-factories/account-service.factory";
import {
KdfConfigServiceInitOptions,
kdfConfigServiceFactory,
} from "../../../auth/background/service-factories/kdf-config-service.factory";
import { import {
internalMasterPasswordServiceFactory, internalMasterPasswordServiceFactory,
MasterPasswordServiceInitOptions, MasterPasswordServiceInitOptions,
@ -18,7 +22,10 @@ import {
} from "../../background/service-factories/log-service.factory"; } from "../../background/service-factories/log-service.factory";
import { BrowserCryptoService } from "../../services/browser-crypto.service"; import { BrowserCryptoService } from "../../services/browser-crypto.service";
import { biometricStateServiceFactory } from "./biometric-state-service.factory"; import {
BiometricStateServiceInitOptions,
biometricStateServiceFactory,
} from "./biometric-state-service.factory";
import { import {
cryptoFunctionServiceFactory, cryptoFunctionServiceFactory,
CryptoFunctionServiceInitOptions, CryptoFunctionServiceInitOptions,
@ -46,7 +53,9 @@ export type CryptoServiceInitOptions = CryptoServiceFactoryOptions &
LogServiceInitOptions & LogServiceInitOptions &
StateServiceInitOptions & StateServiceInitOptions &
AccountServiceInitOptions & AccountServiceInitOptions &
StateProviderInitOptions; StateProviderInitOptions &
BiometricStateServiceInitOptions &
KdfConfigServiceInitOptions;
export function cryptoServiceFactory( export function cryptoServiceFactory(
cache: { cryptoService?: AbstractCryptoService } & CachedServices, cache: { cryptoService?: AbstractCryptoService } & CachedServices,
@ -68,6 +77,7 @@ export function cryptoServiceFactory(
await accountServiceFactory(cache, opts), await accountServiceFactory(cache, opts),
await stateProviderFactory(cache, opts), await stateProviderFactory(cache, opts),
await biometricStateServiceFactory(cache, opts), await biometricStateServiceFactory(cache, opts),
await kdfConfigServiceFactory(cache, opts),
), ),
); );
} }

View File

@ -3,15 +3,10 @@ import { DerivedStateProvider } from "@bitwarden/common/platform/state";
import { BackgroundDerivedStateProvider } from "../../state/background-derived-state.provider"; import { BackgroundDerivedStateProvider } from "../../state/background-derived-state.provider";
import { CachedServices, FactoryOptions, factory } from "./factory-options"; import { CachedServices, FactoryOptions, factory } from "./factory-options";
import {
StorageServiceProviderInitOptions,
storageServiceProviderFactory,
} from "./storage-service-provider.factory";
type DerivedStateProviderFactoryOptions = FactoryOptions; type DerivedStateProviderFactoryOptions = FactoryOptions;
export type DerivedStateProviderInitOptions = DerivedStateProviderFactoryOptions & export type DerivedStateProviderInitOptions = DerivedStateProviderFactoryOptions;
StorageServiceProviderInitOptions;
export async function derivedStateProviderFactory( export async function derivedStateProviderFactory(
cache: { derivedStateProvider?: DerivedStateProvider } & CachedServices, cache: { derivedStateProvider?: DerivedStateProvider } & CachedServices,
@ -21,7 +16,6 @@ export async function derivedStateProviderFactory(
cache, cache,
"derivedStateProvider", "derivedStateProvider",
opts, opts,
async () => async () => new BackgroundDerivedStateProvider(),
new BackgroundDerivedStateProvider(await storageServiceProviderFactory(cache, opts)),
); );
} }

View File

@ -1,3 +1,4 @@
import { ClientType } from "@bitwarden/common/enums";
import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service"; import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service";
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner"; import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
@ -27,6 +28,7 @@ export async function migrationRunnerFactory(
await diskStorageServiceFactory(cache, opts), await diskStorageServiceFactory(cache, opts),
await logServiceFactory(cache, opts), await logServiceFactory(cache, opts),
new MigrationBuilderService(), new MigrationBuilderService(),
ClientType.Browser,
), ),
); );
} }

View File

@ -30,7 +30,6 @@ import {
type StateServiceFactoryOptions = FactoryOptions & { type StateServiceFactoryOptions = FactoryOptions & {
stateServiceOptions: { stateServiceOptions: {
useAccountCache?: boolean;
stateFactory: StateFactory<GlobalState, Account>; stateFactory: StateFactory<GlobalState, Account>;
}; };
}; };
@ -64,7 +63,6 @@ export async function stateServiceFactory(
await environmentServiceFactory(cache, opts), await environmentServiceFactory(cache, opts),
await tokenServiceFactory(cache, opts), await tokenServiceFactory(cache, opts),
await migrationRunnerFactory(cache, opts), await migrationRunnerFactory(cache, opts),
opts.stateServiceOptions.useAccountCache,
), ),
); );
// TODO: If we run migration through a chrome installed/updated event we can turn off running migrations // TODO: If we run migration through a chrome installed/updated event we can turn off running migrations

View File

@ -238,10 +238,6 @@ export class BrowserApi {
return typeof window !== "undefined" && window === BrowserApi.getBackgroundPage(); return typeof window !== "undefined" && window === BrowserApi.getBackgroundPage();
} }
static getApplicationVersion(): string {
return chrome.runtime.getManifest().version;
}
/** /**
* Gets the extension views that match the given properties. This method is not * Gets the extension views that match the given properties. This method is not
* available within background service worker. As a result, it will return an * available within background service worker. As a result, it will return an

View File

@ -203,7 +203,7 @@ describe("BrowserPopupUtils", () => {
expect(BrowserPopupUtils["buildPopoutUrl"]).not.toHaveBeenCalled(); expect(BrowserPopupUtils["buildPopoutUrl"]).not.toHaveBeenCalled();
}); });
it("replaces any existing `uilocation=` query params within the passed extension url path to state the the uilocaiton is a popup", async () => { it("replaces any existing `uilocation=` query params within the passed extension url path to state the uilocation is a popup", async () => {
const url = "popup/index.html?uilocation=sidebar#/tabs/vault"; const url = "popup/index.html?uilocation=sidebar#/tabs/vault";
jest.spyOn(BrowserPopupUtils as any, "isSingleActionPopoutOpen").mockResolvedValueOnce(false); jest.spyOn(BrowserPopupUtils as any, "isSingleActionPopoutOpen").mockResolvedValueOnce(false);

View File

@ -0,0 +1,9 @@
<footer
class="tw-p-3 tw-border-0 tw-border-solid tw-border-t tw-border-secondary-300 tw-bg-background"
>
<div class="tw-max-w-screen-sm tw-mx-auto">
<div class="tw-flex tw-justify-start tw-gap-2">
<ng-content></ng-content>
</div>
</div>
</footer>

View File

@ -0,0 +1,9 @@
import { Component } from "@angular/core";
@Component({
selector: "popup-footer",
templateUrl: "popup-footer.component.html",
standalone: true,
imports: [],
})
export class PopupFooterComponent {}

View File

@ -0,0 +1,19 @@
<header
class="tw-p-4 tw-border-0 tw-border-solid tw-border-b tw-border-secondary-300 tw-bg-background"
>
<div class="tw-max-w-screen-sm tw-mx-auto tw-flex tw-justify-between tw-w-full">
<div class="tw-inline-flex tw-items-center tw-gap-2 tw-h-9">
<button
bitIconButton="bwi-back"
type="button"
*ngIf="showBackButton"
[title]="'back' | i18n"
[ariaLabel]="'back' | i18n"
></button>
<h1 bitTypography="h3" class="!tw-mb-0.5 tw-text-headers">{{ pageTitle }}</h1>
</div>
<div class="tw-inline-flex tw-items-center tw-gap-2 tw-h-9">
<ng-content select="[slot=end]"></ng-content>
</div>
</div>
</header>

View File

@ -0,0 +1,34 @@
import { BooleanInput, coerceBooleanProperty } from "@angular/cdk/coercion";
import { CommonModule, Location } from "@angular/common";
import { Component, Input } from "@angular/core";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { IconButtonModule, TypographyModule } from "@bitwarden/components";
@Component({
selector: "popup-header",
templateUrl: "popup-header.component.html",
standalone: true,
imports: [TypographyModule, CommonModule, IconButtonModule, JslibModule],
})
export class PopupHeaderComponent {
/** Display the back button, which uses Location.back() to go back one page in history */
@Input()
get showBackButton() {
return this._showBackButton;
}
set showBackButton(value: BooleanInput) {
this._showBackButton = coerceBooleanProperty(value);
}
private _showBackButton = false;
/** Title string that will be inserted as an h1 */
@Input({ required: true }) pageTitle: string;
constructor(private location: Location) {}
back() {
this.location.back();
}
}

View File

@ -0,0 +1,138 @@
import { Meta, Story, Canvas } from "@storybook/addon-docs";
import * as stories from "./popup-layout.stories";
<Meta of={stories} />
Please note that because these stories use `router-outlet`, there are issues with rendering content
when Light & Dark mode is selected. The stories are best viewed by selecting one color mode.
# Popup Tab Navigation
The popup tab navigation component composes together the popup page and the bottom tab navigation
footer. This component is intended to be used a level _above_ each extension tab's page code.
The navigation footer contains the 4 main page links for the browser extension. It uses the Angular
router to determine which page is currently active, and style the button appropriately. Clicking on
the buttons will navigate to the correct route. The navigation footer has a max-width built in so
that the page looks nice when the extension is popped out.
Long button names will be ellipsed.
Usage example:
```html
<popup-tab-navigation>
<popup-page></popup-page>
</popup-tab-navigation>
```
# Popup Page
The popup page handles positioning a page's `header` and `footer` elements, and inserting the rest
of the content into the `main` element with scroll. There is also a max-width built in so that the
page looks nice when the extension is popped out.
**Slots**
- `header`
- Use `popup-header` component.
- Every page should have a header.
- `footer`
- Use the `popup-footer` component.
- Not every page will have a footer.
- default
- Whatever content you want in `main`.
Basic usage example:
```html
<popup-page>
<popup-header slot="header"></popup-header>
<div>This is content</div>
<popup-footer slot="footer"></popup-footer>
</popup-page>
```
## Popup header
**Args**
- `pageTitle`: required
- Inserts title as an `h1`.
- `showBackButton`: optional, defaults to `false`
- Toggles the back button to appear. The back button uses `Location.back()` to navigate back one
page in history.
**Slots**
- `end`
- Use to insert one or more interactive elements.
- The header handles the spacing between elements passed to the `end` slot.
Usage example:
```html
<popup-header pageTitle="Test" showBackButton>
<ng-container slot="end">
<button></button>
<button></button>
</ng-container>
</popup-header>
```
Common interactive elements to insert into the `end` slot are:
- `app-current-account`: shows current account and switcher
- `app-pop-out`: shows popout button when the extension is not already popped out
- "Add" button: this can be accomplished with the Button component and any custom functionality for
that particular page
## Popup footer
Popup footer should be used when the page displays action buttons. It functions similarly to the
Dialog footer in that the calling code is responsible for passing in the different buttons that need
to be rendered.
Usage example:
```html
<popup-footer>
<button bitButton buttonType="primary">Save</button>
<button bitButton buttonType="secondary">Cancel</button>
</popup-footer>
```
# Page types
There are a few types of pages that are used in the browser extension.
View the story source code to see examples of how to construct these types of pages.
## Extension Tab
Example of wrapping an extension page in the `popup-tab-navigation` component.
<Canvas>
<Story of={stories.PopupTabNavigation} />
</Canvas>
## Extension Page
Examples of using just the `popup-page` component, without and with a footer.
<Canvas>
<Story of={stories.PopupPage} />
</Canvas>
<Canvas>
<Story of={stories.PopupPageWithFooter} />
</Canvas>
## Popped out
When the browser extension is popped out, the "popout" button should not be passed to the header.
<Canvas>
<Story of={stories.PoppedOut} />
</Canvas>

View File

@ -0,0 +1,367 @@
import { CommonModule } from "@angular/common";
import { Component, importProvidersFrom } from "@angular/core";
import { RouterModule } from "@angular/router";
import { Meta, StoryObj, applicationConfig, moduleMetadata } from "@storybook/angular";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import {
AvatarModule,
ButtonModule,
I18nMockService,
IconButtonModule,
} from "@bitwarden/components";
import { PopupFooterComponent } from "./popup-footer.component";
import { PopupHeaderComponent } from "./popup-header.component";
import { PopupPageComponent } from "./popup-page.component";
import { PopupTabNavigationComponent } from "./popup-tab-navigation.component";
@Component({
selector: "extension-container",
template: `
<div class="tw-h-[640px] tw-w-[380px] tw-border tw-border-solid tw-border-secondary-300">
<ng-content></ng-content>
</div>
`,
standalone: true,
})
class ExtensionContainerComponent {}
@Component({
selector: "vault-placeholder",
template: `
<div class="tw-mb-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item</div>
<div class="tw-my-8 tw-text-main">vault item last item</div>
`,
standalone: true,
})
class VaultComponent {}
@Component({
selector: "generator-placeholder",
template: ` <div class="tw-text-main">generator stuff here</div> `,
standalone: true,
})
class GeneratorComponent {}
@Component({
selector: "send-placeholder",
template: ` <div class="tw-text-main">send some stuff</div> `,
standalone: true,
})
class SendComponent {}
@Component({
selector: "settings-placeholder",
template: ` <div class="tw-text-main">change your settings</div> `,
standalone: true,
})
class SettingsComponent {}
@Component({
selector: "mock-add-button",
template: `
<button bitButton buttonType="primary" type="button">
<i class="bwi bwi-plus-f" aria-hidden="true"></i>
Add
</button>
`,
standalone: true,
imports: [ButtonModule],
})
class MockAddButtonComponent {}
@Component({
selector: "mock-popout-button",
template: `
<button
bitIconButton="bwi-popout"
size="small"
type="button"
title="Pop out"
aria-label="Pop out"
></button>
`,
standalone: true,
imports: [IconButtonModule],
})
class MockPopoutButtonComponent {}
@Component({
selector: "mock-current-account",
template: `
<button class="tw-bg-transparent tw-border-none" type="button">
<bit-avatar text="Ash Ketchum" size="small"></bit-avatar>
</button>
`,
standalone: true,
imports: [AvatarModule],
})
class MockCurrentAccountComponent {}
@Component({
selector: "mock-vault-page",
template: `
<popup-page>
<popup-header slot="header" pageTitle="Test">
<ng-container slot="end">
<mock-add-button></mock-add-button>
<mock-popout-button></mock-popout-button>
<mock-current-account></mock-current-account>
</ng-container>
</popup-header>
<vault-placeholder></vault-placeholder>
</popup-page>
`,
standalone: true,
imports: [
PopupPageComponent,
PopupHeaderComponent,
MockAddButtonComponent,
MockPopoutButtonComponent,
MockCurrentAccountComponent,
VaultComponent,
],
})
class MockVaultPageComponent {}
@Component({
selector: "mock-vault-page-popped",
template: `
<popup-page>
<popup-header slot="header" pageTitle="Test">
<ng-container slot="end">
<mock-add-button></mock-add-button>
<mock-current-account></mock-current-account>
</ng-container>
</popup-header>
<vault-placeholder></vault-placeholder>
</popup-page>
`,
standalone: true,
imports: [
PopupPageComponent,
PopupHeaderComponent,
MockAddButtonComponent,
MockPopoutButtonComponent,
MockCurrentAccountComponent,
VaultComponent,
],
})
class MockVaultPagePoppedComponent {}
@Component({
selector: "mock-generator-page",
template: `
<popup-page>
<popup-header slot="header" pageTitle="Test">
<ng-container slot="end">
<mock-add-button></mock-add-button>
<mock-popout-button></mock-popout-button>
<mock-current-account></mock-current-account>
</ng-container>
</popup-header>
<generator-placeholder></generator-placeholder>
</popup-page>
`,
standalone: true,
imports: [
PopupPageComponent,
PopupHeaderComponent,
MockAddButtonComponent,
MockPopoutButtonComponent,
MockCurrentAccountComponent,
GeneratorComponent,
],
})
class MockGeneratorPageComponent {}
@Component({
selector: "mock-send-page",
template: `
<popup-page>
<popup-header slot="header" pageTitle="Test">
<ng-container slot="end">
<mock-add-button></mock-add-button>
<mock-popout-button></mock-popout-button>
<mock-current-account></mock-current-account>
</ng-container>
</popup-header>
<send-placeholder></send-placeholder>
</popup-page>
`,
standalone: true,
imports: [
PopupPageComponent,
PopupHeaderComponent,
MockAddButtonComponent,
MockPopoutButtonComponent,
MockCurrentAccountComponent,
SendComponent,
],
})
class MockSendPageComponent {}
@Component({
selector: "mock-settings-page",
template: `
<popup-page>
<popup-header slot="header" pageTitle="Test">
<ng-container slot="end">
<mock-add-button></mock-add-button>
<mock-popout-button></mock-popout-button>
<mock-current-account></mock-current-account>
</ng-container>
</popup-header>
<settings-placeholder></settings-placeholder>
</popup-page>
`,
standalone: true,
imports: [
PopupPageComponent,
PopupHeaderComponent,
MockAddButtonComponent,
MockPopoutButtonComponent,
MockCurrentAccountComponent,
SettingsComponent,
],
})
class MockSettingsPageComponent {}
@Component({
selector: "mock-vault-subpage",
template: `
<popup-page>
<popup-header slot="header" pageTitle="Test" showBackButton>
<ng-container slot="end">
<mock-popout-button></mock-popout-button>
</ng-container>
</popup-header>
<vault-placeholder></vault-placeholder>
<popup-footer slot="footer">
<button bitButton buttonType="primary">Save</button>
<button bitButton buttonType="secondary">Cancel</button>
</popup-footer>
</popup-page>
`,
standalone: true,
imports: [
PopupPageComponent,
PopupHeaderComponent,
PopupFooterComponent,
ButtonModule,
MockAddButtonComponent,
MockPopoutButtonComponent,
MockCurrentAccountComponent,
VaultComponent,
],
})
class MockVaultSubpageComponent {}
export default {
title: "Browser/Popup Layout",
component: PopupPageComponent,
decorators: [
moduleMetadata({
imports: [
PopupTabNavigationComponent,
CommonModule,
RouterModule,
ExtensionContainerComponent,
MockVaultSubpageComponent,
MockVaultPageComponent,
MockSendPageComponent,
MockGeneratorPageComponent,
MockSettingsPageComponent,
MockVaultPagePoppedComponent,
],
providers: [
{
provide: I18nService,
useFactory: () => {
return new I18nMockService({
back: "Back",
});
},
},
],
}),
applicationConfig({
providers: [
importProvidersFrom(
RouterModule.forRoot(
[
{ path: "", redirectTo: "vault", pathMatch: "full" },
{ path: "vault", component: MockVaultPageComponent },
{ path: "generator", component: MockGeneratorPageComponent },
{ path: "send", component: MockSendPageComponent },
{ path: "settings", component: MockSettingsPageComponent },
// in case you are coming from a story that also uses the router
{ path: "**", redirectTo: "vault" },
],
{ useHash: true },
),
),
],
}),
],
} as Meta;
type Story = StoryObj<PopupPageComponent>;
export const PopupTabNavigation: Story = {
render: (args) => ({
props: args,
template: /* HTML */ `
<extension-container>
<popup-tab-navigation>
<router-outlet></router-outlet>
</popup-tab-navigation>
</extension-container>
`,
}),
};
export const PopupPage: Story = {
render: (args) => ({
props: args,
template: /* HTML */ `
<extension-container>
<mock-vault-page></mock-vault-page>
</extension-container>
`,
}),
};
export const PopupPageWithFooter: Story = {
render: (args) => ({
props: args,
template: /* HTML */ `
<extension-container>
<mock-vault-subpage></mock-vault-subpage>
</extension-container>
`,
}),
};
export const PoppedOut: Story = {
render: (args) => ({
props: args,
template: /* HTML */ `
<div class="tw-h-[640px] tw-w-[900px] tw-border tw-border-solid tw-border-secondary-300">
<mock-vault-page-popped></mock-vault-page-popped>
</div>
`,
}),
};

View File

@ -0,0 +1,7 @@
<ng-content select="[slot=header]"></ng-content>
<main class="tw-bg-background-alt tw-p-3 tw-flex-1 tw-overflow-y-auto">
<div class="tw-max-w-screen-sm tw-mx-auto">
<ng-content></ng-content>
</div>
</main>
<ng-content select="[slot=footer]"></ng-content>

View File

@ -0,0 +1,11 @@
import { Component } from "@angular/core";
@Component({
selector: "popup-page",
templateUrl: "popup-page.component.html",
standalone: true,
host: {
class: "tw-h-full tw-flex tw-flex-col tw-flex-1 tw-overflow-y-auto",
},
})
export class PopupPageComponent {}

View File

@ -0,0 +1,32 @@
<div class="tw-h-full tw-overflow-y-auto [&>*]:tw-h-full [&>*]:tw-overflow-y-auto">
<ng-content></ng-content>
</div>
<footer class="tw-bg-background tw-border-0 tw-border-t tw-border-secondary-300 tw-border-solid">
<div class="tw-max-w-screen-sm tw-mx-auto">
<div class="tw-flex tw-flex-1">
<a
*ngFor="let button of navButtons"
class="tw-group tw-flex tw-flex-col tw-items-center tw-gap-1 tw-px-0.5 tw-pb-2 tw-pt-3 tw-w-1/4 tw-no-underline hover:tw-no-underline hover:tw-text-primary-600 hover:tw-bg-primary-100 tw-border-2 tw-border-solid tw-border-transparent focus-visible:tw-rounded-lg focus-visible:tw-border-primary-500"
[ngClass]="rla.isActive ? 'tw-font-bold tw-text-primary-600' : 'tw-text-muted'"
[title]="button.label"
[routerLink]="button.page"
routerLinkActive
#rla="routerLinkActive"
ariaCurrentWhenActive="page"
>
<i *ngIf="!rla.isActive" class="bwi bwi-lg bwi-{{ button.iconKey }}" aria-hidden="true"></i>
<i
*ngIf="rla.isActive"
class="bwi bwi-lg bwi-{{ button.iconKeyActive }}"
aria-hidden="true"
></i>
<span
class="tw-truncate tw-max-w-full"
[ngClass]="!rla.isActive && 'group-hover:tw-underline'"
>
{{ button.label }}
</span>
</a>
</div>
</div>
</footer>

View File

@ -0,0 +1,43 @@
import { CommonModule } from "@angular/common";
import { Component } from "@angular/core";
import { RouterModule } from "@angular/router";
import { LinkModule } from "@bitwarden/components";
@Component({
selector: "popup-tab-navigation",
templateUrl: "popup-tab-navigation.component.html",
standalone: true,
imports: [CommonModule, LinkModule, RouterModule],
host: {
class: "tw-block tw-h-full tw-w-full tw-flex tw-flex-col",
},
})
export class PopupTabNavigationComponent {
navButtons = [
{
label: "Vault",
page: "/vault",
iconKey: "lock",
iconKeyActive: "lock-f",
},
{
label: "Generator",
page: "/generator",
iconKey: "generate",
iconKeyActive: "generate-f",
},
{
label: "Send",
page: "/send",
iconKey: "send",
iconKeyActive: "send-f",
},
{
label: "Settings",
page: "/settings",
iconKey: "cog",
iconKeyActive: "cog-f",
},
];
}

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