1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-19 11:15:21 +01:00

Merge branch 'master' into patrickhlauke-a11y-patch4

This commit is contained in:
Patrick H. Lauke 2021-09-18 22:42:45 +01:00 committed by GitHub
commit 641328c8c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
93 changed files with 4464 additions and 1532 deletions

93
.github/ISSUE_TEMPLATE/bug.yml vendored Normal file
View File

@ -0,0 +1,93 @@
name: Bug Report
description: File a bug report
labels: [bug]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests.
- type: textarea
id: reproduce
attributes:
label: Steps To Reproduce
description: How can we reproduce the behavior.
value: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. Click on '...'
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Result
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual Result
description: A clear and concise description of what is happening.
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots or Videos
description: If applicable, add screenshots and/or a short video to help explain your problem.
- type: textarea
id: additional-context
attributes:
label: Additional Context
description: Add any other context about the problem here.
- type: dropdown
id: os
attributes:
label: Operating System
description: What operating system are you seeing the problem on?
multiple: true
options:
- Windows
- macOS
- Linux
- Android
- iOS
validations:
required: true
- type: input
id: os-version
attributes:
label: Operating System Version
description: What version of the operating system(s) are you seeing the problem on?
- type: dropdown
id: browsers
attributes:
label: Web Browser
description: What browser(s) are you seeing the problem on?
multiple: true
options:
- Chrome
- Safari
- Microsoft Edge
- Firefox
- Opera
- Brave
- Vivaldi
validations:
required: true
- type: input
id: browser-version
attributes:
label: Browser Version
description: What version of the browser(s) are you seeing the problem on?
- type: input
id: version
attributes:
label: Build Version
description: What version of our software are you running? (go to "Settings" → "About" in the extension)
validations:
required: true

20
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,20 @@
blank_issues_enabled: false
contact_links:
- name: Report failure of prompt to save credentials
url: https://docs.google.com/forms/d/e/1FAIpQLSeG-Dtpn2xnr9N7oF04NyY6ETUM-JF8pagFfAv8mW7bgcMVxA/viewform
about: We are aware of many sites' login forms where the Bitwarden browser extension either on a single platform/browser or multiple will not prompt the user to save a new password or update an existing password. This is something the Bitwarden team is actively working on but need your help as a community and active Bitwarden users!
- name: Report autofill failure
url: https://docs.google.com/forms/d/e/1FAIpQLSfkxh1w6vK8fLYwAbAAEVhvhMAJwfFNDtYtPUVk1y5WTHvJmQ/viewform
about: We are aware of many sites' login forms, payment gateways, identity forms, etc. where the Bitwarden browser extension either on a single platform/browser or multiple will not autofill information. This is something the Bitwarden team is actively working on but need your help as a community and active Bitwarden users!
- name: Feature Requests
url: https://community.bitwarden.com/c/feature-requests/
about: Request new features using the Community Forums. Please search existing feature requests before making a new one.
- name: Bitwarden Community Forums
url: https://community.bitwarden.com
about: Please visit the community forums for general community discussion, support and the development roadmap.
- name: Customer Support
url: https://bitwarden.com/contact/
about: Please contact our customer support for account issues and general customer support.
- name: Security Issues
url: https://hackerone.com/bitwarden
about: We use HackerOne to manage security disclosures.

View File

@ -1,3 +1,4 @@
---
name: Build
on:
@ -10,6 +11,7 @@ on:
jobs:
cloc:
name: CLOC
runs-on: ubuntu-latest
steps:
- name: Checkout repo
@ -24,6 +26,7 @@ jobs:
setup:
name: Setup
runs-on: ubuntu-latest
outputs:
repo_url: ${{ steps.gen_vars.outputs.repo_url }}
@ -38,10 +41,11 @@ jobs:
repo_url=https://github.com/$GITHUB_REPOSITORY.git
adj_build_num=${GITHUB_SHA:0:7}
echo "::set-output name=repo_url::$repo_url"
echo "::set-output name=adj_build_number::$adj_build_num"
echo "::set-output name=repo_url::$repo_url"
echo "::set-output name=adj_build_number::$adj_build_num"
locales-test:
name: Locales Test
runs-on: ubuntu-latest
needs: setup
steps:
@ -63,21 +67,21 @@ jobs:
found_error=true
fi
done
if $found_error; then
echo
echo "Please fix 'extName' for the locales listed above."
exit 1
else
echo "Test passed!"
fi
fi
build:
name: Build
runs-on: windows-latest
needs: [ setup, locales-test ]
needs: [setup, locales-test]
env:
REPO_URL: ${{ needs.setup.outputs.repo_url }}
BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }}
_BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }}
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
@ -96,41 +100,47 @@ jobs:
node --version
npm --version
- name: npm setup & test
- name: NPM setup & test
run: |
npm install
npm run dist
npm run test
- name: gulp
- name: Gulp
run: gulp ci
- name: Upload opera artifact
- name: Upload Opera artifact
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
with:
name: dist-opera-${{ env.BUILD_NUMBER }}.zip
path: dist/dist-opera-${{ env.BUILD_NUMBER }}.zip
name: dist-opera-${{ env._BUILD_NUMBER }}.zip
path: dist/dist-opera.zip
if-no-files-found: error
- name: Upload chrome artifact
- name: Upload Chrome artifact
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
with:
name: dist-chrome-${{ env.BUILD_NUMBER }}.zip
path: dist/dist-chrome-${{ env.BUILD_NUMBER }}.zip
name: dist-chrome-${{ env._BUILD_NUMBER }}.zip
path: dist/dist-chrome.zip
if-no-files-found: error
- name: Upload firefox artifact
- name: Upload Firefox artifact
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
with:
name: dist-firefox-${{ env.BUILD_NUMBER }}.zip
path: dist/dist-firefox-${{ env.BUILD_NUMBER }}.zip
name: dist-firefox-${{ env._BUILD_NUMBER }}.zip
path: dist/dist-firefox.zip
if-no-files-found: error
- name: Upload edge artifact
- name: Upload Edge artifact
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
with:
name: dist-edge-${{ env.BUILD_NUMBER }}.zip
path: dist/dist-edge-${{ env.BUILD_NUMBER }}.zip
name: dist-edge-${{ env._BUILD_NUMBER }}.zip
path: dist/dist-edge.zip
if-no-files-found: error
- name: Upload coverage artifact
if: false
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
with:
name: coverage-${{ env.BUILD_NUMBER }}.zip
path: coverage/coverage-${{ env.BUILD_NUMBER }}.zip
name: coverage-${{ env._BUILD_NUMBER }}.zip
path: coverage/coverage-${{ env._BUILD_NUMBER }}.zip
if-no-files-found: error

49
.github/workflows/crowdin-sync.yml vendored Normal file
View File

@ -0,0 +1,49 @@
---
name: Crowdin Sync
on:
workflow_dispatch:
inputs: {}
# schedule:
# - cron: '0 0 * * *'
jobs:
crowdin-sync:
name: Autosync
runs-on: ubuntu-20.04
env:
_CROWDIN_PROJECT_ID: "268134"
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
- name: Login to Azure
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
with:
keyvault: "bitwarden-prod-kv"
secrets: "crowdin-api-token"
- name: Download translations
uses: crowdin/github-action@e39093fd75daae7859c68eded4b43d42ec78d8ea
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
with:
config: crowdin.yml
crowdin_branch_name: master
upload_sources: false
upload_translations: false
download_translations: true
github_user_name: "github-actions"
github_user_email: "<>"
commit_message: "Autosync the updated translations"
localization_branch_name: crowdin-auto-sync
create_pull_request: true
pull_request_title: "Autosync Crowdin Translations"
pull_request_body: "Autosync the updated translations"

View File

@ -1,3 +1,4 @@
---
name: Release
on:
@ -10,6 +11,7 @@ on:
jobs:
setup:
name: Setup
runs-on: ubuntu-latest
outputs:
tag_version: ${{ steps.create_tags.outputs.tag_version }}
@ -25,7 +27,7 @@ jobs:
echo "==================================="
exit 1
fi
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
@ -37,8 +39,8 @@ jobs:
$build_num = [int]$env:GITHUB_RUN_NUMBER
$adj_build_num = $build_num + 3000
echo "::set-output name=repo_url::$repo_url"
echo "::set-output name=adj_build_number::$adj_build_num"
echo "::set-output name=repo_url::$repo_url"
echo "::set-output name=adj_build_number::$adj_build_num"
- name: Create Release Vars
id: create_tags
@ -68,12 +70,13 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ env.RELEASE_TAG_NAME }}
release_name: ${{ env.RELEASE_NAME }}
release_name: Version ${{ env.RELEASE_NAME }}
draft: true
prerelease: false
locales-test:
name: Locales Test
runs-on: ubuntu-latest
needs: setup
steps:
@ -105,11 +108,12 @@ jobs:
fi
build:
name: Build
runs-on: windows-latest
needs: [ setup, locales-test ]
needs: [setup, locales-test]
env:
REPO_URL: ${{ needs.setup.outputs.repo_url }}
BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }}
_REPO_URL: ${{ needs.setup.outputs.repo_url }}
_BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }}
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
@ -128,84 +132,84 @@ jobs:
node --version
npm --version
- name: npm setup & test
- name: NPM setup & test
run: |
npm install
npm run dist
npm run test
- name: gulp
- name: Gulp
run: gulp ci
- name: Build sources for reviewers
shell: cmd
run: |
mkdir dist\Source
call git clone %REPO_URL% dist\Source
call git clone %_REPO_URL% dist\Source
cd dist\Source
call git checkout %GITHUB_SHA%
call git submodule update --init --recursive
cd ../
del /S/Q "Source\.git\objects\pack\*"
call 7z a browser-source-%BUILD_NUMBER%.zip "Source\*"
call 7z a browser-source-%_BUILD_NUMBER%.zip "Source\*"
- name: upload opera release asset
- name: Upload Opera release asset
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.setup.outputs.release_upload_url }}
asset_name: dist-opera-${{ env.BUILD_NUMBER }}.zip
asset_path: dist/dist-opera-${{ env.BUILD_NUMBER }}.zip
asset_name: dist-opera-${{ env._BUILD_NUMBER }}.zip
asset_path: dist/dist-opera.zip
asset_content_type: application
- name: upload chrome release asset
- name: Upload Chrome release asset
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.setup.outputs.release_upload_url }}
asset_name: dist-chrome-${{ env.BUILD_NUMBER }}.zip
asset_path: dist/dist-chrome-${{ env.BUILD_NUMBER }}.zip
asset_name: dist-chrome-${{ env._BUILD_NUMBER }}.zip
asset_path: dist/dist-chrome.zip
asset_content_type: application/zip
- name: upload firefox release asset
- name: Upload Firefox release asset
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.setup.outputs.release_upload_url }}
asset_name: dist-firefox-${{ env.BUILD_NUMBER }}.zip
asset_path: dist/dist-firefox-${{ env.BUILD_NUMBER }}.zip
asset_name: dist-firefox-${{ env._BUILD_NUMBER }}.zip
asset_path: dist/dist-firefox.zip
asset_content_type: application/zip
- name: upload edge release asset
- name: Upload Edge release asset
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.setup.outputs.release_upload_url }}
asset_name: dist-edge-${{ env.BUILD_NUMBER }}.zip
asset_path: dist/dist-edge-${{ env.BUILD_NUMBER }}.zip
asset_name: dist-edge-${{ env._BUILD_NUMBER }}.zip
asset_path: dist/dist-edge.zip
asset_content_type: application/zip
- name: upload browser source zip release asset
- name: Upload browser source zip release asset
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.setup.outputs.release_upload_url }}
asset_name: browser-source-${{ env.BUILD_NUMBER }}.zip
asset_path: dist/browser-source-${{ env.BUILD_NUMBER }}.zip
asset_name: browser-source-${{ env._BUILD_NUMBER }}.zip
asset_path: dist/browser-source-${{ env._BUILD_NUMBER }}.zip
asset_content_type: application/zip
- name: upload coverage release asset
- name: Upload coverage release asset
if: false
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.setup.outputs.release_upload_url }}
asset_name: coverage-${{ env.BUILD_NUMBER }}.zip
asset_path: coverage/coverage-${{ env.BUILD_NUMBER }}.zip
asset_name: coverage-${{ env._BUILD_NUMBER }}.zip
asset_path: coverage/coverage-${{ env._BUILD_NUMBER }}.zip
asset_content_type: application/zip

View File

@ -1,52 +0,0 @@
<!--
Please do not submit feature requests. The [Community Forums][1] has a
section for submitting, voting for, and discussing product feature requests.
[1]: https://community.bitwarden.com
-->
## Describe the Bug
<!-- Comment:
A clear and concise description of what the bug is.
-->
## Steps To Reproduce
<!-- Comment:
How can we reproduce the behavior:
-->
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. Click on '...'
## Expected Result
<!-- Comment:
A clear and concise description of what you expected to happen.
-->
## Actual Result
<!-- Comment:
A clear and concise description of what is happening.
-->
## Screenshots or Videos
<!-- Comment:
If applicable, add screenshots and/or a short video to help explain your problem.
-->
## Environment
- Operating system: [e.g. Windows 10, Mac OS Catalina]
- Browser: [e.g. Firefox 73.0.1]
- Build Version (go to "Settings" → "About" in the app): [e.g. 1.42.2]
## Additional Context
<!-- Comment:
Add any other context about the problem here.
-->

View File

@ -1,3 +1,5 @@
project_id_env: _CROWDIN_PROJECT_ID
api_token_env: CROWDIN_API_TOKEN
files:
- source: /src/_locales/en/messages.json
translation: /src/_locales/%two_letters_code%/%original_file_name%

2
jslib

@ -1 +1 @@
Subproject commit 23309d33e2a335574ed898d6543040372d41526a
Subproject commit 83548a6753a974c57cb373b529a4da3ea5c3b5c0

File diff suppressed because it is too large Load Diff

View File

@ -151,7 +151,7 @@
"message": "Захаваць"
},
"move": {
"message": "Move"
"message": "Перамясціць"
},
"addFolder": {
"message": "Дадаць папку"
@ -600,7 +600,7 @@
"description": "Light color"
},
"solarizedDark": {
"message": "Solarized Dark",
"message": "Цёмная Solarized",
"description": "'Solarized' is a noun and the name of a color scheme. It should not be translated."
},
"exportVault": {
@ -614,7 +614,7 @@
"description": "WARNING (should stay in capitalized letters if the language permits)"
},
"confirmVaultExport": {
"message": "Confirm Vault Export"
"message": "Пацвердзіць экспарт сховішча"
},
"exportWarningDesc": {
"message": "Экспартуемы файл утрымлівае даныя вашага сховішча ў незашыфраваным фармаце. Яго не варта захоўваць ці адпраўляць па небяспечным каналам (напрыклад, па электроннай пошце). Выдаліце яго адразу пасля выкарыстання."

View File

@ -623,7 +623,7 @@
"message": "Tento export zašifruje vaše data pomocí šifrovacího klíče vašeho účtu. Pokud někdy změníte šifrovací klíč vašeho účtu, měli by jste vyexportovat data znovu, protože tento exportovaný soubor nebudete moci dešifrovat."
},
"encExportAccountWarningDesc": {
"message": "Šifrovací klíče účtu jsou pro každý uživatelský účet Bitwarden jedinečné, tudíž nelze importovat šifrovaný export do jiného účtu."
"message": "Šifrovací klíče účtu jsou pro každý uživatelský účet Bitwarden jedinečné, takže nelze importovat šifrovaný export do jiného účtu."
},
"exportMasterPassword": {
"message": "Zadejte své hlavní heslo pro export dat."
@ -1492,7 +1492,7 @@
"message": "Biometrie v prohlížeči není na tomto zařízení podporována."
},
"nativeMessaginPermissionErrorTitle": {
"message": "Povolení nebylo poskytnuto"
"message": "Oprávnění nebylo uděleno"
},
"nativeMessaginPermissionErrorDesc": {
"message": "Bez oprávnění ke komunikaci s počítačovou aplikací Bitwarden nelze v rozšíření prohlížeče používat biometrické údaje. Zkuste to prosím znovu."
@ -1543,7 +1543,7 @@
"message": "Soubor"
},
"allSends": {
"message": "Všechny Sendy",
"message": "Všechny Sends",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"maxAccessCountReached": {
@ -1583,7 +1583,7 @@
"message": "Zakázáno"
},
"removePasswordConfirmation": {
"message": "Jste si jisti, že chcete heslo odstranit?"
"message": "Jste si jisti, že chcete odstranit heslo?"
},
"deleteSend": {
"message": "Smazat Send",
@ -1616,7 +1616,7 @@
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"expirationDate": {
"message": "Datum expirace"
"message": "Datum vypršení platnosti"
},
"expirationDateDesc": {
"message": "Je-li nastaveno, přístup k tomuto Send vyprší v daný datum a čas.",
@ -1664,7 +1664,7 @@
"message": "Text, který chcete odeslat."
},
"sendHideText": {
"message": "Skrýt ve výchozím stavu obsah tohoto Sendu.",
"message": "Skrýt ve výchozím stavu text tohoto Send.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"currentAccessCount": {
@ -1724,10 +1724,10 @@
"message": "Uvedené datum odstranění není platné."
},
"expirationDateAndTimeRequired": {
"message": "Je vyžadováno datum a čas vypršení platnosti."
"message": "Je vyžadován datum a čas vypršení platnosti."
},
"deletionDateAndTimeRequired": {
"message": "Je vyžadováno datum a čas odstranění."
"message": "Je vyžadován datum a čas odstranění."
},
"dateParsingError": {
"message": "Došlo k chybě při ukládání data odstranění a vypršení platnosti."

View File

@ -816,7 +816,7 @@
"message": "Stecke deinen Sicherheitsschlüssel in den USB-Port deines Computers. Falls ein Knopf vorhanden ist, berühre diesen."
},
"webAuthnNewTab": {
"message": "Fahre mit der WebAuthn 2FA Verifizierung im neuen Tab fort."
"message": "Um die WebAuthn 2FA Verifizierung zu starten, klicke auf die Schaltfläche unten, um einen neuen Tab zu öffnen und folge den Anweisungen, die im neuen Tab angezeigt werden."
},
"webAuthnNewTabOpen": {
"message": "Neuen Tab öffnen"
@ -909,7 +909,7 @@
"message": "Die URLs der Umgebung wurden gespeichert."
},
"enableAutoFillOnPageLoad": {
"message": "Aktiviere automatisches Ausfüllen beim Laden der Seite"
"message": "Auto-Ausfüllen beim Seitenladen aktivieren"
},
"enableAutoFillOnPageLoadDesc": {
"message": "Wenn eine Zugangsmaske erkannt wird, füge automatisch die Zugangsdaten ein während die Webseite lädt."

View File

@ -88,6 +88,9 @@
"generatePasswordCopied": {
"message": "Generate Password (copied)"
},
"copyElementIdentifier": {
"message": "Copy Custom Field Name"
},
"noMatchingLogins": {
"message": "No matching logins."
},
@ -773,6 +776,9 @@
"disableAutoTotpCopyDesc": {
"message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login."
},
"disableAutoBiometricsPrompt": {
"message": "Do not prompt for biometrics on launch"
},
"premiumRequired": {
"message": "Premium Required"
},
@ -1752,5 +1758,54 @@
},
"emailVerificationRequiredDesc": {
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
},
"updatedMasterPassword": {
"message": "Updated Master Password"
},
"updateMasterPassword": {
"message": "Update Master Password"
},
"updateMasterPasswordWarning": {
"message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour."
},
"resetPasswordPolicyAutoEnroll": {
"message": "Automatic Enrollment"
},
"resetPasswordAutoEnrollInviteWarning": {
"message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password."
},
"selectFolder": {
"message": "Select folder..."
},
"ssoCompleteRegistration": {
"message": "In order to complete logging in with SSO, please set a master password to access and protect your vault."
},
"hours": {
"message": "Hours"
},
"minutes": {
"message": "Minutes"
},
"vaultTimeoutPolicyInEffect": {
"message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)",
"placeholders": {
"hours": {
"content": "$1",
"example": "5"
},
"minutes": {
"content": "$2",
"example": "5"
}
}
},
"vaultTimeoutToLarge": {
"message": "Your vault timeout exceeds the restrictions set by your organization."
},
"vaultExportDisabled": {
"message": "Vault Export Disabled"
},
"personalVaultExportPolicyInEffect": {
"message": "One or more organization policies prevents you from exporting your personal vault."
}
}

View File

@ -151,7 +151,7 @@
"message": "Guardar"
},
"move": {
"message": "Move"
"message": "Mover"
},
"addFolder": {
"message": "Añadir carpeta"
@ -632,19 +632,19 @@
"message": "Compartido"
},
"learnOrg": {
"message": "Learn about Organizations"
"message": "Aprende sobre Organizaciones"
},
"learnOrgConfirmation": {
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
"message": "Bitwarden te permite compartir tus objetos de bóveda con otros usando una organización. ¿Quieres visitar el sitio web de bitwarden.com para saber más?"
},
"moveToOrganization": {
"message": "Move to Organization"
"message": "Mover a la Organización"
},
"share": {
"message": "Compartir"
},
"movedItemToOrg": {
"message": "$ITEMNAME$ moved to $ORGNAME$",
"message": "$ITEMNAME$ se desplazó a $ORGNAME$",
"placeholders": {
"itemname": {
"content": "$1",
@ -657,7 +657,7 @@
}
},
"moveToOrgDesc": {
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
"message": "Elige una organización a la que deseas mover este objeto. Moviendo a una organización transfiere la propiedad del objeto a esa organización. Ya no serás el dueño directo de este objeto una vez que haya sido movido."
},
"learnMore": {
"message": "Más información"
@ -816,13 +816,13 @@
"message": "Inserta tu llave de seguridad en el puerto USB de tu equipo. Si tiene un botón, púlsalo."
},
"webAuthnNewTab": {
"message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab."
"message": "Para iniciar la verificación de WebAuthn 2FA. Haga clic en el botón de abajo para abrir una nueva pestaña y siga las instrucciones proporcionadas en la nueva pestaña."
},
"webAuthnNewTabOpen": {
"message": "Open new tab"
"message": "Abrir nueva pestaña"
},
"webAuthnAuthenticate": {
"message": "Authenticate WebAuthn"
"message": "Autenticar WebAuthn"
},
"loginUnavailable": {
"message": "Entrada no disponible"
@ -867,7 +867,7 @@
"message": "FIDO2 WebAuthn"
},
"webAuthnDesc": {
"message": "Use any WebAuthn enabled security key to access your account."
"message": "Utilice cualquier clave de seguridad WebAuthn habilitada para acceder a su cuenta."
},
"emailTitle": {
"message": "Correo electrónico"
@ -918,22 +918,22 @@
"message": "Esta es una característica experimental. Úsala bajo tu propio riesgo."
},
"defaultAutoFillOnPageLoad": {
"message": "Default autofill setting for login items"
"message": "Configuración de autorrelleno por defecto para elementos de inicio de sesión"
},
"defaultAutoFillOnPageLoadDesc": {
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
"message": "Después de activar el autorelleno en Carga de página, puede activar o desactivar la función para entradas individuales. Esta es la configuración predeterminada para elementos de inicio de sesión que no están configurados por separado."
},
"itemAutoFillOnPageLoad": {
"message": "Auto-fill on Page Load (if enabled in Options)"
"message": "Auto-relleno en carga de página (si está habilitado en opciones)"
},
"autoFillOnPageLoadUseDefault": {
"message": "Use default setting"
"message": "Usar configuración predeterminada"
},
"autoFillOnPageLoadYes": {
"message": "Auto-fill on page load"
"message": "Autocompletar al cargar la página"
},
"autoFillOnPageLoadNo": {
"message": "Do not auto-fill on page load"
"message": "No rellenar automáticamente al cargar la página"
},
"commandOpenPopup": {
"message": "Abrir ventana emergente de la caja fuerte"
@ -990,10 +990,10 @@
"message": "Los iconos del sitio web añaden una imagen reconocible al lado de cada entrada de tu caja fuerte."
},
"disableBadgeCounter": {
"message": "Disable Badge Counter"
"message": "Desactivar contador de insignias"
},
"disableBadgeCounterDesc": {
"message": "Badge counter indicates how many logins you have for the current page in your vault."
"message": "El contador de insinuaciones indica cuántos registros tienes para la página actual en tu bóveda."
},
"cardholderName": {
"message": "Nombre en la tarjeta"
@ -1657,7 +1657,7 @@
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendShareDesc": {
"message": "Copy this Send's link to clipboard upon save.",
"message": "Copiar el enlace del Send en el portapapeles al guardar.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendTextDesc": {
@ -1668,7 +1668,7 @@
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"currentAccessCount": {
"message": "Current Access Count"
"message": "Número de acceso actual"
},
"createSend": {
"message": "Crear Envío nuevo",
@ -1682,7 +1682,7 @@
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendDisabledWarning": {
"message": "Due to an enterprise policy, you are only able to delete an existing Send.",
"message": "Debido a una política empresarial, sólo puede eliminar el existente Send",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"createdSend": {
@ -1694,19 +1694,19 @@
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendLinuxChromiumFileWarning": {
"message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner."
"message": "Para elegir un archivo, abra la extensión en la barra lateral (si es posible) o salga a una nueva ventana haciendo clic en este anouncio."
},
"sendFirefoxFileWarning": {
"message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner."
"message": "Para elegir un archivo usando Firefox, abra la extensión en la barra lateral o salga a una nueva ventana haciendo clic en este anouncio."
},
"sendSafariFileWarning": {
"message": "In order to choose a file using Safari, pop out to a new window by clicking this banner."
"message": "Para elegir un archivo usando Safari, salga a una nueva ventana haciendo clic en este anouncio."
},
"sendFileCalloutHeader": {
"message": "Before you start"
"message": "Antes de empezar"
},
"sendFirefoxCustomDatePopoutMessage1": {
"message": "To use a calendar style date picker",
"message": "Para usar un selector de fechas de estilo calendario",
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'"
},
"sendFirefoxCustomDatePopoutMessage2": {
@ -1714,43 +1714,43 @@
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'"
},
"sendFirefoxCustomDatePopoutMessage3": {
"message": "to pop out your window.",
"message": "para abrir la ventana.",
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'"
},
"expirationDateIsInvalid": {
"message": "The expiration date provided is not valid."
"message": "La fecha de caducidad proporcionada no es válida."
},
"deletionDateIsInvalid": {
"message": "The deletion date provided is not valid."
"message": "La fecha de eliminación proporcionada no es válida."
},
"expirationDateAndTimeRequired": {
"message": "An expiration date and time are required."
"message": "Se requiere una fecha y hora de caducidad."
},
"deletionDateAndTimeRequired": {
"message": "A deletion date and time are required."
"message": "Se requiere una fecha y hora de eliminación."
},
"dateParsingError": {
"message": "There was an error saving your deletion and expiration dates."
"message": "Hubo un error al guardar las fechas de eliminación y caducidad."
},
"hideEmail": {
"message": "Hide my email address from recipients."
"message": "Ocultar mi dirección de correo electrónico a los destinatarios."
},
"sendOptionsPolicyInEffect": {
"message": "One or more organization policies are affecting your Send options."
"message": "Una o más políticas de organización están afectando sus opciones del Send."
},
"passwordPrompt": {
"message": "Master password re-prompt"
"message": "Volver a preguntar contraseña maestra"
},
"passwordConfirmation": {
"message": "Master password confirmation"
"message": "Confirmación de contraseña maestra"
},
"passwordConfirmationDesc": {
"message": "This action is protected. To continue, please re-enter your master password to verify your identity."
"message": "Esta acción está protegida. Para continuar, vuelva a introducir su contraseña maestra para verificar su identidad."
},
"emailVerificationRequired": {
"message": "Email Verification Required"
"message": "Verificación de correo electrónico requerida"
},
"emailVerificationRequiredDesc": {
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
"message": "Debes verificar tu correo electrónico para usar esta función. Puedes verificar tu correo electrónico en la bóveda web."
}
}

View File

@ -526,10 +526,10 @@
"description": "This is the folder for uncategorized items"
},
"disableAddLoginNotification": {
"message": "Keela \"Lisa konto andmed\" märguanne"
"message": "Keela \"Lisa konto andmed\" teavitus"
},
"addLoginNotificationDesc": {
"message": "\"Lisa konto andmed\" märguanne ilmub pärast esimest sisselogimist ning võimaldab Sul kontoandmeid automaatselt Bitwardenisse lisada."
"message": "\"Lisa konto andmed\" teavitus ilmub pärast esimest sisselogimist ning võimaldab kontoandmeid automaatselt Bitwardenisse lisada."
},
"dontShowCardsCurrentTab": {
"message": "Ära kuva \"Kaart\" vaates krediitkaardi andmeid"
@ -564,7 +564,7 @@
"message": "Keela Muudetud parooli teavitus"
},
"disableChangedPasswordNotificationDesc": {
"message": "Kui mistahes veebilehel on toimunud parooli vahetamine, annab \"Muudetud parooli teavitus\" sulle märku, et vahetaksid selle ära ka Bitwardeni paroolihoidlas."
"message": "Kui mistahes veebilehel on toimunud parooli vahetamine, annab \"Muudetud parooli teavitus\" märku, et värskendaksid seda ka Bitwardeni paroolihoidlas."
},
"notificationChangeDesc": {
"message": "Soovid seda parooli ka Bitwardenis uuendada?"
@ -837,7 +837,7 @@
"message": "Kaheastmelise sisselogimise valikud"
},
"recoveryCodeDesc": {
"message": "Sul ei ole ligipääsu ühelegi kaheastmelise kinnitamise teenusele? Kasuta Taastamise koodi, et kaheastmeline kinnitamine oma kontol välja lülitada."
"message": "Puudub ligipääs kaheastmelise kinnitamise teenusele? Kasuta Taastamise koodi, et kaheastmeline kinnitamine oma kontol välja lülitada."
},
"recoveryCodeTitle": {
"message": "Taastamise kood"
@ -933,7 +933,7 @@
"message": "Täida kontoandmed lehe laadimisel"
},
"autoFillOnPageLoadNo": {
"message": "Ära täida kontoandmed lehe laadimisel"
"message": "Ära täida kontoandmeid lehe laadimisel"
},
"commandOpenPopup": {
"message": "Ava hoidla uues aknas"

View File

@ -1609,14 +1609,14 @@
"message": "Tiedosto, jonka haluat lähettää."
},
"deletionDate": {
"message": "Poistopäivä"
"message": "Poistoajankohta"
},
"deletionDateDesc": {
"message": "Send poistetaan pysyvästi määritettynä ajankohtana.",
"message": "Send poistuu pysyvästi määritettynä ajankohtana.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"expirationDate": {
"message": "Erääntymispäivä"
"message": "Erääntymisajankohta"
},
"expirationDateDesc": {
"message": "Jos määritetty, Send erääntyy määritettynä ajankohtana.",
@ -1718,19 +1718,19 @@
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'"
},
"expirationDateIsInvalid": {
"message": "Asetettu erääntymismispäivä on virheellinen."
"message": "Määritetty erääntymismisajankohta on virheellinen."
},
"deletionDateIsInvalid": {
"message": "Asetettu poistopäivä on virheellinen."
"message": "Määritetty poistoajankohta on virheellinen."
},
"expirationDateAndTimeRequired": {
"message": "Viimeinen voimassaolopäivä ja aika vaaditaan."
"message": "Erääntymispäivä ja -aika vaaditaan."
},
"deletionDateAndTimeRequired": {
"message": "Poistopäivä ja -aika vaaditaan."
},
"dateParsingError": {
"message": "Tapahtui virhe tallennettaessa poisto- ja erääntymispäiviä."
"message": "Tapahtui virhe tallennettaessa poisto- ja erääntymisajankohtia."
},
"hideEmail": {
"message": "Piilota sähköpostiosoitteeni vastaanottajilta."

File diff suppressed because it is too large Load Diff

View File

@ -151,7 +151,7 @@
"message": "Enregistrer"
},
"move": {
"message": "Move"
"message": "Se déplacer"
},
"addFolder": {
"message": "Ajouter un dossier"
@ -632,19 +632,19 @@
"message": "Partagé"
},
"learnOrg": {
"message": "Learn about Organizations"
"message": "En savoir plus sur les organisations"
},
"learnOrgConfirmation": {
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
"message": "Bitwarden vous permet de partager des éléments de votre coffre avec d'autres personnes en utilisant un compte d'organisation. Souhaitez-vous visiter le site web bitwarden.com pour en savoir plus ?"
},
"moveToOrganization": {
"message": "Move to Organization"
"message": "Déplacer vers l'organisation"
},
"share": {
"message": "Partager"
},
"movedItemToOrg": {
"message": "$ITEMNAME$ moved to $ORGNAME$",
"message": "$ITEMNAME$ a été déplacé vers $ORGNAME$",
"placeholders": {
"itemname": {
"content": "$1",
@ -657,7 +657,7 @@
}
},
"moveToOrgDesc": {
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
"message": "Choisissez une organisation vers laquelle vous souhaitez déplacer cet élément. Déplacer un élément vers une organisation transfère la propriété de l'élément à cette organisation. Vous ne serez plus le propriétaire direct de cet élément une fois qu'il aura été déplacé."
},
"learnMore": {
"message": "En savoir plus"
@ -816,10 +816,10 @@
"message": "Insérez votre clé de sécurité dans le port USB de votre ordinateur. S'il dispose d'un bouton, appuyez dessus."
},
"webAuthnNewTab": {
"message": "Poursuivez la vérification 2FA WebAuthn dans le nouvel onglet."
"message": "Pour démarrer la vérification 2FA WebAuthn, cliquez sur le bouton ci-dessous et suivez les instructions dans le nouvel onglet."
},
"webAuthnNewTabOpen": {
"message": "Open new tab"
"message": "Ouvrir un nouvel onglet"
},
"webAuthnAuthenticate": {
"message": "Authentifier WebAuthn"
@ -909,7 +909,7 @@
"message": "Les URLs d'environnement ont été enregistrées."
},
"enableAutoFillOnPageLoad": {
"message": "Activer lauto-complétion au chargement de la page"
"message": "Activer le remplissage automatique au chargement de la page"
},
"enableAutoFillOnPageLoadDesc": {
"message": "Si un formulaire de connexion est détecté, remplir automatiquement les champs au chargement de la page web."
@ -918,22 +918,22 @@
"message": "Ceci est actuellement une fonctionnalité expérimentale. À utiliser avec prudence."
},
"defaultAutoFillOnPageLoad": {
"message": "Default autofill setting for login items"
"message": "Paramètre de saisie automatique par défaut pour les identifiants"
},
"defaultAutoFillOnPageLoadDesc": {
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
"message": "Après avoir activé le remplissage automatique au chargement de la page, vous pourrez activer ou désactiver la fonctionnalité pour chaque identifiant. Ceci est le paramètre par défaut pour les identifiants qui ne sont pas configurés individuellement."
},
"itemAutoFillOnPageLoad": {
"message": "Auto-fill on Page Load (if enabled in Options)"
"message": "Remplissage automatique au chargement de la page (si activé dans les options)"
},
"autoFillOnPageLoadUseDefault": {
"message": "Use default setting"
"message": "Utiliser le paramètre par défaut"
},
"autoFillOnPageLoadYes": {
"message": "Auto-fill on page load"
"message": "Remplissage automatique au chargement de la page"
},
"autoFillOnPageLoadNo": {
"message": "Do not auto-fill on page load"
"message": "Ne pas remplir automatiquement au chargement de la page"
},
"commandOpenPopup": {
"message": "Ouvrir la popup du coffre"
@ -1748,9 +1748,9 @@
"message": "Cette action est protégée. Pour continuer, veuillez ressaisir votre mot de passe maître pour vérifier votre identité."
},
"emailVerificationRequired": {
"message": "Email Verification Required"
"message": "Vérification de l'adresse e-mail nécessaire"
},
"emailVerificationRequiredDesc": {
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
"message": "Vous devez vérifier votre adresse e-mail pour utiliser cette fonctionnalité. Vous pouvez vérifier votre adresse e-mail dans le coffre web."
}
}

View File

@ -644,7 +644,7 @@
"message": "שתף"
},
"movedItemToOrg": {
"message": "$ITEMNAME$ moved to $ORGNAME$",
"message": "$ITEMNAME$ הועבר ל- $ORGNAME$",
"placeholders": {
"itemname": {
"content": "$1",
@ -918,19 +918,19 @@
"message": "זוהי אופציה נסיונית. השימוש באופציה זו על אחריותך."
},
"defaultAutoFillOnPageLoad": {
"message": "Default autofill setting for login items"
"message": "הגדרת ברירת מחדל למילוי אוטומטי של פרטי התחברות"
},
"defaultAutoFillOnPageLoadDesc": {
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
"message": "לאחר הפעלת מילוי אוטומטי של פרטים בעת טעינת דפים, אפשר להפעיל או לכבות את האפשרות לפרטי התחברות ספציפיים. זו הגדרת ברירת המחדל לפרטי התחברות שלא הוגדרו בנפרד."
},
"itemAutoFillOnPageLoad": {
"message": "Auto-fill on Page Load (if enabled in Options)"
"message": "מילוי אוטומטי בעת טעינת דפים (אם מופעל בהגדרות)"
},
"autoFillOnPageLoadUseDefault": {
"message": "Use default setting"
"message": "שימוש בהגדרות ברירת המחדל"
},
"autoFillOnPageLoadYes": {
"message": "Auto-fill on page load"
"message": "מילוי אוטומטי אחרי טעינת דפים"
},
"autoFillOnPageLoadNo": {
"message": "Do not auto-fill on page load"

File diff suppressed because it is too large Load Diff

View File

@ -151,7 +151,7 @@
"message": "Spremi"
},
"move": {
"message": "Move"
"message": "Premjesti"
},
"addFolder": {
"message": "Dodaj mapu"
@ -632,19 +632,19 @@
"message": "Dijeljeno"
},
"learnOrg": {
"message": "Learn about Organizations"
"message": "Više o organizacijama"
},
"learnOrgConfirmation": {
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
"message": "Bitwarden omogućuje dijeljenje trezora s drugima pomoću organizacijskog računa. Želiš li sada posjetiti bitwarden.com za više informacija?"
},
"moveToOrganization": {
"message": "Move to Organization"
"message": "Premjesti u organizaciju"
},
"share": {
"message": "Podijeli"
},
"movedItemToOrg": {
"message": "$ITEMNAME$ moved to $ORGNAME$",
"message": "$ITEMNAME$ premješteno u $ORGNAME$",
"placeholders": {
"itemname": {
"content": "$1",
@ -657,7 +657,7 @@
}
},
"moveToOrgDesc": {
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
"message": "Odaberi organizaciju u koju želiš premjestiti ovu stavku. Premještanje prenosi vlasništvo stavke na organizaciju. Nakon premještanja više nećeš biti izravni vlasnik ove stavke."
},
"learnMore": {
"message": "Saznaj više"
@ -819,7 +819,7 @@
"message": "Nastavi na WebAuthn 2FA verifikaciju u novoj kartici."
},
"webAuthnNewTabOpen": {
"message": "Open new tab"
"message": "Otvori novu karticu"
},
"webAuthnAuthenticate": {
"message": "Ovjeri WebAuthn"
@ -918,22 +918,22 @@
"message": "Ovo je trenutno eksperimentalna značajka. Koristi na vlastitu odgovornost."
},
"defaultAutoFillOnPageLoad": {
"message": "Default autofill setting for login items"
"message": "Zadana postvaka Auto-ispune za prijave"
},
"defaultAutoFillOnPageLoadDesc": {
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
"message": "Nakon omogućavanja Auto-ispune kod učitavanja stranice, moguće je uključiti/isključiti ovu značajku za svaku pojedinu prijavu. Ovo je zadana postavka za prijave koje nisu pojedinčano određene."
},
"itemAutoFillOnPageLoad": {
"message": "Auto-fill on Page Load (if enabled in Options)"
"message": "Auto-ispuna kod učitavanja stranice (ako je uključeno u Postavkama)"
},
"autoFillOnPageLoadUseDefault": {
"message": "Use default setting"
"message": "Koristi zadane postavke"
},
"autoFillOnPageLoadYes": {
"message": "Auto-fill on page load"
"message": "Auto-ispuna kod učitavanja"
},
"autoFillOnPageLoadNo": {
"message": "Do not auto-fill on page load"
"message": "Ne koristi Auto-ispunu kod učitavanja"
},
"commandOpenPopup": {
"message": "Otvori iskočni prozor trezora"
@ -1748,9 +1748,9 @@
"message": "Ova radnja je zaštićena. Za nastavak i potvrdu identiteta, unesi svoju glavnu lozinku."
},
"emailVerificationRequired": {
"message": "Email Verification Required"
"message": "Potrebna je potvrda e-pošte"
},
"emailVerificationRequiredDesc": {
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
"message": "Moraš ovjeriti svoju e-poštu u mrežnom trezoru za koritšenje ove značajke."
}
}

View File

@ -139,7 +139,7 @@
"message": "Verifica in due passaggi"
},
"logOut": {
"message": "Disconnessione"
"message": "Esci"
},
"about": {
"message": "Informazioni"
@ -732,7 +732,7 @@
"message": "Opzioni addizionali di login in due passaggi come YubiKey, FIDO U2F, e Duo."
},
"ppremiumSignUpReports": {
"message": "Sicurezza delle password, integrità dell'account e rapporti sulla violazione di dati per mantenere sicura la tua cassaforte."
"message": "Sicurezza delle password, integrità dell'account e resoconti sulla violazione di dati per mantenere sicura la tua cassaforte."
},
"ppremiumSignUpTotp": {
"message": "Generatore di codice di verifica TOTP (2FA) per i login nella tua cassaforte."
@ -783,7 +783,7 @@
"message": "Inserisci il codice di verifica a 6 cifre dalla tua applicazione di autenticazione."
},
"enterVerificationCodeEmail": {
"message": "Inserisci il codice di verifica a 6 cifre ricevuto per email",
"message": "Inserisci il codice di verifica a 6 cifrato inviato a $EMAIL$.",
"placeholders": {
"email": {
"content": "$1",
@ -918,22 +918,22 @@
"message": "Al momento questa funzionalità è sperimentale. Usala a tuo rischio e pericolo."
},
"defaultAutoFillOnPageLoad": {
"message": "Impostazioni di riempimento automatico predefinito per gli elementi di accesso"
"message": "Impostazioni di completamento automatico predefinito per i login"
},
"defaultAutoFillOnPageLoadDesc": {
"message": "Dopo aver abilitato il completamento automatico al caricamento della pagina, è possibile abilitare o disabilitare la funzione per singoli elementi di accesso. Questa è l'impostazione predefinita per gli elementi di accesso che non sono configurati separatamente."
"message": "Dopo aver abilitato il completamento automatico al caricamento della pagina, è possibile abilitare o disabilitare la funzione per singoli login. Questa è l'impostazione predefinita per i login che non sono configurati separatamente."
},
"itemAutoFillOnPageLoad": {
"message": "Riempimento automatico al caricamento della pagina (se abilitato nelle opzioni)"
"message": "Autocompletamento al caricamento della pagina (se abilitato nelle opzioni)"
},
"autoFillOnPageLoadUseDefault": {
"message": "Usa impostazione predefinita"
},
"autoFillOnPageLoadYes": {
"message": "Riempimento automatico al caricamento della pagina"
"message": "Autocompletamento al caricamento della pagina"
},
"autoFillOnPageLoadNo": {
"message": "Non riempire automaticamente al caricamento della pagina"
"message": "Non completare automaticamente al caricamento della pagina"
},
"commandOpenPopup": {
"message": "Apri popup cassaforte"
@ -942,10 +942,10 @@
"message": "Apri la cassaforte nella barra laterale"
},
"commandAutofillDesc": {
"message": "Auto-completa con l'ultimo login utilizzato sul sito corrente."
"message": "Auto-completa con l'ultimo accesso utilizzato sul sito corrente"
},
"commandGeneratePasswordDesc": {
"message": "Genera e copia una nuova password casuale negli appunti."
"message": "Genera e copia una nuova password casuale negli appunti"
},
"commandLockVaultDesc": {
"message": "Blocca la cassaforte"
@ -1668,7 +1668,7 @@
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"currentAccessCount": {
"message": "Numero di accessi correnti"
"message": "Numero di accessi attuale"
},
"createSend": {
"message": "Crea nuovo Send",
@ -1748,7 +1748,7 @@
"message": "Questa azione è protetta. Per continuare, inserisci nuovamente la tua password principale per verificare la tua identità."
},
"emailVerificationRequired": {
"message": "Verifica email necessaria"
"message": "Verifica email richiesta"
},
"emailVerificationRequiredDesc": {
"message": "Devi verificare la tua email per utilizzare questa funzionalità. Puoi verificare la tua email nella cassaforte web."

View File

@ -151,7 +151,7 @@
"message": "저장"
},
"move": {
"message": "Move"
"message": "이동"
},
"addFolder": {
"message": "폴더 추가"
@ -632,19 +632,19 @@
"message": "공유됨"
},
"learnOrg": {
"message": "Learn about Organizations"
"message": "조직에 대해 알아보기"
},
"learnOrgConfirmation": {
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
"message": "Bitwarden은 조직용 계정을 사용하면 사용자의 보관함을 타인에게 공유할 수 있습니다. bitwarden.com 웹 사이트를 방문하여 더 자세히 알아보시겠습니까?"
},
"moveToOrganization": {
"message": "Move to Organization"
"message": "조직으로 이동하기"
},
"share": {
"message": "공유"
},
"movedItemToOrg": {
"message": "$ITEMNAME$ moved to $ORGNAME$",
"message": "$ITEMNAME$이(가) $ORGNAME$(으)로 이동됨",
"placeholders": {
"itemname": {
"content": "$1",
@ -657,7 +657,7 @@
}
},
"moveToOrgDesc": {
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
"message": "이 항목을 이동할 조직을 선택하십시오. 항목이 조직으로 이동되면 소유권이 조직으로 이전됩니다. 일단 이동되면, 더는 이동된 항목의 직접적인 소유자가 아니게 됩니다."
},
"learnMore": {
"message": "더 알아보기"
@ -819,7 +819,7 @@
"message": "새 탭에서 WebAuthn 2단계 인증을 계속하세요."
},
"webAuthnNewTabOpen": {
"message": "Open new tab"
"message": "새 탭 열기"
},
"webAuthnAuthenticate": {
"message": "WebAuthn 인증"
@ -918,22 +918,22 @@
"message": "현재 실험 중인 기능입니다. 위험을 감수하여 사용하세요."
},
"defaultAutoFillOnPageLoad": {
"message": "Default autofill setting for login items"
"message": "로그인 항목에 대한 기본 자동 완성 설정"
},
"defaultAutoFillOnPageLoadDesc": {
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
"message": "페이지 로드 시 자동 완성을 켠 뒤에는 각 로그인 항목별로 이 기능을 켜거나 끌 수 있습니다. 이 옵션은 해당 기능을 개별적으로 구성하지 않은 항목에 사용되는 기본 설정값입니다."
},
"itemAutoFillOnPageLoad": {
"message": "Auto-fill on Page Load (if enabled in Options)"
"message": "페이지 로드 시 자동 완성 (옵션에서 켜져 있을 경우)"
},
"autoFillOnPageLoadUseDefault": {
"message": "Use default setting"
"message": "기본 설정 사용"
},
"autoFillOnPageLoadYes": {
"message": "Auto-fill on page load"
"message": "페이지 로드 시 자동 완성"
},
"autoFillOnPageLoadNo": {
"message": "Do not auto-fill on page load"
"message": "페이지 로드 시 자동 완성 안 함"
},
"commandOpenPopup": {
"message": "보관함 팝업 열기"
@ -1748,9 +1748,9 @@
"message": "이 작업은 보호되어 있습니다. 계속하려면 마스터 비밀번호를 입력하여 신원을 인증하세요."
},
"emailVerificationRequired": {
"message": "Email Verification Required"
"message": "이메일 인증 필요함"
},
"emailVerificationRequiredDesc": {
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
"message": "이 기능을 사용하려면 이메일 인증이 필요합니다. 웹 보관함에서 이메일을 인증할 수 있습니다."
}
}

View File

@ -151,7 +151,7 @@
"message": "Saglabāt"
},
"move": {
"message": "Move"
"message": "Pārvietot"
},
"addFolder": {
"message": "Pievienot mapi"
@ -632,19 +632,19 @@
"message": "Kopīgots"
},
"learnOrg": {
"message": "Learn about Organizations"
"message": "Uzzināt par apvienībām"
},
"learnOrgConfirmation": {
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
"message": "Bitwarden nodrošina iespēju kopīgot glabātavas vienumus ar citiem, kad tiek izmantota apvienība. Vai apmeklēt bitwarden.com tīmekļa vietni, lai uzzinātu vairāk?"
},
"moveToOrganization": {
"message": "Move to Organization"
"message": "Pārvietot uz apvienību"
},
"share": {
"message": "Kopīgot"
},
"movedItemToOrg": {
"message": "$ITEMNAME$ moved to $ORGNAME$",
"message": "$ITEMNAME$ pārvietots uz $ORGNAME$",
"placeholders": {
"itemname": {
"content": "$1",
@ -657,7 +657,7 @@
}
},
"moveToOrgDesc": {
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
"message": "Izvēlies apvienību, uz kuru pārvietot šo vienumu. Pārvietošana nodod šī vienuma piederību apvienībai. Tu vairs nebūsi šī vienuma tiešais īpašnieks pēc tā pārvietošanas."
},
"learnMore": {
"message": "Uzzināt vairāk"
@ -819,7 +819,7 @@
"message": "Turpināt WebAuthn 2FA apstiprināšanu jaunā cilnē."
},
"webAuthnNewTabOpen": {
"message": "Open new tab"
"message": "Atvērt jaunu cilni"
},
"webAuthnAuthenticate": {
"message": "Autentificēt WebAuthn"
@ -918,22 +918,22 @@
"message": "Šī iespēja pašlaik ir izmēģināšanā. Izmantošanas atbildība ir katra paša pārziņā. "
},
"defaultAutoFillOnPageLoad": {
"message": "Default autofill setting for login items"
"message": "Noklusējuma automātiskās aizpildes iestatījums pierakstīšanās vienumiem"
},
"defaultAutoFillOnPageLoadDesc": {
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
"message": "Pēc automātiskās aizpildes lapas ielādes brīdī iespējošanas šo iespēju var ieslēgt vai izslēgt atsevišķiem pierakstīšanās vienumiem. Šis ir noklusējuma iestatījums visiem ierakstiem, kuriem nav norādīts šis uzstādījums."
},
"itemAutoFillOnPageLoad": {
"message": "Auto-fill on Page Load (if enabled in Options)"
"message": "Automātiski aizpildīt lapas ielādes brīdī (ja iespējots iestatījumos)"
},
"autoFillOnPageLoadUseDefault": {
"message": "Use default setting"
"message": "Izmantot noklusējuma iestatījumu"
},
"autoFillOnPageLoadYes": {
"message": "Auto-fill on page load"
"message": "Automātiski aizpildīt lapas ielādes brīdī"
},
"autoFillOnPageLoadNo": {
"message": "Do not auto-fill on page load"
"message": "Neaizpildīt lapas ielādes brīdī"
},
"commandOpenPopup": {
"message": "Atvērt glabātavas uznirstošo logu"
@ -1748,9 +1748,9 @@
"message": "Šī darbība ir aizsargāta. Lai turpinātu, ir jāievada galvenā parole, lai apstiprinātu identitāti."
},
"emailVerificationRequired": {
"message": "Email Verification Required"
"message": "Nepieciešama e-pasta adreses apstiprināšana"
},
"emailVerificationRequiredDesc": {
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
"message": "Ir nepieciešams apstiprināt e-pasta adresi, lai būtu iespējams izmantot šo iespēju. To var izdarīt tīmekļa glabātavā."
}
}

View File

@ -151,7 +151,7 @@
"message": "Lagre"
},
"move": {
"message": "Move"
"message": "Flytt"
},
"addFolder": {
"message": "Legg til en mappe"
@ -600,7 +600,7 @@
"description": "Light color"
},
"solarizedDark": {
"message": "Solarized Dark",
"message": "Solarisert mørk",
"description": "'Solarized' is a noun and the name of a color scheme. It should not be translated."
},
"exportVault": {
@ -620,10 +620,10 @@
"message": "Eksporten inneholder dine hvelvdataer i et ukryptert format. Du burde ikke lagre eller sende den eksporterte filen over usikre tjenester (f.eks. E-post). Slett det umiddelbart etter at du er ferdig med å bruke dem."
},
"encExportKeyWarningDesc": {
"message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file."
"message": "Denne eksporten krypterer dataene dine ved hjelp av kontoen din sin krypteringsnøkkel. Hvis du noen gang endrer krypteringsnøkkelen til kontoen din, bør du eksportere dataene igjen, ettersom du da ikke vil kunne dekryptere denne eksportfilen."
},
"encExportAccountWarningDesc": {
"message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account."
"message": "Kontokrypteringsnøkler er unike for hver Bitwarden sin brukerkonto, og du kan ikke importere en kryptert eksport til en annen konto."
},
"exportMasterPassword": {
"message": "Skriv inn ditt superpassord for å eksportere dine hvelvdataer."
@ -632,19 +632,19 @@
"message": "Delt"
},
"learnOrg": {
"message": "Learn about Organizations"
"message": "Lær om organisasjoner"
},
"learnOrgConfirmation": {
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
"message": "Bitwarden lar deg dele dine hvelvgjenstander med andre ved å bruke en organisasjon. Vil du besøke bitwarden.com-nettstedet for å lære mer?"
},
"moveToOrganization": {
"message": "Move to Organization"
"message": "Flytt til organisasjon"
},
"share": {
"message": "Del"
},
"movedItemToOrg": {
"message": "$ITEMNAME$ moved to $ORGNAME$",
"message": "$ITEMNAME$ flyttet til $ORGNAME$",
"placeholders": {
"itemname": {
"content": "$1",
@ -657,7 +657,7 @@
}
},
"moveToOrgDesc": {
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
"message": "Velg en organisasjon som du ønsker å flytte denne gjenstanden til. Flytting til en organisasjon overfører eierskap til den aktuelle organisasjonen. Du vil ikke lenger være den direkte eieren av denne varen når den er flyttet."
},
"learnMore": {
"message": "Lær mer"
@ -816,13 +816,13 @@
"message": "Sett din sikkerhetsnøkkel inn i din datamaskins USB-uttak. Dersom den har en knapp, trykk på den."
},
"webAuthnNewTab": {
"message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab."
"message": "For å starte WebAuthn 2FA bekreftelsen. Klikk på knappen nedenfor for å åpne en ny fane og følge instruksene som er gitt i den nye fanen."
},
"webAuthnNewTabOpen": {
"message": "Open new tab"
"message": "Åpne ny fane"
},
"webAuthnAuthenticate": {
"message": "Authenticate WebAuthn"
"message": "Autentiser WebAuthn"
},
"loginUnavailable": {
"message": "Innloggingen er utilgjengelig"
@ -867,7 +867,7 @@
"message": "FIDO2 WebAuthn"
},
"webAuthnDesc": {
"message": "Use any WebAuthn enabled security key to access your account."
"message": "Bruk en hvilken som helst WebAuthn aktivert sikkerhetsnøkkel til å få tilgang til kontoen din."
},
"emailTitle": {
"message": "E-post"
@ -918,10 +918,10 @@
"message": "Dette er for øyeblikket en eksperimentell egenskap. Bruk det på din egen risiko."
},
"defaultAutoFillOnPageLoad": {
"message": "Default autofill setting for login items"
"message": "Standard autofyll innstilling for innloggingselementer"
},
"defaultAutoFillOnPageLoadDesc": {
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
"message": "Etter aktivering av auto-utfylling på sidelasser, kan du aktivere eller deaktivere funksjonen for individuelle innloggingselementer. Dette er standardinnstillingen for innloggingselementer som ikke er satt opp separat."
},
"itemAutoFillOnPageLoad": {
"message": "Auto-fill on Page Load (if enabled in Options)"
@ -1616,10 +1616,10 @@
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"expirationDate": {
"message": "Expiration Date"
"message": "Utløpsdato"
},
"expirationDateDesc": {
"message": "If set, access to this Send will expire on the specified date and time.",
"message": "Hvis satt, vil tilgang til denne Send gå ut på angitt dato og klokkeslett.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"oneDay": {
@ -1635,25 +1635,25 @@
}
},
"custom": {
"message": "Custom"
"message": "Egendefinert"
},
"maximumAccessCount": {
"message": "Maximum Access Count"
"message": "Maksimal antall tilganger"
},
"maximumAccessCountDesc": {
"message": "If set, users will no longer be able to access this Send once the maximum access count is reached.",
"message": "Hvis satt, vil ikke brukere lenger ha tilgang til dette Send når maksimal antall tilgang er nådd.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendPasswordDesc": {
"message": "Optionally require a password for users to access this Send.",
"message": "Eventuelt krever et passord for brukere å få tilgang til denne Send.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendNotesDesc": {
"message": "Private notes about this Send.",
"message": "Private notater om denne Send-en.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendDisableDesc": {
"message": "Disable this Send so that no one can access it.",
"message": "Deaktiver denne Send-en, slik at ingen får tilgang til den.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendShareDesc": {
@ -1703,54 +1703,54 @@
"message": "In order to choose a file using Safari, pop out to a new window by clicking this banner."
},
"sendFileCalloutHeader": {
"message": "Before you start"
"message": "Før du starter"
},
"sendFirefoxCustomDatePopoutMessage1": {
"message": "To use a calendar style date picker",
"message": "Hvis du vil bruke en kalenderstil-datovelger",
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'"
},
"sendFirefoxCustomDatePopoutMessage2": {
"message": "click here",
"message": "kilkk her",
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'"
},
"sendFirefoxCustomDatePopoutMessage3": {
"message": "to pop out your window.",
"message": "å pope ut vinduet.",
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'"
},
"expirationDateIsInvalid": {
"message": "The expiration date provided is not valid."
"message": "Utløpsdatoen angitt er ikke gyldig."
},
"deletionDateIsInvalid": {
"message": "The deletion date provided is not valid."
"message": "Slettingsdatoen som er gitt er ikke gyldig."
},
"expirationDateAndTimeRequired": {
"message": "An expiration date and time are required."
"message": "Utløps dato og tid er påkrevd."
},
"deletionDateAndTimeRequired": {
"message": "A deletion date and time are required."
"message": "Det kreves en slettingsdato og -tid."
},
"dateParsingError": {
"message": "There was an error saving your deletion and expiration dates."
"message": "Det oppstod en feil ved lagring av slettingen og utløpsdatoene."
},
"hideEmail": {
"message": "Hide my email address from recipients."
"message": "Skjul min e-postadresse fra mottakere."
},
"sendOptionsPolicyInEffect": {
"message": "One or more organization policies are affecting your Send options."
"message": "En eller flere av organisasjons retningslinjer påvirker generatorinnstillingene dine."
},
"passwordPrompt": {
"message": "Master password re-prompt"
},
"passwordConfirmation": {
"message": "Master password confirmation"
"message": "Superpassord bekreftelse"
},
"passwordConfirmationDesc": {
"message": "This action is protected. To continue, please re-enter your master password to verify your identity."
"message": "Denne handlingen er beskyttet. For å fortsette, skriv inn superpassordet på nytt for å bekrefte identiteten din."
},
"emailVerificationRequired": {
"message": "Email Verification Required"
"message": "E-postbekreftelse kreves"
},
"emailVerificationRequiredDesc": {
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
"message": "Du må bekrefte e-posten din for å bruke denne funksjonen. Du kan bekrefte e-postadressen din i netthvelvet."
}
}

View File

@ -635,7 +635,7 @@
"message": "Dowiedz się więcej o organizacjach"
},
"learnOrgConfirmation": {
"message": "Bitwarden pozwala na udostępnianie zawartości sejfu innym osobom za pośrednictwem organizacji. Czy chcesz odwiedzić witrynę bitwarden.com, aby dowiedzieć się więcej?"
"message": "Bitwarden pozwala na udostępnianie zawartości sejfu innym osobom za pośrednictwem organizacji. Czy chcesz odwiedzić stronę bitwarden.com, aby dowiedzieć się więcej?"
},
"moveToOrganization": {
"message": "Przenieś do organizacji"
@ -644,7 +644,7 @@
"message": "Udostępnij"
},
"movedItemToOrg": {
"message": "Element $ITEMNAME$ przeniesiono do organizacji $ORGNAME$",
"message": "Element $ITEMNAME$ został przeniesiony do organizacji $ORGNAME$",
"placeholders": {
"itemname": {
"content": "$1",
@ -657,7 +657,7 @@
}
},
"moveToOrgDesc": {
"message": "Wybierz organizację, do której chcesz przenieść ten element. Przeniesienie do organizacji przenosi uprawnienia właścicielskie względem elementu na tę organizację. Po przeniesieniu elementu utracisz bezpośrednie uprawnienia właścicielskie."
"message": "Wybierz organizację, do której chcesz przenieść ten element. Ta czynność spowoduje utratę własności elementu i przenosi te uprawnienia do organizacji."
},
"learnMore": {
"message": "Dowiedz się więcej"
@ -918,22 +918,22 @@
"message": "Obecnie jest to funkcja eksperymentalna. Używaj na własne ryzyko."
},
"defaultAutoFillOnPageLoad": {
"message": "Domyślne ustawienia autouzupełniania dla danych logowania"
"message": "Domyślne ustawienie autouzupełniania"
},
"defaultAutoFillOnPageLoadDesc": {
"message": "Gdy włączysz opcję autouzupełniania po wczytaniu strony, możesz włączyć lub wyłączyć tę funkcję dla poszczególnych danych logowania. Jest to domyślne ustawienie dla danych logowania, które nie zostały skonfigurowane oddzielnie."
"message": "Po włączeniu autouzupełnianiu po załadowaniu strony, możesz włączyć lub wyłączyć tę funkcję dla poszczególnych wpisów."
},
"itemAutoFillOnPageLoad": {
"message": "Autouzupełnianie po wczytaniu strony (jeśli włączone w Opcjach)"
"message": "Automatycznie uzupełniaj po załadowaniu strony (jeśli włączono w opcjach)"
},
"autoFillOnPageLoadUseDefault": {
"message": "Użyj ustawienia domyślnego"
"message": "Użyj domyślnego ustawienia"
},
"autoFillOnPageLoadYes": {
"message": "Automatycznie uzupełniaj po wczytaniu strony"
"message": "Automatycznie uzupełniaj po załadowaniu strony"
},
"autoFillOnPageLoadNo": {
"message": "Nie uzupełniaj automatycznie po wczytaniu strony"
"message": "Nie uzupełniaj automatycznie po załadowaniu strony"
},
"commandOpenPopup": {
"message": "Otwórz sejf w oknie"
@ -990,10 +990,10 @@
"message": "Wyświetlaj rozpoznawalną ikonę serwisu obok danych logowania w sejfie."
},
"disableBadgeCounter": {
"message": "Wyłącz licznik danych logowania"
"message": "Wyłącz licznik logowań"
},
"disableBadgeCounterDesc": {
"message": "Licznik informuje, ile danych logowania zawiera sejf dla obecnej strony."
"message": "Licznik informuje, ile razy zalogowałeś się na obecnej stronie w sejfie."
},
"cardholderName": {
"message": "Właściciel karty"
@ -1694,7 +1694,7 @@
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendLinuxChromiumFileWarning": {
"message": "Aby wybrać plik, otwórz rozszerzenie w pasku bocznym (jeśli to możliwe) albo w nowym oknie po kliknięciu tego banera."
"message": "Aby wybrać plik, otwórz rozszerzenie na pasku bocznym (jeśli to możliwe) lub w nowym oknie."
},
"sendFirefoxFileWarning": {
"message": "Aby wybrać plik za pomocą przeglądarki Firefox, otwórz rozszerzenie w nowym oknie."
@ -1748,9 +1748,9 @@
"message": "Ta operacja jest chroniona. Aby kontynuować, wpisz ponownie hasło główne."
},
"emailVerificationRequired": {
"message": "Wymagana weryfikacja adresu e-mail"
"message": "Weryfikacja adresu e-mail jest wymagana"
},
"emailVerificationRequiredDesc": {
"message": "Musisz zweryfikować swój adres e-mail, aby korzystać z tej funkcji. Swój adres e-mail możesz zweryfikować w sejfie internetowym."
"message": "Musisz zweryfikować adres e-mail, aby korzystać z tej funkcji. Adres możesz zweryfikować w sejfie internetowym."
}
}

View File

@ -32,7 +32,7 @@
"message": "Submit"
},
"emailAddress": {
"message": "Email Address"
"message": "වි-තැපැල් ලිපිනය"
},
"masterPass": {
"message": "Master Password"
@ -56,7 +56,7 @@
"message": "My Vault"
},
"tools": {
"message": "Tools"
"message": "මෙවලම්"
},
"settings": {
"message": "සැකසුම්"
@ -65,25 +65,25 @@
"message": "Current Tab"
},
"copyPassword": {
"message": "Copy Password"
"message": "මුරපදය පිටපත් කරන්න"
},
"copyNote": {
"message": "Copy Note"
"message": "සටහන පිටපත් කරන්න"
},
"copyUri": {
"message": "Copy URI"
},
"copyUsername": {
"message": "Copy Username"
"message": "පරිශීලකනාමය පිටපත් කරන්න"
},
"copyNumber": {
"message": "Copy Number"
"message": "අංකය පිටපත් කරන්න"
},
"copySecurityCode": {
"message": "Copy Security Code"
"message": "ආරක්ෂක කේතය පිටපත් කරන්න"
},
"autoFill": {
"message": "Auto-fill"
"message": "ස්වයං-පිරවීම"
},
"generatePasswordCopied": {
"message": "Generate Password (copied)"
@ -101,7 +101,7 @@
"message": "There are no logins available to auto-fill for the current browser tab."
},
"addLogin": {
"message": "Add a Login"
"message": "පිවිසුමක් එකතු කරන්න"
},
"addItem": {
"message": "Add Item"
@ -116,13 +116,13 @@
"message": "Get master password hint"
},
"continue": {
"message": "Continue"
"message": "ඉදිරියට"
},
"verificationCode": {
"message": "Verification Code"
},
"account": {
"message": "Account"
"message": "ගිණුම"
},
"changeMasterPassword": {
"message": "Change Master Password"
@ -139,25 +139,25 @@
"message": "Two-step Login"
},
"logOut": {
"message": "Log Out"
"message": "නික්මෙන්න"
},
"about": {
"message": "About"
"message": "පිලිබඳව"
},
"version": {
"message": "Version"
"message": "අනුවාදය"
},
"save": {
"message": "Save"
"message": "සුරකින්න"
},
"move": {
"message": "Move"
},
"addFolder": {
"message": "Add Folder"
"message": "බහාලුම එකතු කරන්න"
},
"name": {
"message": "Name"
"message": "නම"
},
"editFolder": {
"message": "Edit Folder"
@ -166,7 +166,7 @@
"message": "Delete Folder"
},
"folders": {
"message": "Folders"
"message": "බහාලුම්"
},
"noFolders": {
"message": "There are no folders to list."
@ -240,7 +240,7 @@
"message": "Search vault"
},
"edit": {
"message": "Edit"
"message": "සංස්කරණය"
},
"view": {
"message": "View"
@ -252,28 +252,28 @@
"message": "Item Information"
},
"username": {
"message": "Username"
"message": "පරිශීලක නාමය"
},
"password": {
"message": "Password"
"message": "මුරපදය"
},
"passphrase": {
"message": "Passphrase"
},
"favorite": {
"message": "Favorite"
"message": "ප්‍රියතමය"
},
"notes": {
"message": "Notes"
"message": "සටහන්"
},
"note": {
"message": "Note"
"message": "සටහන"
},
"editItem": {
"message": "Edit Item"
},
"folder": {
"message": "Folder"
"message": "බහාලුම"
},
"deleteItem": {
"message": "Delete Item"
@ -282,10 +282,10 @@
"message": "View Item"
},
"launch": {
"message": "Launch"
"message": "දියත්කරන්න"
},
"website": {
"message": "Website"
"message": "වියමන අඩවිය"
},
"toggleVisibility": {
"message": "Toggle Visibility"
@ -294,7 +294,7 @@
"message": "Manage"
},
"other": {
"message": "Other"
"message": "වෙනත්"
},
"rateExtension": {
"message": "Rate the Extension"
@ -312,7 +312,7 @@
"message": "Your vault is locked. Verify your master password to continue."
},
"unlock": {
"message": "Unlock"
"message": "අගුලුහරින්න"
},
"loggedInAsOn": {
"message": "Logged in as $EMAIL$ on $HOSTNAME$.",
@ -334,40 +334,40 @@
"message": "Vault Timeout"
},
"lockNow": {
"message": "Lock Now"
"message": "දැන් අගුලුදමන්න"
},
"immediately": {
"message": "Immediately"
},
"tenSeconds": {
"message": "10 seconds"
"message": "තත්පර 10"
},
"twentySeconds": {
"message": "20 seconds"
"message": "තත්පර 20"
},
"thirtySeconds": {
"message": "30 seconds"
"message": "තත්පර 30"
},
"oneMinute": {
"message": "1 minute"
"message": "විනාඩි 1"
},
"twoMinutes": {
"message": "2 minutes"
"message": "විනාඩි 2"
},
"fiveMinutes": {
"message": "5 minutes"
"message": "විනාඩි 5"
},
"fifteenMinutes": {
"message": "15 minutes"
"message": "විනාඩි 15"
},
"thirtyMinutes": {
"message": "30 minutes"
"message": "විනාඩි 30"
},
"oneHour": {
"message": "1 hour"
"message": "පැය 1"
},
"fourHours": {
"message": "4 hours"
"message": "පැය 4"
},
"onLocked": {
"message": "On System Lock"
@ -379,7 +379,7 @@
"message": "Never"
},
"security": {
"message": "Security"
"message": "ආරක්ෂාව"
},
"errorOccurred": {
"message": "An error has occurred"
@ -513,7 +513,7 @@
"message": "Are you sure you want to overwrite the current password?"
},
"searchFolder": {
"message": "Search folder"
"message": "බහාලුම සොයන්න"
},
"searchCollection": {
"message": "Search collection"
@ -555,7 +555,7 @@
"message": "Should Bitwarden remember this password for you?"
},
"notificationAddSave": {
"message": "Yes, Save Now"
"message": "ඔව්, දැන් සුරකින්න"
},
"notificationNeverSave": {
"message": "Never for this website"
@ -570,7 +570,7 @@
"message": "Do you want to update this password in Bitwarden?"
},
"notificationChangeSave": {
"message": "Yes, Update Now"
"message": "ඔව්, දැන් යාවත්කාල කරන්න"
},
"disableContextMenuItem": {
"message": "Disable Context Menu Options"
@ -586,7 +586,7 @@
"message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill."
},
"theme": {
"message": "Theme"
"message": "තේමාව"
},
"themeDesc": {
"message": "Change the application's color theme."
@ -610,7 +610,7 @@
"message": "File Format"
},
"warning": {
"message": "WARNING",
"message": "අවවාදයයි",
"description": "WARNING (should stay in capitalized letters if the language permits)"
},
"confirmVaultExport": {
@ -693,7 +693,7 @@
"message": "The attachment has been saved."
},
"file": {
"message": "File"
"message": "ගොනුව"
},
"selectFile": {
"message": "Select a file."
@ -1014,40 +1014,40 @@
"message": "Expiration"
},
"january": {
"message": "January"
"message": "දුරුතු"
},
"february": {
"message": "February"
"message": "නවම්"
},
"march": {
"message": "March"
"message": "මැදින්"
},
"april": {
"message": "April"
"message": "බක්"
},
"may": {
"message": "May"
"message": "වෙසක්"
},
"june": {
"message": "June"
"message": "පොසොන්"
},
"july": {
"message": "July"
"message": "ඇසළ"
},
"august": {
"message": "August"
"message": "නිකිණි"
},
"september": {
"message": "September"
"message": "බිනර"
},
"october": {
"message": "October"
"message": "වප්"
},
"november": {
"message": "November"
"message": "ඉල්"
},
"december": {
"message": "December"
"message": "උඳුවප්"
},
"securityCode": {
"message": "Security Code"

View File

@ -151,7 +151,7 @@
"message": "Shrani"
},
"move": {
"message": "Move"
"message": "Premakni"
},
"addFolder": {
"message": "Dodaj mapo"
@ -513,10 +513,10 @@
"message": "Ali ste prepričani, da želite prepisati vaše trenutno geslo?"
},
"searchFolder": {
"message": "Search folder"
"message": "Preišči mapo"
},
"searchCollection": {
"message": "Search collection"
"message": "Preišči zbirko"
},
"searchType": {
"message": "Search type"
@ -870,10 +870,10 @@
"message": "Use any WebAuthn enabled security key to access your account."
},
"emailTitle": {
"message": "Email"
"message": "E-pošta"
},
"emailDesc": {
"message": "Verification codes will be emailed to you."
"message": "Potrditvene kode vam bodo posredovane po e-pošti."
},
"selfHostedEnvironment": {
"message": "Self-hosted Environment"
@ -888,10 +888,10 @@
"message": "For advanced users. You can specify the base URL of each service independently."
},
"baseUrl": {
"message": "Server URL"
"message": "URL naslov strežnika"
},
"apiUrl": {
"message": "API Server URL"
"message": "URL naslov API strežnika"
},
"webVaultUrl": {
"message": "Web Vault Server URL"
@ -927,7 +927,7 @@
"message": "Auto-fill on Page Load (if enabled in Options)"
},
"autoFillOnPageLoadUseDefault": {
"message": "Use default setting"
"message": "Uporabi privzete nastavitve"
},
"autoFillOnPageLoadYes": {
"message": "Auto-fill on page load"
@ -969,10 +969,10 @@
"message": "Drag to sort"
},
"cfTypeText": {
"message": "Text"
"message": "Besedilo"
},
"cfTypeHidden": {
"message": "Hidden"
"message": "Skrito"
},
"cfTypeBoolean": {
"message": "Boolean"
@ -1152,28 +1152,28 @@
"message": "Collections"
},
"favorites": {
"message": "Favorites"
"message": "Priljubljeno"
},
"popOutNewWindow": {
"message": "Pop out to a new window"
},
"refresh": {
"message": "Refresh"
"message": "Osveži"
},
"cards": {
"message": "Cards"
"message": "Plačilne kartice"
},
"identities": {
"message": "Identities"
"message": "Identitete"
},
"logins": {
"message": "Logins"
"message": "Prijave"
},
"secureNotes": {
"message": "Secure Notes"
},
"clear": {
"message": "Clear",
"message": "Počisti",
"description": "To clear something out. example: To clear browser history."
},
"checkPassword": {

View File

@ -29,6 +29,8 @@ export default class ContextMenusBackground {
this.contextMenus.onClicked.addListener(async (info: any, tab: any) => {
if (info.menuItemId === 'generate-password') {
await this.generatePasswordToClipboard();
} else if (info.menuItemId === 'copy-identifier') {
await this.getClickedElement();
} else if (info.parentMenuItemId === 'autofill' ||
info.parentMenuItemId === 'copy-username' ||
info.parentMenuItemId === 'copy-password' ||
@ -45,6 +47,15 @@ export default class ContextMenusBackground {
this.passwordGenerationService.addHistory(password);
}
private async getClickedElement() {
const tab = await BrowserApi.getTabFromCurrentWindow();
if (tab == null) {
return;
}
BrowserApi.tabSendMessageData(tab, 'getClickedElement');
}
private async cipherAction(info: any) {
const id = info.menuItemId.split('_')[1];
if (id === 'noop') {

View File

@ -1,10 +1,8 @@
import { ConstantsService } from 'jslib-common/services/constants.service';
import {
StorageService,
VaultTimeoutService,
} from 'jslib-common/abstractions';
import { NotificationsService } from 'jslib-common/abstractions/notifications.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
import { ConstantsService } from 'jslib-common/services/constants.service';
const IdleInterval = 60 * 5; // 5 minutes

View File

@ -1,69 +1,65 @@
import { CipherType } from 'jslib-common/enums';
import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType';
import { CipherType } from 'jslib-common/enums/cipherType';
import {
ApiService,
AppIdService,
AuditService,
AuthService,
CipherService,
CollectionService,
ConstantsService,
ContainerService,
EnvironmentService,
FolderService,
PasswordGenerationService,
SettingsService,
StateService,
SyncService,
TokenService,
TotpService,
UserService,
} from 'jslib-common/services';
import { ApiService } from 'jslib-common/services/api.service';
import { AppIdService } from 'jslib-common/services/appId.service';
import { AuditService } from 'jslib-common/services/audit.service';
import { AuthService } from 'jslib-common/services/auth.service';
import { CipherService } from 'jslib-common/services/cipher.service';
import { CollectionService } from 'jslib-common/services/collection.service';
import { ConsoleLogService } from 'jslib-common/services/consoleLog.service';
import { ConstantsService } from 'jslib-common/services/constants.service';
import { ContainerService } from 'jslib-common/services/container.service';
import { EnvironmentService } from 'jslib-common/services/environment.service';
import { EventService } from 'jslib-common/services/event.service';
import { ExportService } from 'jslib-common/services/export.service';
import { FileUploadService } from 'jslib-common/services/fileUpload.service';
import { FolderService } from 'jslib-common/services/folder.service';
import { NotificationsService } from 'jslib-common/services/notifications.service';
import { PasswordGenerationService } from 'jslib-common/services/passwordGeneration.service';
import { PolicyService } from 'jslib-common/services/policy.service';
import { SearchService } from 'jslib-common/services/search.service';
import { SendService } from 'jslib-common/services/send.service';
import { SettingsService } from 'jslib-common/services/settings.service';
import { StateService } from 'jslib-common/services/state.service';
import { SyncService } from 'jslib-common/services/sync.service';
import { SystemService } from 'jslib-common/services/system.service';
import { TokenService } from 'jslib-common/services/token.service';
import { TotpService } from 'jslib-common/services/totp.service';
import { UserService } from 'jslib-common/services/user.service';
import { WebCryptoFunctionService } from 'jslib-common/services/webCryptoFunction.service';
import {
ApiService as ApiServiceAbstraction,
AppIdService as AppIdServiceAbstraction,
AuditService as AuditServiceAbstraction,
AuthService as AuthServiceAbstraction,
CipherService as CipherServiceAbstraction,
CollectionService as CollectionServiceAbstraction,
CryptoService as CryptoServiceAbstraction,
EnvironmentService as EnvironmentServiceAbstraction,
FolderService as FolderServiceAbstraction,
I18nService as I18nServiceAbstraction,
LogService as LogServiceAbstraction,
MessagingService as MessagingServiceAbstraction,
PasswordGenerationService as PasswordGenerationServiceAbstraction,
PlatformUtilsService as PlatformUtilsServiceAbstraction,
SettingsService as SettingsServiceAbstraction,
StateService as StateServiceAbstraction,
StorageService as StorageServiceAbstraction,
SyncService as SyncServiceAbstraction,
TokenService as TokenServiceAbstraction,
TotpService as TotpServiceAbstraction,
UserService as UserServiceAbstraction,
VaultTimeoutService as VaultTimeoutServiceAbstraction,
} from 'jslib-common/abstractions';
import { ApiService as ApiServiceAbstraction } from 'jslib-common/abstractions/api.service';
import { AppIdService as AppIdServiceAbstraction } from 'jslib-common/abstractions/appId.service';
import { AuditService as AuditServiceAbstraction } from 'jslib-common/abstractions/audit.service';
import { AuthService as AuthServiceAbstraction } from 'jslib-common/abstractions/auth.service';
import { CipherService as CipherServiceAbstraction } from 'jslib-common/abstractions/cipher.service';
import { CollectionService as CollectionServiceAbstraction } from 'jslib-common/abstractions/collection.service';
import { CryptoService as CryptoServiceAbstraction } from 'jslib-common/abstractions/crypto.service';
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from 'jslib-common/abstractions/cryptoFunction.service';
import { EnvironmentService as EnvironmentServiceAbstraction } from 'jslib-common/abstractions/environment.service';
import { EventService as EventServiceAbstraction } from 'jslib-common/abstractions/event.service';
import { ExportService as ExportServiceAbstraction } from 'jslib-common/abstractions/export.service';
import { FileUploadService as FileUploadServiceAbstraction } from 'jslib-common/abstractions/fileUpload.service';
import { FolderService as FolderServiceAbstraction } from 'jslib-common/abstractions/folder.service';
import { I18nService as I18nServiceAbstraction } from 'jslib-common/abstractions/i18n.service';
import { LogService as LogServiceAbstraction } from 'jslib-common/abstractions/log.service';
import { MessagingService as MessagingServiceAbstraction } from 'jslib-common/abstractions/messaging.service';
import { NotificationsService as NotificationsServiceAbstraction } from 'jslib-common/abstractions/notifications.service';
import { PasswordGenerationService as PasswordGenerationServiceAbstraction } from 'jslib-common/abstractions/passwordGeneration.service';
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService as PolicyServiceAbstraction } from 'jslib-common/abstractions/policy.service';
import { SearchService as SearchServiceAbstraction } from 'jslib-common/abstractions/search.service';
import { SendService as SendServiceAbstraction } from 'jslib-common/abstractions/send.service';
import { SettingsService as SettingsServiceAbstraction } from 'jslib-common/abstractions/settings.service';
import { StateService as StateServiceAbstraction } from 'jslib-common/abstractions/state.service';
import { StorageService as StorageServiceAbstraction } from 'jslib-common/abstractions/storage.service';
import { SyncService as SyncServiceAbstraction } from 'jslib-common/abstractions/sync.service';
import { SystemService as SystemServiceAbstraction } from 'jslib-common/abstractions/system.service';
import { TokenService as TokenServiceAbstraction } from 'jslib-common/abstractions/token.service';
import { TotpService as TotpServiceAbstraction } from 'jslib-common/abstractions/totp.service';
import { UserService as UserServiceAbstraction } from 'jslib-common/abstractions/user.service';
import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from 'jslib-common/abstractions/vaultTimeout.service';
import { AutofillService as AutofillServiceAbstraction } from '../services/abstractions/autofill.service';
import { Utils } from 'jslib-common/misc/utils';
@ -197,7 +193,7 @@ export default class MainBackground {
this.policyService = new PolicyService(this.userService, this.storageService);
this.vaultTimeoutService = new VaultTimeoutService(this.cipherService, this.folderService,
this.collectionService, this.cryptoService, this.platformUtilsService, this.storageService,
this.messagingService, this.searchService, this.userService, this.tokenService,
this.messagingService, this.searchService, this.userService, this.tokenService, this.policyService,
async () => {
if (this.notificationsService != null) {
this.notificationsService.updateConnection(false);
@ -244,7 +240,7 @@ export default class MainBackground {
this.runtimeBackground = new RuntimeBackground(this, this.autofillService, this.cipherService,
this.platformUtilsService as BrowserPlatformUtilsService, this.storageService, this.i18nService,
this.notificationsService, this.systemService, this.vaultTimeoutService,
this.environmentService, this.policyService, this.userService, this.messagingService);
this.environmentService, this.policyService, this.userService, this.messagingService, this.folderService);
this.nativeMessagingBackground = new NativeMessagingBackground(this.storageService, this.cryptoService, this.cryptoFunctionService,
this.vaultTimeoutService, this.runtimeBackground, this.i18nService, this.userService, this.messagingService, this.appIdService,
this.platformUtilsService);
@ -512,6 +508,14 @@ export default class MainBackground {
title: this.i18nService.t('generatePasswordCopied'),
});
await this.contextMenusCreate({
type: 'normal',
id: 'copy-identifier',
parentId: 'root',
contexts: ['all'],
title: this.i18nService.t('copyElementIdentifier'),
});
this.buildingContextMenu = false;
}

View File

@ -10,7 +10,7 @@ import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.serv
import { ConstantsService } from 'jslib-common/services/constants.service';
import { Utils } from 'jslib-common/misc/utils';
import { SymmetricCryptoKey } from 'jslib-common/models/domain';
import { SymmetricCryptoKey } from 'jslib-common/models/domain/symmetricCryptoKey';
import { BrowserApi } from '../browser/browserApi';
import RuntimeBackground from './runtime.background';

View File

@ -1,4 +1,4 @@
import { CipherType } from 'jslib-common/enums';
import { CipherType } from 'jslib-common/enums/cipherType';
import { CipherView } from 'jslib-common/models/view/cipherView';
import { LoginUriView } from 'jslib-common/models/view/loginUriView';
@ -6,6 +6,7 @@ import { LoginView } from 'jslib-common/models/view/loginView';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
import { FolderService } from 'jslib-common/abstractions/folder.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { NotificationsService } from 'jslib-common/abstractions/notifications.service';
@ -24,7 +25,6 @@ import MainBackground from './main.background';
import { Utils } from 'jslib-common/misc/utils';
import { OrganizationUserStatusType } from 'jslib-common/enums/organizationUserStatusType';
import { PolicyType } from 'jslib-common/enums/policyType';
export default class RuntimeBackground {
@ -39,7 +39,8 @@ export default class RuntimeBackground {
private notificationsService: NotificationsService,
private systemService: SystemService, private vaultTimeoutService: VaultTimeoutService,
private environmentService: EnvironmentService, private policyService: PolicyService,
private userService: UserService, private messagingService: MessagingService) {
private userService: UserService, private messagingService: MessagingService,
private folderService: FolderService) {
// onInstalled listener must be wired up before anything else, so we do it in the ctor
chrome.runtime.onInstalled.addListener((details: any) => {
@ -107,7 +108,7 @@ export default class RuntimeBackground {
this.removeTabFromNotificationQueue(sender.tab);
break;
case 'bgAddSave':
await this.saveAddLogin(sender.tab);
await this.saveAddLogin(sender.tab, msg.folder);
break;
case 'bgChangeSave':
await this.saveChangePassword(sender.tab);
@ -195,6 +196,8 @@ export default class RuntimeBackground {
type: 'info',
});
break;
case 'getClickedElementResponse':
this.platformUtilsService.copyToClipboard(msg.identifier, { window: window });
default:
break;
}
@ -216,7 +219,7 @@ export default class RuntimeBackground {
this.pageDetailsToAutoFill = [];
}
private async saveAddLogin(tab: any) {
private async saveAddLogin(tab: any, folderId: string) {
if (await this.vaultTimeoutService.isLocked()) {
return;
}
@ -247,6 +250,13 @@ export default class RuntimeBackground {
model.type = CipherType.Login;
model.login = loginModel;
if (!Utils.isNullOrWhitespace(folderId)) {
const folders = await this.folderService.getAllDecrypted();
if (folders.some(x => x.id === folderId)) {
model.folderId = folderId;
}
}
const cipher = await this.cipherService.encrypt(model);
await this.cipherService.saveWithServer(cipher);
}
@ -450,24 +460,14 @@ export default class RuntimeBackground {
notificationChangeSave: this.i18nService.t('notificationChangeSave'),
notificationChangeDesc: this.i18nService.t('notificationChangeDesc'),
};
} else if (responseCommand === 'notificationBarGetFoldersList') {
responseData.folders = await this.folderService.getAllDecrypted();
}
await BrowserApi.tabSendMessageData(tab, responseCommand, responseData);
}
private async allowPersonalOwnership(): Promise<boolean> {
const personalOwnershipPolicies = await this.policyService.getAll(PolicyType.PersonalOwnership);
if (personalOwnershipPolicies != null) {
for (const policy of personalOwnershipPolicies) {
if (policy.enabled) {
const org = await this.userService.getOrganization(policy.organizationId);
if (org != null && org.enabled && org.usePolicies && !org.canManagePolicies
&& org.status === OrganizationUserStatusType.Confirmed) {
return false;
}
}
}
}
return true;
return !await this.policyService.policyAppliesToUser(PolicyType.PersonalOwnership);
}
}

View File

@ -2,7 +2,7 @@ import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
import { UriMatchType } from 'jslib-common/enums';
import { UriMatchType } from 'jslib-common/enums/uriMatchType';
export default class WebRequestBackground {
private pendingAuthRequests: any[] = [];

View File

@ -835,12 +835,14 @@
document.elementForOPID = getElementByOpId;
// normalize the event since firefox handles events differently than others
// normalize the event based on API support
function normalizeEvent(el, eventName) {
var ev;
if (isFirefox) {
ev = document.createEvent('KeyboardEvent');
ev.initKeyEvent(eventName, true, false, null, false, false, false, false, 0, 0);
if ('KeyboardEvent' in window) {
ev = new window.KeyboardEvent(eventName, {
bubbles: true,
cancelable: false,
});
}
else {
ev = el.ownerDocument.createEvent('Events');

View File

@ -0,0 +1,45 @@
const inputTags = ['input', 'textarea', 'select'];
const attributes = ['id', 'name', 'label-aria', 'placeholder'];
let clickedEl: HTMLElement = null;
// Find the best attribute to be used as the Name for an element in a custom field.
function getClickedElementIdentifier() {
if (clickedEl == null) {
return 'Unable to identify clicked element.';
}
if (!inputTags.includes(clickedEl.nodeName.toLowerCase())) {
return 'Invalid element type.';
}
for (const attr of attributes) {
const attributeValue = clickedEl.getAttribute(attr);
const selector = '[' + attr + '="' + attributeValue + '"]';
if (!isNullOrEmpty(attributeValue) && document.querySelectorAll(selector)?.length === 1) {
return attributeValue;
}
}
return 'No unique identifier found.';
}
function isNullOrEmpty(s: string) {
return s == null || s === '';
}
// We only have access to the element that's been clicked when the context menu is first opened.
// Remember it for use later.
document.addEventListener('contextmenu', event => {
clickedEl = event.target as HTMLElement;
});
// Runs when the 'Copy Custom Field Name' context menu item is actually clicked.
chrome.runtime.onMessage.addListener(event => {
if (event.command === 'getClickedElement') {
const identifier = getClickedElementIdentifier();
chrome.runtime.sendMessage({
command: 'getClickedElementResponse',
sender: 'contextMenuHandler',
identifier: identifier,
});
}
});

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "__MSG_extName__",
"short_name": "__MSG_appName__",
"version": "1.51.1",
"version": "1.52.1",
"description": "__MSG_extDesc__",
"default_locale": "en",
"author": "Bitwarden Inc.",
@ -20,7 +20,8 @@
"js": [
"content/autofill.js",
"content/autofiller.js",
"content/notificationBar.js"
"content/notificationBar.js",
"content/contextMenuHandler.js"
],
"matches": [
"http://*/*",

View File

@ -23,6 +23,7 @@
<div class="add-text"></div>
<div class="add-buttons">
<button class="never-save link"></button>
<select class="select-folder"></select>
<button class="add-save"></button>
</div>
</div>

View File

@ -17,7 +17,6 @@ document.addEventListener('DOMContentLoaded', () => {
// delay 50ms so that we get proper body dimensions
setTimeout(load, 50);
function load() {
var closeButton = document.getElementById('close-button'),
@ -34,10 +33,12 @@ document.addEventListener('DOMContentLoaded', () => {
if (bodyRect.width < 768) {
document.querySelector('#template-add .add-save').textContent = i18n.yes;
document.querySelector('#template-add .never-save').textContent = i18n.never;
document.querySelector('#template-add .select-folder').style.display = 'none';
document.querySelector('#template-change .change-save').textContent = i18n.yes;
} else {
document.querySelector('#template-add .add-save').textContent = i18n.notificationAddSave;
document.querySelector('#template-add .never-save').textContent = i18n.notificationNeverSave;
document.querySelector('#template-add .select-folder').style.display = 'initial';
document.querySelector('#template-change .change-save').textContent = i18n.notificationChangeSave;
}
@ -52,8 +53,10 @@ document.addEventListener('DOMContentLoaded', () => {
addButton.addEventListener('click', (e) => {
e.preventDefault();
const folderId = document.querySelector('#template-add-clone .select-folder').value;
sendPlatformMessage({
command: 'bgAddSave'
command: 'bgAddSave',
folder: folderId,
});
});
@ -63,6 +66,17 @@ document.addEventListener('DOMContentLoaded', () => {
command: 'bgNeverSave'
});
});
const responseFoldersCommand = 'notificationBarGetFoldersList';
chrome.runtime.onMessage.addListener((msg) => {
if (msg.command === responseFoldersCommand && msg.data) {
fillSelectorWithFolders(msg.data.folders);
}
});
sendPlatformMessage({
command: 'bgGetDataForTab',
responseCommand: responseFoldersCommand
});
} else if (getQueryVariable('change')) {
setContent(document.getElementById('template-change'));
var changeButton = document.querySelector('#template-change-clone .change-save');
@ -120,4 +134,13 @@ document.addEventListener('DOMContentLoaded', () => {
function sendPlatformMessage(msg) {
chrome.runtime.sendMessage(msg);
}
function fillSelectorWithFolders(folders) {
const select = document.querySelector('#template-add-clone .select-folder');
select.appendChild(new Option(chrome.i18n.getMessage('selectFolder'), null, true));
folders.forEach((folder) => {
//Select "No Folder" (id=null) folder by default
select.appendChild(new Option(folder.name, folder.id || '', false));
});
}
});

View File

@ -101,3 +101,4 @@ body[class*='lang-en'] .add-buttons {
display: none;
}
}

View File

@ -1,4 +1,4 @@
<form #form class="modal-content" (ngSubmit)="submit()">
<form #form (ngSubmit)="submit()">
<header>
<div class="left">
<a routerLink="/home">{{'close' | i18n}}</a>

View File

@ -1,6 +1,8 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { ConstantsService } from 'jslib-common/services/constants.service';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
@ -20,6 +22,8 @@ import Swal from 'sweetalert2';
templateUrl: 'lock.component.html',
})
export class LockComponent extends BaseLockComponent {
private isInitialLockScreen: boolean;
constructor(router: Router, i18nService: I18nService,
platformUtilsService: PlatformUtilsService, messagingService: MessagingService,
userService: UserService, cryptoService: CryptoService,
@ -29,12 +33,21 @@ export class LockComponent extends BaseLockComponent {
super(router, i18nService, platformUtilsService, messagingService, userService, cryptoService,
storageService, vaultTimeoutService, environmentService, stateService, apiService);
this.successRoute = '/tabs/current';
this.isInitialLockScreen = (window as any).previousPopupUrl == null;
}
async ngOnInit() {
await super.ngOnInit();
window.setTimeout(() => {
const disableAutoBiometricsPrompt = await this.storageService.get<boolean>(
ConstantsService.disableAutoBiometricsPromptKey) ?? true;
window.setTimeout(async () => {
document.getElementById(this.pinLock ? 'pin' : 'masterPassword').focus();
if (this.biometricLock && !disableAutoBiometricsPrompt && this.isInitialLockScreen) {
if (await this.vaultTimeoutService.isLocked()) {
await this.unlockBiometric();
}
}
}, 100);
}

View File

@ -10,6 +10,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
import { StateService } from 'jslib-common/abstractions/state.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { SyncService } from 'jslib-common/abstractions/sync.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { LoginComponent as BaseLoginComponent } from 'jslib-angular/components/login.component';
@ -23,10 +24,14 @@ export class LoginComponent extends BaseLoginComponent {
protected stateService: StateService, protected environmentService: EnvironmentService,
protected passwordGenerationService: PasswordGenerationService,
protected cryptoFunctionService: CryptoFunctionService, storageService: StorageService,
syncService: SyncService) {
syncService: SyncService, private userService: UserService) {
super(authService, router, platformUtilsService, i18nService, stateService, environmentService, passwordGenerationService, cryptoFunctionService, storageService);
super.onSuccessfulLogin = () => {
return syncService.fullSync(true);
super.onSuccessfulLogin = async () => {
await syncService.fullSync(true).then(async () => {
if (await this.userService.getForcePasswordReset()) {
this.router.navigate(['update-temp-password']);
}
});
};
super.successRoute = '/tabs/vault';
}

View File

@ -20,22 +20,11 @@
<div *ngIf="!syncLoading">
<div class="box">
<app-callout type="tip">{{'ssoCompleteRegistration' | i18n}}</app-callout>
<app-callout type="info" *ngIf="enforcedPolicyOptions">
{{'masterPasswordPolicyInEffect' | i18n}}
<ul>
<li *ngIf="enforcedPolicyOptions?.minComplexity > 0">
{{'policyInEffectMinComplexity' | i18n : getPasswordScoreAlertDisplay()}}
</li>
<li *ngIf="enforcedPolicyOptions?.minLength > 0">
{{'policyInEffectMinLength' | i18n : enforcedPolicyOptions?.minLength.toString()}}
</li>
<li *ngIf="enforcedPolicyOptions?.requireUpper">{{'policyInEffectUppercase' | i18n}}</li>
<li *ngIf="enforcedPolicyOptions?.requireLower">{{'policyInEffectLowercase' | i18n}}</li>
<li *ngIf="enforcedPolicyOptions?.requireNumbers">{{'policyInEffectNumbers' | i18n}}</li>
<li *ngIf="enforcedPolicyOptions?.requireSpecial">
{{'policyInEffectSpecial' | i18n : '!@#$%^&*'}}
</li>
</ul>
<app-callout type="warning" title="{{'resetPasswordPolicyAutoEnroll' | i18n}}"
*ngIf="resetPasswordAutoEnroll">
{{'resetPasswordAutoEnrollInviteWarning' | i18n}}
</app-callout>
<app-callout type="info" [enforcedPolicyOptions]="enforcedPolicyOptions" *ngIf="enforcedPolicyOptions">
</app-callout>
</div>
<div class="box">

View File

@ -31,6 +31,13 @@ export class SetPasswordComponent extends BaseSetPasswordComponent {
syncService: SyncService, route: ActivatedRoute) {
super(i18nService, cryptoService, messagingService, userService, passwordGenerationService,
platformUtilsService, policyService, router, apiService, syncService, route);
super.onSuccessfulChangePassword = async () => {
if (await this.userService.getForcePasswordReset()) {
this.router.navigate(['update-temp-password']);
} else {
this.router.navigate([this.successRoute]);
}
};
}
get masterPasswordScoreWidth() {

View File

@ -15,6 +15,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
import { StateService } from 'jslib-common/abstractions/state.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { SyncService } from 'jslib-common/abstractions/sync.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { SsoComponent as BaseSsoComponent } from 'jslib-angular/components/sso.component';
import { BrowserApi } from '../../browser/browserApi';
@ -29,7 +30,7 @@ export class SsoComponent extends BaseSsoComponent {
storageService: StorageService, stateService: StateService,
platformUtilsService: PlatformUtilsService, apiService: ApiService,
cryptoFunctionService: CryptoFunctionService, passwordGenerationService: PasswordGenerationService,
syncService: SyncService, environmentService: EnvironmentService) {
syncService: SyncService, environmentService: EnvironmentService, private userService: UserService) {
super(authService, router, i18nService, route, storageService, stateService, platformUtilsService,
apiService, cryptoFunctionService, environmentService, passwordGenerationService);
@ -44,5 +45,13 @@ export class SsoComponent extends BaseSsoComponent {
const thisWindow = window.open('', '_self');
thisWindow.close();
};
super.onSuccessfulLoginNavigate = async () => {
if (await this.userService.getForcePasswordReset()) {
this.router.navigate(['update-temp-password']);
} else {
this.router.navigate([this.successRoute]);
}
};
}
}

View File

@ -60,7 +60,7 @@
</div>
</ng-container>
<ng-container *ngIf="selectedProviderType === providerType.WebAuthn && !webAuthnNewTab">
<div id="web-authn-frame"><iframe id="webauthn_iframe"></iframe></div>
<div id="web-authn-frame"><iframe id="webauthn_iframe" [allow]="webAuthnAllow"></iframe></div>
<div class="box">
<div class="box-content">
<div class="box-content-row box-content-row-checkbox" appBoxRow>

View File

@ -20,6 +20,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
import { StateService } from 'jslib-common/abstractions/state.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { SyncService } from 'jslib-common/abstractions/sync.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
@ -44,11 +45,16 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
environmentService: EnvironmentService, private ngZone: NgZone,
private broadcasterService: BroadcasterService, private changeDetectorRef: ChangeDetectorRef,
private popupUtilsService: PopupUtilsService, stateService: StateService,
storageService: StorageService, route: ActivatedRoute, private messagingService: MessagingService) {
storageService: StorageService, route: ActivatedRoute, private messagingService: MessagingService,
private userService: UserService) {
super(authService, router, i18nService, apiService, platformUtilsService, window, environmentService,
stateService, storageService, route);
super.onSuccessfulLogin = () => {
return syncService.fullSync(true);
super.onSuccessfulLogin = async () => {
return syncService.fullSync(true).then(async () => {
if (await this.userService.getForcePasswordReset()) {
this.router.navigate(['update-temp-password']);
}
});
};
super.successRoute = '/tabs/vault';
this.webAuthnNewTab = this.platformUtilsService.isFirefox() || this.platformUtilsService.isSafari();

View File

@ -0,0 +1,86 @@
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
<header>
<div class="left">
<a (click)="logOut()">{{'logOut' | i18n}}</a>
</div>
<div class="center">
<span class="title">{{'updateMasterPassword' | i18n}}</span>
</div>
<div class="right">
<button type="submit" appBlurClick [disabled]="form.loading">
<span [hidden]="form.loading">{{'submit' | i18n}}</span>
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
</button>
</div>
</header>
<content>
<app-callout type="warning" title="{{'updateMasterPassword' | i18n}}">
{{'updateMasterPasswordWarning' | i18n}}
</app-callout>
<app-callout type="info" [enforcedPolicyOptions]="enforcedPolicyOptions" *ngIf="enforcedPolicyOptions">
</app-callout>
<div class="box">
<div class="box-content">
<div class="box-content-row" appBoxRow>
<div class="box-content-row-flex">
<div class="row-main">
<label for="masterPassword">
{{'masterPass' | i18n}}
<strong class="sub-label text-{{masterPasswordScoreStyle.Color}}"
*ngIf="masterPasswordScoreStyle.Text">
{{masterPasswordScoreStyle.Text}}
</strong>
</label>
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}"
name="MasterPassword" class="monospaced" [(ngModel)]="masterPassword" required
appInputVerbatim (input)="updatePasswordStrength()">
</div>
<div class="action-buttons">
<a class="row-btn" href="#" appStopClick appBlurClick
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)">
<i class="fa fa-lg" aria-hidden="true"
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
</a>
</div>
</div>
<div class="progress">
<div class="progress-bar bg-{{masterPasswordScoreStyle.Color}}" role="progressbar"
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"
[ngStyle]="{width: (masterPasswordScoreStyle.Width + '%')}"
attr.aria-valuenow="{{masterPasswordScoreStyle.Width}}"></div>
</div>
</div>
</div>
</div>
<div class="box">
<div class="box-content">
<div class="box-content-row box-content-row-flex" appBoxRow>
<div class="row-main">
<label for="masterPasswordRetype">{{'reTypeMasterPass' | i18n}}</label>
<input id="masterPasswordRetype" type="{{showPassword ? 'text' : 'password'}}"
name="MasterPasswordRetype" class="monospaced" [(ngModel)]="masterPasswordRetype" required
appInputVerbatim>
</div>
<div class="action-buttons">
<a class="row-btn" href="#" appStopClick appBlurClick
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)">
<i class="fa fa-lg" aria-hidden="true"
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
</a>
</div>
</div>
</div>
</div>
<div class="box">
<div class="box-content">
<div class="box-content-row" appBoxRow>
<label for="hint">{{'masterPassHint' | i18n}}</label>
<input id="hint" type="text" name="Hint" [(ngModel)]="hint">
</div>
</div>
<div class="box-footer">
{{'masterPassHintDesc' | i18n}}
</div>
</div>
</content>
</form>

View File

@ -0,0 +1,62 @@
import { Component } from '@angular/core';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { UpdateTempPasswordComponent as BaseUpdateTempPasswordComponent } from 'jslib-angular/components/update-temp-password.component';
interface MasterPasswordScore {
Color: string;
Text: string;
Width: number;
}
@Component({
selector: 'app-update-temp-password',
templateUrl: 'update-temp-password.component.html',
})
export class UpdateTempPasswordComponent extends BaseUpdateTempPasswordComponent {
get masterPasswordScoreStyle(): MasterPasswordScore {
const scoreWidth = this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20;
switch (this.masterPasswordScore) {
case 4:
return {
Color: 'bg-success',
Text: 'strong',
Width: scoreWidth,
};
case 3:
return {
Color: 'bg-primary',
Text: 'good',
Width: scoreWidth,
};
case 2:
return {
Color: 'bg-warning',
Text: 'weak',
Width: scoreWidth,
};
default:
return {
Color: 'bg-danger',
Text: 'weak',
Width: scoreWidth,
};
}
}
constructor(i18nService: I18nService, platformUtilsService: PlatformUtilsService,
passwordGenerationService: PasswordGenerationService, policyService: PolicyService,
cryptoService: CryptoService, userService: UserService,
messagingService: MessagingService, apiService: ApiService) {
super(i18nService, platformUtilsService, passwordGenerationService, policyService, cryptoService,
userService, messagingService, apiService);
}
}

View File

@ -22,6 +22,7 @@ import { SetPasswordComponent } from './accounts/set-password.component';
import { SsoComponent } from './accounts/sso.component';
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
import { TwoFactorComponent } from './accounts/two-factor.component';
import { UpdateTempPasswordComponent } from './accounts/update-temp-password.component';
import { PasswordGeneratorHistoryComponent } from './generator/password-generator-history.component';
import { PasswordGeneratorComponent } from './generator/password-generator.component';
@ -261,6 +262,12 @@ const routes: Routes = [
canActivate: [AuthGuardService],
data: { state: 'edit-send' },
},
{
path: 'update-temp-password',
component: UpdateTempPasswordComponent,
canActivate: [AuthGuardService],
data: { state: 'update-temp-password' },
},
{
path: 'tabs',
component: TabsComponent,

View File

@ -106,8 +106,6 @@ export class AppComponent implements OnInit {
});
} else if (msg.command === 'showDialog') {
await this.showDialog(msg);
} else if (msg.command === 'showPasswordDialog') {
await this.showPasswordDialog(msg);
} else if (msg.command === 'showToast') {
this.ngZone.run(() => {
this.showToast(msg);
@ -251,30 +249,4 @@ export class AppComponent implements OnInit {
confirmed: confirmed.value,
});
}
private async showPasswordDialog(msg: any) {
const platformUtils = this.platformUtilsService as BrowserPlatformUtilsService;
const result = await Swal.fire({
heightAuto: false,
titleText: msg.title,
input: 'password',
text: msg.body,
confirmButtonText: this.i18nService.t('ok'),
showCancelButton: true,
cancelButtonText: this.i18nService.t('cancel'),
inputAttributes: {
autocapitalize: 'off',
autocorrect: 'off',
},
inputValidator: async (value: string): Promise<any> => {
if (await platformUtils.resolvePasswordDialogPromise(msg.dialogId, false, value)) {
return false;
}
return this.i18nService.t('invalidMasterPassword');
},
});
platformUtils.resolvePasswordDialogPromise(msg.dialogId, true, null);
}
}

View File

@ -1,3 +1,4 @@
import { A11yModule } from '@angular/cdk/a11y';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { ScrollingModule } from '@angular/cdk/scrolling';
import { ToasterModule } from 'angular2-toaster';
@ -20,6 +21,7 @@ import { SetPasswordComponent } from './accounts/set-password.component';
import { SsoComponent } from './accounts/sso.component';
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
import { TwoFactorComponent } from './accounts/two-factor.component';
import { UpdateTempPasswordComponent } from './accounts/update-temp-password.component';
import { PasswordGeneratorHistoryComponent } from './generator/password-generator-history.component';
import { PasswordGeneratorComponent } from './generator/password-generator.component';
@ -36,6 +38,7 @@ import { OptionsComponent } from './settings/options.component';
import { PremiumComponent } from './settings/premium.component';
import { SettingsComponent } from './settings/settings.component';
import { SyncComponent } from './settings/sync.component';
import { VaultTimeoutInputComponent } from './settings/vault-timeout-input.component';
import { AddEditComponent } from './vault/add-edit.component';
import { AttachmentsComponent } from './vault/attachments.component';
@ -57,6 +60,7 @@ import { ApiActionDirective } from 'jslib-angular/directives/api-action.directiv
import { AutofocusDirective } from 'jslib-angular/directives/autofocus.directive';
import { BlurClickDirective } from 'jslib-angular/directives/blur-click.directive';
import { BoxRowDirective } from 'jslib-angular/directives/box-row.directive';
import { CipherListVirtualScroll } from 'jslib-angular/directives/cipherListVirtualScroll.directive';
import { FallbackSrcDirective } from 'jslib-angular/directives/fallback-src.directive';
import { InputVerbatimDirective } from 'jslib-angular/directives/input-verbatim.directive';
import { SelectCopyDirective } from 'jslib-angular/directives/select-copy.directive';
@ -70,8 +74,10 @@ import { SearchCiphersPipe } from 'jslib-angular/pipes/search-ciphers.pipe';
import { ActionButtonsComponent } from './components/action-buttons.component';
import { CipherRowComponent } from './components/cipher-row.component';
import { PasswordRepromptComponent } from './components/password-reprompt.component';
import { PopOutComponent } from './components/pop-out.component';
import { SendListComponent } from './components/send-list.component';
import { SetPinComponent } from './components/set-pin.component';
import { CalloutComponent } from 'jslib-angular/components/callout.component';
import { IconComponent } from 'jslib-angular/components/icon.component';
@ -169,6 +175,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
@NgModule({
imports: [
A11yModule,
AppRoutingModule,
BrowserAnimationsModule,
BrowserModule,
@ -190,6 +197,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
BlurClickDirective,
BoxRowDirective,
CalloutComponent,
CipherListVirtualScroll,
CipherRowComponent,
CiphersComponent,
CollectionsComponent,
@ -224,8 +232,10 @@ registerLocaleData(localeZhTw, 'zh-TW');
SendGroupingsComponent,
SendListComponent,
SendTypeComponent,
SetPasswordComponent,
SettingsComponent,
ShareComponent,
SsoComponent,
StopClickDirective,
StopPropDirective,
SyncComponent,
@ -233,9 +243,11 @@ registerLocaleData(localeZhTw, 'zh-TW');
TrueFalseValueDirective,
TwoFactorOptionsComponent,
TwoFactorComponent,
SsoComponent,
UpdateTempPasswordComponent,
ViewComponent,
SetPasswordComponent,
PasswordRepromptComponent,
SetPinComponent,
VaultTimeoutInputComponent,
],
entryComponents: [],
providers: [

View File

@ -1,5 +1,5 @@
<a (click)="selectCipher(cipher)" (dblclick)="launchCipher(cipher)" href="#" appStopClick
title="{{title}} - {{cipher.name}}" class="box-content-row box-content-row-flex">
title="{{title}} - {{cipher.name}}" class="box-content-row box-content-row-flex virtual-scroll-item">
<div class="row-main">
<app-vault-icon [cipher]="cipher"></app-vault-icon>
<div class="row-main-content">

View File

@ -0,0 +1,38 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true">
<div class="modal-dialog modal-dialog-scrollable" role="document">
<form class="modal-content" #form (ngSubmit)="submit()">
<div class="modal-body">
<div class="box">
<div class="box-header">{{'passwordConfirmation' | i18n}}</div>
<div class="box-content">
<div class="box-content-row box-content-row-flex" appBoxRow>
<div class="row-main">
<label for="masterPassword">{{'masterPass' | i18n}}</label>
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
class="monospaced" [(ngModel)]="masterPassword" required appAutofocus>
</div>
<div class="action-buttons">
<a class="row-btn" href="#" appStopClick appBlurClick role="button"
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()">
<i class="fa fa-lg" aria-hidden="true"
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
</a>
</div>
</div>
</div>
<div class="box-footer">
{{'passwordConfirmationDesc' | i18n}}
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary btn-submit" appBlurClick>
<span>{{'ok' | i18n}}</span>
</button>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
{{'cancel' | i18n}}
</button>
</div>
</form>
</div>
</div>

View File

@ -0,0 +1,8 @@
import { Component } from '@angular/core';
import { PasswordRepromptComponent as BasePasswordRepromptComponent } from 'jslib-angular/components/password-reprompt.component';
@Component({
templateUrl: 'password-reprompt.component.html',
})
export class PasswordRepromptComponent extends BasePasswordRepromptComponent {}

View File

@ -0,0 +1,44 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" cdkTrapFocus cdkTrapFocusAutoCapture>
<div class="modal-dialog modal-dialog-scrollable" role="document">
<form class="modal-content" #form (ngSubmit)="submit()">
<div class="modal-body">
<div>
{{'setYourPinCode' | i18n}}
</div>
<div class="box">
<div class="box-content">
<div class="box-content-row box-content-row-flex" appBoxRow>
<div class="row-main">
<label for="pin">{{'pin' | i18n}}</label>
<input id="pin" type="{{showPin ? 'text' : 'password'}}" name="Pin"
class="monospaced" [(ngModel)]="pin" required appInputVerbatim cdkFocusInitial>
</div>
<div class="action-buttons">
<a class="row-btn" href="#" appStopClick appBlurClick appA11yTitle="{{'toggleVisibility' | i18n}}"
(click)="toggleVisibility()">
<i class="fa fa-lg" aria-hidden="true"
[ngClass]="{'fa-eye': !showPin, 'fa-eye-slash': showPin}"></i>
</a>
</div>
</div>
</div>
</div>
<div class="checkbox">
<label for="masterPasswordOnRestart">
<input type="checkbox" id="masterPasswordOnRestart" name="MasterPasswordOnRestart"
[(ngModel)]="masterPassOnRestart">
<span>{{'lockWithMasterPassOnRestart' | i18n}}</span>
</label>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary btn-submit" appBlurClick>
<span>{{'ok' | i18n}}</span>
</button>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
{{'cancel' | i18n}}
</button>
</div>
</form>
</div>
</div>

View File

@ -0,0 +1,8 @@
import { Component } from '@angular/core';
import { SetPinComponent as BaseSetPinComponent } from 'jslib-angular/components/set-pin.component';
@Component({
templateUrl: 'set-pin.component.html',
})
export class SetPinComponent extends BaseSetPinComponent {}

View File

@ -200,6 +200,13 @@
}
}
&.last:last-child:before {
border-bottom: 1px solid #000000;
@include themify($themes) {
border-bottom-color: themed('boxBorderColor');
}
}
&:after {
content: "";
display: table;

11
src/popup/scss/grid.scss Normal file
View File

@ -0,0 +1,11 @@
.row {
display: flex;
margin: 0 -15px;
width: 100%;
}
.col {
flex-basis: 0;
flex-grow: 1;
padding: 0 15px;
}

View File

@ -339,6 +339,11 @@ app-vault-icon {
}
}
}
.enforced-policy-options ul {
padding-left: 30px;
margin: 0;
}
}
input[type="password"]::-ms-reveal {

351
src/popup/scss/modal.scss Normal file
View File

@ -0,0 +1,351 @@
@import "variables.scss";
$white: white;
$black: black;
$line-height-base: 14px;
$border-radius-lg: $border-radius;
// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss
$grid-breakpoints: ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px ) !default;
$zindex-modal-backdrop: 1040 !default;
$zindex-modal: 1050 !default;
// Padding applied to the modal body
$modal-inner-padding: 10px !default;
$modal-dialog-margin: .5rem !default;
$modal-dialog-margin-y-sm-up: 1.75rem !default;
$modal-title-line-height: $line-height-base !default;
//$modal-content-bg: $background-color-alt !default;
$modal-content-border-color: rgba($black, .2) !default;
$modal-content-border-width: 1px !default;
$modal-content-box-shadow-xs: none;
$modal-content-box-shadow-sm-up: none;
$modal-backdrop-bg: $black !default;
$modal-backdrop-opacity: .5 !default;
$modal-header-border-color: $border-color-dark !default;
$modal-footer-border-color: $modal-header-border-color !default;
$modal-header-border-width: $modal-content-border-width !default;
$modal-footer-border-width: $modal-header-border-width !default;
$modal-header-padding: 12px !default;
$modal-lg: 800px !default;
$modal-md: 500px !default;
$modal-sm: 300px !default;
$modal-transition: transform .3s ease-out !default;
$close-font-size: $font-size-base * 1.5 !default;
$close-font-weight: bold !default;
$close-color: $black !default;
$close-text-shadow: 0 1px 0 $white !default;
// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/mixins/_breakpoints.scss
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints);
@if $min {
@media (min-width: $min) {
@content;
}
}
@else {
@content;
}
}
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
$min: map-get($breakpoints, $name);
@return if($min != 0, $min, null);
}
// Custom Added CSS animations
@keyframes modalshow {
0% {
opacity: 0;
transform: translate(0, -25%);
}
100% {
opacity: 1;
transform: translate(0, 0);
}
}
@keyframes backdropshow {
0% {
opacity: 0;
}
100% {
opacity: $modal-backdrop-opacity;
}
}
// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_modal.scss
// .modal-open - body class for killing the scroll
// .modal - container to scroll within
// .modal-dialog - positioning shell for the actual modal
// .modal-content - actual modal w/ bg and corners and stuff
// Kill the scroll on the body
.modal-open {
overflow: hidden;
}
// Container that the modal scrolls within
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: $zindex-modal;
//display: none;
overflow: hidden;
// Prevent Chrome on Windows from adding a focus outline. For details, see
// https://github.com/twbs/bootstrap/pull/10951.
outline: 0;
// We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a
// gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342
// See also https://github.com/twbs/bootstrap/issues/17695
.modal-open & {
overflow-x: hidden;
overflow-y: auto;
}
}
// Shell div to position the modal with bottom padding
.modal-dialog {
position: relative;
width: auto;
margin: $modal-dialog-margin;
// allow clicks to pass through for custom click handling to close modal
pointer-events: none;
// When fading in the modal, animate it to slide down
.modal.fade & {
//@include transition($modal-transition);
//transform: translate(0, -25%);
animation: modalshow 0.3s ease-in;
}
//.modal.show & {
// transform: translate(0, 0);
//}
transform: translate(0, 0);
}
.modal-dialog-centered {
display: flex;
align-items: center;
min-height: calc(100% - (#{$modal-dialog-margin} * 2));
}
// Actual modal
.modal-content {
position: relative;
display: flex;
flex-direction: column;
width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog`
// counteract the pointer-events: none; in the .modal-dialog
pointer-events: auto;
//background-color: $modal-content-bg;
background-clip: padding-box;
border: $modal-content-border-width solid $modal-content-border-color;
//@include border-radius($border-radius-lg);
//@include box-shadow($modal-content-box-shadow-xs);
border-radius: $border-radius-lg;
box-shadow: $modal-content-box-shadow-xs;
// Remove focus outline from opened modal
outline: 0;
@include themify($themes) {
background-color: themed('backgroundColorAlt');
}
}
// Modal background
.modal-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: $zindex-modal-backdrop;
background-color: $modal-backdrop-bg;
// Fade for backdrop
&.fade {
//opacity: 0;
animation: backdropshow 0.1s ease-in;
}
//&.show {
// opacity: $modal-backdrop-opacity;
//}
opacity: $modal-backdrop-opacity;
}
// Modal header
// Top section of the modal w/ title and dismiss
.modal-header {
display: flex;
align-items: flex-start; // so the close btn always stays on the upper right corner
justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends
padding: $modal-header-padding $modal-inner-padding;
border-bottom: $modal-header-border-width solid $modal-header-border-color;
//@include border-top-radius($border-radius-lg);
@include themify($themes) {
border-bottom-color: themed('borderColor');
}
.close {
padding: $modal-header-padding $modal-inner-padding;
// auto on the left force icon to the right even when there is no .modal-title
margin: (-$modal-header-padding) (-$modal-inner-padding) (-$modal-header-padding) auto;
}
h5 {
font-size: $font-size-base;
font-weight: bold;
display: flex;
align-items: center;
.fa {
margin-right: 5px;
}
}
}
// Title text within header
.modal-title {
margin-bottom: 0;
line-height: $modal-title-line-height;
}
// Modal body
// Where all modal content resides (sibling of .modal-header and .modal-footer)
.modal-body {
position: relative;
// Enable `flex-grow: 1` so that the body take up as much space as possible
// when should there be a fixed height on `.modal-dialog`.
flex: 1 1 auto;
padding: $modal-inner-padding;
}
// Footer (for actions)
.modal-footer {
display: flex;
align-items: center; // vertically center
//justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items
padding: $modal-inner-padding;
border-top: $modal-footer-border-width solid $modal-footer-border-color;
@include themify($themes) {
border-top-color: themed('borderColor');
}
// Easily place margin between footer elements
button {
margin-right: 10px;
&:last-child {
margin-right: 0;
}
}
.right {
margin-left: auto;
display: flex;
}
}
// Measure scrollbar width for padding body during modal show/hide
.modal-scrollbar-measure {
position: absolute;
top: -9999px;
width: 50px;
height: 50px;
overflow: scroll;
}
// Scale up the modal
@include media-breakpoint-up(sm) {
// Automatically set modal's width for larger viewports
.modal-dialog {
max-width: $modal-md;
margin: $modal-dialog-margin-y-sm-up auto;
}
.modal-dialog-centered {
min-height: calc(100% - (#{$modal-dialog-margin-y-sm-up} * 2));
}
.modal-content {
//@include box-shadow($modal-content-box-shadow-sm-up);
box-shadow: $modal-content-box-shadow-sm-up;
}
.modal-sm {
max-width: $modal-sm;
}
}
@include media-breakpoint-up(lg) {
.modal-lg {
max-width: $modal-lg;
}
}
// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_close.scss
.close {
float: right;
font-size: $close-font-size;
font-weight: $close-font-weight;
line-height: 1;
color: $close-color;
text-shadow: $close-text-shadow;
opacity: .5;
&:hover, &:focus {
color: $close-color;
text-decoration: none;
opacity: .75;
}
// Opinionated: add "hand" cursor to non-disabled .close elements
&:not(:disabled):not(.disabled) {
cursor: pointer;
}
}
// Additional properties for button version
// iOS requires the button element instead of an anchor tag.
// If you want the anchor version, it requires `href="#"`.
// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
// stylelint-disable property-no-vendor-prefix, selector-no-qualifying-type
button.close {
padding: 0;
background-color: transparent;
border: 0;
-webkit-appearance: none;
}
// stylelint-enable
// box
.modal-content .box {
margin-top: 20px;
&:first-child {
margin-top: 0;
}
}

View File

@ -1,9 +1,11 @@
@import "../css/webfonts.css";
@import "variables.scss";
@import "base.scss";
@import "grid.scss";
@import "box.scss";
@import "buttons.scss";
@import "misc.scss";
@import "modal.scss";
@import "plugins.scss";
@import "environment.scss";
@import "pages.scss";

View File

@ -116,7 +116,7 @@
<i *ngIf="showOptions" class="fa fa-chevron-up fa-sm icon"></i>
</div>
</div>
<ng-container *ngIf="showOptions">
<div [hidden]="!showOptions">
<app-send-efflux-dates
[initialDeletionDate]="send.deletionDate" [initialExpirationDate]="send.expirationDate"
[editMode]="editMode" [disabled]="disableSend" (datesChanged)="setDates($event)" (popOutWindow)="popOutWindow()">
@ -200,7 +200,7 @@
</div>
</div>
</div>
</ng-container>
</div>
<!-- Delete -->
<div class="box list" *ngIf="editMode">
<div class="box-content single-line">

View File

@ -0,0 +1,11 @@
import { Injectable } from '@angular/core';
import { PasswordRepromptService as BasePasswordRepromptService } from 'jslib-angular/services/passwordReprompt.service';
import { PasswordRepromptComponent } from '../components/password-reprompt.component';
@Injectable()
export class PasswordRepromptService extends BasePasswordRepromptService {
component = PasswordRepromptComponent;
}

View File

@ -9,10 +9,12 @@ import { ToasterModule } from 'angular2-toaster';
import { DebounceNavigationService } from './debounceNavigationService';
import { LaunchGuardService } from './launch-guard.service';
import { LockGuardService } from './lock-guard.service';
import { PasswordRepromptService } from './password-reprompt.service';
import { UnauthGuardService } from './unauth-guard.service';
import { AuthGuardService } from 'jslib-angular/services/auth-guard.service';
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
import { ModalService } from 'jslib-angular/services/modal.service';
import { ValidationService } from 'jslib-angular/services/validation.service';
import { BrowserApi } from '../../browser/browserApi';
@ -48,7 +50,6 @@ import { TokenService } from 'jslib-common/abstractions/token.service';
import { TotpService } from 'jslib-common/abstractions/totp.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
import { PasswordRepromptService } from 'jslib-common/services/passwordReprompt.service';
import { AutofillService } from '../../services/abstractions/autofill.service';
import BrowserMessagingService from '../../services/browserMessaging.service';
@ -76,8 +77,6 @@ const messagingService = new BrowserMessagingService();
const searchService = isPrivateMode ? null : new PopupSearchService(getBgService<SearchService>('searchService')(),
getBgService<CipherService>('cipherService')(), getBgService<ConsoleLogService>('consoleLogService')(),
getBgService<I18nService>('i18nService')());
const passwordRepromptService = isPrivateMode ? null : new PasswordRepromptService(getBgService<I18nService>('i18nService')(),
getBgService<CryptoService>('cryptoService')(), getBgService<PlatformUtilsService>('platformUtilsService')());
export function initFactory(platformUtilsService: PlatformUtilsService, i18nService: I18nService, storageService: StorageService,
popupUtilsService: PopupUtilsService): Function {
@ -126,6 +125,7 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ
DebounceNavigationService,
PopupUtilsService,
BroadcasterService,
ModalService,
{ provide: MessagingService, useValue: messagingService },
{ provide: AuthServiceAbstraction, useFactory: getBgService<AuthService>('authService'), deps: [] },
{ provide: StateServiceAbstraction, useValue: stateService },
@ -188,7 +188,7 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ
useFactory: () => isPrivateMode ? null : getBgService<I18nService>('i18nService')().translationLocale,
deps: [],
},
{ provide: PasswordRepromptServiceAbstraction, useValue: passwordRepromptService },
{ provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService },
],
})
export class ServicesModule {

View File

@ -10,15 +10,19 @@
<span class="title">{{'exportVault' | i18n}}</span>
</div>
<div class="right">
<button appBlurClick type="submit">{{'submit' | i18n}}</button>
<button appBlurClick type="submit" [disabled]="disabledByPolicy">{{'submit' | i18n}}</button>
</div>
</header>
<content>
<app-callout type="warning" title="{{'vaultExportDisabled' | i18n}}" *ngIf="disabledByPolicy">
{{'personalVaultExportPolicyInEffect' | i18n}}
</app-callout>
<div class="box">
<div class="box-content">
<div class="box-content-row" appBoxRow>
<label for="format">{{'fileFormat' | i18n}}</label>
<select id="format" name="Format" [(ngModel)]="format">
<select id="format" name="Format" [(ngModel)]="format" [disabled]="disabledByPolicy">
<option value="json">.json</option>
<option value="csv">.csv</option>
<option value="encrypted_json">.json (Encrypted)</option>
@ -28,7 +32,8 @@
<div class="row-main">
<label for="masterPassword">{{'masterPass' | i18n}}</label>
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
class="monospaced" [(ngModel)]="masterPassword" required appInputVerbatim appAutofocus>
class="monospaced" [(ngModel)]="masterPassword" required appInputVerbatim appAutofocus
[disabled]="disabledByPolicy">
</div>
<div class="action-buttons">
<a class="row-btn" href="#" appStopClick appBlurClick

View File

@ -6,6 +6,7 @@ import { EventService } from 'jslib-common/abstractions/event.service';
import { ExportService } from 'jslib-common/abstractions/export.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { ExportComponent as BaseExportComponent } from 'jslib-angular/components/export.component';
@ -16,8 +17,8 @@ import { ExportComponent as BaseExportComponent } from 'jslib-angular/components
export class ExportComponent extends BaseExportComponent {
constructor(cryptoService: CryptoService, i18nService: I18nService,
platformUtilsService: PlatformUtilsService, exportService: ExportService,
eventService: EventService, private router: Router) {
super(cryptoService, i18nService, platformUtilsService, exportService, eventService, window);
eventService: EventService, policyService: PolicyService, private router: Router) {
super(cryptoService, i18nService, platformUtilsService, exportService, eventService, policyService, window);
}
protected saved() {

View File

@ -28,13 +28,7 @@
<div class="box list">
<div class="box-header">{{'security' | i18n}}</div>
<div class="box-content single-line">
<div class="box-content-row display-block" appBoxRow>
<label for="vaultTimeout">{{'vaultTimeout' | i18n}}</label>
<select #vaultTimeoutSelect id="vaultTimeout" name="VaultTimeouts" [ngModel]="vaultTimeout"
(ngModelChange)="saveVaultTimeout($event)">
<option *ngFor="let o of vaultTimeouts" [ngValue]="o.value">{{o.name}}</option>
</select>
</div>
<app-vault-timeout-input [vaultTimeouts]="vaultTimeouts" [formControl]="vaultTimeout" ngDefaultControl></app-vault-timeout-input>
<div class="box-content-row display-block" appBoxRow>
<label for="vaultTimeoutAction">{{'vaultTimeoutAction' | i18n}}</label>
<select #vaultTimeoutActionSelect id="vaultTimeoutAction" name="VaultTimeoutActions"
@ -50,6 +44,10 @@
<label for="biometric">{{'unlockWithBiometrics' | i18n}}</label>
<input id="biometric" type="checkbox" (change)="updateBiometric()" [(ngModel)]="biometric">
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow *ngIf="supportsBiometric">
<label for="autoBiometricsPrompt">{{'disableAutoBiometricsPrompt' | i18n}}</label>
<input id="autoBiometricsPrompt" type="checkbox" (change)="updateAutoBiometricsPrompt()" [disabled]="!biometric" [(ngModel)]="disableAutoBiometricsPrompt">
</div>
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
(click)="lock()">
<div class="row-main">{{'lockNow' | i18n}}</div>

View File

@ -1,12 +1,13 @@
import Swal from 'sweetalert2/src/sweetalert2.js';
import {
Component,
ElementRef,
OnInit,
ViewChild,
} from '@angular/core';
import { FormControl } from '@angular/forms';
import { Router } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import Swal from 'sweetalert2/src/sweetalert2.js';
import { BrowserApi } from '../../browser/browserApi';
@ -24,6 +25,10 @@ import { UserService } from 'jslib-common/abstractions/user.service';
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
import { PopupUtilsService } from '../services/popup-utils.service';
import { ModalService } from 'jslib-angular/services/modal.service';
import { SetPinComponent } from '../components/set-pin.component';
const RateUrls = {
[DeviceType.ChromeExtension]:
'https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews',
@ -44,22 +49,24 @@ const RateUrls = {
templateUrl: 'settings.component.html',
})
export class SettingsComponent implements OnInit {
@ViewChild('vaultTimeoutSelect', { read: ElementRef, static: true }) vaultTimeoutSelectRef: ElementRef;
@ViewChild('vaultTimeoutActionSelect', { read: ElementRef, static: true }) vaultTimeoutActionSelectRef: ElementRef;
vaultTimeouts: any[];
vaultTimeout: number = null;
vaultTimeoutActions: any[];
vaultTimeoutAction: string;
pin: boolean = null;
supportsBiometric: boolean;
biometric: boolean = false;
disableAutoBiometricsPrompt = true;
previousVaultTimeout: number = null;
vaultTimeout: FormControl = new FormControl(null);
constructor(private platformUtilsService: PlatformUtilsService, private i18nService: I18nService,
private vaultTimeoutService: VaultTimeoutService, private storageService: StorageService,
public messagingService: MessagingService, private router: Router,
private environmentService: EnvironmentService, private cryptoService: CryptoService,
private userService: UserService, private popupUtilsService: PopupUtilsService) {
private userService: UserService, private popupUtilsService: PopupUtilsService,
private modalService: ModalService, private toasterService: ToasterService) {
}
async ngOnInit() {
@ -89,14 +96,18 @@ export class SettingsComponent implements OnInit {
{ name: this.i18nService.t('logOut'), value: 'logOut' },
];
let timeout = await this.storageService.get<number>(ConstantsService.vaultTimeoutKey);
let timeout = await this.vaultTimeoutService.getVaultTimeout();
if (timeout != null) {
if (timeout === -2 && !showOnLocked) {
timeout = -1;
}
this.vaultTimeout = timeout;
this.vaultTimeout.setValue(timeout);
}
this.previousVaultTimeout = this.vaultTimeout;
this.previousVaultTimeout = this.vaultTimeout.value;
this.vaultTimeout.valueChanges.subscribe(value => {
this.saveVaultTimeout(value);
});
const action = await this.storageService.get<string>(ConstantsService.vaultTimeoutActionKey);
this.vaultTimeoutAction = action == null ? 'lock' : action;
@ -105,6 +116,8 @@ export class SettingsComponent implements OnInit {
this.supportsBiometric = await this.platformUtilsService.supportsBiometric();
this.biometric = await this.vaultTimeoutService.isBiometricLockSet();
this.disableAutoBiometricsPrompt = await this.storageService.get<boolean>(
ConstantsService.disableAutoBiometricsPromptKey) ?? true;
}
async saveVaultTimeout(newValue: number) {
@ -113,18 +126,19 @@ export class SettingsComponent implements OnInit {
this.i18nService.t('neverLockWarning'), null,
this.i18nService.t('yes'), this.i18nService.t('cancel'), 'warning');
if (!confirmed) {
this.vaultTimeouts.forEach((option: any, i) => {
if (option.value === this.vaultTimeout) {
this.vaultTimeoutSelectRef.nativeElement.value = i + ': ' + this.vaultTimeout;
}
});
this.vaultTimeout.setValue(this.previousVaultTimeout);
return;
}
}
this.previousVaultTimeout = this.vaultTimeout;
this.vaultTimeout = newValue;
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout != null ? this.vaultTimeout : null,
this.vaultTimeoutAction);
if (!this.vaultTimeout.valid) {
this.toasterService.popAsync('error', null, this.i18nService.t('vaultTimeoutToLarge'));
return;
}
this.previousVaultTimeout = this.vaultTimeout.value;
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout.value, this.vaultTimeoutAction);
if (this.previousVaultTimeout == null) {
this.messagingService.send('bgReseedStorage');
}
@ -145,65 +159,27 @@ export class SettingsComponent implements OnInit {
return;
}
}
if (!this.vaultTimeout.valid) {
this.toasterService.popAsync('error', null, this.i18nService.t('vaultTimeoutToLarge'));
return;
}
this.vaultTimeoutAction = newValue;
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout != null ? this.vaultTimeout : null,
this.vaultTimeoutAction);
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout.value, this.vaultTimeoutAction);
}
async updatePin() {
if (this.pin) {
const div = document.createElement('div');
const label = document.createElement('label');
label.className = 'checkbox';
const checkboxText = document.createElement('span');
const restartText = document.createTextNode(this.i18nService.t('lockWithMasterPassOnRestart'));
checkboxText.appendChild(restartText);
label.innerHTML = '<input type="checkbox" id="master-pass-restart" checked>';
label.appendChild(checkboxText);
const ref = this.modalService.open(SetPinComponent, { allowMultipleModals: true });
div.innerHTML =
`<div class="swal2-text">${this.i18nService.t('setYourPinCode')}</div>` +
'<input type="text" class="swal2-input" id="pin-val" autocomplete="off" ' +
'autocapitalize="none" autocorrect="none" spellcheck="false" inputmode="verbatim">';
(div.querySelector('#pin-val') as HTMLInputElement).placeholder = this.i18nService.t('pin');
div.appendChild(label);
const submitted = await Swal.fire({
heightAuto: false,
buttonsStyling: false,
html: div,
showCancelButton: true,
cancelButtonText: this.i18nService.t('cancel'),
showConfirmButton: true,
confirmButtonText: this.i18nService.t('submit'),
});
let pin: string = null;
let masterPassOnRestart: boolean = null;
if (submitted.value) {
pin = (document.getElementById('pin-val') as HTMLInputElement).value;
masterPassOnRestart = (document.getElementById('master-pass-restart') as HTMLInputElement).checked;
}
if (pin != null && pin.trim() !== '') {
const kdf = await this.userService.getKdf();
const kdfIterations = await this.userService.getKdfIterations();
const email = await this.userService.getEmail();
const pinKey = await this.cryptoService.makePinKey(pin, email, kdf, kdfIterations);
const key = await this.cryptoService.getKey();
const pinProtectedKey = await this.cryptoService.encrypt(key.key, pinKey);
if (masterPassOnRestart) {
const encPin = await this.cryptoService.encrypt(pin);
await this.storageService.save(ConstantsService.protectedPin, encPin.encryptedString);
this.vaultTimeoutService.pinProtectedKey = pinProtectedKey;
} else {
await this.storageService.save(ConstantsService.pinProtectedKey, pinProtectedKey.encryptedString);
}
} else {
if (ref == null) {
this.pin = false;
return;
}
}
if (!this.pin) {
this.pin = await ref.onClosedPromise();
} else {
await this.cryptoService.clearPinProtectedKey();
await this.vaultTimeoutService.clear();
}
@ -277,6 +253,10 @@ export class SettingsComponent implements OnInit {
}
}
async updateAutoBiometricsPrompt() {
await this.storageService.save(ConstantsService.disableAutoBiometricsPromptKey, this.disableAutoBiometricsPrompt);
}
async lock() {
await this.vaultTimeoutService.lock(true);
}

View File

@ -0,0 +1,29 @@
<app-callout type="info" *ngIf="vaultTimeoutPolicy">
{{'vaultTimeoutPolicyInEffect' | i18n : vaultTimeoutPolicyHours : vaultTimeoutPolicyMinutes}}
</app-callout>
<div [formGroup]="form">
<div class="box-content-row last display-block" appBoxRow>
<label for="vaultTimeout">{{'vaultTimeout' | i18n}}</label>
<select id="vaultTimeout" name="VaultTimeout" formControlName="vaultTimeout" class="form-control">
<option *ngFor="let o of vaultTimeouts" [ngValue]="o.value">{{o.name}}</option>
</select>
</div>
<div class="box-content-row last" *ngIf="showCustom">
<div formGroupName="custom" class="row">
<div class="col">
<div class="display-block" appBoxRow>
<label for="customVaultTimeout">{{'hours' | i18n }}</label>
<input id="hours" class="form-control" type="number" min="0" name="hours" formControlName="hours">
</div>
</div>
<div class="col">
<div class="display-block" appBoxRow>
<label for="customVaultTimeout">{{'minutes' | i18n }}</label>
<input id="minutes" class="form-control" type="number" min="0" max="59" name="minutes"
formControlName="minutes">
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,28 @@
import { Component } from '@angular/core';
import {
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
} from '@angular/forms';
import {
VaultTimeoutInputComponent as VaultTimeoutInputComponentBase
} from 'jslib-angular/components/settings/vault-timeout-input.component';
@Component({
selector: 'app-vault-timeout-input',
templateUrl: 'vault-timeout-input.component.html',
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: VaultTimeoutInputComponent,
},
{
provide: NG_VALIDATORS,
multi: true,
useExisting: VaultTimeoutInputComponent,
},
],
})
export class VaultTimeoutInputComponent extends VaultTimeoutInputComponentBase {
}

View File

@ -63,7 +63,8 @@
</button>
</ng-container>
</div>
<cdk-virtual-scroll-viewport itemSize="46" *ngIf="ciphers.length" #virtualScrollViewport>
<cdk-virtual-scroll-viewport itemSize="46" minBufferPx="400" maxBufferPx="600" *ngIf="ciphers.length"
#virtualScrollViewport>
<div class="box list only-list">
<div class="box-header">
{{groupingTitle}}

View File

@ -145,7 +145,8 @@
<div class="no-items" *ngIf="!ciphers || !ciphers.length">
<p>{{'noItemsInList' | i18n}}</p>
</div>
<cdk-virtual-scroll-viewport itemSize="46" *ngIf="ciphers && ciphers.length > 0">
<cdk-virtual-scroll-viewport itemSize="46" minBufferPx="400" maxBufferPx="600"
*ngIf="ciphers && ciphers.length > 0">
<div class="box list full-list">
<div class="box-content">
<app-cipher-row *cdkVirtualFor="let searchedCipher of ciphers" [cipher]="searchedCipher"

View File

@ -21,18 +21,19 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
import { TokenService } from 'jslib-common/abstractions/token.service';
import { TotpService } from 'jslib-common/abstractions/totp.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { Cipher } from 'jslib-common/models/domain';
import { LoginUriView } from 'jslib-common/models/view';
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
import { Cipher } from 'jslib-common/models/domain/cipher';
import { LoginUriView } from 'jslib-common/models/view/loginUriView';
import { CipherType } from 'jslib-common/enums/cipherType';
import { ViewComponent as BaseViewComponent } from 'jslib-angular/components/view.component';
import { BrowserApi } from '../../browser/browserApi';
import { AutofillService } from '../../services/abstractions/autofill.service';
import { PopupUtilsService } from '../services/popup-utils.service';
import { CipherType } from 'jslib-common/enums';
const BroadcasterSubscriptionId = 'ChildViewComponent';
@Component({

View File

@ -1,9 +1,16 @@
import {
CipherType,
FieldType,
} from 'jslib-common/enums';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { EventService } from 'jslib-common/abstractions/event.service';
import { TotpService } from 'jslib-common/abstractions/totp.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { CipherView } from 'jslib-common/models/view';
import { AutofillService as AutofillServiceInterface } from './abstractions/autofill.service';
import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType';
import { CipherType } from 'jslib-common/enums/cipherType';
import { EventType } from 'jslib-common/enums/eventType';
import { FieldType } from 'jslib-common/enums/fieldType';
import { CipherView } from 'jslib-common/models/view/cipherView';
import AutofillField from '../models/autofillField';
import AutofillPageDetails from '../models/autofillPageDetails';
@ -11,18 +18,6 @@ import AutofillScript from '../models/autofillScript';
import { BrowserApi } from '../browser/browserApi';
import { AutofillService as AutofillServiceInterface } from './abstractions/autofill.service';
import {
CipherService,
TotpService,
UserService,
} from 'jslib-common/abstractions';
import { EventService } from 'jslib-common/abstractions/event.service';
import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType';
import { EventType } from 'jslib-common/enums/eventType';
const CardAttributes: string[] = ['autoCompleteType', 'data-stripe', 'htmlName', 'htmlID', 'label-tag',
'placeholder', 'label-left', 'label-top', 'data-recurly'];

View File

@ -150,33 +150,6 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
});
}
async showPasswordDialog(title: string, body: string, passwordValidation: (value: string) => Promise<boolean>) {
const dialogId = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
this.messagingService.send('showPasswordDialog', {
title: title,
body: body,
dialogId: dialogId,
});
return new Promise<boolean>(resolve => {
this.passwordDialogResolves.set(dialogId, {
tryResolve: async (canceled: boolean, password: string) => {
if (canceled) {
resolve(false);
return false;
}
if (await passwordValidation(password)) {
resolve(true);
return true;
}
},
date: new Date(),
});
});
}
isDev(): boolean {
return process.env.ENV === 'development';
}

View File

@ -8,8 +8,9 @@ export default class I18nService extends BaseI18nService {
return await file.json();
});
// Please leave 'en' where it is, as it's our fallback language in case no translation can be found
this.supportedTranslationLocales = [
'az', 'en', 'be', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en-GB', 'en-IN', 'es', 'et', 'fa', 'fi', 'fr', 'he', 'hr', 'hu',
'en', 'az', 'be', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en-GB', 'en-IN', 'es', 'et', 'fa', 'fi', 'fr', 'he', 'hr', 'hu',
'id', 'it', 'ja', 'kn', 'ko', 'lv', 'ml', 'nb', 'nl', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru', 'sk', 'sr', 'sv', 'th', 'tr', 'uk',
'vi', 'zh-CN', 'zh-TW',
];

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -118,58 +118,57 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Name" xml:space="preserve">
<value>Bitwarden Free Password Manager</value>
<value>Bitwarden Ödənişsiz Şifrə Meneceri</value>
</data>
<data name="Summary" xml:space="preserve">
<value>A secure and free password manager for all of your devices</value>
<value>Bütün cihazlarınız üçün təhlükəsiz və ödənişsiz bir şifrə meneceri</value>
</data>
<data name="Description" xml:space="preserve">
<value>Bitwarden, Inc. is the parent company of 8bit Solutions LLC.
<value>Bitwarden, Inc., 8bit Solutions LLC-nin ana şirkətidir.
NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET, AND MORE.
THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET VƏ BİR ÇOXUNA GÖRƏ ƏN YAXŞI ŞİFRƏ MENECERİDİR.
Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go.
Hər yerdən limitsiz cihazda limitsiz şifrəni idarə edin, saxlayın, qoruyun və paylaşın. Bitwarden evdə, işdə və ya yolda hər kəsə açıq mənbəli şifrə idarəetmə həllərini təqdim edir.
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
Çox istifadə etdiyiniz hər veb sayt üçün təhlükəsizlik tələblərinə görə güclü, unikal və təsadüfi şifrələr yaradın.
Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone.
Bitwarden Send şifrələnmiş məlumatların (fayl və sadə mətnləri) birbaşa və sürətli göndərilməsini təmin edir.
Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues.
Bitwarden, şifrələri iş yoldaşlarınızla təhlükəsiz paylaşa bilməyiniz üçün şirkətlərə Teams və Enterprise planları təklif edir.
Why Choose Bitwarden:
Nəyə görə Bitwarden-i seçməliyik:
World-Class Encryption
Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private.
Yüksək səviyyə şifrələmə
Şifrələriniz qabaqcıl ucdan-uca şifrələmə (AES-256 bit, salted hashtag və PBKDF2 SHA-256) ilə qorunur, beləcə verilənlərinizin təhlükəsiz və gizli qalmasını təmin edir.
Built-in Password Generator
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
Daxili şifrə yaradıcı
Çox istifadə etdiyiniz hər veb sayt üçün təhlükəsizlik tələblərinə görə güclü, unikal və təsadüfi şifrələr yaradın.
Global Translations
Bitwarden translations exist in 40 languages and are growing, thanks to our global community.
Qlobal tərcümələr
Bitwarden tərcümələri 40 dildə mövcuddur və qlobal cəmiyyətimiz sayəsində böyüməyə davam edir.
Cross-Platform Applications
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
</value>
Çarpaz platform tətbiqləri
Bitwarden anbarındakı həssas verilənləri, istənilən səyyahdan, mobil cihazdan və ya masaüstü əməliyyat sistemindən və daha çoxundan qoruyub paylaşın.</value>
</data>
<data name="AssetTitle" xml:space="preserve">
<value>A secure and free password manager for all of your devices</value>
<value>Bütün cihazlarınız üçün təhlükəsiz və ödənişsiz bir şifrə meneceri</value>
</data>
<data name="ScreenshotSync" xml:space="preserve">
<value>Sync and access your vault from multiple devices</value>
<value>Anbarınıza bir neçə cihazdan eyniləşdirərək müraciət edin</value>
</data>
<data name="ScreenshotVault" xml:space="preserve">
<value>Manage all your logins and passwords from a secure vault</value>
<value>Bütün giriş məlumatlarınızı və şifrələrinizi təhlükəsiz bir anbardan idarə edin</value>
</data>
<data name="ScreenshotAutofill" xml:space="preserve">
<value>Quickly auto-fill your login credentials into any website that you visit</value>
<value>Giriş kimlik məlumatlarınızı ziyarət etdiyiniz istənilən veb sayta dərhal avtomatik doldurun</value>
</data>
<data name="ScreenshotMenu" xml:space="preserve">
<value>Your vault is also conveniently accessible from the right-click menu</value>
<value>Anbarınıza sağ klikləmə menyusundan da asanlıqla müraciət edə bilərsiniz</value>
</data>
<data name="ScreenshotPassword" xml:space="preserve">
<value>Automatically generate strong, random, and secure passwords</value>
<value>Güclü, təsadüfi və etibarlı şifrələrin avtomatik yaradılması</value>
</data>
<data name="ScreenshotEdit" xml:space="preserve">
<value>Your information is managed securely using AES-256 bit encryption</value>
<value>Məlumatlarınız AES-256 bit şifrələmə istifadə edilərək təhlükəsiz şəkildə idarə olunur</value>
</data>
</root>

View File

@ -59,46 +59,46 @@
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>

View File

@ -124,15 +124,31 @@
<value>Turvallinen ja ilmainen salasanojen hallinta kaikille laitteillesi</value>
</data>
<data name="Description" xml:space="preserve">
<value>Bitwarden on helpoin ja turvallisin tapa säilyttää käyttäjätunnuksesi ja salasanasi, samalla pitäen ne synkronoituna laitteidesi välillä.
<value>Bitwarden, inc. on 8bit Solutions LLC:n emoyhtiö.
Salasanavarkaudet ovat vakava ongelma ja monet käyttämäsi sivustot ja sovellukset ovat päivittäisten hyökkäysten kohteina. Tietoturvavuotoja tapahtuu ja salasanoja varastetaan. Jos käytät samoja salasanoja uudelleen eri sivustoilla ja sovelluksissa, saattavat hakkerit päästä helposti käsiksi sähköpostiisi, pankkiisi tai muihin tärkeisiin käyttäjätileihisi.
NIMENNYT PARHAAKSI SALASANOJEN HALLINNAKSI MM. THE VERGE, U.S. NEWS &amp; WORLD REPORT JA CNET.
Tietoturva-asiantuntijat suosittelevat ainutlaatuisten, satunnaisesti luotujen salasanojen käyttöä kaikilla käyttäjätileilläsi. Mutta kuinka sitten hallitset näitä kaikkia erilaisia salasanoja? Bitwarden tekee laadukkaiden ja ainutlaatuisten salasanojen luonnista, säilytyksestä ja käytöstä helppoa.
Hallinnoi, säilytä, suojaa ja jaa rajattomasti salasanoja missä tahansa ja miltä tahansa laitteelta. Bitwarden tarjoaa avoimeen lähdekoodin perustuvan salasanojen hallintaratkaisun kaikille, olitpa sitten kotona, töissä tai liikkeellä.
Bitwarden säilyttää kaikki kirjautumistietosi salattussa holvissa, joka synkronoidaan laitteidesi välillä. Koska tietosi ovat täysin salattuja jo ennen kuin ne edes lähtevät laitteeltasi, vain sinä pääset niihin käsiksi. Edes Bitwardenin kehittäjät eivät voi lukea tietojasi, vaikka haluaisivat. Tietosi suojataan 256-bittisellä AES-salauksella, suolatulla hajautuksella sekä PBKDF2 ja SHA-256 -menetelmillä.
Luo usein käyttämillesi sivustoille automaattisesti vahvoja, yksilöllisiä ja satunnaisia salasanoja.
Bitwarden on 100% avointa lähdekoodia. Bitwardenin lähdekoodi on esillä GitHubissa ja kuka tahansa voi tutkia ja tarkastella sitä sekä osallistua Bitwardenin kehitykseen.</value>
Bitwarden Send -ominaisuudella lähetät tietoa nopeasti salattuna — tiedostoja ja tekstiä — suoraan kenelle tahansa.
Yrityksille Bitwarden tarjoaa Teams ja Enterprise -tilaukset, jotta voit jakaa salasanoja kollegoiden kesken turvallisesti.
Miksi Bitwarden?:
Maailmanluokan salaus
Salasanat on suojattu tehokkaalla päästä päähän salauksella (AES-256 Bit, suolattu hajautus ja PBKDF2 SHA-256), joten tietosi pysyvät turvassa ja yksityisinä.
Sisäänrakennettu salasanageneraattori
Luo usein käyttämillesi sivustoille vahvoja, yksilöllisiä ja satunnaisia salasanoja.
Monikielinen
Bitwardenin sovelluksia on käännetty yli 40 kielelle ja määrä kasvaa jatkuvasti, kiitos kansainvälisen yhteisömme.
Alustariippumattomaton
Suojaa, käytä ja jaa Bitwarden-holvisi arkaluontoisia tietoja kaikilla selaimilla, mobiililaitteilla, pöytätietokoneilla ja muissa järjestelmissä.</value>
</data>
<data name="AssetTitle" xml:space="preserve">
<value>Turvallinen ja ilmainen salasanojen hallinta kaikille laitteillesi</value>

175
store/locales/fil/copy.resx Normal file
View File

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Name" xml:space="preserve">
<value>Bitwarden Free Password Manager</value>
</data>
<data name="Summary" xml:space="preserve">
<value>A secure and free password manager for all of your devices</value>
</data>
<data name="Description" xml:space="preserve">
<value>Bitwarden, Inc. is the parent company of 8bit Solutions LLC.
NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET, AND MORE.
Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go.
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone.
Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues.
Why Choose Bitwarden:
World-Class Encryption
Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private.
Built-in Password Generator
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
Global Translations
Bitwarden translations exist in 40 languages and are growing, thanks to our global community.
Cross-Platform Applications
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
</value>
</data>
<data name="AssetTitle" xml:space="preserve">
<value>A secure and free password manager for all of your devices</value>
</data>
<data name="ScreenshotSync" xml:space="preserve">
<value>Sync and access your vault from multiple devices</value>
</data>
<data name="ScreenshotVault" xml:space="preserve">
<value>Manage all your logins and passwords from a secure vault</value>
</data>
<data name="ScreenshotAutofill" xml:space="preserve">
<value>Quickly auto-fill your login credentials into any website that you visit</value>
</data>
<data name="ScreenshotMenu" xml:space="preserve">
<value>Your vault is also conveniently accessible from the right-click menu</value>
</data>
<data name="ScreenshotPassword" xml:space="preserve">
<value>Automatically generate strong, random, and secure passwords</value>
</data>
<data name="ScreenshotEdit" xml:space="preserve">
<value>Your information is managed securely using AES-256 bit encryption</value>
</data>
</root>

View File

@ -124,15 +124,31 @@
<value>Un gestionnaire de mots de passe sécurisé et gratuit pour tous vos appareils</value>
</data>
<data name="Description" xml:space="preserve">
<value>Bitwarden est le moyen le plus facile et sûr de stocker tous vos identifiants et mots de passe tout en les synchronisant facilement entre tous vos appareils.
<value>Bitwarden, Inc. est la société mère de 8bit Solutions LLC.
Le vol de mot de passe est un problème sérieux. Les sites web et les applications que vous utilisez sont attaqués tous les jours. Des failles de sécurité apparaissent et vos mots de passe sont volés. Quand vous réutilisez les mêmes mots de passe sur divers sites web et applications, des hackers peuvent facilement accéder à vos e-mails, vos comptes bancaires et à d'autres informations importantes.
NOMMÉ MEILLEUR GESTIONNAIRE DE MOTS DE PASSE PAR THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET, ET PLUS ENCORE.
Les experts en sécurité recommandent l'utilisation de mots de passe différents et générés aléatoirement pour chaque compte que vous créez. Mais comment allez-vous gérer tous ces mots de passe ? Bitwarden facilite la création, le stockage et l'accès de vos mots de passe.
Gérez, stockez, sécurisez et partagez un nombre illimité de mots de passe sur un nombre illimité d'appareils, où que vous soyez. Bitwarden fournit des solutions de gestion de mots de passe open source à tout le monde, que ce soit à la maison, au travail ou en déplacement.
Bitwarden stocke tous vos identifiants dans un coffre chiffré qui est synchronisé entre tous vos appareils. Puisqu'il est entièrement chiffré avant même qu'il ne sorte de votre appareil, vous êtes la seule personne à avoir accès à vos données. Personne, pas même l'équipe de Bitwarden ne peut lire vos données, même si nous le voulions. Vos données sont scellées par un chiffrement AES-256 bit, salées et hachées en utilisant PBKDF2 avec SHA-256.
Générez des mots de passe forts, uniques et aléatoires basés sur des exigences de sécurité pour chaque site web que vous fréquentez.
Bitwarden est un logiciel 100% open source. Le code source de Bitwarden est hébergé sur Github et tout le monde est libre de le consulter, de l'auditer et de contribuer au code de Bitwarden.</value>
Bitwarden Send transmet rapidement des informations chiffrées --- fichiers et texte --- directement à quiconque.
Bitwarden propose les plans Teams et Enterprise pour les entreprises afin que vous puissiez partager des mots de passe en toute sécurité avec vos collègues.
Pourquoi choisir Bitwarden :
Un chiffrement de classe internationale
Les mots de passe sont protégés par un chiffrement avancé de bout en bout (AES-256 bit, salted hashtag, et PBKDF2 SHA-256) afin que vos données restent sécurisées et privées.
Générateur de mots de passe intégré
Générez des mots de passe forts, uniques et aléatoires en fonction des exigences de sécurité pour chaque site web que vous fréquentez.
Traductions mondiales
Les traductions de Bitwarden existent dans 40 langues et ne cessent de croître, grâce à notre communauté mondiale.
Applications multiplateformes
Sécurisez et partagez des données sensibles dans votre coffre-fort Bitwarden à partir de n'importe quel navigateur, appareil mobile ou système d'exploitation de bureau, et plus encore.</value>
</data>
<data name="AssetTitle" xml:space="preserve">
<value>Un gestionnaire de mots de passe sécurisé et gratuit pour tous vos appareils</value>

View File

@ -124,13 +124,31 @@
<value>Bezpieczny i darmowy menedżer haseł dla wszystkich Twoich urządzeń</value>
</data>
<data name="Description" xml:space="preserve">
<value>bitwarden to najłatwiejszy i najbezpieczniejszy sposób przechowywania wszystkich Twoich loginów i haseł, umożliwiający ich wygodną synchronizację pomiędzy wszystkimi Twoimi urządzeniami.
<value>Bitwarden, Inc. jest macierzystą firmą 8bit Solutions LLC.
Kradzież hasła to poważny problem. Witryny i aplikacje, których używasz są atakowane każdego dnia. Twoje hasła mogą zostać skradzione w wyniku złamania zabezpieczeń. Gdy używasz tego samego hasła dla różnych aplikacji i stron internetowych, hakerzy mogą z łatwością uzyskać dostęp do twojego konta e-mail, banku i innych ważnych kont.
NAZWANY NAJLEPSZYM MENEDŻEREM HASEŁ PRZEZ THE VERGE, US NEWS &amp; WORLD REPORT, CNET I WIĘCEJ.
Eksperci od bezpieczeństwa zalecają używanie różnych, losowo wygenerowanych haseł dla każdego nowo tworzonego konta. Ale jak można zarządzać wszystkimi tymi hasłami? bitwarden sprawia, że tworzenie, przechowywanie i dostęp do Twoich haseł jest naprawdę łatwy.
Zarządzaj, przechowuj, zabezpieczaj i udostępniaj nieograniczoną liczbę haseł na nieograniczonej liczbie urządzeń z każdego miejsca. Bitwarden dostarcza rozwiązania do zarządzania hasłami z otwartym kodem źródłowym każdemu, niezależnie od tego, czy jest w domu, w pracy, czy w podróży.
bitwarden przechowuje wszystkie Twoje dane logowania w zaszyfrowanym sejfie, który jest synchronizowany pomiędzy wszystkimi Twoimi urządzeniami. Dzięki temu, że dane są w pełni zaszyfrowane zanim opuszczą Twoje urządzenie, tylko masz do nich dostęp. Nawet zespół bitwarden nie ma dostępu do Twoich danych. Dane są zabezpieczone za pomocą szyfrowania metodą AES-256, stosowania ciągów zaburzających i algorytmu PBKDF2 SHA-256.</value>
Generuj silne, unikalne i losowe hasła w oparciu o wymagania bezpieczeństwa dla każdej odwiedzanej strony.
Funkcja Bitwarden Send szybko przesyła zaszyfrowane informacje --- pliki i zwykły tekst -- bezpośrednio do każdego.
Bitwarden oferuje plany dla zespołów i firm, dzięki czemu możesz bezpiecznie udostępniać hasła współpracownikom.
Dlaczego warto wybrać Bitwarden:
Szyfrowanie światowej klasy
Hasła są chronione za pomocą zaawansowanego szyfrowania typu end-to-end (AES-256 bitów, dodatkowy ciąg zaburzający i PBKDF2 SHA-256), dzięki czemu Twoje dane pozostają bezpieczne i prywatne.
Wbudowany generator haseł
Generuj silne, unikalne i losowe hasła w oparciu o wymagania bezpieczeństwa dla każdej odwiedzanej strony.
Przetłumaczone aplikacje
Tłumaczenia Bitwarden są dostępne w 40 językach i rosną dzięki naszej globalnej społeczności.
Aplikacje wieloplatformowe
Zabezpiecz i udostępniaj poufne dane w swoim sejfie Bitwarden z dowolnej przeglądarki, urządzenia mobilnego, systemu operacyjnego i nie tylko.</value>
</data>
<data name="AssetTitle" xml:space="preserve">
<value>Bezpieczny i darmowy menedżer haseł dla wszystkich Twoich urządzeń</value>

View File

@ -124,13 +124,31 @@
<value>Một trình quản lý mật khẩu an toàn và miễn phí cho mọi thiết bị của bạn</value>
</data>
<data name="Description" xml:space="preserve">
<value>Bitwarden là cách dễ dàng và an toàn nhất để lưu trữ tất cả các thông tin đăng nhập và mật khẩu của bạn và giữ chúng được đồng bộ giữa tất cả các thiết bị của bạn.
<value>Bitwarden, Inc là công ty mẹ của 8bit Solutions LLC
Rò rỉ mật khẩu là một vấn đề rất nghiêm trọng. Các trang web và ứng dụng mà bạn sử dụng đang bị tấn công mỗi ngày. Vi phạm an ninh mạng xảy ra khiến mật khẩu của bạn bị đánh cắp. Khi bạn sử dụng cùng một mật khẩu trên nhiều ứng dụng và trang web, tin tặc có thể dễ dàng truy cập vào email, tài khoản ngân hàng và các tài khoản quan trọng khác của bạn.
ĐƯỢC ĐÁNH GIÁ LÀ TRÌNH QUẢN LÝ MẬT KHẨU TỐT NHẤT BỞI NHÀ BÁO LỚN NHƯ THE VERGE, CNET, U.S. NEWS &amp; WORLD REPORT VÀ HƠN NỮA
Các chuyên gia bảo mật khuyên bạn nên sử dụng một mật khẩu được tạo ngẫu nhiên cho mỗi tài khoản của bạn. Nhưng làm thế nào để bạn quản lý tất cả những mật khẩu đó? bitwarden giúp bạn tạo, lưu trữ và truy cập tất cả mật khẩu một cách dễ dàng.
Quản lý, lưu trữ, bảo mật và chia sẻ mật khẩu không giới hạn trên các thiết bị không giới hạn mọi lúc, mọi nơi. Bitwarden cung cấp các giải pháp quản lý mật khẩu mã nguồn mở cho tất cả mọi người, cho dù ở nhà, tại cơ quan hay khi đang di chuyển .
Bitwarden lưu trữ tất cả các thông tin đăng nhập của bạn trong một hầm được mã hóa và đồng bộ trên tất cả các thiết bị của bạn. Vì nó được mã hóa đầy đủ trước khi nó rời khỏi thiết bị của bạn nên chỉ có bạn mới có thể truy cập vào dữ liệu của mình. Ngay cả nhóm nghiên cứu tại bitwarden cũng không thể đọc được dữ liệu của bạn khi hộ muốn. Dữ liệu của bạn được bảo vệ bằng mã hóa AES-256 bit, hàm băm và PBKDF2 SHA-256.</value>
Tạo mật khẩu mạnh, không bị trùng và ngẫu nhiên dựa trên các yêu cầu bảo mật cho mọi trang web bạn thường xuyên sử dụng.
Tính năng 'Bitwarden Send' nhanh chóng truyền thông tin được mã hóa --- tệp và bản rõ - trực tiếp đến bất kỳ ai.
Bitwarden cung cấp các gói 'Nhóm' và 'Doanh nghiệp' cho các công ty để bạn có thể chia sẻ mật khẩu với đồng nghiệp một cách an toàn.
Tại sao bạn nên chọn Bitwarden:
Mã hóa tốt nhất thế giới
Mật khẩu được bảo vệ bằng mã hóa đầu cuối (end-to-end encryption) tiên tiến như AES-256 bit, salted hashtag, và PBKDF2 SHA-256 nên dữ liệu của bạn luôn an toàn và riêng tư.
Trình tạo mật khẩu tích hợp
Tạo mật khẩu mạnh, không bị trùng và ngẫu nhiên dựa trên các yêu cầu bảo mật cho mọi trang web bạn thường xuyên sử dụng.
Bản dịch ngôn ngữ từ cộng đồng
Bitwarden đã có bản dịch 40 ngôn ngữ và đang phát triển nhờ vào cộng đồng toàn cầu của chúng tôi.
Ứng dụng đa nền tảng
Bảo mật và chia sẻ dữ liệu nhạy cảm trong kho lưu trữ Bitwarden của bạn từ bất kỳ trình duyệt, điện thoại thông minh hoặc hệ điều hành máy tính nào, vân vân</value>
</data>
<data name="AssetTitle" xml:space="preserve">
<value>Một trình quản lý mật khẩu an toàn và miễn phí cho mọi thiết bị của bạn</value>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -130,6 +130,7 @@ const config = {
'content/autofill': './src/content/autofill.js',
'content/autofiller': './src/content/autofiller.ts',
'content/notificationBar': './src/content/notificationBar.ts',
'content/contextMenuHandler': './src/content/contextMenuHandler.ts',
'content/shortcuts': './src/content/shortcuts.ts',
'content/message_handler': './src/content/message_handler.ts',
'notification/bar': './src/notification/bar.js',