Compare commits

..

No commits in common. "develop" and "1.9.9.2" have entirely different histories.

83 changed files with 1798 additions and 5564 deletions

195
.eslintrc Normal file
View file

@ -0,0 +1,195 @@
{
"extends": "eslint:recommended",
"ignorePatterns": ["**/*.min.js"],
"env": {
"browser": true,
"es2022": true,
"jquery": true,
"webextensions": true
},
"parserOptions": {
"ecmaVersion": 13
},
"rules": {
"array-bracket-spacing": ["error", "always"],
"arrow-body-style": "warn",
"arrow-parens": "off",
"arrow-spacing": "warn",
"block-scoped-var": "off",
"brace-style": ["warn", "1tbs"],
"camelcase": "warn",
"class-methods-use-this": "off",
"comma-dangle": "off",
"computed-property-spacing": ["error", "never"],
"consistent-return": "off",
"dot-notation": "off",
"eqeqeq": "error",
"func-names": "off",
"function-paren-newline": "off",
"guard-for-in": "off",
"implicit-arrow-linebreak": "off",
"indent": ["error", 4],
"linebreak-style": ["error", "unix"],
"lines-around-comment": "off",
"max-len": "off",
"no-alert": "error",
"no-await-in-loop": "off",
"no-bitwise": "off",
"no-console": "off",
"no-continue": "off",
"no-control-regex": "off",
"no-else-return": "off",
"no-empty-function": ["error", { "allow": ["arrowFunctions", "methods", "asyncMethods"] }],
"no-extend-native": "off",
"no-global-assign": "off",
"no-lonely-if": "off",
"no-loop-func": "off",
"no-mixed-operators": "off",
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
"no-multi-spaces": "warn",
"no-param-reassign": "off",
"no-plusplus": "off",
"no-prototype-builtins": "off",
"no-redeclare": "off",
"no-restricted-globals": "off",
"no-restricted-syntax": "off",
"no-return-await": "off",
"no-tabs": "warn",
"no-underscore-dangle": "off",
"no-unused-vars": ["warn", { "args": "none", "varsIgnorePattern": "[A-Z_]+|tr|[$]" }],
"no-use-before-define": "off",
"no-useless-escape": "off",
"no-useless-return": "off",
"no-var": "error",
"object-curly-spacing": ["warn", "always"],
"object-shorthand": "off",
"operator-linebreak": "off",
"prefer-arrow-callback": "off",
"prefer-const": "warn",
"prefer-destructuring": "off",
"prefer-template": "off",
"quote-props": "off",
"quotes": ["error", "single", { "avoidEscape": true }],
"semi": ["error", "always"],
"space-before-blocks": "warn",
"space-before-function-paren": "off",
"space-in-parens": ["error", "never"],
"space-unary-ops": "off",
"spaced-comment": "off",
"strict": "off",
"vars-on-top": "off"
},
"globals": {
"_called": "readonly",
"acceptedOTPFields": "readonly",
"assertInputFields": "readonly",
"assertPasswordChangeFields": "readonly",
"assertRegex": "readonly",
"assertSearchField": "readonly",
"assertSearchForm": "readonly",
"assertTOTPField": "readonly",
"AssociatedAction": "readonly",
"AuthenticatorAssertionResponse": "readonly",
"AuthenticatorAttestationResponse": "readonly",
"Autocomplete": "readonly",
"BannerPosition": "readonly",
"BLUE_BUTTON": "readonly",
"bootstrap": "readonly",
"browser": "readonly",
"browserAction": "readonly",
"CHECK_UPDATE_NEVER": "readonly",
"CHECK_UPDATE_ONE_MONTH": "readonly",
"CHECK_UPDATE_ONE_WEEK": "readonly",
"CHECK_UPDATE_THREE_DAYS": "readonly",
"cloneInto": "readonly",
"compareVersion": "readonly",
"createResult": "readonly",
"createStylesheet": "readonly",
"DatabaseState": "readonly",
"debugLogMessage": "readonly",
"EXTENSION_NAME": "readonly",
"getCurrentTab": "readonly",
"getLoginData": "readonly",
"getTopLevelDomainFromUrl": "readonly",
"GRAY_BUTTON_CLASS": "readonly",
"GREEN_BUTTON": "readonly",
"httpAuth": "readonly",
"Icon": "readonly",
"IGNORE_AUTOSUBMIT": "readonly",
"IGNORE_FULL": "readonly",
"IGNORE_NORMAL": "readonly",
"IGNORE_NOTHING": "readonly",
"importScripts": "readonly",
"IMPROVED_DETECTION_PREDEFINED_SITELIST": "readonly",
"initColorTheme": "readonly",
"isEdge": "readonly",
"isFirefox": "readonly",
"keepass": "readonly",
"keepassClient": "readonly",
"kpActions": "readonly",
"kpErrors": "readonly",
"kpxc": "readonly",
"kpxcAssert": "readonly",
"kpxcBanner": "readonly",
"kpxcCustomLoginFieldsBanner": "readonly",
"kpxcEvent": "readonly",
"kpxcFields": "readonly",
"kpxcFill": "readonly",
"kpxcForm": "readonly",
"kpxcIcons": "readonly",
"kpxcObserverHelper": "readonly",
"kpxcPasswordGenerator": "readonly",
"kpxcPasswordIcons": "readonly",
"kpxcSites": "readonly",
"kpxcTOTPAutocomplete": "readonly",
"kpxcTOTPIcons": "readonly",
"kpxcUI": "readonly",
"kpxcUserAutocomplete": "readonly",
"kpxcUsernameIcons": "readonly",
"logDebug": "readonly",
"logError": "readonly",
"kpxcPasskeysUtils": "readonly",
"ManualFill": "readonly",
"matchesWithNodeName": "readonly",
"MAX_AUTOCOMPLETE_NAME_LEN": "readonly",
"MAX_OPACITY": "readonly",
"MAX_TOTP_INPUT_LENGTH": "readonly",
"menuContexts": "readonly",
"MIN_INPUT_FIELD_OFFSET_WIDTH": "readonly",
"MIN_INPUT_FIELD_WIDTH_PX": "readonly",
"MIN_OPACITY": "readonly",
"MIN_TOTP_INPUT_LENGTH": "readonly",
"module": "readonly",
"nacl": "readonly",
"ORANGE_BUTTON": "readonly",
"page": "readonly",
"Pixels": "readonly",
"PublicKeyCredential": "readonly",
"PREDEFINED_SITELIST": "readonly",
"RED_BUTTON": "readonly",
"retrieveColorScheme": "readonly",
"sendMessage": "readonly",
"showNotification": "readonly",
"siteMatch": "readonly",
"slashNeededForUrl": "readonly",
"SORT_BY_GROUP_AND_TITLE": "readonly",
"SORT_BY_GROUP_AND_USERNAME": "readonly",
"SORT_BY_MATCHING_CREDENTIALS_SETTING": "readonly",
"SORT_BY_RELEVANT_ENTRY": "readonly",
"SORT_BY_TITLE": "readonly",
"SORT_BY_USERNAME": "readonly",
"statusResponse": "readonly",
"Tests": "readonly",
"tr": "readonly",
"trimURL": "readonly",
"updateDefaultPasswordManager": "readonly"
},
"overrides": [
{
"files": ["./*.js"],
"env": {
"node": true
}
}
]
}

View file

@ -1,196 +0,0 @@
# Contributing to KeePassXC-Browser
The following is a set of guidelines for contributing to KeePassXC-Browser on GitHub.
These are just guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
#### Table of contents
[What should I know before I get started?](#what-should-i-know-before-i-get-started)
* [Open Source Contribution Policy](#open-source-contribution-policy)
[How can I contribute?](#how-can-i-contribute)
* [Feature requests](#feature-requests)
* [Bug reports](#bug-reports)
* [Discuss with the team](#discuss-with-the-team)
* [Your first code contribution](#your-first-code-contribution)
* [Using AI](#using-ai)
* [Pull requests](#pull-requests)
* [Translations](#translations)
[Styleguides](#styleguides)
* [Git branch strategy](#git-branch-strategy)
* [Git commit messages](#git-commit-messages)
* [Coding styleguide](#coding-styleguide)
## What should I know before I get started?
### Open Source Contribution Policy
**Source**: [Version 0.3, 20151118](https://medium.com/@jmaynard/a-contribution-policy-for-open-source-that-works-bfc4600c9d83#.i9ntbhmad)
#### Policy
We will accept contributions of good code that we can use from anyone.
#### What this means
This means exactly that. We dont care about anything but your code. We dont care about your race, religion, national origin, biological gender, perceived gender, sexual orientation, lifestyle, political viewpoint, or anything extraneous like that. We will neither reject your contribution nor grant it preferential treatment on any basis except the code itself. We do, however, reserve the right to limit your access to our community if you violate our [Code of Conduct][code-of-conduct].
#### If Your Contribution Is Rejected
If we reject your contribution, it means only that we do not consider it suitable for our project in the form it was submitted. It is not personal. If you ask civilly, we will be happy to discuss it with you and help you understand why it was rejected, and if possible improve it so we can accept it.
## How can I contribute?
### Feature requests
We're always looking for suggestions to improve our application. If you have a suggestion to improve an existing feature, or would like to suggest a completely new feature for KeePassXC, please use the [issue tracker on GitHub][issues-section].
### Bug reports
Our software isn't always perfect, but we strive to always improve our work. You may file bug reports in the issue tracker.
Before submitting a bug report, check if the problem has already been reported. Please refrain from opening a duplicate issue. If you want to add further information to an existing issue, simply add a comment on that issue.
### Discuss with the team
As with feature requests, you can talk to the KeePassXC team about bugs, new features, other issues and pull requests on the dedicated issue tracker, on the [Matrix development channel](https://matrix.to/#/!RhJPJPGwQIFVQeXqZa:matrix.org?via=matrix.org), or in the IRC channel on Libera.Chat (`#keepassxc-dev` on `irc.libera.chat`, or use a [webchat link](https://web.libera.chat/#keepassxc-dev)).
### Your first code contribution
Unsure where to begin contributing to KeePassXC? You can start by looking through these `beginner` and `help-wanted` issues:
* [Beginner issues][beginner] issues which should only require a few lines of code, and a test or two.
* ['Help wanted' issues][help-wanted] issues which should be a bit more involved than `beginner` issues.
Both issue lists are sorted by total number of comments. While not perfect, looking at the number of comments on an issue can give a general idea of how much an impact a given change will have.
### Using AI
Submissions written using generative AI (even partially) are not accepted.
### Pull requests
Along with our desire to hear your feedback and suggestions, we're also interested in accepting direct assistance in the form of code.
All pull requests must comply with the above requirements and with the [styleguides](#styleguides).
### Translations
Translations are managed on [Transifex](https://explore.transifex.com/keepassxc/keepassxc-browser/) which offers a web interface.
Please join an existing language team or request a new one if there is none.
If you open a Pull Request with new strings that require translations, it is enough to include new strings to the `_locales/en/messages.json` file.
### Architecture
Some basic information about the extension architecture is described in the [Extension details][extension-details] wiki page.
## Styleguides
### Git branch strategy
The Branch Strategy is based on [git-flow-lite](http://nvie.com/posts/a-successful-git-branching-model/).
* **develop** points to the development of the next release, contains tested and reviewed code
* **feature/**[name] points to a branch with a new feature, one which is candidate for merge into develop (subject to rebase)
* **fix/**[name] points to a branch with a fix for a particular issue ID
* **refactor/**[name] - points to a branch with a refactored feature
### Git commit messages
* Use the present tense ("Add feature" not "Added feature")
* Use the imperative mood ("Move cursor to…" not "Moves cursor to…")
* Limit the first line to 72 characters or less
* Reference issues and pull requests liberally
* If your pull request fixes an existing issue, add "Fixes #ISSUENUMBER" to your pull request description
### Coding styleguide
The coding style of the project is applied using `ESLint` and `Prettier` tools. A thorough description
of the coding style can be found in the `.eslintrc` and `.prettierrc` files, but the main conventions are presented here.
ESLint can be run manually by using the command `npm run lint`. Prettier formatting is not used by default because it can break some specific code styles, but can be enabled modifying the `.prettierignore` file.
#### Naming convention
`lowerCamelCase`
For names made of only one word, the first letter should be lowercase.
For names made of multiple concatenated words, the first letter of the whole is lowercase, and the first letter of each subsequent word is capitalized.
Applies to functions and Objects as well.
`UpperCamelCase`
For classes and enum-like Objects.
`ALL_CAPS`
For global/const variables and enum-like Object values.
#### Indention
- For **JavaScript files** (*.js): 4 spaces
- For **HTML files** (*.ui*): 2 spaces
- For **JSON files** (*.json): 2 spaces
- For **TypeScript files** (*.ts): 2 spaces
#### Global/const variables
```javascript
const TIMEOUT_VALUE 2000;
const DEFAULT_VALUE = 'all';
```
#### Classes
```javascript
class Icon {
constructor(databaseState) {
this.databaseState = databaseState;
this.icon = null;
}
}
```
#### Enum-like Objects
```javascript
const ManualFill = {
NONE: 0,
PASSWORD: 1,
BOTH: 2
};
```
#### Braces
```javascript
if (condition) {
doSomething();
} else {
doSomethingElse();
}
const exampleFunction = async function() {
doSomething();
};
```
#### Multiple conditions
```javascript
if (condition1 === condition2
|| condition3 === condition4
|| condition5 === condition6) {
doSomething();
}
if (['text1', 'text2', 'text3'].includes(inputText)) {
doSomething();
}
```
#### Variables
Always use `const` and `let` to define a variable. Do not use `var`.
[beginner]:https://github.com/keepassxreboot/keepassxc-browser/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22
[code-of-conduct]:https://github.com/keepassxreboot/keepassxc/blob/develop/CODE-OF-CONDUCT.md
[help-wanted]:https://github.com/keepassxreboot/keepassxc-browser/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22help%20wanted%22
[issues-section]:https://github.com/keepassxreboot/keepassxc-browser/issues
[extension-details]:https://github.com/keepassxreboot/keepassxc-browser/wiki/Extension-details@

View file

@ -1,94 +1,3 @@
1.10.0.1 (2026-03-08)
=========================
- Remove webRequestBlocking permission from V3 manifests [#2893]
- Fix dynamic password input detection when replacing username [#2896]
1.10.0 (2026-03-04)
=========================
- Add preliminary support for Safari [#2800]
- Add 'mfaCode' to accepted 2FA token fields (thanks hostops) [#2804]
- Add "postcode" to ignored TOTP list (thanks JackDunnCodes) [#2793]
- Add support for Related Origin Requests with passkeys [#2828]
- Add support for features list [#2848]
- Add support for publicKey in passkeys response [#2782]
- Fix hiding form switch animation when options page loads (thanks stefansundin) [#2807]
- Fix TOTP field detection with Microsoft sites [#2832]
- Fix the ability to fake same-orogin with passkeys (thanks a2kolbasov) [#2849]
- Fix detecting transitions [#2855]
- Fix Google password input detection [#2861]
- Fix Epic Games and Paypal password input detection [#2863]
- Fix using invalid parameters with MutationObserver [#2784]
- Fix ignoring partial nodeNames [#2745]
- Fix incorrect error message on keyboard fill [#2814]
- Fix reopen database shortcut (thanks a2kolbasov) [#2767]
- Fix showing notifications always on the top window [#2789]
- Fix missing digits in TOTP fill on some sites (thanks ElementW) [#2794]
- Fix setting default redirect allowance to 3 (thanks SinnySupernova) [#2797]
- Fix createObserver() check [#2873]
- Fix retry on input field detection with Custom Login Fields [#2875]
- Fix detecting new password input on forms [#2878]
- Fix form submit to ignore password related buttons [#2882]
- Refactor icon handling [#2791]
- Update webextension-polyfill library [#2822]
1.9.11 (2025-11-26)
=========================
- Add support for reseting all settings to defaults [#2720]
- Add support for toJSON() with createPublicKeyCredential (passkeys) [#2734]
- Add site exception for dei.gr [#2760]
- Add submit button exception for Dubverse [#2759]
- Add support for selecting a custom submit button with Custom Login Fields [#2756]
- Fix check for Firefox browser [#2724, #2725]
- Fix JavaScript error in console (thanks ygoe) [#2721]
- Fix overlap check with labels [#2731]
- Fix checking overlays before fill [#2733]
- Fix requerying form if password input changed [#2738]
- Fix incorrect fields variable [#2740]
- Fix malformed page content with passkeys script injection (thanks a2kolbasov) [#2757]
- Fix layout issues with banners [#2764]
- Update Playwright libraries [#2727]
1.9.10 (2025-10-05)
=========================
- Add Disable passkeys option to Site Preferences [#2694]
- Add overlay exceptions feature to Predefined Sites [#2693]
- Change DOM to use popover for icons and content [#2687]
- Change some icons [#2706]
- Fix detecting existing login combination [#2682]
- Fix Mutation Observer to handle multiple element mutations (thanks mihai-vlc) [#2635]
- Fix using popovers with Firefox ESR 115 [#2690]
- Fix filling relevant entries [#2691]
- Fix filling wrapped input fields [#2699]
- Fix filling username to already filled field [#2700]
- Fix ignore regex list (thanks EamonNerbonne) [#2711]
- Fix is element inside function [#2714]
- Fix handling window offsets for DOM content positioning [#2698]
- Refactor Site Preferences options settings page [#2666]
- Refactor browser information function [#2709]
1.9.9.6 (2025-09-09)
=========================
- Add caching to overlay detection for improved performance [#2670]
- Fix protection against form overlays [#2676]
- Fix using custom functions with Elements in TreeWalker [#2677]
1.9.9.5 (2025-09-03)
=========================
- Fix topmost input element check with labels [#2667]
- Fix Custom Login Fields with topmost element check [#2673]
1.9.9.4 (2025-08-29)
=========================
- Fix topmost element check with Shadow DOM [#2659]
1.9.9.3 (2025-08-27)
=========================
- Add protection against style changes for wrapper div elements [#2646]
- Add protection against for sandboxed iframes [#2648]
- Add protection against overlays [#2651]
- Add protection against html, body and form opacity [#2653]
- Add error message for untrusted iframes during fill [#2649]
1.9.9.2 (2025-08-21) 1.9.9.2 (2025-08-21)
========================= =========================
- Fix parent element opacity check for better clickjacking attempt prevention [#2641] - Fix parent element opacity check for better clickjacking attempt prevention [#2641]

View file

@ -1,12 +1,15 @@
# KeePassXC-Browser # KeePassXC-Browser
Browser extension for [KeePassXC](https://keepassxc.org/) with [native messaging](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging). Browser extension for [KeePassXC](https://keepassxc.org/) with [Native Messaging](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging).
Based on [pfn](https://github.com/pfn)'s [chromeIPass](https://github.com/pfn/passifox).
Some changes merged also from [smorks](https://github.com/smorks)' [KeePassHttp-Connector](https://github.com/smorks/keepasshttp-connector).
## Download and use ## Download and use
This browser extension was first supported in KeePassXC 2.3.0 (release end of 2017). In general it is advised to only use the latest available release. This browser extension was first supported in KeePassXC 2.3.0 (release end of 2017). In general it is advised to only use the latest available release.
Get the extension for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) or [Chrome/Chromium](https://chromewebstore.google.com/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk) or [Microsoft Edge](https://microsoftedge.microsoft.com/addons/detail/pdffhmdngciaglkoonimfcmckehcpafo). Get the extension for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) or [Chrome/Chromium](https://chromewebstore.google.com/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk) or [Microsoft Edge](https://microsoftedge.microsoft.com/addons/detail/pdffhmdngciaglkoonimfcmckehcpafo) (requires KeePassXC 2.5.3 or newer).
Please see this [document](https://keepassxc.org/docs/KeePassXC_GettingStarted.html#_browser_integration) for instructions how to configure KeePassXC in order to connect the database correctly. Please see this [document](https://keepassxc.org/docs/KeePassXC_GettingStarted.html#_browser_integration) for instructions how to configure KeePassXC in order to connect the database correctly.
@ -49,10 +52,6 @@ Check [keepassxc-protocol](keepassxc-protocol.md) for the details about the mess
Translations are managed on [Transifex](https://explore.transifex.com/keepassxc/keepassxc-browser/) which offers a web interface. Please join an existing language team or request a new one if there is none. Translations are managed on [Transifex](https://explore.transifex.com/keepassxc/keepassxc-browser/) which offers a web interface. Please join an existing language team or request a new one if there is none.
## Contributing
You may directly contribute your own code by submitting a pull request. Please read the [CONTRIBUTING](.github/CONTRIBUTING.md) document for further information.
## Development and testing ## Development and testing
See [wiki](https://github.com/keepassxreboot/keepassxc-browser/wiki/Loading-the-extension-manually). See [wiki](https://github.com/keepassxreboot/keepassxc-browser/wiki/Loading-the-extension-manually).

View file

@ -1,9 +1,9 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "KeePassXC-Browser", "name": "KeePassXC-Browser",
"version": "1.10.0.1", "version": "1.9.9.2",
"version_name": "1.10.0.1", "version_name": "1.9.9.2",
"minimum_chrome_version": "124", "minimum_chrome_version": "93",
"description": "__MSG_extensionDescription__", "description": "__MSG_extensionDescription__",
"author": "KeePassXC Team", "author": "KeePassXC Team",
"icons": { "icons": {
@ -53,8 +53,7 @@
"content/fields.js", "content/fields.js",
"content/fill.js", "content/fill.js",
"content/form.js", "content/form.js",
"content/icon.js", "content/icons.js",
"content/icon-handler.js",
"content/keepassxc-browser.js", "content/keepassxc-browser.js",
"content/observer-helper.js", "content/observer-helper.js",
"content/pwgen.js", "content/pwgen.js",
@ -119,15 +118,12 @@
"choose_credential_fields": { "choose_credential_fields": {
"description": "__MSG_popupChooseCredentialsText__" "description": "__MSG_popupChooseCredentialsText__"
}, },
"retrieve_credentials_forced": { "retrive_credentials_forced": {
"description": "__MSG_credentialsRetrieveButton__" "description": "__MSG_popupReopenButton__"
}, },
"request_autotype": { "request_autotype": {
"description": "__MSG_contextMenuRequestGlobalAutoType__" "description": "__MSG_contextMenuRequestGlobalAutoType__"
}, },
"reopen_database": {
"description": "__MSG_popupReopenButton__"
},
"reload_extension": { "reload_extension": {
"description": "__MSG_popupReloadButton__" "description": "__MSG_popupReloadButton__"
} }
@ -170,7 +166,8 @@
"tabs", "tabs",
"webNavigation", "webNavigation",
"webRequest", "webRequest",
"webRequestAuthProvider" "webRequestAuthProvider",
"webRequestBlocking"
], ],
"optional_permissions": [ "optional_permissions": [
"privacy" "privacy"

View file

@ -1,7 +1,7 @@
{ {
"manifest_version": 2, "manifest_version": 2,
"name": "KeePassXC-Browser", "name": "KeePassXC-Browser",
"version": "1.10.0.1", "version": "1.9.9.2",
"description": "__MSG_extensionDescription__", "description": "__MSG_extensionDescription__",
"author": "KeePassXC Team", "author": "KeePassXC Team",
"icons": { "icons": {
@ -66,8 +66,7 @@
"content/fields.js", "content/fields.js",
"content/fill.js", "content/fill.js",
"content/form.js", "content/form.js",
"content/icon.js", "content/icons.js",
"content/icon-handler.js",
"content/keepassxc-browser.js", "content/keepassxc-browser.js",
"content/observer-helper.js", "content/observer-helper.js",
"content/pwgen.js", "content/pwgen.js",
@ -132,15 +131,12 @@
"choose_credential_fields": { "choose_credential_fields": {
"description": "__MSG_popupChooseCredentialsText__" "description": "__MSG_popupChooseCredentialsText__"
}, },
"retrieve_credentials_forced": { "retrive_credentials_forced": {
"description": "__MSG_credentialsRetrieveButton__" "description": "__MSG_popupReopenButton__"
}, },
"request_autotype": { "request_autotype": {
"description": "__MSG_contextMenuRequestGlobalAutoType__" "description": "__MSG_contextMenuRequestGlobalAutoType__"
}, },
"reopen_database": {
"description": "__MSG_popupReopenButton__"
},
"reload_extension": { "reload_extension": {
"description": "__MSG_popupReloadButton__" "description": "__MSG_popupReloadButton__"
} }
@ -185,7 +181,7 @@
"applications": { "applications": {
"gecko": { "gecko": {
"id": "keepassxc-browser@keepassxc.org", "id": "keepassxc-browser@keepassxc.org",
"strict_min_version": "100.0" "strict_min_version": "96.0"
} }
}, },
"storage": { "storage": {

View file

@ -1,216 +0,0 @@
import { defineConfig, globalIgnores } from "eslint/config";
import globals from "globals";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
});
export default defineConfig([globalIgnores(["**/*.min.js"]), {
extends: compat.extends("eslint:recommended"),
languageOptions: {
globals: {
...globals.browser,
...globals.jquery,
...globals.webextensions,
_called: "readonly",
acceptedOTPFields: "readonly",
assertInputFields: "readonly",
assertPasswordChangeFields: "readonly",
assertRegex: "readonly",
assertSearchField: "readonly",
assertSearchForm: "readonly",
assertTOTPField: "readonly",
AssociatedAction: "readonly",
AuthenticatorAssertionResponse: "readonly",
AuthenticatorAttestationResponse: "readonly",
Autocomplete: "readonly",
BannerPosition: "readonly",
BLUE_BUTTON: "readonly",
bootstrap: "readonly",
browser: "readonly",
browserAction: "readonly",
CHECK_UPDATE_NEVER: "readonly",
CHECK_UPDATE_ONE_MONTH: "readonly",
CHECK_UPDATE_ONE_WEEK: "readonly",
CHECK_UPDATE_THREE_DAYS: "readonly",
cloneInto: "readonly",
compareVersion: "readonly",
createResult: "readonly",
createStylesheet: "readonly",
DatabaseState: "readonly",
debugLogMessage: "readonly",
DEFINED_CUSTOM_FIELDS: "readonly",
elementsOverlap: "readonly",
EXTENSION_NAME: "readonly",
getCurrentTab: "readonly",
getIconClass: "readonly",
getLoginData: "readonly",
getTopLevelDomainFromUrl: "readonly",
GRAY_BUTTON_CLASS: "readonly",
GREEN_BUTTON: "readonly",
httpAuth: "readonly",
Icon: "readonly",
IGNORE_AUTOSUBMIT: "readonly",
IGNORE_FULL: "readonly",
IGNORE_NORMAL: "readonly",
IGNORE_NOTHING: "readonly",
IGNORE_PASSKEYS: "readonly",
importScripts: "readonly",
IMPROVED_DETECTION_PREDEFINED_SITELIST: "readonly",
initColorTheme: "readonly",
isEdge: "readonly",
isElementInside: "readonly",
isFirefox: "readonly",
isIframeAllowed: "readonly",
isSafari: "readonly",
keepass: "readonly",
keepassClient: "readonly",
kpActions: "readonly",
kpErrors: "readonly",
kpxc: "readonly",
kpxcAssert: "readonly",
kpxcBanner: "readonly",
kpxcCustomLoginFieldsBanner: "readonly",
kpxcEvent: "readonly",
kpxcFields: "readonly",
kpxcFill: "readonly",
kpxcForm: "readonly",
kpxcIcons: "readonly",
kpxcObserverHelper: "readonly",
kpxcPasswordGenerator: "readonly",
kpxcPasswordIcons: "readonly",
kpxcSites: "readonly",
kpxcTOTPAutocomplete: "readonly",
kpxcTOTPIcons: "readonly",
kpxcUI: "readonly",
kpxcUserAutocomplete: "readonly",
kpxcUsernameIcons: "readonly",
logDebug: "readonly",
logError: "readonly",
kpxcPasskeysUtils: "readonly",
ManualFill: "readonly",
matchesWithNodeName: "readonly",
MAX_AUTOCOMPLETE_NAME_LEN: "readonly",
MAX_OPACITY: "readonly",
MAX_TOTP_INPUT_LENGTH: "readonly",
menuContexts: "readonly",
MIN_INPUT_FIELD_OFFSET_WIDTH: "readonly",
MIN_INPUT_FIELD_WIDTH_PX: "readonly",
MIN_OPACITY: "readonly",
MIN_TOTP_INPUT_LENGTH: "readonly",
module: "readonly",
nacl: "readonly",
OBSERVER_OPTIONS: "readonly",
ORANGE_BUTTON: "readonly",
page: "readonly",
Pixels: "readonly",
PublicKeyCredential: "readonly",
PREDEFINED_SITELIST: "readonly",
RED_BUTTON: "readonly",
retrieveColorScheme: "readonly",
sendMessage: "readonly",
showNotification: "readonly",
siteMatch: "readonly",
SitePreferences: "readonly",
slashNeededForUrl: "readonly",
SORT_BY_GROUP_AND_TITLE: "readonly",
SORT_BY_GROUP_AND_USERNAME: "readonly",
SORT_BY_MATCHING_CREDENTIALS_SETTING: "readonly",
SORT_BY_RELEVANT_ENTRY: "readonly",
SORT_BY_TITLE: "readonly",
SORT_BY_USERNAME: "readonly",
statusResponse: "readonly",
Tests: "readonly",
tr: "readonly",
trimURL: "readonly",
updateDefaultPasswordManager: "readonly",
},
ecmaVersion: 13,
sourceType: "script",
},
rules: {
"array-bracket-spacing": ["error", "always"],
"arrow-body-style": "warn",
"arrow-parens": "off",
"arrow-spacing": "warn",
"block-scoped-var": "off",
"brace-style": ["warn", "1tbs"],
"camelcase": "warn",
"class-methods-use-this": "off",
"comma-dangle": "off",
"computed-property-spacing": ["error", "never"],
"consistent-return": "off",
"dot-notation": "off",
"eqeqeq": "error",
"func-names": "off",
"function-paren-newline": "off",
"guard-for-in": "off",
"implicit-arrow-linebreak": "off",
"indent": ["error", 4],
"linebreak-style": ["error", "unix"],
"lines-around-comment": "off",
"max-len": "off",
"no-alert": "error",
"no-await-in-loop": "off",
"no-bitwise": "off",
"no-console": "off",
"no-continue": "off",
"no-control-regex": "off",
"no-else-return": "off",
"no-empty-function": ["error", {
"allow": ["arrowFunctions", "methods", "asyncMethods"],
}],
"no-extend-native": "off",
"no-global-assign": "off",
"no-lonely-if": "off",
"no-loop-func": "off",
"no-mixed-operators": "off",
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
"no-multi-spaces": "warn",
"no-param-reassign": "off",
"no-plusplus": "off",
"no-prototype-builtins": "off",
"no-redeclare": "off",
"no-restricted-globals": "off",
"no-restricted-syntax": "off",
"no-return-await": "off",
"no-tabs": "warn",
"no-underscore-dangle": "off",
"no-unused-vars": ["warn", {
"args": "none",
"caughtErrorsIgnorePattern": "^_",
"varsIgnorePattern": "[A-Z_]+|tr|[$]",
}],
"no-use-before-define": "off",
"no-useless-escape": "off",
"no-useless-return": "off",
"no-var": "error",
"object-curly-spacing": ["warn", "always"],
"object-shorthand": "off",
"operator-linebreak": "off",
"prefer-arrow-callback": "off",
"prefer-const": "warn",
"prefer-destructuring": "off",
"prefer-template": "off",
"quote-props": "off",
"quotes": ["error", "single", {
"avoidEscape": true,
}],
"semi": ["error", "always"],
"space-before-blocks": "warn",
"space-before-function-paren": "off",
"space-in-parens": ["error", "never"],
"space-unary-ops": "off",
"spaced-comment": "off",
"strict": "off",
"vars-on-top": "off",
},
}]);

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "Текстово поле", "message": "Поле за низ",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Изпращащ бутон",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Избиране поле за потребителското име", "message": "Избиране поле за потребителското име",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Избиране на поле за низ", "message": "Избиране на поле за низ",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Избиране на изпращащ бутон",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Потвърдете избора си или изберете повече полета като текстови полета.", "message": "Потвърдете избора си или изберете повече полета като полета за низ.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Също можете да използвате цифрите, за да избирате полета посредством клавиатурата.", "message": "Също можете да използвате цифрите, за да избирате полета посредством клавиатурата.",
@ -370,10 +362,6 @@
"message": "Полета за низове", "message": "Полета за низове",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Изпращащ бутон",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- без потребителско име -", "message": "- без потребителско име -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Не са намерени данни за вход.", "message": "Не са намерени данни за вход.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Попълването на регистрации е спряно в несигурна рамка.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Повече от една регистрация е намерена в KeePassXC!", "message": "Повече от една регистрация е намерена в KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Изтекъл", "message": "Изтекъл",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Получаване на регистрации",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Грешка: Не са намерени полета, които да бъдат попълнени.", "message": "Грешка: Не са намерени полета, които да бъдат попълнени.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Предпочитания за сайтове", "message": "Предпочитания за сайтове",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Настройки",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Относно", "message": "Относно",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Изнасяне на настройки", "message": "Изнасяне на настройки",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Нулиране на настройките",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Група по подразбиране при добавяне на регистрации:", "message": "Група по подразбиране при добавяне на регистрации:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Изисква KeePassXC издание: $1", "message": "Изисква KeePassXC издание: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "Разширението изисква KeePassXC издание $1. По-ранни издания могат да доведат до нежелано поведение.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "По подразбиране: $1", "message": "По подразбиране: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Текущите настройки ще бъдат презаписани. Наистина ли желаете да бъдат внесени настройките от файла?", "message": "Текущите настройки ще бъдат презаписани. Наистина ли желаете да бъдат внесени настройките от файла?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Желаете ли настройките да бъдат нулирани до подразбираните стойности?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Хранилища, свързани с KeePassXC-Browser.", "message": "Хранилища, свързани с KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Адрес на страница", "message": "Адрес на страница",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Възможности", "message": "Пренебрегване",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Изключване на автоматично изпращане", "message": "Изключване на автоматично изпращане",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Изключване на Passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Изключване на всички функции", "message": "Изключване на всички функции",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -370,10 +370,6 @@
"message": "Chyba:\nNenalezena žádná uživatelská jména.", "message": "Chyba:\nNenalezena žádná uživatelská jména.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Chyba:\nV KeePassXC nalezeno více než jedno uživateské jméno!\nKliknutím na ikonu KeePassXC-Browser zobrazíte další možnosti.", "message": "Chyba:\nV KeePassXC nalezeno více než jedno uživateské jméno!\nKliknutím na ikonu KeePassXC-Browser zobrazíte další možnosti.",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "Strengfelt",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Vælg et brugernavnsfelt", "message": "Vælg et brugernavnsfelt",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Vælg strengfelter", "message": "Vælg strengfelter",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "Bekræft venligst dine valg eller vælge flere felter as strengfelter.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Du kan også bruge nummeret til at vælge inputfelterne fra tastaturet.", "message": "Du kan også bruge nummeret til at vælge inputfelterne fra tastaturet.",
@ -370,10 +362,6 @@
"message": "Strengfelter", "message": "Strengfelter",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- intet brugernavn -", "message": "- intet brugernavn -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Fandt ingen logins.", "message": "Fandt ingen logins.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Fandt mere end ét login i KeePassXC!", "message": "Fandt mere end ét login i KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Udløbet", "message": "Udløbet",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Fejl: Kan ikke finde felterne som skal udfyldes.", "message": "Fejl: Kan ikke finde felterne som skal udfyldes.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Sideindstillinger", "message": "Sideindstillinger",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Om", "message": "Om",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Eksportér indstillinger", "message": "Eksportér indstillinger",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Standardgruppe for gemte nye adgangskoder:", "message": "Standardgruppe for gemte nye adgangskoder:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Kræver KeePassXC-version: $1", "message": "Kræver KeePassXC-version: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Standard: $1", "message": "Standard: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "De nuværende indstillinger tilsidesættes. Vil du virkelig importere indstillingsfilen?", "message": "De nuværende indstillinger tilsidesættes. Vil du virkelig importere indstillingsfilen?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Databaser som er forbundet til KeePassXC-Browser.", "message": "Databaser som er forbundet til KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Sidens URL", "message": "Sidens URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "Ignorer",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Slå autoindsendelse fra", "message": "Slå autoindsendelse fra",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Deaktivér alle funktionaliteter", "message": "Deaktivér alle funktionaliteter",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -322,10 +322,6 @@
"message": "Zeichenkettenfeld", "message": "Zeichenkettenfeld",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Senden-Schaltfläche",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Feld für Benutzernamen auswählen", "message": "Feld für Benutzernamen auswählen",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Zeichenkettenfelder auswählen", "message": "Zeichenkettenfelder auswählen",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Senden-Schaltfläche auswählen",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Bitte bestätigen Sie Ihre Auswahl oder wählen Sie weitere Felder als Zeichenkettenfelder aus.", "message": "Bitte bestätigen Sie Ihre Auswahl oder wählen Sie weitere Felder als <em>Zeichenkettenfelder</em> aus.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Sie können die Zahlen auch verwenden, um die Eingabefelder über die Tastatur auszuwählen.", "message": "Sie können die Zahlen auch verwenden, um die Eingabefelder über die Tastatur auszuwählen.",
@ -370,10 +362,6 @@
"message": "Zeichenkettenfelder", "message": "Zeichenkettenfelder",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Senden-Schaltfläche",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- kein Benutzername -", "message": "- kein Benutzername -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Keine Anmeldungen gefunden.", "message": "Keine Anmeldungen gefunden.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Ausfüllen der Anmeldedaten in nicht vertrauenswürdigen iframes blockiert.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "In KeePassXC wurde mehr als eine Anmeldung gefunden!", "message": "In KeePassXC wurde mehr als eine Anmeldung gefunden!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Abgelaufen", "message": "Abgelaufen",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Anmeldedaten abrufen",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Fehler:\nAuszufüllende Felder können nicht gefunden werden.", "message": "Fehler:\nAuszufüllende Felder können nicht gefunden werden.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Seiteneinstellungen", "message": "Seiteneinstellungen",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Einstellungen",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Über", "message": "Über",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Einstellungen exportieren", "message": "Einstellungen exportieren",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Alle Einstellungen zurücksetzen",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Standardgruppe zum Speichern neuer Passwörter:", "message": "Standardgruppe zum Speichern neuer Passwörter:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Benötigt KeePassXC-Version: $1", "message": "Benötigt KeePassXC-Version: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "Die Erweiterung erfordert die KeePassXC-Version: $1. Frühere Versionen können zu unerwünschtem Verhalten führen.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Standard: $1", "message": "Standard: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Die aktuellen Einstellungen werden überschrieben. Möchten Sie die Einstellungsdatei wirklich importieren?", "message": "Die aktuellen Einstellungen werden überschrieben. Möchten Sie die Einstellungsdatei wirklich importieren?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Alle Einstellungen werden auf die Standardeinstellungen zurückgesetzt. Sind Sie sicher?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Die folgenden KeePassXC-Datenbanken sind mit dem KeePassXC-Browser verbunden.", "message": "Die folgenden KeePassXC-Datenbanken sind mit dem KeePassXC-Browser verbunden.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Seiten-URL", "message": "Seiten-URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Funktionen", "message": "Ignorieren",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Automatisches Absenden deaktivieren", "message": "Automatisches Absenden deaktivieren",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Passkeys deaktivieren",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Alle Funktionen deaktivieren", "message": "Alle Funktionen deaktivieren",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "Πεδίο String",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Επιλέξτε ένα πεδίο ονόματος χρήστη", "message": "Επιλέξτε ένα πεδίο ονόματος χρήστη",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Επιλέξτε Πεδία Strings", "message": "Επιλέξτε Πεδία Strings",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "Επιβεβαιώστε την επιλογή σας ή επιλέξτε περισσότερα πεδία ως πεδία String.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Μπορείτε επίσης να χρησιμοποιήσετε τους αριθμούς για να επιλέξετε τα πεδία εισαγωγής από το πληκτρολόγιο.", "message": "Μπορείτε επίσης να χρησιμοποιήσετε τους αριθμούς για να επιλέξετε τα πεδία εισαγωγής από το πληκτρολόγιο.",
@ -370,10 +362,6 @@
"message": "Πεδία Strings", "message": "Πεδία Strings",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- χωρίς όνομα χρήστη -", "message": "- χωρίς όνομα χρήστη -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Δεν βρέθηκαν συνδέσεις.", "message": "Δεν βρέθηκαν συνδέσεις.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Περισσότερες από μία συνδέσεις βρέθηκαν στο KeePassXC!", "message": "Περισσότερες από μία συνδέσεις βρέθηκαν στο KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Έληξε", "message": "Έληξε",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Σφάλμα: Δεν είναι δυνατή η εύρεση πεδίων για συμπλήρωση.", "message": "Σφάλμα: Δεν είναι δυνατή η εύρεση πεδίων για συμπλήρωση.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Site Preferences", "message": "Site Preferences",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Σχετικά με", "message": "Σχετικά με",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Ρυθμίσεις εξαγωγής", "message": "Ρυθμίσεις εξαγωγής",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Προεπιλεγμένη ομάδα για την αποθήκευση νέων κωδικών πρόσβασης:", "message": "Προεπιλεγμένη ομάδα για την αποθήκευση νέων κωδικών πρόσβασης:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Απαιτείται έκδοση KeePassXC: $1", "message": "Απαιτείται έκδοση KeePassXC: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Προεπιλογή: $1", "message": "Προεπιλογή: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Οι τρέχουσες ρυθμίσεις θα παρακαμφθούν. Θέλετε πραγματικά να εισαγάγετε το αρχείο ρυθμίσεων;", "message": "Οι τρέχουσες ρυθμίσεις θα παρακαμφθούν. Θέλετε πραγματικά να εισαγάγετε το αρχείο ρυθμίσεων;",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Συνδεδεμένες βάσεις δεδομένων με το KeePassXC-Browser.", "message": "Συνδεδεμένες βάσεις δεδομένων με το KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Διεύθυνση URL σελίδας", "message": "Διεύθυνση URL σελίδας",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "Αγνοήστε",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Απενεργοποίηση Αυτόματης Υποβολής", "message": "Απενεργοποίηση Αυτόματης Υποβολής",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Απενεργοποίηση όλων των λειτουργιών", "message": "Απενεργοποίηση όλων των λειτουργιών",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "String field",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Choose a username field", "message": "Choose a username field",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Choose String Fields", "message": "Choose String Fields",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "Please confirm your selection or choose more fields as String fields.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "You can also use the numbers to choose the input fields from keyboard.", "message": "You can also use the numbers to choose the input fields from keyboard.",
@ -370,10 +362,6 @@
"message": "String Fields", "message": "String Fields",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- no username -", "message": "- no username -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "No logins found.", "message": "No logins found.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "More than one login was found in KeePassXC!", "message": "More than one login was found in KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Expired", "message": "Expired",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Error: Cannot find fields to fill in.", "message": "Error: Cannot find fields to fill in.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Site Preferences", "message": "Site Preferences",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "About", "message": "About",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Export settings", "message": "Export settings",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Default group for saving new passwords:", "message": "Default group for saving new passwords:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Requires KeePassXC version: $1", "message": "Requires KeePassXC version: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Default: $1", "message": "Default: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Current settings will be overridden. Do you really want to import the settings file?", "message": "Current settings will be overridden. Do you really want to import the settings file?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Databases connected to KeePassXC-Browser.", "message": "Databases connected to KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Page URL", "message": "Page URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "Ignore",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Disable Auto-Submit", "message": "Disable Auto-Submit",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Disable all features", "message": "Disable all features",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "String field",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Choose a username field", "message": "Choose a username field",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Choose String Fields", "message": "Choose String Fields",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "Please confirm your selection or choose more fields as String fields.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "You can also use the numbers to choose the input fields from keyboard.", "message": "You can also use the numbers to choose the input fields from keyboard.",
@ -370,10 +362,6 @@
"message": "String Fields", "message": "String Fields",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- no username -", "message": "- no username -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "No logins found.", "message": "No logins found.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "More than one login was found in KeePassXC!", "message": "More than one login was found in KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Expired", "message": "Expired",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Error: Cannot find fields to fill in.", "message": "Error: Cannot find fields to fill in.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Site Preferences", "message": "Site Preferences",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "About", "message": "About",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Export settings", "message": "Export settings",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Default group for saving new passwords:", "message": "Default group for saving new passwords:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Requires KeePassXC version: $1", "message": "Requires KeePassXC version: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behaviour.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Default: $1", "message": "Default: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Current settings will be overridden. Do you really want to import the settings file?", "message": "Current settings will be overridden. Do you really want to import the settings file?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Databases connected to KeePassXC-Browser.", "message": "Databases connected to KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Page URL", "message": "Page URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "Ignore",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Disable Auto-Submit", "message": "Disable Auto-Submit",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Disable all features", "message": "Disable all features",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -322,10 +322,6 @@
"message": "Campo de cadena", "message": "Campo de cadena",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Botón Enviar",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Elija un campo nombre de usuario", "message": "Elija un campo nombre de usuario",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Elija Campos de Cadena", "message": "Elija Campos de Cadena",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Seleccione el botón enviar",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Confirme su selección o elija más campos como campos de cadena.", "message": "Confirme su selección o elija más campos como Campos de cadena.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "También puede utilizar los números para elegir los campos de entrada desde el teclado.", "message": "También puede utilizar los números para elegir los campos de entrada desde el teclado.",
@ -370,10 +362,6 @@
"message": "Campos de Cadena", "message": "Campos de Cadena",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Botón Enviar",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- sin nombre de usuario -", "message": "- sin nombre de usuario -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "No se encontraron inicios de sesión.", "message": "No se encontraron inicios de sesión.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Relleno de credenciales bloqueado en iframe que no es de confianza.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "¡Se encontró más de un inicio de sesión en KeePassXC!", "message": "¡Se encontró más de un inicio de sesión en KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Caducado", "message": "Caducado",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Error: No se pueden encontrar campos para rellenar.", "message": "Error: No se pueden encontrar campos para rellenar.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Preferencias del sitio", "message": "Preferencias del sitio",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Configuración",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Acerca de", "message": "Acerca de",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Exportar configuración", "message": "Exportar configuración",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Restablecer todos los ajustes",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Grupo predeterminado para guardar nuevas contraseñas:", "message": "Grupo predeterminado para guardar nuevas contraseñas:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Requiere la versión de KeePassXC: $1", "message": "Requiere la versión de KeePassXC: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Por defecto: $1", "message": "Por defecto: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "La configuración actual será sobrescrita. ¿Desea importar el archivo de configuración?", "message": "La configuración actual será sobrescrita. ¿Desea importar el archivo de configuración?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Todos los ajustes se restablecerán a los valores predeterminados. ¿Está seguro?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Las siguientes bases de datos KeePassXC están conectadas a KeePassXC-Browser.", "message": "Las siguientes bases de datos KeePassXC están conectadas a KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "URL de la página", "message": "URL de la página",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Características", "message": "Ignorar",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Deshabilitar autoenvío", "message": "Deshabilitar autoenvío",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Deshabilitar claves de acceso",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Desactivar todas las características", "message": "Desactivar todas las características",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "Lisämerkkijonokenttä", "message": "Lisämerkkijonokenttä #",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Lähetä-nappi",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Valitse käyttäjätunnuksen kenttä", "message": "Valitse käyttäjätunnuksen kenttä",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Valitse lisämerkkijonokentät", "message": "Valitse lisämerkkijonokentät",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Valitse lähetä-nappi",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Vahvista valintasi tai merkitse lisää kenttiä lisämerkkijonokentiksi.", "message": "Vahvista valintasi tai merkitse lisää kenttiä <em>lisämerkkijonokentiksi</em>.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Voit myös valita kenttiä käyttämällä näppäimistön numeroita.", "message": "Voit myös valita kenttiä käyttämällä näppäimistön numeroita.",
@ -370,10 +362,6 @@
"message": "Lisämerkkijonokentät", "message": "Lisämerkkijonokentät",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Lähetä-nappi",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- ei käyttäjätunnusta -", "message": "- ei käyttäjätunnusta -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Virhe:\nTunnuksia ei löydy.", "message": "Virhe:\nTunnuksia ei löydy.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Tietueiden täyttö estettiin epäluotettavaan iframe-upotukseen.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Virhe:\nKeePassXC löysi useampia tilitietoja!\nPaina selainlaajennuksen ikonia nähdäksesi lisävalinnat.", "message": "Virhe:\nKeePassXC löysi useampia tilitietoja!\nPaina selainlaajennuksen ikonia nähdäksesi lisävalinnat.",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Vanhentunut", "message": "Vanhentunut",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Hae tietueet",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Virhe:\nTäytön tarvitsemia kenttiä ei löydy.", "message": "Virhe:\nTäytön tarvitsemia kenttiä ei löydy.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Sivustokohtaiset asetukset", "message": "Sivustokohtaiset asetukset",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Asetukset",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Tietoja", "message": "Tietoja",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Vie asetukset", "message": "Vie asetukset",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Palauta kaikki asetukset oletuksiin",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Oletusryhmä johon uudet salasanat tallennetaan:", "message": "Oletusryhmä johon uudet salasanat tallennetaan:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Vaatii KeePassXC:n version: $1", "message": "Vaatii KeePassXC:n version: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "Tämä selainlaajennus vaatii KeePassXC-version: $1. Aiemmat versiot voivat aiheuttaa epätoivottua käytöstä.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Oletus: $1", "message": "Oletus: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Nykyiset asetukset ylikirjoitetaan. Oletko varma, että haluat tuoda asetustiedoston?", "message": "Nykyiset asetukset ylikirjoitetaan. Oletko varma, että haluat tuoda asetustiedoston?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Kaikki asetukset palautetaan oletuksiin. Oletko varma?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Seuraavat KeePassXC:n tietokannat ovat yhdistettynä selainlaajennukseen.", "message": "Seuraavat KeePassXC:n tietokannat ovat yhdistettynä selainlaajennukseen.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Sivun URL", "message": "Sivun URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Ominaisuudet", "message": "Älä huomioi",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Automattisyöttö pois päältä", "message": "Automattisyöttö pois päältä",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Poista pääsyavaimet käytöstä",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Poista kaikki ominaisuudet käytöstä", "message": "Poista kaikki ominaisuudet käytöstä",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "Champ de chaînes de caractères", "message": "Champ de chaîne de caractères",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Bouton denvoi",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Choisissez un champ de nom dutilisateur", "message": "Choisissez un champ de nom dutilisateur",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Choisissez des champs de chaînes de caractères", "message": "Choisissez des champs de chaînes de caractères",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choisir le bouton denvoi",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Confirmez votre choix ou choisissez dautres champs comme champs de chaînes de caractères.", "message": "Confirmez votre choix ou choisissez dautres champs comme champs de chaînes de caractères.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Vous pouvez aussi utiliser les chiffres pour choisir les champs dentrée avec le clavier.", "message": "Vous pouvez aussi utiliser les chiffres pour choisir les champs dentrée avec le clavier.",
@ -370,10 +362,6 @@
"message": "Champs de type chaîne", "message": "Champs de type chaîne",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Bouton denvoi",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": " aucun nom dutilisateur ", "message": " aucun nom dutilisateur ",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Aucun identifiant na été trouvé.", "message": "Aucun identifiant na été trouvé.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "La saisie des identifiants a été bloquée par un cadre intégré non fiable",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Plus dun identifiant a été trouvé dans KeePassXC", "message": "Plus dun identifiant a été trouvé dans KeePassXC",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "est expiré", "message": "est expiré",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Obtenir les identifiants.",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Erreur : Impossible de trouver des champs à remplir.", "message": "Erreur : Impossible de trouver des champs à remplir.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Préférences des sites", "message": "Préférences des sites",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Paramètres",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "À propos", "message": "À propos",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Exporter les paramètres", "message": "Exporter les paramètres",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Réinitialiser tous les paramètres",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Groupe par défaut pour lenregistrement des nouveaux mots de passe :", "message": "Groupe par défaut pour lenregistrement des nouveaux mots de passe :",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Exige KeePassXC version : $1", "message": "Exige KeePassXC version : $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "Lextension nécessite la version KeePassXC : $1. Les versions antérieures peuvent entraîner des comportements indésirables.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Par défaut : $1", "message": "Par défaut : $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Les paramètres actuels seront remplacés. Voulez-vous importer le fichier de paramètres?", "message": "Les paramètres actuels seront remplacés. Voulez-vous importer le fichier de paramètres?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Tous les paramètres seront réinitialisés aux valeurs par défaut. Confirmez-vous?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Bases de données KeePassXC connectées à KeePassXC-Browser.", "message": "Bases de données KeePassXC connectées à KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "URL de la page", "message": "URL de la page",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Fonctions", "message": "Ignorer",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Désactiver lenvoi automatique", "message": "Désactiver lenvoi automatique",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Désactiver les clés daccès",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Désactiver toutes les fonctions", "message": "Désactiver toutes les fonctions",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "שדה מחרוזת #",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "נא לבחור שדה שם משתמש", "message": "נא לבחור שדה שם משתמש",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "נא לבחור שדה מחרוזת", "message": "נא לבחור שדה מחרוזת",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "נא לאשר את הבחירה או לבחור שדות נוספים כשדות מחרוזת.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "ניתן להשתמש גם במספרים לבחירת שדות הקלט מלוח המקשים.", "message": "ניתן להשתמש גם במספרים לבחירת שדות הקלט מלוח המקשים.",
@ -370,10 +362,6 @@
"message": "שדות מחרוזת", "message": "שדות מחרוזת",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- אין שם משתמש -", "message": "- אין שם משתמש -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "לא נמצאו התחברויות.", "message": "לא נמצאו התחברויות.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "נמצאה יותר מהתחברות אחת ל־KeePassXC!", "message": "נמצאה יותר מהתחברות אחת ל־KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "תפוגה", "message": "תפוגה",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "שגיאה: לא ניתן למצוא שדות למילוי.", "message": "שגיאה: לא ניתן למצוא שדות למילוי.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "העדפות אתר", "message": "העדפות אתר",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "אודות", "message": "אודות",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "ייצוא הגדרות", "message": "ייצוא הגדרות",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "קבוצת ברירת מחדל לשמירת ססמאות חדשות:", "message": "קבוצת ברירת מחדל לשמירת ססמאות חדשות:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "נדרשת גרסת KeePassXC: $1", "message": "נדרשת גרסת KeePassXC: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "ברירת מחדל: $1", "message": "ברירת מחדל: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "ההגדרות הנוכחיות יידרסו. האם לייבא את קובץ ההגדרות?", "message": "ההגדרות הנוכחיות יידרסו. האם לייבא את קובץ ההגדרות?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "מסדי נתונים מחוברים לדפדפן־KeePassXC.", "message": "מסדי נתונים מחוברים לדפדפן־KeePassXC.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "מען URL עמוד", "message": "מען URL עמוד",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "להתעלם",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "השבתת הגשה אוטומטית", "message": "השבתת הגשה אוטומטית",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "השבתת כל התכונות", "message": "השבתת כל התכונות",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -8,7 +8,7 @@
"description": "Add button title text on Site Preferences tab." "description": "Add button title text on Site Preferences tab."
}, },
"editSitePreferenceButtonTitle": { "editSitePreferenceButtonTitle": {
"message": "URL-cím szerkesztése ezen webhely beállításai számára.", "message": "Edit URL for this Site Preferences.",
"description": "Edit button title text on Site Preferences tab." "description": "Edit button title text on Site Preferences tab."
}, },
"allowIframeButtonTitle": { "allowIframeButtonTitle": {
@ -20,7 +20,7 @@
"description": "Connect button title text." "description": "Connect button title text."
}, },
"copyDebugInfoButtonTitle": { "copyDebugInfoButtonTitle": {
"message": "Hibakeresési információk másolása a vágólapra", "message": "Copy debug info to clipboard",
"description": "Copy debug info button title text on About tab." "description": "Copy debug info button title text on About tab."
}, },
"dismissHttpAuthButtonTitle": { "dismissHttpAuthButtonTitle": {
@ -322,10 +322,6 @@
"message": "Karakterláncmező", "message": "Karakterláncmező",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Beküldés gomb",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Válasszon egy felhasználónév-mezőt", "message": "Válasszon egy felhasználónév-mezőt",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Válasszon egy karakterláncmezőt", "message": "Válasszon egy karakterláncmezőt",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Beküldés gomb kijelölése",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Erősítse meg a választását vagy válasszon több mezőt <em>karakterlánc mezőkként</em>.", "message": "Erősítse meg a választását vagy válasszon több mezőt <em>karakterlánc mezőkként</em>.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Használhatja a billentyűzeten lévő számokat is a beviteli mezők kiválasztásához.", "message": "Használhatja a billentyűzeten lévő számokat is a beviteli mezők kiválasztásához.",
@ -370,10 +362,6 @@
"message": "Karakterláncmezők", "message": "Karakterláncmezők",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Beküldés gomb",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": " nincs felhasználónév ", "message": " nincs felhasználónév ",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Hiba:\nNem találhatók bejelentkezések.", "message": "Hiba:\nNem találhatók bejelentkezések.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "A hitelesítő adatok kitöltése blokkolása a nem megbízható iframe-ben.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Hiba:\nTöbb mint egy bejelentkezés található a KeePassXC programban!\nNyomja meg a KeePassXC-böngésző ikont a több lehetőségért.", "message": "Hiba:\nTöbb mint egy bejelentkezés található a KeePassXC programban!\nNyomja meg a KeePassXC-böngésző ikont a több lehetőségért.",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Lejárt", "message": "Lejárt",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Hitelesítő adatok lekérése",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Hiba:\nNem találhatók kitöltendő mezők.", "message": "Hiba:\nNem találhatók kitöltendő mezők.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -647,11 +627,11 @@
"description": "Dismiss button text when in HTTP Authentication popup." "description": "Dismiss button text when in HTTP Authentication popup."
}, },
"optionsDefaultSettingsTitle": { "optionsDefaultSettingsTitle": {
"message": "Alapértelmezett beállítások", "message": "Default settings",
"description": "Default settings title for Getting Started page." "description": "Default settings title for Getting Started page."
}, },
"optionsWelcomeTitle": { "optionsWelcomeTitle": {
"message": "KeePassXC-böngésző", "message": "KeePassXC-Browser",
"description": "Main card title for Getting Started page." "description": "Main card title for Getting Started page."
}, },
"optionsTitle": { "optionsTitle": {
@ -694,10 +674,6 @@
"message": "Oldalbeállítások", "message": "Oldalbeállítások",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Beállítások",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Névjegy", "message": "Névjegy",
"description": "About page header." "description": "About page header."
@ -723,7 +699,7 @@
"description": "Add button text." "description": "Add button text."
}, },
"optionsButtonEdit": { "optionsButtonEdit": {
"message": "Szerkesztés", "message": "Edit",
"description": "Edit button text." "description": "Edit button text."
}, },
"optionsButtonUpdate": { "optionsButtonUpdate": {
@ -750,10 +726,6 @@
"message": "Beállítások exportálása", "message": "Beállítások exportálása",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Minden beállítás visszaállítása",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Alapértelmezett csoport az új jelszavak mentéséhez:", "message": "Alapértelmezett csoport az új jelszavak mentéséhez:",
"description": "Default group options text." "description": "Default group options text."
@ -811,7 +783,7 @@
"description": "Automatically fill-in single credential entry checkbox text." "description": "Automatically fill-in single credential entry checkbox text."
}, },
"optionsCheckboxAutoFillRelevantCredential": { "optionsCheckboxAutoFillRelevantCredential": {
"message": "Releváns hitelesítésiadat-bejegyzések automatikus kitöltése", "message": "Automatically fill in relevant credential entries",
"description": "Automatically fill-in relevant credential entry checkbox text." "description": "Automatically fill-in relevant credential entry checkbox text."
}, },
"optionsCheckboxAutoFillSingleTotp": { "optionsCheckboxAutoFillSingleTotp": {
@ -855,11 +827,11 @@
"description": "Show login notifications checkbox text." "description": "Show login notifications checkbox text."
}, },
"optionsDefaultPasswordManager": { "optionsDefaultPasswordManager": {
"message": "Beállítás alapértelmezett jelszókezelőnek.", "message": "Set as default password manager",
"description": "Default password manager checkbox text." "description": "Default password manager checkbox text."
}, },
"optionsDefaultPasswordManagerHelpText": { "optionsDefaultPasswordManagerHelpText": {
"message": "A KeePassXC-böngészőt beállítja alapértelmezett jelszókezelőnek a böngészőben.", "message": "Sets KeePassXC-Browser as the default password manager for the browser.",
"description": "Default password manager help text." "description": "Default password manager help text."
}, },
"optionsRedirectAllowance": { "optionsRedirectAllowance": {
@ -959,7 +931,7 @@
"description": "OTP field icon option help text." "description": "OTP field icon option help text."
}, },
"optionsHideIconsAlertText": { "optionsHideIconsAlertText": {
"message": "Szükség esetén az ikonok manuálisan is elrejthetők Shift+kattintással.", "message": "You can also hide icons manually when needed with shift+click.",
"description": "Hide icons alert text text." "description": "Hide icons alert text text."
}, },
"optionsAutoRetrieveCredentialsHelpText": { "optionsAutoRetrieveCredentialsHelpText": {
@ -975,7 +947,7 @@
"description": "Auto-Fill Single Entry option help text." "description": "Auto-Fill Single Entry option help text."
}, },
"optionsAutoFillRelevantCredentialHelpText": { "optionsAutoFillRelevantCredentialHelpText": {
"message": "Releváns hitelesítésiadat-bejegyzések automatikus kitöltése ha egy második kitöltés is szükséges.", "message": "Automatically fill in the relevant credential if a second fill is needed.",
"description": "Auto-Fill Relevant Credential option help text." "description": "Auto-Fill Relevant Credential option help text."
}, },
"optionsAutoFillSingleEntryWarning": { "optionsAutoFillSingleEntryWarning": {
@ -1058,10 +1030,6 @@
"message": "Szükséges KeePassXC verzió: $1", "message": "Szükséges KeePassXC verzió: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "A kiterjesztéshez a KeePassXC ezen verziója szükséges: $1. A korábbi verziók nem kívánt viselkedést okozhatnak.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Alapértelmezett: $1", "message": "Alapértelmezett: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "A jelenlegi beállítások felül lesznek írva. Biztos, hogy importálja a beállításfájlt?", "message": "A jelenlegi beállítások felül lesznek írva. Biztos, hogy importálja a beállításfájlt?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Minden beállítás alapértelmezett értékre áll vissza. Valóban ezt szeretné?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "A következő KeePassXC adatbázisok vannak kapcsolódva a KeePassXC-böngészőhöz.", "message": "A következő KeePassXC adatbázisok vannak kapcsolódva a KeePassXC-böngészőhöz.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Oldal URL", "message": "Oldal URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Képességek", "message": "Mellőzés",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Automatikus beküldés letiltása", "message": "Automatikus beküldés letiltása",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Jelkulcsok letiltása",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Az összes funkció letiltása", "message": "Az összes funkció letiltása",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
@ -1435,31 +1395,31 @@
"description": "Lock database button title text." "description": "Lock database button title text."
}, },
"welcomeText": { "welcomeText": {
"message": "Üdvözöljük a KeePassXC-böngészőben!", "message": "Welcome to KeePassXC-Browser!",
"description": "Main title of Getting Started page." "description": "Main title of Getting Started page."
}, },
"documentationGettingStarted": { "documentationGettingStarted": {
"message": "A bevezető útmutatónk segítségével gyorsan elsajátíthatja a használatot.", "message": "Our Getting Started Guide will get you up and running quickly.",
"description": "Getting Started document text." "description": "Getting Started document text."
}, },
"documentationUserGuide": { "documentationUserGuide": {
"message": "Átfogóbb dokumentációra lenne szüksége? A felhasználói útmutatónk segíthet.", "message": "Looking for more comprehensive documentation? Our User Guide is there to help.",
"description": "User Guide text." "description": "User Guide text."
}, },
"documentationTroubleshootingGuide": { "documentationTroubleshootingGuide": {
"message": "Segítségre van szüksége a böngésző integrációjának hibaelhárításában? Olvassa el a hibaelhárítási útmutatót.", "message": "Need help troubleshooting the browser integration? Check the Troubleshooting Guide.",
"description": "Troubleshooting Guide text." "description": "Troubleshooting Guide text."
}, },
"gettingStartedWelcomeText": { "gettingStartedWelcomeText": {
"message": "Üdvözlet a KeePassXC-böngészőben, a KeePassXC hivatalos böngészőbővítményében.", "message": "Welcome to KeePassXC-Browser, the official browser extension for KeePassXC.",
"description": "Welcome to KeePassXC-Browser, the official browser extension for KeePassXC." "description": "Welcome to KeePassXC-Browser, the official browser extension for KeePassXC."
}, },
"gettingStartedSecondWelcomeText": { "gettingStartedSecondWelcomeText": {
"message": "Kérjük, nézze át az alapértelmezett beállításokat és ellenőrizze az összes kívánt opciót.", "message": "Please go through the default settings and check all your preferred options.",
"description": "Please go through the default settings and check all your preferred options." "description": "Please go through the default settings and check all your preferred options."
}, },
"gettingStartedNewUser": { "gettingStartedNewUser": {
"message": "Új felhasználó? Nézze meg a hivatkozott dokumentációt!", "message": "Are you a new user? Check links to our documentation.",
"description": "Are you a new user? Check links to our documentation." "description": "Are you a new user? Check links to our documentation."
} }
} }

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "Ruas lema",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Pilih ruas nama pengguna", "message": "Pilih ruas nama pengguna",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Pilih Ruas String", "message": "Pilih Ruas String",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "Harap konfirmasi pilihan Anda atau pilih lebih banyak bidang sebagai bidang String.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Anda juga dapat menggunakan angka untuk memilih bidang input dari keyboard.", "message": "Anda juga dapat menggunakan angka untuk memilih bidang input dari keyboard.",
@ -370,10 +362,6 @@
"message": "Ruas String", "message": "Ruas String",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- tidak ada nama pengguna -", "message": "- tidak ada nama pengguna -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Login tidak ditemukan.", "message": "Login tidak ditemukan.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Lebih dari satu login ditemukan di KeePassXC!", "message": "Lebih dari satu login ditemukan di KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Kedaluwarsa", "message": "Kedaluwarsa",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Error: Tidak dapat menemukan bidang yang harus diisi.", "message": "Error: Tidak dapat menemukan bidang yang harus diisi.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Site Preferences", "message": "Site Preferences",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Tentang", "message": "Tentang",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Ekspor pengaturan", "message": "Ekspor pengaturan",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Grup baku untuk menyimpan sandi baru:", "message": "Grup baku untuk menyimpan sandi baru:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Membutuhkan KeePassXC versi: $1", "message": "Membutuhkan KeePassXC versi: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Standar: $1", "message": "Standar: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Pengaturan saat ini akan diganti. Apakah Anda benar-benar ingin mengimpor berkas pengaturan?", "message": "Pengaturan saat ini akan diganti. Apakah Anda benar-benar ingin mengimpor berkas pengaturan?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Basis data terhubung ke KeePassXC-Browser.", "message": "Basis data terhubung ke KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Halaman URL", "message": "Halaman URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "Abaikan",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Nonaktifkan Pengiriman Otomatis", "message": "Nonaktifkan Pengiriman Otomatis",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Nonaktifkan semua fitur", "message": "Nonaktifkan semua fitur",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -8,7 +8,7 @@
"description": "Add button title text on Site Preferences tab." "description": "Add button title text on Site Preferences tab."
}, },
"editSitePreferenceButtonTitle": { "editSitePreferenceButtonTitle": {
"message": "Modifica URL per queste preferenze sito", "message": "Modifica URL per queste Preferenze Sito",
"description": "Edit button title text on Site Preferences tab." "description": "Edit button title text on Site Preferences tab."
}, },
"allowIframeButtonTitle": { "allowIframeButtonTitle": {
@ -20,7 +20,7 @@
"description": "Connect button title text." "description": "Connect button title text."
}, },
"copyDebugInfoButtonTitle": { "copyDebugInfoButtonTitle": {
"message": "Copia informazioni debug negli appunti", "message": "Copia informazioni di debug negli appunti",
"description": "Copy debug info button title text on About tab." "description": "Copy debug info button title text on About tab."
}, },
"dismissHttpAuthButtonTitle": { "dismissHttpAuthButtonTitle": {
@ -244,7 +244,7 @@
"description": "Error notification shown when not connected to KeePassXC." "description": "Error notification shown when not connected to KeePassXC."
}, },
"errorCurrentDatabaseNotConnected": { "errorCurrentDatabaseNotConnected": {
"message": "Il database attuale non è connesso.", "message": "Il database corrente non è connesso.",
"description": "Error notification shown when current database is not connected during action." "description": "Error notification shown when current database is not connected during action."
}, },
"passwordGeneratorErrorTooLong": { "passwordGeneratorErrorTooLong": {
@ -322,10 +322,6 @@
"message": "Campo stringa", "message": "Campo stringa",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Pulsante Invia",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Scegli un campo nome utente", "message": "Scegli un campo nome utente",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Scegli campi stringa", "message": "Scegli campi stringa",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Scegli pulsante Invia",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Conferma la selezione o scegli più campi come campi stringa.", "message": "Conferma la selezione o scegli altri campi come campi stringa.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Puoi anche usare i numeri per scegliere i campi di input dalla tastiera.", "message": "Puoi anche usare i numeri per scegliere i campi di input dalla tastiera.",
@ -370,10 +362,6 @@
"message": "Campi stringa", "message": "Campi stringa",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Pulsante Invia",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- nessun nome utente -", "message": "- nessun nome utente -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,16 +370,12 @@
"message": "Errore:\nNessun accesso trovato.", "message": "Errore:\nNessun accesso trovato.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Riempimento delle credenziali bloccato in iframe non attendibile.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "In KeePassXC è stato trovato più di un accesso!", "message": "In KeePassXC è stato trovato più di un accesso!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
}, },
"credentialsMultipleFoundSecondLine": { "credentialsMultipleFoundSecondLine": {
"message": "Per ulteriori opzioni seelziona l'icona di KeePassXC-Browser.", "message": "Premi l'icona di KeePassXC-Browser per ulteriori opzioni.",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
}, },
"credentialsNoUsernameFound": { "credentialsNoUsernameFound": {
@ -406,10 +390,6 @@
"message": "Scaduta", "message": "Scaduta",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Recupera credenziali",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Errore: impossibile trovare campi da compilare.", "message": "Errore: impossibile trovare campi da compilare.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -503,7 +483,7 @@
"description": "Checking status message in popup." "description": "Checking status message in popup."
}, },
"popupNotConfigured": { "popupNotConfigured": {
"message": "KeePassXC-Browser non è stato configurato. \nPer associarlo a KeePassXC seleziona il pulsante 'Connetti'.", "message": "KeePassXC-Browser non è stato configurato. Premi il pulsante connetti per associarlo a KeePassXC.",
"description": "A popup message shown when the extension has not been connected to KeePassXC." "description": "A popup message shown when the extension has not been connected to KeePassXC."
}, },
"popupNeedReconfigure": { "popupNeedReconfigure": {
@ -511,7 +491,7 @@
"description": "A popup message shown when the extension has been disconnected from KeePassXC." "description": "A popup message shown when the extension has been disconnected from KeePassXC."
}, },
"popupNeedReconfigureMessage": { "popupNeedReconfigureMessage": {
"message": "Per stabilire una nuova connessione seleziona il pulsante 'Riconnetti'.", "message": "Premi il pulsante riconnetti per stabilire una nuova connessione.",
"description": "A popup message shown when reconnect is needed." "description": "A popup message shown when reconnect is needed."
}, },
"popupConfiguredNotAssociated": { "popupConfiguredNotAssociated": {
@ -551,7 +531,7 @@
"description": "A message shown choosing what credentials user wants to update." "description": "A message shown choosing what credentials user wants to update."
}, },
"rememberChooseGroup": { "rememberChooseGroup": {
"message": "Per memorizzare le nuove credenziali scegli un gruppo.", "message": "Scegli un gruppo per memorizzare le nuove credenziali.",
"description": "A message shown choosing what group user wants to use for new credentials." "description": "A message shown choosing what group user wants to use for new credentials."
}, },
"rememberInfoDefaultGroupNotFound": { "rememberInfoDefaultGroupNotFound": {
@ -694,10 +674,6 @@
"message": "Preferenze sito", "message": "Preferenze sito",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Impostazioni",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Info", "message": "Info",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Esporta impostazioni", "message": "Esporta impostazioni",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Ripristina tutte le impostazioni",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Gruppo predefinito salvataggio nuove password:", "message": "Gruppo predefinito salvataggio nuove password:",
"description": "Default group options text." "description": "Default group options text."
@ -763,7 +735,7 @@
"description": "Default group help text." "description": "Default group help text."
}, },
"optionsLabelDefaultPasskeyGroup": { "optionsLabelDefaultPasskeyGroup": {
"message": "Gruppo predefinito salvataggio nuove passkey:", "message": "Gruppo predefinito per il salvataggio delle nuove passkeys:",
"description": "Default passkey group options text." "description": "Default passkey group options text."
}, },
"optionsLabelDefaultGroupCheckboxText": { "optionsLabelDefaultGroupCheckboxText": {
@ -855,11 +827,11 @@
"description": "Show login notifications checkbox text." "description": "Show login notifications checkbox text."
}, },
"optionsDefaultPasswordManager": { "optionsDefaultPasswordManager": {
"message": "Imposta come password manager predefinito", "message": "Imposta come password manager di default",
"description": "Default password manager checkbox text." "description": "Default password manager checkbox text."
}, },
"optionsDefaultPasswordManagerHelpText": { "optionsDefaultPasswordManagerHelpText": {
"message": "Imposta KeePassXC-Browser come password manager predefinito per il browser.", "message": "Imposta KeePassXC-Browser come password manager di default per il browser.",
"description": "Default password manager help text." "description": "Default password manager help text."
}, },
"optionsRedirectAllowance": { "optionsRedirectAllowance": {
@ -959,7 +931,7 @@
"description": "OTP field icon option help text." "description": "OTP field icon option help text."
}, },
"optionsHideIconsAlertText": { "optionsHideIconsAlertText": {
"message": "Puoi nascondere le icone manualmente quando occorre con Maiusc+Clic", "message": "Puoi nascondere le icone manualmente quando occorre con Shift+Click",
"description": "Hide icons alert text text." "description": "Hide icons alert text text."
}, },
"optionsAutoRetrieveCredentialsHelpText": { "optionsAutoRetrieveCredentialsHelpText": {
@ -975,7 +947,7 @@
"description": "Auto-Fill Single Entry option help text." "description": "Auto-Fill Single Entry option help text."
}, },
"optionsAutoFillRelevantCredentialHelpText": { "optionsAutoFillRelevantCredentialHelpText": {
"message": "Se è necessario un secondo riempimento compila automaticamente le credenziali pertinenti.", "message": "Compila automaticamente le credenziali pertinenti se è necessario un secondo riempimento.",
"description": "Auto-Fill Relevant Credential option help text." "description": "Auto-Fill Relevant Credential option help text."
}, },
"optionsAutoFillSingleEntryWarning": { "optionsAutoFillSingleEntryWarning": {
@ -1058,10 +1030,6 @@
"message": "Richiede KeePassXC versione: $1", "message": "Richiede KeePassXC versione: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "L'estensione richiede la versione KeePassXC: $1. Le versioni precedenti possono causare comportamenti indesiderati.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Predefinito: $1", "message": "Predefinito: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Le impostazioni attuali verranno sovrascritte. Vuoi veramente importare le impostazioni?", "message": "Le impostazioni attuali verranno sovrascritte. Vuoi veramente importare le impostazioni?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Tutte le impostazioni verranno ripristinate ai valori predefiniti. \nVuoi continuare?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Database KeePassXC connessi a KeePassXC-Browser.", "message": "Database KeePassXC connessi a KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1115,7 +1079,7 @@
"description": "Confirmation text when removing database from the list." "description": "Confirmation text when removing database from the list."
}, },
"optionsDatabasesRemoveIdentifierConfirmFirst": { "optionsDatabasesRemoveIdentifierConfirmFirst": {
"message": "Vuoi rimuovere l'identificatore $1 dall'elenco database? ", "message": "Vuoi davvero rimuovere l'identificatore $1 dall'elenco del database? ",
"description": "Confirmation text when removing database from the list." "description": "Confirmation text when removing database from the list."
}, },
"optionsDatabasesRemoveIdentifierConfirmSecond": { "optionsDatabasesRemoveIdentifierConfirmSecond": {
@ -1146,8 +1110,8 @@
"message": "URL pagina", "message": "URL pagina",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Funzionalità", "message": "Ignora",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Disabilita l'invio automatico", "message": "Disabilita l'invio automatico",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disabilita passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Disattiva tutte le funzionalità", "message": "Disattiva tutte le funzionalità",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
@ -1435,23 +1395,23 @@
"description": "Lock database button title text." "description": "Lock database button title text."
}, },
"welcomeText": { "welcomeText": {
"message": "Benvenuto in KeePassXC-Browser!", "message": "Benvenuto su KeePassXC-Browser!",
"description": "Main title of Getting Started page." "description": "Main title of Getting Started page."
}, },
"documentationGettingStarted": { "documentationGettingStarted": {
"message": "Grazie alla nostra 'Guida introduttiva' sarai subito operativo.", "message": "Grazie alla nostra Guida introduttiva sarai subito operativo.",
"description": "Getting Started document text." "description": "Getting Started document text."
}, },
"documentationUserGuide": { "documentationUserGuide": {
"message": "Cerchi una documentazione più completa? \nLa nostra 'Guida per l'utente' è qui per aiutarti.", "message": "Cerchi una documentazione più completa? La nostra Guida per l'utente è qui per aiutarti.",
"description": "User Guide text." "description": "User Guide text."
}, },
"documentationTroubleshootingGuide": { "documentationTroubleshootingGuide": {
"message": "Hai bisogno di aiuto per risolvere i problemi di integrazione del browser? Consulta la 'Guida alla risoluzione dei problemi'.", "message": "Hai bisogno di aiuto per risolvere i problemi di integrazione del browser? Consulta la Guida alla risoluzione dei problemi.",
"description": "Troubleshooting Guide text." "description": "Troubleshooting Guide text."
}, },
"gettingStartedWelcomeText": { "gettingStartedWelcomeText": {
"message": "Benvenuti in KeePassXC-Browser, l'estensione ufficiale del browser per KeePassXC.", "message": "Benvenuti su KeePassXC-Browser, l'estensione ufficiale del browser per KeePassXC.",
"description": "Welcome to KeePassXC-Browser, the official browser extension for KeePassXC." "description": "Welcome to KeePassXC-Browser, the official browser extension for KeePassXC."
}, },
"gettingStartedSecondWelcomeText": { "gettingStartedSecondWelcomeText": {
@ -1459,7 +1419,7 @@
"description": "Please go through the default settings and check all your preferred options." "description": "Please go through the default settings and check all your preferred options."
}, },
"gettingStartedNewUser": { "gettingStartedNewUser": {
"message": "Sei un nuovo utente? \nConsulta i collegamenti alla nostra documentazione.", "message": "Sei un nuovo utente? Consulta i link alla nostra documentazione.",
"description": "Are you a new user? Check links to our documentation." "description": "Are you a new user? Check links to our documentation."
} }
} }

View file

@ -8,7 +8,7 @@
"description": "Add button title text on Site Preferences tab." "description": "Add button title text on Site Preferences tab."
}, },
"editSitePreferenceButtonTitle": { "editSitePreferenceButtonTitle": {
"message": "このサイト設定の URL を編集します。", "message": "Edit URL for this Site Preferences.",
"description": "Edit button title text on Site Preferences tab." "description": "Edit button title text on Site Preferences tab."
}, },
"allowIframeButtonTitle": { "allowIframeButtonTitle": {
@ -20,7 +20,7 @@
"description": "Connect button title text." "description": "Connect button title text."
}, },
"copyDebugInfoButtonTitle": { "copyDebugInfoButtonTitle": {
"message": "クリップボードにデバッグ情報をコピー", "message": "Copy debug info to clipboard",
"description": "Copy debug info button title text on About tab." "description": "Copy debug info button title text on About tab."
}, },
"dismissHttpAuthButtonTitle": { "dismissHttpAuthButtonTitle": {
@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "文字列フィールド",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "ユーザー名フィールドを選択してください", "message": "ユーザー名フィールドを選択してください",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "文字列フィールドを選択してください", "message": "文字列フィールドを選択してください",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "選択したものを確認するか、文字列フィールドとして別のフィールドを追加で選択してください。",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "キーボードの数字キーで入力フィールドを選択できます。", "message": "キーボードの数字キーで入力フィールドを選択できます。",
@ -370,10 +362,6 @@
"message": "文字列フィールド", "message": "文字列フィールド",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- ユーザー名なし -", "message": "- ユーザー名なし -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "ログイン情報が見つかりません。", "message": "ログイン情報が見つかりません。",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "KeePassXC に複数のログイン情報が見つかりました!", "message": "KeePassXC に複数のログイン情報が見つかりました!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "期限切れ", "message": "期限切れ",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "エラー: 入力するフィールドを見つけられません。", "message": "エラー: 入力するフィールドを見つけられません。",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "サイト設定", "message": "サイト設定",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "情報", "message": "情報",
"description": "About page header." "description": "About page header."
@ -723,7 +699,7 @@
"description": "Add button text." "description": "Add button text."
}, },
"optionsButtonEdit": { "optionsButtonEdit": {
"message": "編集", "message": "Edit",
"description": "Edit button text." "description": "Edit button text."
}, },
"optionsButtonUpdate": { "optionsButtonUpdate": {
@ -750,10 +726,6 @@
"message": "設定をエクスポート", "message": "設定をエクスポート",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "新しいパスワードを保存するデフォルトのグループ:", "message": "新しいパスワードを保存するデフォルトのグループ:",
"description": "Default group options text." "description": "Default group options text."
@ -811,7 +783,7 @@
"description": "Automatically fill-in single credential entry checkbox text." "description": "Automatically fill-in single credential entry checkbox text."
}, },
"optionsCheckboxAutoFillRelevantCredential": { "optionsCheckboxAutoFillRelevantCredential": {
"message": "関連する資格情報を自動的に補完する", "message": "Automatically fill in relevant credential entries",
"description": "Automatically fill-in relevant credential entry checkbox text." "description": "Automatically fill-in relevant credential entry checkbox text."
}, },
"optionsCheckboxAutoFillSingleTotp": { "optionsCheckboxAutoFillSingleTotp": {
@ -855,11 +827,11 @@
"description": "Show login notifications checkbox text." "description": "Show login notifications checkbox text."
}, },
"optionsDefaultPasswordManager": { "optionsDefaultPasswordManager": {
"message": "デフォルトのパスワードマネージャーに設定する", "message": "Set as default password manager",
"description": "Default password manager checkbox text." "description": "Default password manager checkbox text."
}, },
"optionsDefaultPasswordManagerHelpText": { "optionsDefaultPasswordManagerHelpText": {
"message": "KeePassXC-Browser をブラウザーのデフォルトのパスワードマネージャーに設定します", "message": "Sets KeePassXC-Browser as the default password manager for the browser.",
"description": "Default password manager help text." "description": "Default password manager help text."
}, },
"optionsRedirectAllowance": { "optionsRedirectAllowance": {
@ -871,7 +843,7 @@
"description": "Redirect allowance help text." "description": "Redirect allowance help text."
}, },
"optionsCheckboxAutoFillAndSend": { "optionsCheckboxAutoFillAndSend": {
"message": "HTTP ベーシック認証への資格情報の補完を許可する", "message": "HTTP Basic 認証の資格情報の入力を許可する",
"description": "Allow filling HTTP Basic Auth credentials checkbox text." "description": "Allow filling HTTP Basic Auth credentials checkbox text."
}, },
"optionsDebugLogging": { "optionsDebugLogging": {
@ -959,7 +931,7 @@
"description": "OTP field icon option help text." "description": "OTP field icon option help text."
}, },
"optionsHideIconsAlertText": { "optionsHideIconsAlertText": {
"message": "必要に応じて Shift + クリックでアイコンを隠すこともできます。", "message": "You can also hide icons manually when needed with shift+click.",
"description": "Hide icons alert text text." "description": "Hide icons alert text text."
}, },
"optionsAutoRetrieveCredentialsHelpText": { "optionsAutoRetrieveCredentialsHelpText": {
@ -975,7 +947,7 @@
"description": "Auto-Fill Single Entry option help text." "description": "Auto-Fill Single Entry option help text."
}, },
"optionsAutoFillRelevantCredentialHelpText": { "optionsAutoFillRelevantCredentialHelpText": {
"message": "2 回目の入力が必要な場合、関連する資格情報を自動的に補完します。", "message": "Automatically fill in the relevant credential if a second fill is needed.",
"description": "Auto-Fill Relevant Credential option help text." "description": "Auto-Fill Relevant Credential option help text."
}, },
"optionsAutoFillSingleEntryWarning": { "optionsAutoFillSingleEntryWarning": {
@ -1055,13 +1027,9 @@
"description": "Settings page info text about the latest KeePassXC version." "description": "Settings page info text about the latest KeePassXC version."
}, },
"optionsKeePassXCVersionRequired": { "optionsKeePassXCVersionRequired": {
"message": "次のバージョン以上の KeePassXC が必要です: $1", "message": "次のバージョンの KeePassXC が必要です: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "デフォルト: $1", "message": "デフォルト: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "現在の設定を上書きします。本当に設定ファイルをインポートしますか?", "message": "現在の設定を上書きします。本当に設定ファイルをインポートしますか?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "KeePassXC-Browser に接続されているデータベースです。", "message": "KeePassXC-Browser に接続されているデータベースです。",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "ページの URL", "message": "ページの URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "無視",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "自動送信を無効にする", "message": "自動送信を無効にする",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "すべての機能を無効にする", "message": "すべての機能を無効にする",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
@ -1435,7 +1395,7 @@
"description": "Lock database button title text." "description": "Lock database button title text."
}, },
"welcomeText": { "welcomeText": {
"message": "KeePassXC-Browser にようこそ!", "message": "Welcome to KeePassXC-Browser!",
"description": "Main title of Getting Started page." "description": "Main title of Getting Started page."
}, },
"documentationGettingStarted": { "documentationGettingStarted": {

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "문자열 필드",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "사용자 이름 필드 선택", "message": "사용자 이름 필드 선택",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "문자열 필드 선택", "message": "문자열 필드 선택",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "선택 사항을 확인하거나 더 많은 <em>문자열 필드</em>를 선택하십시오.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "키보드에서 숫자를 눌러서 입력 필드를 선택할 수 있습니다.", "message": "키보드에서 숫자를 눌러서 입력 필드를 선택할 수 있습니다.",
@ -370,10 +362,6 @@
"message": "문자열 필드", "message": "문자열 필드",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- 사용자 이름 없음 -", "message": "- 사용자 이름 없음 -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "오류:\n로그인을 찾을 수 없습니다.", "message": "오류:\n로그인을 찾을 수 없습니다.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "오류:\nKeePassXC에 하나 이상의 로그인 정보가 있습니다!\nKeePassXC-브라우저 아이콘을 눌러서 더 많은 옵션을 보십시오.", "message": "오류:\nKeePassXC에 하나 이상의 로그인 정보가 있습니다!\nKeePassXC-브라우저 아이콘을 눌러서 더 많은 옵션을 보십시오.",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "만료됨", "message": "만료됨",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "오류:\n입력할 필드를 찾을 수 없습니다.", "message": "오류:\n입력할 필드를 찾을 수 없습니다.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Site Preferences", "message": "Site Preferences",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "정보", "message": "정보",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "설정 내보내기", "message": "설정 내보내기",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "새 암호를 저장할 기본 그룹:", "message": "새 암호를 저장할 기본 그룹:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "필요한 KeePassXC 버전: $1", "message": "필요한 KeePassXC 버전: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "기본값: $1", "message": "기본값: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "현재 설정을 덮어쓸 것입니다. 설정 파일을 가져오시겠습니까?", "message": "현재 설정을 덮어쓸 것입니다. 설정 파일을 가져오시겠습니까?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "다음 KeePassXC 데이터베이스가 KeePassXC-브라우저에 연결되어 있습니다.", "message": "다음 KeePassXC 데이터베이스가 KeePassXC-브라우저에 연결되어 있습니다.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "페이지 URL", "message": "페이지 URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "무시",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "자동 제출 비활성화", "message": "자동 제출 비활성화",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "모든 기능 비활성화", "message": "모든 기능 비활성화",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "Eilutės laukas",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Pasirinkite vartotojo vardo lauką", "message": "Pasirinkite vartotojo vardo lauką",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Pasirinkite eilučių laukus", "message": "Pasirinkite eilučių laukus",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "Patvirtinkite savo pasirinkimą arba pasirinkite daugiau laukų kaip eilutės laukus.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Taip pat galite naudoti skaičius, kad pasirinktumėte įvesties laukus iš klaviatūros.", "message": "Taip pat galite naudoti skaičius, kad pasirinktumėte įvesties laukus iš klaviatūros.",
@ -370,10 +362,6 @@
"message": "Eilučių laukai", "message": "Eilučių laukai",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- nėra naudotojo vardo -", "message": "- nėra naudotojo vardo -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Nerasta jokių prisijungimų.", "message": "Nerasta jokių prisijungimų.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "KeePassXC buvo rastas daugiau nei vienas prisijungimas!", "message": "KeePassXC buvo rastas daugiau nei vienas prisijungimas!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Nebegalioja", "message": "Nebegalioja",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Klaida: nepavyksta rasti pildomų laukų.", "message": "Klaida: nepavyksta rasti pildomų laukų.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Svetainės nuostatos", "message": "Svetainės nuostatos",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Apie", "message": "Apie",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Eksportuoti nustatymus", "message": "Eksportuoti nustatymus",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Numatytoji naujų slaptažodžių įrašymo grupė:", "message": "Numatytoji naujų slaptažodžių įrašymo grupė:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Reikalinga KeePassXC versija: $1", "message": "Reikalinga KeePassXC versija: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Numatytoji reikšmė: $1", "message": "Numatytoji reikšmė: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Dabartiniai nustatymai bus nepaisomi. Ar tikrai norite importuoti nustatymų failą?", "message": "Dabartiniai nustatymai bus nepaisomi. Ar tikrai norite importuoti nustatymų failą?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Duomenų bazės, prijungtos prie \"KeePassXC-Browser\".", "message": "Duomenų bazės, prijungtos prie \"KeePassXC-Browser\".",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Puslapio URL", "message": "Puslapio URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "Nepaisyti",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Automatinio pateikimo išjungimas", "message": "Automatinio pateikimo išjungimas",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Išjungti visas ypatybes", "message": "Išjungti visas ypatybes",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "Tekstfelt",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Velg et brukernavnfelt", "message": "Velg et brukernavnfelt",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Velg tekstfelt", "message": "Velg tekstfelt",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "Bekreft utvalget, eller velg flere felt som tekstfelt.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Du kan også bruke tallene til å velge innputtfeltene fra tastatur.", "message": "Du kan også bruke tallene til å velge innputtfeltene fra tastatur.",
@ -370,10 +362,6 @@
"message": "Tekstfelt", "message": "Tekstfelt",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- ikke noe brukernavn -", "message": "- ikke noe brukernavn -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Fant ingen pålogginger.", "message": "Fant ingen pålogginger.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Mer enn én pålogging ble funnet i KeePassXC!", "message": "Mer enn én pålogging ble funnet i KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Utløpt", "message": "Utløpt",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Feil: Finner ikke felt å fylle ut.", "message": "Feil: Finner ikke felt å fylle ut.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Site Preferences", "message": "Site Preferences",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Om", "message": "Om",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Eksporter innstillinger", "message": "Eksporter innstillinger",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Standardgruppe for lagring av nye passord:", "message": "Standardgruppe for lagring av nye passord:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Krever KeePassXC-versjon: $1", "message": "Krever KeePassXC-versjon: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Standard: $1", "message": "Standard: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Gjeldende innstillinger vil bli overstyrt. Vil du virkelig importere filen med nye innstillinger?", "message": "Gjeldende innstillinger vil bli overstyrt. Vil du virkelig importere filen med nye innstillinger?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Databaser koblet til KeePassXCBrowser.", "message": "Databaser koblet til KeePassXCBrowser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Nettside-URL", "message": "Nettside-URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "Ignorere",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Deaktiver automatisk sending", "message": "Deaktiver automatisk sending",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Deaktiver alle funksjoner", "message": "Deaktiver alle funksjoner",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -322,10 +322,6 @@
"message": "Tekenreeksveld", "message": "Tekenreeksveld",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Knop Indienen",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Kies een gebruikersnaamveld", "message": "Kies een gebruikersnaamveld",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Kies tekenreeksvelden", "message": "Kies tekenreeksvelden",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Knop Indienen kiezen",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Bevestig de selectie of kies meer velden als tekenreeksvelden.", "message": "Bevestig je selectie of stel meerdere velden in als <em>tekenreeksvelden</em>.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Je kunt tevens gebruikmaken van de numerieke toetsen op je toetsenbord.", "message": "Je kunt tevens gebruikmaken van de numerieke toetsen op je toetsenbord.",
@ -370,10 +362,6 @@
"message": "Tekenreeksvelden", "message": "Tekenreeksvelden",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Knop Indienen",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- geen gebruikersnaam -", "message": "- geen gebruikersnaam -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Geen inloggegevens aangetroffen.", "message": "Geen inloggegevens aangetroffen.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Invulling van de inloggegevens geblokkeerd in niet-vertrouwd iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Er zijn meerdere inloggegevens aangetroffen in KeePassXC!", "message": "Er zijn meerdere inloggegevens aangetroffen in KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Verlopen", "message": "Verlopen",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Inloggegevens ophalen",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Fout: geen invulvelden aangetroffen.", "message": "Fout: geen invulvelden aangetroffen.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Websitevoorkeuren", "message": "Websitevoorkeuren",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Instellingen",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Over", "message": "Over",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Instellingen exporteren", "message": "Instellingen exporteren",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Alle instellingen opnieuw instellen",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Standaardgroep voor het opslaan van nieuwe wachtwoorden:", "message": "Standaardgroep voor het opslaan van nieuwe wachtwoorden:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Vereiste KeePassXC-versie: $1", "message": "Vereiste KeePassXC-versie: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "De extensie vereist KeePassXC-versie: $1. Eerdere versies kunnen ongewenst gedrag veroorzaken.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Standaard: $1", "message": "Standaard: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "De huidige instellingen worden overschreven. Weet je zeker dat je het instellingenbestand wilt importeren?", "message": "De huidige instellingen worden overschreven. Weet je zeker dat je het instellingenbestand wilt importeren?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Alle instellingen worden teruggezet naar standaardinstellingen. Weet je het zeker?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Databases verbonden met KeePassXC-Browser.", "message": "Databases verbonden met KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Pagina-url", "message": "Pagina-url",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Functies", "message": "Negeren",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Automatisch indienen uitschakelen", "message": "Automatisch indienen uitschakelen",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Passkeys uitschakelen",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Alle functies uitschakelen", "message": "Alle functies uitschakelen",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -322,10 +322,6 @@
"message": "Pole ciągu", "message": "Pole ciągu",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Przycisk przesyłania",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Wybierz pole nazwy użytkownika", "message": "Wybierz pole nazwy użytkownika",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Wybierz pola ciągów", "message": "Wybierz pola ciągów",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Wybierz przycisk przesyłania",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Potwierdź swój wybór lub wybierz więcej pól jako pola ciągów.", "message": "Potwierdź swój wybór lub wybierz więcej pól jako pola ciągów.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Możesz także użyć liczb, aby wybrać pola wprowadzania z klawiatury.", "message": "Możesz także użyć liczb, aby wybrać pola wprowadzania z klawiatury.",
@ -370,10 +362,6 @@
"message": "Pola ciągów", "message": "Pola ciągów",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Przycisk przesyłania",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- brak nazwy użytkownika -", "message": "- brak nazwy użytkownika -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Nie znaleziono danych logowania.", "message": "Nie znaleziono danych logowania.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Wypełnienie danych uwierzytelniających zablokowane w niezaufanej ramce iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Znaleziono więcej niż jedne dane logowania w KeePassXC!", "message": "Znaleziono więcej niż jedne dane logowania w KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Wygasłe", "message": "Wygasłe",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Pobierz dane uwierzytelniające",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Błąd:\nNie można znaleźć pól do wypełnienia.", "message": "Błąd:\nNie można znaleźć pól do wypełnienia.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Ustawienia witryn", "message": "Ustawienia witryn",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Ustawienia",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Informacje", "message": "Informacje",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Eksportuj ustawienia", "message": "Eksportuj ustawienia",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Resetuj wszystkie ustawienia",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Domyślna grupa do zapisywania nowych haseł:", "message": "Domyślna grupa do zapisywania nowych haseł:",
"description": "Default group options text." "description": "Default group options text."
@ -963,7 +935,7 @@
"description": "Hide icons alert text text." "description": "Hide icons alert text text."
}, },
"optionsAutoRetrieveCredentialsHelpText": { "optionsAutoRetrieveCredentialsHelpText": {
"message": "KeePassXC-Browser natychmiast pobierze dane uwierzytelniające po aktywowaniu karty.", "message": "KeePassXC-Browser natychmiast odbierze dane uwierzytelniające po aktywowaniu karty.",
"description": "Auto-Retrive Credentials option help text." "description": "Auto-Retrive Credentials option help text."
}, },
"optionsAutomaticReconnectHelpText": { "optionsAutomaticReconnectHelpText": {
@ -1058,10 +1030,6 @@
"message": "Wymaga KeePassXC w wersji: $1", "message": "Wymaga KeePassXC w wersji: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "Rozszerzenie wymaga KeePassXC w wersji $1. Starsze wersje mogą powodować niepożądane zachowania.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Domyślne: $1", "message": "Domyślne: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Bieżące ustawienia zostaną zastąpione. Czy na pewno chcesz zaimportować plik ustawień?", "message": "Bieżące ustawienia zostaną zastąpione. Czy na pewno chcesz zaimportować plik ustawień?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Wszystkie ustawienia zostaną przywrócone do wartości domyślnych. Czy na pewno chcesz to zrobić?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Bazy danych podłączone do KeePassXC-Browser.", "message": "Bazy danych podłączone do KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Adres URL strony", "message": "Adres URL strony",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Funkcje", "message": "Ignorowanie",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Wyłącz automatyczne przesyłanie", "message": "Wyłącz automatyczne przesyłanie",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Wyłącz klucze dostępu",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Wyłącz wszystkie funkcje", "message": "Wyłącz wszystkie funkcje",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "Campo do Texto", "message": "Campo para texto",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Botão Enviar",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Escolha um campo para o nome de usuário", "message": "Escolha um campo para o nome de usuário",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Escolha os campos para texto", "message": "Escolha os campos para texto",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Selecione o botão enviar",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Por favor, confirme sua seleção ou escolha mais campos como Campos de Texto.", "message": "Confirme a sua seleção ou escolha mais campos como texto.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Você também pode usar os números para escolher os campos de entrada do teclado.", "message": "Você também pode usar os números para escolher os campos de entrada do teclado.",
@ -370,10 +362,6 @@
"message": "Campos para texto", "message": "Campos para texto",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Botão Enviar",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- sem usuário -", "message": "- sem usuário -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Nenhum login foi encontrado.", "message": "Nenhum login foi encontrado.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Preenchimento de credenciais bloqueado em iframe não confiável.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Mais de um login foi encontrado no KeePassXC!", "message": "Mais de um login foi encontrado no KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Expirado", "message": "Expirado",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Recuperar credenciais",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Erro: Não foi possível encontrar campos para preencher.", "message": "Erro: Não foi possível encontrar campos para preencher.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Preferências do Site", "message": "Preferências do Site",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Configurações",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Sobre", "message": "Sobre",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Exportar as configurações", "message": "Exportar as configurações",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Redefinir todas as configurações",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Grupo padrão para salvar novas senhas:", "message": "Grupo padrão para salvar novas senhas:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Precisa da versão do KeePassXC: $1", "message": "Precisa da versão do KeePassXC: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "A extensão requer a versão KeePassXC: $1. Versões anteriores podem causar comportamentos indesejados.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Padrão: $1", "message": "Padrão: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "As configurações atuais serão substituídas. Deseja realmente importar o arquivo de configuração?", "message": "As configurações atuais serão substituídas. Deseja realmente importar o arquivo de configuração?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Todas as configurações serão redefinidas para os padrões. Tem certeza?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Os seguintes bancos de dados do KeePassXC estão conectados ao KeePassXC-Browser.", "message": "Os seguintes bancos de dados do KeePassXC estão conectados ao KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "URL da página", "message": "URL da página",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Características", "message": "Ignorar",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Desativar o envio automático", "message": "Desativar o envio automático",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Desativar chaves de acesso",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Desativar todos os recursos", "message": "Desativar todos os recursos",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "Campo de cadeia",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Escolha o campo para o nome de utilizador", "message": "Escolha o campo para o nome de utilizador",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Escolha os campos de cadeia", "message": "Escolha os campos de cadeia",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "Confirme a sua seleção ou escolha mais campos como campos de cadeia",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Também pode usar os números para escolher os campos com o teclado", "message": "Também pode usar os números para escolher os campos com o teclado",
@ -370,10 +362,6 @@
"message": "Campos de cadeia", "message": "Campos de cadeia",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- sem nome de utilizador -", "message": "- sem nome de utilizador -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Não foram encontradas credenciais", "message": "Não foram encontradas credenciais",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Existe mais do que uma credencial guardada no KeePassXC!", "message": "Existe mais do que uma credencial guardada no KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Caducada", "message": "Caducada",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Erro: não foram encontrados campos que possam ser preenchidos", "message": "Erro: não foram encontrados campos que possam ser preenchidos",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Preferências do site", "message": "Preferências do site",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Acerca", "message": "Acerca",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Exportar definições", "message": "Exportar definições",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Grupo padrão para as novas palavras-passe:", "message": "Grupo padrão para as novas palavras-passe:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Necessita de KeePassXC, versão: $1", "message": "Necessita de KeePassXC, versão: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Padrão: $1", "message": "Padrão: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "As definições atuais serão substituídas. Tem a certeza de que deseja importar os dados do ficheiro?", "message": "As definições atuais serão substituídas. Tem a certeza de que deseja importar os dados do ficheiro?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Bases de dados conectadas com KeePassXC-Browser", "message": "Bases de dados conectadas com KeePassXC-Browser",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "URL da página", "message": "URL da página",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "Ignorar",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Desativar submissão automática", "message": "Desativar submissão automática",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Desativar todas as funcionalidades", "message": "Desativar todas as funcionalidades",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "String field",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Choose a username field", "message": "Choose a username field",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Choose String Fields", "message": "Choose String Fields",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "Confirmați selecția sau alegeți mai multe câmpuri ca și câmpuri de tip șir de caractere.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "De asemenea, puteți utiliza numerele pentru a alege câmpurile de intrare de la tastatură.", "message": "De asemenea, puteți utiliza numerele pentru a alege câmpurile de intrare de la tastatură.",
@ -370,10 +362,6 @@
"message": "String Fields", "message": "String Fields",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "-niciun nume de utilizator-", "message": "-niciun nume de utilizator-",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Nu s-au găsit autentificări.", "message": "Nu s-au găsit autentificări.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Credential fill blocked in untrusted iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "În KeePassXC s-au găsit mai multe autentificări!", "message": "În KeePassXC s-au găsit mai multe autentificări!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Expirat", "message": "Expirat",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Eroare: Imposibil de găsit câmpuri de completat.", "message": "Eroare: Imposibil de găsit câmpuri de completat.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Site Preferences", "message": "Site Preferences",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Settings",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Despre", "message": "Despre",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Setări de export", "message": "Setări de export",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Reset all settings",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Grup implicit pentru salvarea parolelor noi:", "message": "Grup implicit pentru salvarea parolelor noi:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Necesită versiunea de KeePassXC: $1", "message": "Necesită versiunea de KeePassXC: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Implicit: $1", "message": "Implicit: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Setările curente vor fi anulate. Doriți cu adevărat să importați fișierul cu setări?", "message": "Setările curente vor fi anulate. Doriți cu adevărat să importați fișierul cu setări?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "All settings will be reset to defaults. Are you sure?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Baze de date conectate la KeePassXC-Browser.", "message": "Baze de date conectate la KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "URL Site", "message": "URL Site",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Features", "message": "Dezactivare funcții",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Dezactivează funcția de Auto-Trimite", "message": "Dezactivează funcția de Auto-Trimite",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Disable passkeys",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Dezactivează toate funcțiile", "message": "Dezactivează toate funcțiile",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -4,11 +4,11 @@
"description": "Name of the extension." "description": "Name of the extension."
}, },
"addSitePreferenceButtonTitle": { "addSitePreferenceButtonTitle": {
"message": "Добавить настройки сайта для этого URL-адреса.", "message": "Добавить настройки сайта для этого URL.",
"description": "Add button title text on Site Preferences tab." "description": "Add button title text on Site Preferences tab."
}, },
"editSitePreferenceButtonTitle": { "editSitePreferenceButtonTitle": {
"message": "Изменить URL-адрес для этих настроек сайта.", "message": "Edit URL for this Site Preferences.",
"description": "Edit button title text on Site Preferences tab." "description": "Edit button title text on Site Preferences tab."
}, },
"allowIframeButtonTitle": { "allowIframeButtonTitle": {
@ -20,7 +20,7 @@
"description": "Connect button title text." "description": "Connect button title text."
}, },
"copyDebugInfoButtonTitle": { "copyDebugInfoButtonTitle": {
"message": "Копировать отладочную информацию в буфер обмена", "message": "Copy debug info to clipboard",
"description": "Copy debug info button title text on About tab." "description": "Copy debug info button title text on About tab."
}, },
"dismissHttpAuthButtonTitle": { "dismissHttpAuthButtonTitle": {
@ -244,7 +244,7 @@
"description": "Error notification shown when not connected to KeePassXC." "description": "Error notification shown when not connected to KeePassXC."
}, },
"errorCurrentDatabaseNotConnected": { "errorCurrentDatabaseNotConnected": {
"message": "Текущая база данных не подключена.", "message": "Current database is not connected.",
"description": "Error notification shown when current database is not connected during action." "description": "Error notification shown when current database is not connected during action."
}, },
"passwordGeneratorErrorTooLong": { "passwordGeneratorErrorTooLong": {
@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "String Field", "message": "Строковое поле",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Submit Button",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Выберите поле логина", "message": "Выберите поле логина",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Выберите строковые поля", "message": "Выберите строковые поля",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Choose submit button",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Please confirm your selection or choose more fields as String Fields.", "message": "Пожалуйста, подтвердите свой выбор или выберите больше строковых полей.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Вы также можете использовать числа для выбора полей ввода с клавиатуры.", "message": "Вы также можете использовать числа для выбора полей ввода с клавиатуры.",
@ -370,10 +362,6 @@
"message": "Строковые поля", "message": "Строковые поля",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Submit Button",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- нет логина -", "message": "- нет логина -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Не найдены логины.", "message": "Не найдены логины.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Заполнение учётных данных заблокировано в ненадежном iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "В KeePassXC обнаружено более одного логина!", "message": "В KeePassXC обнаружено более одного логина!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Истекло", "message": "Истекло",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Retrieve credentials",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "ОШИБКА: нет полей для заполнения.", "message": "ОШИБКА: нет полей для заполнения.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -647,7 +627,7 @@
"description": "Dismiss button text when in HTTP Authentication popup." "description": "Dismiss button text when in HTTP Authentication popup."
}, },
"optionsDefaultSettingsTitle": { "optionsDefaultSettingsTitle": {
"message": "Настройки по умолчанию", "message": "Default settings",
"description": "Default settings title for Getting Started page." "description": "Default settings title for Getting Started page."
}, },
"optionsWelcomeTitle": { "optionsWelcomeTitle": {
@ -694,10 +674,6 @@
"message": "Настройки сайта", "message": "Настройки сайта",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Настройки",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Сведения", "message": "Сведения",
"description": "About page header." "description": "About page header."
@ -723,7 +699,7 @@
"description": "Add button text." "description": "Add button text."
}, },
"optionsButtonEdit": { "optionsButtonEdit": {
"message": "Изменить", "message": "Edit",
"description": "Edit button text." "description": "Edit button text."
}, },
"optionsButtonUpdate": { "optionsButtonUpdate": {
@ -750,10 +726,6 @@
"message": "Экспорт настроек", "message": "Экспорт настроек",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Сбросить все настройки",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Группа по умолчанию для сохранения новых паролей:", "message": "Группа по умолчанию для сохранения новых паролей:",
"description": "Default group options text." "description": "Default group options text."
@ -811,7 +783,7 @@
"description": "Automatically fill-in single credential entry checkbox text." "description": "Automatically fill-in single credential entry checkbox text."
}, },
"optionsCheckboxAutoFillRelevantCredential": { "optionsCheckboxAutoFillRelevantCredential": {
"message": "Автоматически заполнять соответствующие записи учётных данных", "message": "Automatically fill in relevant credential entries",
"description": "Automatically fill-in relevant credential entry checkbox text." "description": "Automatically fill-in relevant credential entry checkbox text."
}, },
"optionsCheckboxAutoFillSingleTotp": { "optionsCheckboxAutoFillSingleTotp": {
@ -855,11 +827,11 @@
"description": "Show login notifications checkbox text." "description": "Show login notifications checkbox text."
}, },
"optionsDefaultPasswordManager": { "optionsDefaultPasswordManager": {
"message": "Установить как менеджер паролей по умолчанию", "message": "Set as default password manager",
"description": "Default password manager checkbox text." "description": "Default password manager checkbox text."
}, },
"optionsDefaultPasswordManagerHelpText": { "optionsDefaultPasswordManagerHelpText": {
"message": "Устанавливает KeePassXC-Browser в качестве менеджера паролей по умолчанию для браузера.", "message": "Sets KeePassXC-Browser as the default password manager for the browser.",
"description": "Default password manager help text." "description": "Default password manager help text."
}, },
"optionsRedirectAllowance": { "optionsRedirectAllowance": {
@ -959,7 +931,7 @@
"description": "OTP field icon option help text." "description": "OTP field icon option help text."
}, },
"optionsHideIconsAlertText": { "optionsHideIconsAlertText": {
"message": "При необходимости вы также можете скрыть значки вручную, нажав Shift+клик.", "message": "You can also hide icons manually when needed with shift+click.",
"description": "Hide icons alert text text." "description": "Hide icons alert text text."
}, },
"optionsAutoRetrieveCredentialsHelpText": { "optionsAutoRetrieveCredentialsHelpText": {
@ -975,7 +947,7 @@
"description": "Auto-Fill Single Entry option help text." "description": "Auto-Fill Single Entry option help text."
}, },
"optionsAutoFillRelevantCredentialHelpText": { "optionsAutoFillRelevantCredentialHelpText": {
"message": "Автоматически заполнить соответствующие учётные данные, если требуется повторное заполнение.", "message": "Automatically fill in the relevant credential if a second fill is needed.",
"description": "Auto-Fill Relevant Credential option help text." "description": "Auto-Fill Relevant Credential option help text."
}, },
"optionsAutoFillSingleEntryWarning": { "optionsAutoFillSingleEntryWarning": {
@ -1058,10 +1030,6 @@
"message": "Требуемая версия KeePassXC: $1", "message": "Требуемая версия KeePassXC: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "По умолчанию: $1", "message": "По умолчанию: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Текущие настройки будут переопределены. Вы действительно хотите импортировать файл настроек?", "message": "Текущие настройки будут переопределены. Вы действительно хотите импортировать файл настроек?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Все настройки будут сброшены на значения по умолчанию. Вы уверены?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Базы данных, подключенные к KeePassXC-Browser.", "message": "Базы данных, подключенные к KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Адрес страницы", "message": "Адрес страницы",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Функции", "message": "Игнорировать",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Выключить автоподстановку", "message": "Выключить автоподстановку",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Отключить ключи доступа",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Отключить все функции", "message": "Отключить все функции",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
@ -1435,31 +1395,31 @@
"description": "Lock database button title text." "description": "Lock database button title text."
}, },
"welcomeText": { "welcomeText": {
"message": "Добро пожаловать в KeePassXC-Browser!", "message": "Welcome to KeePassXC-Browser!",
"description": "Main title of Getting Started page." "description": "Main title of Getting Started page."
}, },
"documentationGettingStarted": { "documentationGettingStarted": {
"message": "Наше руководство по началу работы поможет вам быстро приступить к работе.", "message": "Our Getting Started Guide will get you up and running quickly.",
"description": "Getting Started document text." "description": "Getting Started document text."
}, },
"documentationUserGuide": { "documentationUserGuide": {
"message": "Ищете более подробную документацию? Наше руководство пользователя вам поможет.", "message": "Looking for more comprehensive documentation? Our User Guide is there to help.",
"description": "User Guide text." "description": "User Guide text."
}, },
"documentationTroubleshootingGuide": { "documentationTroubleshootingGuide": {
"message": "Нужна помощь в устранении неполадок интеграции с браузером? Ознакомьтесь с руководством по устранению неполадок.", "message": "Need help troubleshooting the browser integration? Check the Troubleshooting Guide.",
"description": "Troubleshooting Guide text." "description": "Troubleshooting Guide text."
}, },
"gettingStartedWelcomeText": { "gettingStartedWelcomeText": {
"message": "Добро пожаловать в KeePassXC-Browser, официальное расширение браузера для KeePassXC.", "message": "Welcome to KeePassXC-Browser, the official browser extension for KeePassXC.",
"description": "Welcome to KeePassXC-Browser, the official browser extension for KeePassXC." "description": "Welcome to KeePassXC-Browser, the official browser extension for KeePassXC."
}, },
"gettingStartedSecondWelcomeText": { "gettingStartedSecondWelcomeText": {
"message": "Пожалуйста, проверьте настройки по умолчанию и выберите все предпочтительные параметры.", "message": "Please go through the default settings and check all your preferred options.",
"description": "Please go through the default settings and check all your preferred options." "description": "Please go through the default settings and check all your preferred options."
}, },
"gettingStartedNewUser": { "gettingStartedNewUser": {
"message": "Вы новый пользователь? Посмотрите ссылки на нашу документацию.", "message": "Are you a new user? Check links to our documentation.",
"description": "Are you a new user? Check links to our documentation." "description": "Are you a new user? Check links to our documentation."
} }
} }

View file

@ -322,10 +322,6 @@
"message": "Strängfält", "message": "Strängfält",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Skicka-knapp",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Välj ett användarnamn-fält", "message": "Välj ett användarnamn-fält",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Välj sträng-fält", "message": "Välj sträng-fält",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Välj Skicka-knapp",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Bekräfta ditt val eller välj fler fält som strängfält.", "message": "Vänligen bekräfta ditt val eller välj fler fält som <em>Strängfält</em>.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "You can also use the numbers to choose the input fields from keyboard.", "message": "You can also use the numbers to choose the input fields from keyboard.",
@ -370,10 +362,6 @@
"message": "Strängfält", "message": "Strängfält",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Skicka-knapp",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- inget användarnamn -", "message": "- inget användarnamn -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Fel:\nInga inloggningar hittades.", "message": "Fel:\nInga inloggningar hittades.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Ifyllning av inloggningsuppgifter blockerad av otillförlitlig iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Fel:\nMer än en inloggning hittades i KeePassXC!\nTryck på ikonen för KeePassXC-Browser för fler alternativ.", "message": "Fel:\nMer än en inloggning hittades i KeePassXC!\nTryck på ikonen för KeePassXC-Browser för fler alternativ.",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Förfallen", "message": "Förfallen",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Hämta autentiseringsuppgifter",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Fel:\nKan inte hitta fält att fylla i.", "message": "Fel:\nKan inte hitta fält att fylla i.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Sidinställningar", "message": "Sidinställningar",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Inställningar",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Om", "message": "Om",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Exportera inställningar", "message": "Exportera inställningar",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Återställ alla inställningar",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Default group for saving new passwords:", "message": "Default group for saving new passwords:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Kräver KeePassXC version: $1", "message": "Kräver KeePassXC version: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "The extension requires KeePassXC version: $1. Earlier versions can cause unwanted behavior.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Förinställt: $1", "message": "Förinställt: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Nuvarande inställningar kommer att skrivas över. Vill du verkligen importera inställningsfilen?", "message": "Nuvarande inställningar kommer att skrivas över. Vill du verkligen importera inställningsfilen?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Alla inställningar kommer att återställas till standardinställning. Är du säker?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Följande KeePassXC-databaser är anslutna till KeePassXC-Browser.", "message": "Följande KeePassXC-databaser är anslutna till KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Sid-URL", "message": "Sid-URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Funktioner", "message": "Ignorera",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Skicka inte automatiskt", "message": "Skicka inte automatiskt",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Avaktivera passnycklar",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Inaktivera alla funktioner", "message": "Inaktivera alla funktioner",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -1,6 +1,6 @@
{ {
"extensionDescription": { "extensionDescription": {
"message": "Modern tarayıcılar için KeePassXC bütünleştirmesi", "message": "Modern tarayıcılar için KeePassXC bütünleşmesi",
"description": "Name of the extension." "description": "Name of the extension."
}, },
"addSitePreferenceButtonTitle": { "addSitePreferenceButtonTitle": {
@ -319,13 +319,9 @@
"description": "Clear save data button text when choosing Custom Login Fields." "description": "Clear save data button text when choosing Custom Login Fields."
}, },
"defineStringField": { "defineStringField": {
"message": "Yazı alanı", "message": "Metin alanı",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Gönder düğmesi",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Kullanıcı adı alanını seçin", "message": "Kullanıcı adı alanını seçin",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -339,16 +335,12 @@
"description": "Choosing a TOTP field text when choosing Custom Login Fields." "description": "Choosing a TOTP field text when choosing Custom Login Fields."
}, },
"defineChooseStringFields": { "defineChooseStringFields": {
"message": "Yazı alanlarını seçin", "message": "Metin alanlarını seçin",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Gönder düğmesini seçin",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Lütfen seçiminizi onaylayın ya da yazı alanları olarak ek alanlar seçin.", "message": "Lütfen seçiminizi onaylayın ya da dizge alanları olarak ek alanlar seçin.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Giriş alanlarını tuş takımıyla seçmek için sayıları kullanabilirsiniz.", "message": "Giriş alanlarını tuş takımıyla seçmek için sayıları kullanabilirsiniz.",
@ -367,13 +359,9 @@
"description": "General text for password." "description": "General text for password."
}, },
"stringFields": { "stringFields": {
"message": "Yazı alanları", "message": "Metin alanları",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Gönder düğmesi",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- kullanıcı adı yok -", "message": "- kullanıcı adı yok -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Herhangi bir oturum açma bulunamadı.", "message": "Herhangi bir oturum açma bulunamadı.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Güvenilmeyen bir iFrame nedeniyle kimlik doğrulama bilgilerinin doldurulması engellendi.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "KeePassXC üzerinde birden fazla oturum açma bulundu!", "message": "KeePassXC üzerinde birden fazla oturum açma bulundu!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Süresi dolmuş", "message": "Süresi dolmuş",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Kimlik doğrulama bilgilerini al",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Hata: Doldurulacak alanlar bulunamadı.", "message": "Hata: Doldurulacak alanlar bulunamadı.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -419,7 +399,7 @@
"description": "Message shown when no password fields are found." "description": "Message shown when no password fields are found."
}, },
"fieldsPasswordFillNotAccepted": { "fieldsPasswordFillNotAccepted": {
"message": "Parolanın bir düz yazı alanına yazılması engellenir.", "message": "Parolanın bir düz metin alanına yazılması engellenir.",
"description": "Message shown when password fill to a plain text field is prevented." "description": "Message shown when password fill to a plain text field is prevented."
}, },
"rememberNothingChanged": { "rememberNothingChanged": {
@ -694,10 +674,6 @@
"message": "Site ayarları", "message": "Site ayarları",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Ayarlar",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Hakkında", "message": "Hakkında",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Ayarları dışa aktar", "message": "Ayarları dışa aktar",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Tüm ayarları sıfırla",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Yeni parolaların kaydedileceği varsayılan grup:", "message": "Yeni parolaların kaydedileceği varsayılan grup:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "KeePassXC $1 sürümünü gerektirir", "message": "KeePassXC $1 sürümünü gerektirir",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "Bu eklenti için KeePassXC $1 sürümü gereklidir. Önceki sürümler istenmeyen davranışlara yol açabilir.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Varsayılan: $1", "message": "Varsayılan: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Var olan ayarlar değiştirilecek. Ayarlar dosyasını içe aktarmak istediğinize emin misiniz?", "message": "Var olan ayarlar değiştirilecek. Ayarlar dosyasını içe aktarmak istediğinize emin misiniz?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Tüm ayarları varsayılan değerlerine sıfırlamak istediğinize emin misiniz? ",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "KeePassXC-Browser ile bağlantısı kurulmuş KeePassXC veri tabanları.", "message": "KeePassXC-Browser ile bağlantısı kurulmuş KeePassXC veri tabanları.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "Sayfa adresi", "message": "Sayfa adresi",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Özellikler", "message": "Yok say",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Otomatik gönderim yapılmasın", "message": "Otomatik gönderim yapılmasın",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Geçiş anahtarları kullanılmasın",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Tüm özellikleri kapat", "message": "Tüm özellikleri kapat",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -188,7 +188,7 @@
"description": "Credential is excluded." "description": "Credential is excluded."
}, },
"errorMessagePasskeysRequestCanceled": { "errorMessagePasskeysRequestCanceled": {
"message": "Запит на використання ключів доступу скасовано.", "message": "Запит на Passkeys-ключі скасовано.",
"description": "Passkeys request canceled." "description": "Passkeys request canceled."
}, },
"errorMessagePasskeysInvalidUserVerification": { "errorMessagePasskeysInvalidUserVerification": {
@ -224,7 +224,7 @@
"description": "Wait for timer to expire." "description": "Wait for timer to expire."
}, },
"errorMessagePasskeysUnknownError": { "errorMessagePasskeysUnknownError": {
"message": "Невідома помилка ключів доступу.", "message": "Невідома помилка паролів.",
"description": "Unknown passkeys error." "description": "Unknown passkeys error."
}, },
"errorMessagePasskeysInvalidChallenge": { "errorMessagePasskeysInvalidChallenge": {
@ -322,10 +322,6 @@
"message": "Поле рядка", "message": "Поле рядка",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "Кнопка «Відправити»",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "Виберіть поле імені користувача", "message": "Виберіть поле імені користувача",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "Оберіть поля рядків", "message": "Оберіть поля рядків",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "Виберіть кнопку «Відправити»",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "Підтвердьте свій вибір або виберіть більше полів як рядкові поля.", "message": "Підтвердьте свій вибір або виберіть більше полів як рядків.",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "Ви також можете використовувати числа для вибору полів введення з клавіатури.", "message": "Ви також можете використовувати числа для вибору полів введення з клавіатури.",
@ -370,10 +362,6 @@
"message": "Поля рядків", "message": "Поля рядків",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "Кнопка «Відправити»",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- без імені користувача -", "message": "- без імені користувача -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "Не знайдено облікових даних.", "message": "Не знайдено облікових даних.",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "Заповнення облікових даних заблоковано в ненадійному iframe.",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "Знайдено більше ніж один запис у KeePassXC!", "message": "Знайдено більше ніж один запис у KeePassXC!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "Протерміновано", "message": "Протерміновано",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "Отримати облікові дані",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "Помилка: Не вдалося знайти поля для заповнення.", "message": "Помилка: Не вдалося знайти поля для заповнення.",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "Налаштування сайту", "message": "Налаштування сайту",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "Налаштування",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "Про розширення", "message": "Про розширення",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "Експортувати налаштування", "message": "Експортувати налаштування",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "Скинути всі налаштування",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "Типова група для збереження нових паролів:", "message": "Типова група для збереження нових паролів:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "Потребує версію KeePassXC: $1", "message": "Потребує версію KeePassXC: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "Для розширення потрібна версія KeePassXC: $1. Більш ранні версії можуть спричинити небажану поведінку.",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "Типово: $1", "message": "Типово: $1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "Поточні налаштування будуть перевизначені. Ви дійсно хочете імпортувати файл налаштувань?", "message": "Поточні налаштування будуть перевизначені. Ви дійсно хочете імпортувати файл налаштувань?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "Всі налаштування будуть скинуті. Ви впевнені?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "Під'єднані бази даних до KeePassXC-Browser.", "message": "Під'єднані бази даних до KeePassXC-Browser.",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "URL-адреса сторінки", "message": "URL-адреса сторінки",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "Особливості", "message": "Ігнорувати",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "Вимкнути автовідправлення", "message": "Вимкнути автовідправлення",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "Вимкнути ключі доступу",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "Вимкнути всі можливості", "message": "Вимкнути всі можливості",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
@ -1399,11 +1359,11 @@
"description": "Extension title in settings page" "description": "Extension title in settings page"
}, },
"optionsPasskeysTitle": { "optionsPasskeysTitle": {
"message": "Ключі доступу", "message": "Passkey-ключі",
"description": "Passkeys settings title in settings page." "description": "Passkeys settings title in settings page."
}, },
"optionsPasskeysEnable": { "optionsPasskeysEnable": {
"message": "Увімкнути ключі доступу", "message": "Увімкнути паролі",
"description": "Enabled passkeys option text." "description": "Enabled passkeys option text."
}, },
"optionsPasskeysEnableHelpText": { "optionsPasskeysEnableHelpText": {
@ -1411,11 +1371,11 @@
"description": "Passkeys option help text." "description": "Passkeys option help text."
}, },
"optionsPasskeysEnableFallback": { "optionsPasskeysEnableFallback": {
"message": "Увімкнути резервний метод для ключів доступу", "message": "Увімкнути резервний варіант паролів",
"description": "Enabled passkeys fallback option text." "description": "Enabled passkeys fallback option text."
}, },
"optionsPasskeysEnableFallbackHelpText": { "optionsPasskeysEnableFallbackHelpText": {
"message": "Якщо увімкнено, невдалий або скасований запит до KeePassXC спричинить власний внутрішній запит браузера на ключі доступу. Якщо вимкнено, необхідне підключення до KeePassXC, а скасований запит буде невдалим. За замовчуванням: увімкнено.", "message": "Коли увімкнено, невдала або скасована спроба запиту до KeePassXC викликатиме запит на паролі через внутрішню систему браузера. Якщо вимкнено, для підключення до KeePassXC буде потрібно, і скасований запит зазнає невдачі. За замовчуванням: увімкнено.",
"description": "Passkeys fallback option help text." "description": "Passkeys fallback option help text."
}, },
"openNewTab": { "openNewTab": {

File diff suppressed because it is too large Load diff

View file

@ -322,10 +322,6 @@
"message": "字符串字段", "message": "字符串字段",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "提交按钮",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "选择用户名字段", "message": "选择用户名字段",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "选择字符串字段", "message": "选择字符串字段",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "选择提交按钮",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "请确认您的选择,或选择更多字段作为字符串字段。", "message": "请确认您的选择,或选择更多字段作为字符串字段。",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "您也可以使用键盘的数字键选择输入字段。", "message": "您也可以使用键盘的数字键选择输入字段。",
@ -370,10 +362,6 @@
"message": "字符串字段", "message": "字符串字段",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "提交按钮",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- 没有用户名 -", "message": "- 没有用户名 -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "未找到登录信息。", "message": "未找到登录信息。",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "凭据填充在不受信任的 iframe 中被阻止。",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "在 KeePassXC 中找到多条登录信息!", "message": "在 KeePassXC 中找到多条登录信息!",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "已过期", "message": "已过期",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "检索凭据",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "错误:无法找到可填写的字段。", "message": "错误:无法找到可填写的字段。",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "网站设置", "message": "网站设置",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "设置",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "关于", "message": "关于",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "导出配置", "message": "导出配置",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "重置所有设置",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "保存新密码的默认群组:", "message": "保存新密码的默认群组:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "需要 KeePassXC 版本:$1", "message": "需要 KeePassXC 版本:$1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "该扩展需要 KeePassXC 版本:$1。早期版本可能会导致意外行为。",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "默认值:$1", "message": "默认值:$1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "当前配置将会被覆盖,确定导入?", "message": "当前配置将会被覆盖,确定导入?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "所有设置都将重置为默认。您确定吗?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "已连接到 KeePassXC-Browser 的数据库。", "message": "已连接到 KeePassXC-Browser 的数据库。",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "页面 URL", "message": "页面 URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "功能", "message": "忽略",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "禁用自动提交", "message": "禁用自动提交",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "禁用通行密钥",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "禁用所有功能", "message": "禁用所有功能",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -303,7 +303,7 @@
"description": "More button text when choosing Custom Login Fields." "description": "More button text when choosing Custom Login Fields."
}, },
"defineReset": { "defineReset": {
"message": "重", "message": "重",
"description": "Reset button text when choosing Custom Login Fields." "description": "Reset button text when choosing Custom Login Fields."
}, },
"defineConfirm": { "defineConfirm": {
@ -322,10 +322,6 @@
"message": "字串欄位", "message": "字串欄位",
"description": "Text for string field." "description": "Text for string field."
}, },
"defineSubmitButton": {
"message": "送出按鈕",
"description": "Text for Submit Button."
},
"defineChooseUsername": { "defineChooseUsername": {
"message": "選擇用戶名稱欄位", "message": "選擇用戶名稱欄位",
"description": "Choosing a username field text when choosing Custom Login Fields." "description": "Choosing a username field text when choosing Custom Login Fields."
@ -342,13 +338,9 @@
"message": "選擇字串欄位", "message": "選擇字串欄位",
"description": "Choose String Fields a selection text when choosing Custom Login Fields." "description": "Choose String Fields a selection text when choosing Custom Login Fields."
}, },
"defineChooseSubmitButton": {
"message": "選擇送出按鈕",
"description": "Choose submit button selection text when choosing Custom Login Fields."
},
"defineHelpText": { "defineHelpText": {
"message": "請確認您的選擇,或選擇更多欄位作為字串欄位", "message": "請確認您的選擇,或是選擇更多欄位作為<em>字串欄位</em>。",
"description": "Confirm a selection text when choosing Custom Login Fields which contains String Fields." "description": "Confirm a selection text when choosing Custom Login Fields which contains string fields."
}, },
"defineKeyboardText": { "defineKeyboardText": {
"message": "您也可以使用鍵盤的數字鍵選擇輸入欄位。", "message": "您也可以使用鍵盤的數字鍵選擇輸入欄位。",
@ -370,10 +362,6 @@
"message": "字串欄位", "message": "字串欄位",
"description": "General text for a String Fields." "description": "General text for a String Fields."
}, },
"submitButton": {
"message": "送出按鈕",
"description": "Custom Submit Button text."
},
"credentialsNoUsername": { "credentialsNoUsername": {
"message": "- 無用戶名稱 -", "message": "- 無用戶名稱 -",
"description": "Shown when no username is set in the credentials." "description": "Shown when no username is set in the credentials."
@ -382,10 +370,6 @@
"message": "錯誤:\n找不到登錄資訊。", "message": "錯誤:\n找不到登錄資訊。",
"description": "Shown when no credentials are found for the current page." "description": "Shown when no credentials are found for the current page."
}, },
"credentialsBlockedInIframe": {
"message": "憑證填入在不可信 iframe 而被阻止。",
"description": "Alert message when filling credentials is blocked due to iframe restrictions."
},
"credentialsMultipleFound": { "credentialsMultipleFound": {
"message": "錯誤:\n在 KeePassXC 中找到多個登錄資訊!\n點選 KeePassXC-Browser 圖示來檢視更多選項。", "message": "錯誤:\n在 KeePassXC 中找到多個登錄資訊!\n點選 KeePassXC-Browser 圖示來檢視更多選項。",
"description": "Alert message when trying to fill username and/or password when multiple credentials are found." "description": "Alert message when trying to fill username and/or password when multiple credentials are found."
@ -406,10 +390,6 @@
"message": "已過期", "message": "已過期",
"description": "If a credential is expired, this is appended to the title label." "description": "If a credential is expired, this is appended to the title label."
}, },
"credentialsRetrieveButton": {
"message": "檢索憑證",
"description": "Manual retrieve credentials button text."
},
"fieldsFill": { "fieldsFill": {
"message": "錯誤:\n找不到該填入的欄位。", "message": "錯誤:\n找不到該填入的欄位。",
"description": "Alert message when no fields are found to fill in." "description": "Alert message when no fields are found to fill in."
@ -694,10 +674,6 @@
"message": "網站設定", "message": "網站設定",
"description": "Site Preferences page header." "description": "Site Preferences page header."
}, },
"optionsSitePreferencesSettings": {
"message": "設定",
"description": "Site Preferences settings button text."
},
"optionsMenuAbout": { "optionsMenuAbout": {
"message": "關於", "message": "關於",
"description": "About page header." "description": "About page header."
@ -750,10 +726,6 @@
"message": "導出配置", "message": "導出配置",
"description": "Export settings button text." "description": "Export settings button text."
}, },
"optionsButtonResetSettings": {
"message": "重設所有設定",
"description": "Reset all settings button text."
},
"optionsLabelDefaultGroup": { "optionsLabelDefaultGroup": {
"message": "儲存新密碼的預設群組:", "message": "儲存新密碼的預設群組:",
"description": "Default group options text." "description": "Default group options text."
@ -1058,10 +1030,6 @@
"message": "需要 KeePassXC 版本: $1", "message": "需要 KeePassXC 版本: $1",
"description": "KeePassXC version requirement text." "description": "KeePassXC version requirement text."
}, },
"optionsMinimumKeePassXCVersionRequired": {
"message": "此擴展需要 KeePassXC 版本:$1。更早的版本可能導致意外行為。",
"description": "KeePassXC minimum version requirement text."
},
"optionsDefault": { "optionsDefault": {
"message": "預設值:$1", "message": "預設值:$1",
"description": "Default setting text." "description": "Default setting text."
@ -1098,10 +1066,6 @@
"message": "目前設定將會被覆寫。真的要匯入設定檔案?", "message": "目前設定將會被覆寫。真的要匯入設定檔案?",
"description": "Import settings confirmation dialog help text." "description": "Import settings confirmation dialog help text."
}, },
"optionsResetSettingsDialogText": {
"message": "所有設定都將被重置為預設值。您確定嗎?",
"description": "Reset all settings dialog text."
},
"optionsConnectedDatabasesText": { "optionsConnectedDatabasesText": {
"message": "已連接至 KeePassXC-Browser 的資料庫。", "message": "已連接至 KeePassXC-Browser 的資料庫。",
"description": "Info text about connected databases." "description": "Info text about connected databases."
@ -1146,8 +1110,8 @@
"message": "網頁 URL", "message": "網頁 URL",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnFeatures": { "optionsColumnIgnore": {
"message": "特性", "message": "忽略",
"description": "Site Preferences list column title." "description": "Site Preferences list column title."
}, },
"optionsColumnUsernameOnly": { "optionsColumnUsernameOnly": {
@ -1178,10 +1142,6 @@
"message": "停用自動送出", "message": "停用自動送出",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."
}, },
"optionsSelectionPasskeys": {
"message": "停用通行密鑰",
"description": "Site Preferences option selection."
},
"optionsSelectionFull": { "optionsSelectionFull": {
"message": "停用所有功能", "message": "停用所有功能",
"description": "Site Preferences option selection." "description": "Site Preferences option selection."

View file

@ -83,7 +83,7 @@ browserAction.generateIconName = async function(iconType) {
style = page.settings.colorTheme; style = page.settings.colorTheme;
} }
} }
const filetype = (page.isFirefox || page.isSafari) ? 'svg' : 'png'; const filetype = (isFirefox() ? 'svg' : 'png');
return `/icons/toolbar/${style}/${name}.${filetype}`; return `/icons/toolbar/${style}/${name}.${filetype}`;
}; };

View file

@ -400,7 +400,7 @@ function onDisconnected() {
page.clearAllLogins(); page.clearAllLogins();
keepass.updatePopup('cross'); keepass.updatePopup('cross');
keepass.updateDatabaseHashToContent(); keepass.updateDatabaseHashToContent();
logError(`Failed to connect: ${(browser.runtime.lastError === null ? 'Unknown error' : browser.runtime.lastError?.message)}`); logError(`Failed to connect: ${(browser.runtime.lastError === null ? 'Unknown error' : browser.runtime.lastError.message)}`);
} }
keepassClient.onNativeMessage = function(response) { keepassClient.onNativeMessage = function(response) {

View file

@ -13,14 +13,14 @@ kpxcEvent.onMessage = async function(request, sender) {
} }
}; };
kpxcEvent.showStatus = async function(tab, configured, internalPoll, forceShowDefault = false) { kpxcEvent.showStatus = async function(tab, configured, internalPoll) {
let keyId = null; let keyId = null;
if (configured && keepass.databaseHash !== '' if (configured && keepass.databaseHash !== ''
&& Object.hasOwn(keepass.keyRing, keepass.databaseHash)) { && Object.hasOwn(keepass.keyRing, keepass.databaseHash)) {
keyId = keepass.keyRing[keepass.databaseHash].id; keyId = keepass.keyRing[keepass.databaseHash].id;
} }
if (!internalPoll || forceShowDefault) { if (!internalPoll) {
browserAction.showDefault(tab); browserAction.showDefault(tab);
} }
@ -76,7 +76,7 @@ kpxcEvent.onSaveSettings = async function(tab, settings) {
kpxcEvent.onGetStatus = async function(tab, args = []) { kpxcEvent.onGetStatus = async function(tab, args = []) {
// When internalPoll is true the event is triggered from content script in intervals -> don't poll KeePassXC // When internalPoll is true the event is triggered from content script in intervals -> don't poll KeePassXC
try { try {
const [ internalPoll = false, triggerUnlock = false, forceShowDefault ] = args; const [ internalPoll = false, triggerUnlock = false ] = args;
if (!internalPoll) { if (!internalPoll) {
const response = await keepass.testAssociation(tab, [ true, triggerUnlock ]); const response = await keepass.testAssociation(tab, [ true, triggerUnlock ]);
if (!response) { if (!response) {
@ -85,7 +85,7 @@ kpxcEvent.onGetStatus = async function(tab, args = []) {
} }
const configured = await keepass.isConfigured(); const configured = await keepass.isConfigured();
return kpxcEvent.showStatus(tab, configured, internalPoll, forceShowDefault); return kpxcEvent.showStatus(tab, configured, internalPoll);
} catch (err) { } catch (err) {
logError('No status shown: ' + err); logError('No status shown: ' + err);
return Promise.reject(); return Promise.reject();
@ -241,10 +241,6 @@ kpxcEvent.sendBackToTabs = async function(tab, args = []) {
} }
}; };
kpxcEvent.getFeaturesList = async function() {
return keepass.featuresList;
};
// All methods named in this object have to be declared BEFORE this! // All methods named in this object have to be declared BEFORE this!
kpxcEvent.messageHandlers = { kpxcEvent.messageHandlers = {
'add_credentials': keepass.addCredentials, 'add_credentials': keepass.addCredentials,
@ -253,6 +249,7 @@ kpxcEvent.messageHandlers = {
'banner_set_position': page.setBannerPosition, 'banner_set_position': page.setBannerPosition,
'check_database_hash': keepass.checkDatabaseHash, 'check_database_hash': keepass.checkDatabaseHash,
'check_update_keepassxc': kpxcEvent.onCheckUpdateKeePassXC, 'check_update_keepassxc': kpxcEvent.onCheckUpdateKeePassXC,
'compare_versions': kpxcEvent.compareMultipleVersions,
'create_new_group': keepass.createNewGroup, 'create_new_group': keepass.createNewGroup,
'enable_automatic_reconnect': keepass.enableAutomaticReconnect, 'enable_automatic_reconnect': keepass.enableAutomaticReconnect,
'disable_automatic_reconnect': keepass.disableAutomaticReconnect, 'disable_automatic_reconnect': keepass.disableAutomaticReconnect,
@ -264,7 +261,6 @@ kpxcEvent.messageHandlers = {
'get_database_hash': keepass.getDatabaseHash, 'get_database_hash': keepass.getDatabaseHash,
'get_database_groups': keepass.getDatabaseGroups, 'get_database_groups': keepass.getDatabaseGroups,
'get_error_message': keepass.getErrorMessage, 'get_error_message': keepass.getErrorMessage,
'get_features_list': kpxcEvent.getFeaturesList,
'get_keepassxc_versions': kpxcEvent.onGetKeePassXCVersions, 'get_keepassxc_versions': kpxcEvent.onGetKeePassXCVersions,
'get_login_list': page.getLoginList, 'get_login_list': page.getLoginList,
'get_status': kpxcEvent.onGetStatus, 'get_status': kpxcEvent.onGetStatus,
@ -300,7 +296,6 @@ kpxcEvent.messageHandlers = {
'reconnect': kpxcEvent.onReconnect, 'reconnect': kpxcEvent.onReconnect,
'remove_credentials_from_tab_information': kpxcEvent.onRemoveCredentialsFromTabInformation, 'remove_credentials_from_tab_information': kpxcEvent.onRemoveCredentialsFromTabInformation,
'request_autotype': keepass.requestAutotype, 'request_autotype': keepass.requestAutotype,
'reset_all_settings': page.resetAllSettings,
'retrieve_credentials': page.retrieveCredentials, 'retrieve_credentials': page.retrieveCredentials,
'show_default_browseraction': browserAction.showDefault, 'show_default_browseraction': browserAction.showDefault,
'update_credentials': keepass.updateCredentials, 'update_credentials': keepass.updateCredentials,

View file

@ -6,15 +6,10 @@ httpAuth.requests = [];
httpAuth.pendingCallbacks = []; httpAuth.pendingCallbacks = [];
httpAuth.init = function() { httpAuth.init = function() {
if (page.isSafari) {
debugLogMessage('HTTP Basic Auth implementation is not supported in Safari.');
return;
}
let handleReq = httpAuth.handleRequestPromise; let handleReq = httpAuth.handleRequestPromise;
let reqType = 'blocking'; let reqType = 'blocking';
if (!page.isFirefox) { if (!isFirefox()) {
handleReq = httpAuth.handleRequestCallback; handleReq = httpAuth.handleRequestCallback;
reqType = 'asyncBlocking'; reqType = 'asyncBlocking';
} }

View file

@ -10,6 +10,12 @@ const contextMenuItems = [
{ title: tr('contextMenuRequestGlobalAutoType'), action: 'request_autotype' } { title: tr('contextMenuRequestGlobalAutoType'), action: 'request_autotype' }
]; ];
const menuContexts = [ 'editable' ];
if (isFirefox()) {
menuContexts.push('password');
}
const initListeners = async function() { const initListeners = async function() {
/** /**
* Generate information structure for created tab and invoke all needed * Generate information structure for created tab and invoke all needed
@ -109,8 +115,7 @@ const initListeners = async function() {
if (contextMenuItems.some(e => e.action === command) if (contextMenuItems.some(e => e.action === command)
|| command === 'redetect_fields' || command === 'redetect_fields'
|| command === 'choose_credential_fields' || command === 'choose_credential_fields'
|| command === 'retrieve_credentials_forced' || command === 'retrive_credentials_forced'
|| command === 'reopen_database'
|| command === 'reload_extension') { || command === 'reload_extension') {
const tab = await getCurrentTab(); const tab = await getCurrentTab();
if (tab?.id) { if (tab?.id) {
@ -155,32 +160,26 @@ const initListeners = async function() {
}); });
}; };
const initContextMenuItems = async function() { const initContextMenuItems = async function() {
page.menuContexts = [ 'editable' ];
if (page.isFirefox) {
page.menuContexts.push('password');
}
// Create context menu items // Create context menu items
await browser.contextMenus.removeAll(); await browser.contextMenus.removeAll();
for (const item of contextMenuItems) { for (const item of contextMenuItems) {
try { try {
await browser.contextMenus.create({ await browser.contextMenus.create({
title: item.title, title: item.title,
contexts: page.menuContexts, contexts: menuContexts,
visible: item.visible, visible: item.visible,
id: item.id || item.action id: item.id || item.action
}); });
} catch (e) { } catch (e) {
logError(e); logError(e);
} }
} }
}; };
(async () => { (async () => {
try { try {
await keepass.migrateKeyRing(); await keepass.migrateKeyRing();
await page.initBrowser();
await page.initSettings(); await page.initSettings();
await page.initSitePreferences(); await page.initSitePreferences();
await page.initOpenedTabs(); await page.initOpenedTabs();
@ -190,7 +189,7 @@ const initContextMenuItems = async function() {
await keepass.reconnect(null, 5000); // 5 second timeout for the first connect await keepass.reconnect(null, 5000); // 5 second timeout for the first connect
await keepass.enableAutomaticReconnect(); await keepass.enableAutomaticReconnect();
await keepass.updateDatabase(); await keepass.updateDatabase();
} catch (_e) { } catch (e) {
logError('init.js failed'); logError('init.js failed');
} }
})(); })();

View file

@ -2,31 +2,20 @@
const keepass = {}; const keepass = {};
keepass.associated = { 'value': false, 'hash': null }; keepass.associated = { 'value': false, 'hash': null };
keepass.featuresList = { keepass.keyPair = { publicKey: null, secretKey: null };
downloadFaviconAfterSave: false, keepass.serverPublicKey = '';
newTotp: false,
passwordGenerator: false,
passkeys: false,
passkeysDefaultGroup: false,
requiredKeePassXCVersionFound: false,
};
keepass.cacheTimeout = 30 * 1000; // Milliseconds
keepass.clientID = ''; keepass.clientID = '';
keepass.currentKeePassXC = '';
keepass.databaseHash = '';
keepass.isConnected = false; keepass.isConnected = false;
keepass.isDatabaseClosed = true; keepass.isDatabaseClosed = true;
keepass.isEncryptionKeyUnrecognized = false;
keepass.isKeePassXCAvailable = false; keepass.isKeePassXCAvailable = false;
keepass.keyPair = { publicKey: null, secretKey: null }; keepass.isEncryptionKeyUnrecognized = false;
keepass.currentKeePassXC = '';
keepass.requiredKeePassXC = '2.3.1';
keepass.latestVersionUrl = 'https://api.github.com/repos/keepassxreboot/keepassxc/releases/latest'; keepass.latestVersionUrl = 'https://api.github.com/repos/keepassxreboot/keepassxc/releases/latest';
keepass.cacheTimeout = 30 * 1000; // Milliseconds
keepass.databaseHash = '';
keepass.previousDatabaseHash = ''; keepass.previousDatabaseHash = '';
keepass.reconnectLoop = null; keepass.reconnectLoop = null;
keepass.requiredKeePassXC = '2.6.0';
keepass.serverPublicKey = '';
const DEFAULT_FETCH_TIMEOUT = 5000; // ms
const MAX_RELATED_ORIGIN_LABELS = 60;
const kpActions = { const kpActions = {
SET_LOGIN: 'set-login', SET_LOGIN: 'set-login',
@ -183,7 +172,7 @@ keepass.generatePassword = async function(tab) {
return ''; return '';
} }
if (!keepass.featuresList.passwordGenerator) { if (!compareVersion(keepass.requiredKeePassXC, keepass.currentKeePassXC)) {
return ''; return '';
} }
@ -240,7 +229,9 @@ keepass.associate = async function(tab) {
const response = await keepassClient.sendMessage(kpAction, tab, messageData, nonce, false, true); const response = await keepassClient.sendMessage(kpAction, tab, messageData, nonce, false, true);
if (response) { if (response) {
keepass.setCryptoKey(response.id, idKey); // Use public key as identification key with older KeePassXC releases
const savedKey = compareVersion('2.3.4', keepass.currentKeePassXC) ? idKey : key;
keepass.setCryptoKey(response.id, savedKey); // Save the new identification public key as id key for the database
keepass.associated.value = true; keepass.associated.value = true;
keepass.associated.hash = response.hash || 0; keepass.associated.hash = response.hash || 0;
@ -344,13 +335,7 @@ keepass.getDatabaseHash = async function(tab, args = []) {
} }
try { try {
const request = keepassClient.buildRequest( const request = keepassClient.buildRequest(kpAction, keepassClient.encrypt(messageData, nonce), nonce, keepass.clientID, triggerUnlock);
kpAction,
keepassClient.encrypt(messageData, nonce),
nonce,
keepass.clientID,
triggerUnlock,
);
const response = await keepassClient.sendNativeMessage(request, enableTimeout); const response = await keepassClient.sendNativeMessage(request, enableTimeout);
if (response.message && response.nonce) { if (response.message && response.nonce) {
const res = keepassClient.decrypt(response.message, response.nonce); const res = keepassClient.decrypt(response.message, response.nonce);
@ -427,7 +412,6 @@ keepass.changePublicKeys = async function(tab, enableTimeout = false, connection
try { try {
const response = await keepassClient.sendNativeMessage(request, enableTimeout, connectionTimeout); const response = await keepassClient.sendNativeMessage(request, enableTimeout, connectionTimeout);
keepass.setcurrentKeePassXCVersion(response.version); keepass.setcurrentKeePassXCVersion(response.version);
keepass.updateFeaturesList(response.version);
if (!keepassClient.verifyKeyResponse(response, key, incrementedNonce)) { if (!keepassClient.verifyKeyResponse(response, key, incrementedNonce)) {
if (tab && page.tabs[tab.id]) { if (tab && page.tabs[tab.id]) {
@ -560,7 +544,7 @@ keepass.createNewGroup = async function(tab, args = []) {
keepass.getTotp = async function(tab, args = []) { keepass.getTotp = async function(tab, args = []) {
const [ uuid, oldTotp ] = args; const [ uuid, oldTotp ] = args;
if (!keepass.featuresList.newTotpSupported) { if (!compareVersion('2.6.1', keepass.currentKeePassXC, true)) {
return oldTotp; return oldTotp;
} }
@ -625,14 +609,11 @@ keepass.passkeysRegister = async function(tab, args = []) {
const kpAction = kpActions.PASSKEYS_REGISTER; const kpAction = kpActions.PASSKEYS_REGISTER;
const nonce = keepassClient.getNonce(); const nonce = keepassClient.getNonce();
const [ publicKey, origin ] = args; const [ publicKey, origin ] = args;
const passkeyPublicKey = JSON.parse(JSON.stringify(publicKey));
const relatedOrigins = await keepass.getPasskeysRelatedOrigins(passkeyPublicKey?.rp?.id);
const messageData = { const messageData = {
action: kpAction, action: kpAction,
publicKey: passkeyPublicKey, publicKey: JSON.parse(JSON.stringify(publicKey)),
origin: origin, origin: origin,
relatedOrigins: relatedOrigins,
groupName: page?.settings?.defaultPasskeyGroup, groupName: page?.settings?.defaultPasskeyGroup,
keys: keepass.getCryptoKeys() keys: keepass.getCryptoKeys()
}; };
@ -660,15 +641,13 @@ keepass.passkeysGet = async function(tab, args = []) {
const kpAction = kpActions.PASSKEYS_GET; const kpAction = kpActions.PASSKEYS_GET;
const nonce = keepassClient.getNonce(); const nonce = keepassClient.getNonce();
const [ publicKey, origin ] = args; const publicKey = args[0];
const passkeyPublicKey = JSON.parse(JSON.stringify(publicKey)); const origin = args[1];
const relatedOrigins = await keepass.getPasskeysRelatedOrigins(passkeyPublicKey?.rp?.id);
const messageData = { const messageData = {
action: kpAction, action: kpAction,
publicKey: passkeyPublicKey, publicKey: JSON.parse(JSON.stringify(publicKey)),
origin: origin, origin: origin,
relatedOrigins: relatedOrigins,
keys: keepass.getCryptoKeys() keys: keepass.getCryptoKeys()
}; };
@ -804,9 +783,13 @@ keepass.getCryptoKeys = function() {
keepass.enableAutomaticReconnect = async function() { keepass.enableAutomaticReconnect = async function() {
// Disable for Windows if KeePassXC is older than 2.3.4 // Disable for Windows if KeePassXC is older than 2.3.4
if (!page.settings.autoReconnect) { if (!page.settings.autoReconnect
|| (navigator.platform.toLowerCase().includes('win')
&& keepass.currentKeePassXC
&& !compareVersion('2.3.4', keepass.currentKeePassXC))) {
return; return;
} }
if (keepass.reconnectLoop === null) { if (keepass.reconnectLoop === null) {
keepass.reconnectLoop = setInterval(async () => { keepass.reconnectLoop = setInterval(async () => {
if (!keepass.isKeePassXCAvailable) { if (!keepass.isKeePassXCAvailable) {
@ -824,9 +807,7 @@ keepass.disableAutomaticReconnect = function() {
keepass.reconnect = async function(tab = null, connectionTimeout = 1500) { keepass.reconnect = async function(tab = null, connectionTimeout = 1500) {
keepassClient.connectToNative(); keepassClient.connectToNative();
keepass.generateNewKeyPair(); keepass.generateNewKeyPair();
const keyChangeResult = await keepass const keyChangeResult = await keepass.changePublicKeys(tab, !!connectionTimeout, connectionTimeout).catch(() => false);
.changePublicKeys(tab, !!connectionTimeout, connectionTimeout)
.catch(() => false);
// Change public keys timeout // Change public keys timeout
if (!keyChangeResult) { if (!keyChangeResult) {
@ -882,9 +863,7 @@ keepass.setcurrentKeePassXCVersion = function(version) {
keepass.keePassXCUpdateAvailable = async function() { keepass.keePassXCUpdateAvailable = async function() {
const checkUpdate = Number(page.settings.checkUpdateKeePassXC); const checkUpdate = Number(page.settings.checkUpdateKeePassXC);
if (checkUpdate !== CHECK_UPDATE_NEVER) { if (checkUpdate !== CHECK_UPDATE_NEVER) {
const lastChecked = keepass.latestKeePassXC.lastChecked const lastChecked = (keepass.latestKeePassXC.lastChecked) ? new Date(keepass.latestKeePassXC.lastChecked) : new Date(1986, 11, 21);
? new Date(keepass.latestKeePassXC.lastChecked)
: new Date(1986, 11, 21);
const daysSinceLastCheck = Math.floor(((new Date()).getTime() - lastChecked.getTime()) / 86400000); const daysSinceLastCheck = Math.floor(((new Date()).getTime() - lastChecked.getTime()) / 86400000);
if (daysSinceLastCheck >= checkUpdate) { if (daysSinceLastCheck >= checkUpdate) {
await keepass.checkForNewKeePassXCVersion(); await keepass.checkForNewKeePassXCVersion();
@ -900,7 +879,7 @@ keepass.checkForNewKeePassXCVersion = async function() {
let version = -1; let version = -1;
try { try {
const response = await fetch(keepass.latestVersionUrl, { signal: AbortSignal.timeout(DEFAULT_FETCH_TIMEOUT) }); const response = await fetch(keepass.latestVersionUrl);
const jsonData = await response.json(); const jsonData = await response.json();
if (jsonData?.tag_name && jsonData?.prerelease === false) { if (jsonData?.tag_name && jsonData?.prerelease === false) {
version = jsonData.tag_name; version = jsonData.tag_name;
@ -912,44 +891,6 @@ keepass.checkForNewKeePassXCVersion = async function() {
keepass.latestKeePassXC.lastChecked = new Date().valueOf(); keepass.latestKeePassXC.lastChecked = new Date().valueOf();
}; };
// Implements retrieval of Related Origin Requests for passkeys
// https://www.w3.org/TR/webauthn-3/#sctn-related-origins
keepass.getPasskeysRelatedOrigins = async function(rpId) {
if (!rpId) {
return [];
}
try {
const response = await fetch(`https://${rpId}/.well-known/webauthn`, {
signal: AbortSignal.timeout(DEFAULT_FETCH_TIMEOUT),
});
// Basic reply validation, see: https://www.w3.org/TR/webauthn-3/#sctn-validating-relation-origin
const isJson = response?.headers?.get('content-type')?.includes('application/json');
if (!isJson) {
logError('getRelatedOrigins error: Content-Type is not JSON');
return [];
}
const jsonData = await response.json();
if (!Array.isArray(jsonData?.origins)
|| jsonData?.origins?.length === 0
|| jsonData?.origins?.length > MAX_RELATED_ORIGIN_LABELS
|| !jsonData?.origins?.every((origin) => typeof origin === 'string')) {
logError(
`getRelatedOrigins error: origins is not a list of strings, or it exceeds the maximum count of ${MAX_RELATED_ORIGIN_LABELS}`,
);
return [];
}
return jsonData.origins;
} catch (ex) {
logError(`getRelatedOrigins error: ${ex}`);
}
return [];
};
keepass.clearErrorMessage = function(tab) { keepass.clearErrorMessage = function(tab) {
if (tab && page.tabs[tab.id]) { if (tab && page.tabs[tab.id]) {
page.tabs[tab.id].errorMessage = undefined; page.tabs[tab.id].errorMessage = undefined;
@ -1004,25 +945,6 @@ keepass.updateDatabaseHashToContent = async function() {
} }
}; };
keepass.updateFeaturesList = function (currentVersion) {
const versionResults = keepass.compareMultipleVersions([
keepass.requiredKeePassXC,
'2.6.1',
'2.7.0',
'2.7.7',
'2.7.10'
], currentVersion);
keepass.featuresList = {
downloadFaviconAfterSave: versionResults['2.7.0'],
newTotp: versionResults['2.6.1'],
passwordGenerator: versionResults['2.7.0'],
passkeys: versionResults['2.7.7'],
passkeysDefaultGroup: versionResults['2.7.10'],
requiredKeePassXCVersionFound: versionResults[keepass.requiredKeePassXC],
};
};
// Expects an array of versions to compare // Expects an array of versions to compare
keepass.compareMultipleVersions = function(versions, current, canBeEqual = true) { keepass.compareMultipleVersions = function(versions, current, canBeEqual = true) {
if (!Array.isArray(versions)) { if (!Array.isArray(versions)) {

View file

@ -24,7 +24,7 @@ const defaultSettings = {
downloadFaviconAfterSave: false, downloadFaviconAfterSave: false,
passkeys: false, passkeys: false,
passkeysFallback: true, passkeysFallback: true,
redirectAllowance: 3, redirectAllowance: 1,
saveDomainOnly: true, saveDomainOnly: true,
showGettingStartedGuideAlert: true, showGettingStartedGuideAlert: true,
showGroupNameInAutocomplete: true, showGroupNameInAutocomplete: true,
@ -49,10 +49,7 @@ page.blockedTabs = [];
page.clearCredentialsTimeout = null; page.clearCredentialsTimeout = null;
page.currentRequest = {}; page.currentRequest = {};
page.currentTabId = -1; page.currentTabId = -1;
page.isFirefox = false;
page.isSafari = false;
page.manualFill = ManualFill.NONE; page.manualFill = ManualFill.NONE;
page.menuContexts = [ 'editable' ];
page.passwordFilled = false; page.passwordFilled = false;
page.redirectCount = 0; page.redirectCount = 0;
page.submitted = false; page.submitted = false;
@ -64,17 +61,12 @@ page.popupData = {
popup: 'popup' popup: 'popup'
}; };
page.initBrowser = async function() {
page.isFirefox = isFirefox();
page.isSafari = isSafari();
};
page.initSettings = async function() { page.initSettings = async function() {
try { try {
const item = await browser.storage.local.get({ 'settings': {} }); const item = await browser.storage.local.get({ 'settings': {} });
// Load managed settings if found // Load managed settings if found
if (page.isFirefox && typeof(browser.storage.managed) === 'object') { if (isFirefox() && typeof(browser.storage.managed) === 'object') {
try { try {
const managedSettings = await browser.storage.managed.get('settings'); const managedSettings = await browser.storage.managed.get('settings');
if (managedSettings?.settings) { if (managedSettings?.settings) {
@ -82,16 +74,16 @@ page.initSettings = async function() {
item.settings = managedSettings.settings; item.settings = managedSettings.settings;
} }
} catch (err) { } catch (err) {
debugLogMessage('page.initSettings: ' + err); logError('page.initSettings: ' + err);
} }
} else if (!page.isSafari && typeof chrome.storage.managed === 'object') { } else if (typeof(chrome.storage.managed) === 'object') {
chrome.storage.managed.get('settings').then((managedSettings) => { chrome.storage.managed.get('settings').then((managedSettings) => {
if (managedSettings?.settings) { if (managedSettings?.settings) {
debugLogMessage('Managed settings found.'); debugLogMessage('Managed settings found.');
item.settings = managedSettings.settings; item.settings = managedSettings.settings;
} }
}).catch((err) => { }).catch((err) => {
debugLogMessage('page.initSettings: ' + err); logError('page.initSettings: ' + err);
}); });
} }
@ -146,16 +138,6 @@ page.initSitePreferences = async function() {
await browser.storage.local.set({ 'settings': page.settings }); await browser.storage.local.set({ 'settings': page.settings });
}; };
page.resetAllSettings = async function() {
for (const [ key, value ] of Object.entries(defaultSettings)) {
page.settings[key] = value;
}
page.settings[DEFINED_CUSTOM_FIELDS] = {};
page.settings.sitePreferences = [];
await browser.storage.local.set({ 'settings': page.settings });
};
page.switchTab = async function(tab) { page.switchTab = async function(tab) {
// Clears Fill Attribute selection from context menu // Clears Fill Attribute selection from context menu
page.setFillAttributeContextMenuItemVisible(false); page.setFillAttributeContextMenuItemVisible(false);
@ -275,11 +257,11 @@ page.retrieveCredentials = async function(tab, args = []) {
return credentials; return credentials;
}; };
page.getLoginId = async function(tab, returnSingle = true) { page.getLoginId = async function(tab) {
const currentTab = page.tabs[tab.id]; const currentTab = page.tabs[tab.id];
// If there's only one credential available and loginId is not set // If there's only one credential available and loginId is not set
if (currentTab && returnSingle && !currentTab.loginId && currentTab.credentials.length === 1) { if (currentTab && !currentTab.loginId && currentTab.credentials.length === 1) {
return currentTab.credentials[0].uuid; return currentTab.credentials[0].uuid;
} }
@ -353,15 +335,14 @@ page.fillHttpAuth = async function(tab, credentials) {
} }
}; };
page.isSiteIgnored = async function(tab, args = []) { page.isSiteIgnored = async function(tab, currentLocation) {
const [ currentLocation, checkPasskeys ] = args;
if (!page?.settings?.sitePreferences || !currentLocation) { if (!page?.settings?.sitePreferences || !currentLocation) {
return false; return false;
} }
for (const site of page.settings.sitePreferences) { for (const site of page.settings.sitePreferences) {
if (siteMatch(site.url, currentLocation) || site.url === currentLocation) { if (siteMatch(site.url, currentLocation) || site.url === currentLocation) {
if (site.ignore === IGNORE_FULL || (checkPasskeys && site.ignore === IGNORE_PASSKEYS)) { if (site.ignore === IGNORE_FULL) {
return true; return true;
} }
} }
@ -484,7 +465,7 @@ page.getTopLevelDomainFromUrl = async function(domain, url) {
url: url url: url
}); });
} }
} catch (_e) { } catch (e) {
return domain; return domain;
} }
} }
@ -517,7 +498,7 @@ page.getBaseDomainFromUrl = async function(hostname, url) {
const createContextMenuItem = function({ action, args, ...options }) { const createContextMenuItem = function({ action, args, ...options }) {
return browser.contextMenus.create({ return browser.contextMenus.create({
contexts: page.menuContexts, contexts: menuContexts,
id: action, id: action,
...options ...options
}); });

File diff suppressed because one or more lines are too long

View file

@ -1,13 +1,11 @@
'use strict'; 'use strict';
const EXTENSION_NAME = 'KeePassXC-Browser'; const EXTENSION_NAME = 'KeePassXC-Browser';
const DEFINED_CUSTOM_FIELDS = 'defined-custom-fields';
// Site Preferences ignore options // Site Preferences ignore options
const IGNORE_NOTHING = 'ignoreNothing'; const IGNORE_NOTHING = 'ignoreNothing';
const IGNORE_NORMAL = 'ignoreNormal'; const IGNORE_NORMAL = 'ignoreNormal';
const IGNORE_AUTOSUBMIT = 'ignoreAutoSubmit'; const IGNORE_AUTOSUBMIT = 'ignoreAutoSubmit';
const IGNORE_PASSKEYS = 'ignorePasskeys';
const IGNORE_FULL = 'ignoreFull'; const IGNORE_FULL = 'ignoreFull';
// Credential sorting options // Credential sorting options
@ -28,6 +26,23 @@ const URL_WILDCARD = '1kpxcwc1';
const schemeSegment = '(\\*|http|https|ws|wss|ftp)'; const schemeSegment = '(\\*|http|https|ws|wss|ftp)';
const hostSegment = '(\\*|(?:\\*\\.)?(?:[^/*]+))?'; const hostSegment = '(\\*|(?:\\*\\.)?(?:[^/*]+))?';
const isFirefox = function() {
return navigator.userAgent.indexOf('Firefox') !== -1 || navigator.userAgent.indexOf('Gecko/') !== -1;
};
const isEdge = function() {
return navigator.userAgent.indexOf('Edg') !== -1;
};
const showNotification = function(message) {
browser.notifications.create({
'type': 'basic',
'iconUrl': browser.runtime.getURL('icons/keepassxc_64x64.png'),
'title': 'KeePassXC-Browser',
'message': message
});
};
const AssociatedAction = { const AssociatedAction = {
NOT_ASSOCIATED: 0, NOT_ASSOCIATED: 0,
ASSOCIATED: 1, ASSOCIATED: 1,
@ -46,47 +61,6 @@ const ManualFill = {
BOTH: 2 BOTH: 2
}; };
const SitePreferences = {
ALLOW_IFRAMES: 'allowIframes',
IMPROVED_FIELD_DETECTION: 'improvedFieldDetection',
USERNAME_ONLY: 'usernameOnly',
};
const isFirefox = function() {
return browser.runtime.getURL('')?.startsWith('moz-extension');
};
const isSafari = function() {
return browser.runtime.getURL('')?.startsWith('safari-web-extension');
};
const isEdge = function() {
return navigator.userAgent.indexOf('Edg') !== -1;
};
const getIconClass = function(className) {
if (isFirefox()) {
return className + '-moz';
} else if (isSafari()) {
return className + '-safari';
}
return className;
};
const showNotification = function(message) {
browser.notifications.create({
'type': 'basic',
'iconUrl': browser.runtime.getURL('icons/keepassxc_64x64.png'),
'title': 'KeePassXC-Browser',
'message': message
});
};
// Returns a string with 'px' for CSS styles
const Pixels = function(value) {
return String(value) + 'px';
};
const compareVersion = function(minimum, current, canBeEqual = true) { const compareVersion = function(minimum, current, canBeEqual = true) {
if (!minimum || !current || minimum?.indexOf('.') === -1 || current?.indexOf('.') === -1) { if (!minimum || !current || minimum?.indexOf('.') === -1 || current?.indexOf('.') === -1) {
return false; return false;
@ -183,10 +157,10 @@ const trimURL = function(url) {
}; };
const debugLogMessage = function(message, extra) { const debugLogMessage = function(message, extra) {
console.debug(`[Debug ${getFileAndLine()}] ${EXTENSION_NAME} - ${message}`); console.log(`[Debug ${getFileAndLine()}] ${EXTENSION_NAME} - ${message}`);
if (extra) { if (extra) {
console.debug(extra); console.log(extra);
} }
}; };
@ -208,20 +182,10 @@ const getCurrentTab = async function() {
return tabs?.length > 0 ? tabs[0] : undefined; return tabs?.length > 0 ? tabs[0] : undefined;
}; };
// Check if element b is inside a
const isElementInside = (a, b) => (b.x >= a.x && b.right <= a.right) && (b.y >= a.y && b.bottom <= a.bottom);
// Check if two elements overlap
const elementsOverlap = function(rect1, rect2) {
const overlaps = (a, b) => !(a.right < b.left || a.left > b.right || a.bottom < b.top || a.top > b.bottom);
return isElementInside(rect1, rect2) || overlaps(rect1, rect2);
};
// Exports for tests // Exports for tests
if (typeof module === 'object') { if (typeof module === 'object') {
module.exports = { module.exports = {
compareVersion, compareVersion,
elementsOverlap,
matchesWithNodeName, matchesWithNodeName,
siteMatch, siteMatch,
slashNeededForUrl, slashNeededForUrl,

View file

@ -71,7 +71,7 @@ kpxcSites.detectUsernameFromPage = function() {
* @returns {boolean} True if an Element has a match with the identifier and document location * @returns {boolean} True if an Element has a match with the identifier and document location
*/ */
kpxcSites.exceptionFound = function(identifier, field) { kpxcSites.exceptionFound = function(identifier, field) {
if ((!identifier || identifier.length === 0) && !field) { if (!identifier || identifier.length === 0) {
return; return;
} }
@ -80,7 +80,7 @@ kpxcSites.exceptionFound = function(identifier, field) {
|| (typeof identifier === 'object' && [ 'password', 'form-row', 'show-password' ].every(c => identifier.contains(c))))) { || (typeof identifier === 'object' && [ 'password', 'form-row', 'show-password' ].every(c => identifier.contains(c))))) {
return true; return true;
} else if (document.location.origin.startsWith('https://signin.ebay.') } else if (document.location.origin.startsWith('https://signin.ebay.')
&& (identifier === 'null' || identifier?.value === 'null' || identifier === 'pass')) { && (identifier === 'null' || identifier.value === 'null' || identifier === 'pass')) {
return true; return true;
} else if (document.location.origin.startsWith('https://www.fidelity.com')) { } else if (document.location.origin.startsWith('https://www.fidelity.com')) {
if (typeof identifier === 'string') { if (typeof identifier === 'string') {
@ -100,42 +100,6 @@ kpxcSites.exceptionFound = function(identifier, field) {
} else if (document.location.origin === 'https://id.atlassian.com' && } else if (document.location.origin === 'https://id.atlassian.com' &&
Array.isArray(identifier) && identifier?.contains('password-field')) { Array.isArray(identifier) && identifier?.contains('password-field')) {
return true; return true;
} else if (document.location.origin === 'https://app.fastmail.com'
&& identifier?.contains('u-space-y-5') && field?.id === 'v25') {
return true;
} else if (document.location.origin === 'https://login.dei.gr' &&
identifier?.value?.includes('show-reveal-password')) {
return true;
} else if (document.location.origin === 'https://accounts.google.com' && field?.id === 'password') {
return true;
} else if (document.location.origin === 'https://www.epicgames.com'
&& ((field?.style?.opacity === '1' && field?.style?.willChange === 'auto') || identifier === 'password')) {
return true;
} else if (document.location.origin === 'https://www.paypal.com' && field?.id === 'splitPassword') {
return true;
}
return false;
};
// Handles exceptions when returning or modifying existing combinations
kpxcSites.combinationExceptionFound = function(existingCombination) {
if (!existingCombination) {
return false;
}
// Exception for Google. They replace the username input with password input using identical className.
// If detected, remove the username from the combination.
if (document.location.origin === 'https://accounts.google.com'
&& existingCombination?.username?.className?.length > 0
&& existingCombination?.password?.className?.length > 0
&& existingCombination?.username?.className === existingCombination?.password?.className) {
return true;
}
if (document.location.origin === 'https://www.paypal.com'
&& existingCombination.password?.className?.includes('pin-password')) {
return true;
} }
return false; return false;
@ -250,8 +214,6 @@ kpxcSites.formSubmitButtonExceptionFound = function(form) {
return form.querySelector('button[class*=_primary_]'); return form.querySelector('button[class*=_primary_]');
} else if (!form && document.location.origin === 'https://www.reddit.com') { } else if (!form && document.location.origin === 'https://www.reddit.com') {
return $('button.login'); return $('button.login');
} else if (form?.action === 'https://webapp.dubverse.ai/') {
return $('button[class^=chakra]');
} }
return undefined; return undefined;
@ -270,20 +232,6 @@ kpxcSites.popupExceptionFound = function(combinations) {
return false; return false;
}; };
/**
* Handles exceptions where a certain element is set as a popover, and it prevents input field detections.
* @param {object} elem Popover element
* @returns {boolean} True if exception found
*/
kpxcSites.overlayExceptionFound = function(elem) {
if (document.location.href?.startsWith('https://github.com/login')
&& elem?.nodeName === 'TOOL-TIP' && elem?.baseURI === 'https://github.com/login') {
return true;
}
return false;
};
/** /**
* Handles a few exceptions for certain sites where Username Icon is not placed properly. * Handles a few exceptions for certain sites where Username Icon is not placed properly.
* @param {number} left Absolute left position of the icon * @param {number} left Absolute left position of the icon

View file

@ -100,9 +100,7 @@ class Autocomplete {
styleSheet.addEventListener('load', () => (this.wrapper.style.display = 'block')); styleSheet.addEventListener('load', () => (this.wrapper.style.display = 'block'));
this.container = kpxcUI.createElement('div', 'kpxcAutocomplete-container', { this.container = kpxcUI.createElement('div', 'kpxcAutocomplete-container', {
id: 'kpxcAutocomplete-container', id: 'kpxcAutocomplete-container',
popover: 'manual',
}); });
this.container.style.margin = 0;
// Apply compact mode class // Apply compact mode class
if (kpxc.settings.useCompactMode) { if (kpxc.settings.useCompactMode) {
@ -119,7 +117,6 @@ class Autocomplete {
this.container.append(this.list); this.container.append(this.list);
this.shadowRoot.append(this.container); this.shadowRoot.append(this.container);
document.body.append(this.wrapper); document.body.append(this.wrapper);
kpxcUI.observeWrapper(this.wrapper);
// Add a footer message for auto-submit // Add a footer message for auto-submit
if (this.autoSubmit) { if (this.autoSubmit) {
@ -130,9 +127,6 @@ class Autocomplete {
this.updateList(); this.updateList();
this.container.classList.add('kpxcAutocomplete-container--visible'); this.container.classList.add('kpxcAutocomplete-container--visible');
if (kpxcFields.popoverSupported) {
this.container.showPopover({ source: inputField });
}
this.updatePosition(); this.updatePosition();
} }
@ -240,9 +234,6 @@ class Autocomplete {
} }
this.container.classList.remove('kpxcAutocomplete-container--visible'); this.container.classList.remove('kpxcAutocomplete-container--visible');
if (kpxcFields.popoverSupported) {
this.container.hidePopover();
}
} }
getAllItems() { getAllItems() {
@ -346,7 +337,7 @@ class Autocomplete {
// Get body zoom radio // Get body zoom radio
const zoom = kpxcUI.bodyStyle.zoom || 1; const zoom = kpxcUI.bodyStyle.zoom || 1;
// Calculate Y offset if menu does not fit to the bottom of the screen -> show it at the top of the input field // Calculate Y offset if menu does not fit to the bottom of the screen -> show it at the top of the input field
const menuRect = this.container.getBoundingClientRect(); const menuRect = this.container.getBoundingClientRect();
const totalHeight = menuRect.height + rect.height; const totalHeight = menuRect.height + rect.height;

View file

@ -28,7 +28,7 @@ kpxcBanner.destroy = async function() {
} else { } else {
window.parent.document.body.removeChild(window.parent.document.body.querySelector('#kpxc-banner')); window.parent.document.body.removeChild(window.parent.document.body.querySelector('#kpxc-banner'));
} }
} catch(_e) { } catch(e) {
kpxcBanner.wrapper.style.display = 'hidden'; kpxcBanner.wrapper.style.display = 'hidden';
} }
@ -62,10 +62,10 @@ kpxcBanner.create = async function(credentials = {}) {
const bannerInfo = kpxcUI.createElement('div', 'banner-info'); const bannerInfo = kpxcUI.createElement('div', 'banner-info');
const bannerButtons = kpxcUI.createElement('div', 'banner-buttons'); const bannerButtons = kpxcUI.createElement('div', 'banner-buttons');
const className = getIconClass('kpxc-banner-icon'); const className = (isFirefox() ? 'kpxc-banner-icon-moz' : 'kpxc-banner-icon');
const icon = kpxcUI.createElement('span', className, { 'alt': 'logo' }); const icon = kpxcUI.createElement('span', className, { 'alt': 'logo' });
const infoText = kpxcUI.createElement('span', 'banner-info-text', {}, tr('rememberInfoText')); const infoText = kpxcUI.createElement('span', '', {}, tr('rememberInfoText'));
const usernameText = kpxcUI.createElement('span', 'small', {}, tr('popupUsername') + ' '); const usernameText = kpxcUI.createElement('span', 'small', {}, tr('popupUsername') + ' ');
const usernameSpan = kpxcUI.createElement('span', 'small info information-username', {}, credentials.username); const usernameSpan = kpxcUI.createElement('span', 'small info information-username', {}, credentials.username);
@ -165,7 +165,6 @@ kpxcBanner.create = async function(credentials = {}) {
if (window.self === window.top && !kpxcBanner.created) { if (window.self === window.top && !kpxcBanner.created) {
window.parent.document.body.appendChild(wrapper); window.parent.document.body.appendChild(wrapper);
kpxcUI.observeWrapper(wrapper);
kpxcBanner.created = true; kpxcBanner.created = true;
} }
}; };

View file

@ -5,10 +5,10 @@ const STEP_SELECT_USERNAME = 1;
const STEP_SELECT_PASSWORD = 2; const STEP_SELECT_PASSWORD = 2;
const STEP_SELECT_TOTP = 3; const STEP_SELECT_TOTP = 3;
const STEP_SELECT_STRING_FIELDS = 4; const STEP_SELECT_STRING_FIELDS = 4;
const STEP_SELECT_SUBMIT_BUTTON = 5;
const CHECKBOX_OVERLAY_SIZE = 20; const CHECKBOX_OVERLAY_SIZE = 20;
const DEFINED_CUSTOM_FIELDS = 'defined-custom-fields';
const FIXED_FIELD_CLASS = 'kpxcDefine-fixed-field'; const FIXED_FIELD_CLASS = 'kpxcDefine-fixed-field';
const DARK_FIXED_FIELD_CLASS = 'kpxcDefine-fixed-field-dark'; const DARK_FIXED_FIELD_CLASS = 'kpxcDefine-fixed-field-dark';
const HOVER_FIELD_CLASS = 'kpxcDefine-fixed-hover-field'; const HOVER_FIELD_CLASS = 'kpxcDefine-fixed-hover-field';
@ -19,10 +19,9 @@ const PASSWORD_FIELD_CLASS = 'kpxcDefine-fixed-password-field';
const TOTP_FIELD_CLASS = 'kpxcDefine-fixed-totp-field'; const TOTP_FIELD_CLASS = 'kpxcDefine-fixed-totp-field';
const STRING_FIELD_CLASS = 'kpxcDefine-fixed-string-field'; const STRING_FIELD_CLASS = 'kpxcDefine-fixed-string-field';
const INPUT_BUTTON_QUERY_PATTERN = 'button, input[type=submit]'; const inputQueryPatternStart = 'input';
const INPUT_QUERY_PATTERNS_START = 'input'; const inputQueryPatternNotCheckbox = ':not([type=checkbox])';
const INPUT_QUERY_PATTERN_NOT_CHECKBOX = ':not([type=checkbox])'; const inputQueryPattern = ':not([disabled]):not([type=button]):not([type=radio]):not([type=color]):not([type=date]):not([type=datetime-local]):not([type=file]):not([type=hidden]):not([type=image]):not([type=month]):not([type=range]):not([type=reset]):not([type=submit]):not([type=time]):not([type=week]), select, textarea';
const INPUT_QUERY_PATTERN = ':not([disabled]):not([type=button]):not([type=radio]):not([type=color]):not([type=date]):not([type=datetime-local]):not([type=file]):not([type=hidden]):not([type=image]):not([type=month]):not([type=range]):not([type=reset]):not([type=submit]):not([type=time]):not([type=week]), select, textarea';
const kpxcCustomLoginFieldsBanner = {}; const kpxcCustomLoginFieldsBanner = {};
kpxcCustomLoginFieldsBanner.banner = undefined; kpxcCustomLoginFieldsBanner.banner = undefined;
@ -31,9 +30,8 @@ kpxcCustomLoginFieldsBanner.created = false;
kpxcCustomLoginFieldsBanner.dataStep = STEP_NONE; kpxcCustomLoginFieldsBanner.dataStep = STEP_NONE;
kpxcCustomLoginFieldsBanner.infoText = undefined; kpxcCustomLoginFieldsBanner.infoText = undefined;
kpxcCustomLoginFieldsBanner.wrapper = undefined; kpxcCustomLoginFieldsBanner.wrapper = undefined;
kpxcCustomLoginFieldsBanner.inputQueryPatternNormal = kpxcCustomLoginFieldsBanner.inputQueryPatternNormal = inputQueryPatternStart + inputQueryPatternNotCheckbox + inputQueryPattern;
INPUT_QUERY_PATTERNS_START + INPUT_QUERY_PATTERN_NOT_CHECKBOX + INPUT_QUERY_PATTERN; kpxcCustomLoginFieldsBanner.inputQueryPatternStringFields = inputQueryPatternStart + inputQueryPattern;
kpxcCustomLoginFieldsBanner.inputQueryPatternStringFields = INPUT_QUERY_PATTERNS_START + INPUT_QUERY_PATTERN;
kpxcCustomLoginFieldsBanner.markedFields = []; kpxcCustomLoginFieldsBanner.markedFields = [];
kpxcCustomLoginFieldsBanner.nonSelectedElementsPattern = `div.${FIXED_FIELD_CLASS}:not(.${USERNAME_FIELD_CLASS}):not(.${PASSWORD_FIELD_CLASS}):not(.${TOTP_FIELD_CLASS}):not(.${STRING_FIELD_CLASS})`; kpxcCustomLoginFieldsBanner.nonSelectedElementsPattern = `div.${FIXED_FIELD_CLASS}:not(.${USERNAME_FIELD_CLASS}):not(.${PASSWORD_FIELD_CLASS}):not(.${TOTP_FIELD_CLASS}):not(.${STRING_FIELD_CLASS})`;
@ -46,7 +44,6 @@ kpxcCustomLoginFieldsBanner.selection = {
totpElement: undefined, totpElement: undefined,
fields: [], fields: [],
fieldElements: [], fieldElements: [],
submitButton: undefined,
}; };
kpxcCustomLoginFieldsBanner.buttons = { kpxcCustomLoginFieldsBanner.buttons = {
@ -93,9 +90,9 @@ kpxcCustomLoginFieldsBanner.create = async function() {
const bannerInfo = kpxcUI.createElement('div', 'banner-info'); const bannerInfo = kpxcUI.createElement('div', 'banner-info');
const bannerButtons = kpxcUI.createElement('div', 'banner-buttons'); const bannerButtons = kpxcUI.createElement('div', 'banner-buttons');
const iconClassName = getIconClass('kpxc-banner-icon'); const iconClassName = isFirefox() ? 'kpxc-banner-icon-moz' : 'kpxc-banner-icon';
const icon = kpxcUI.createElement('span', iconClassName); const icon = kpxcUI.createElement('span', iconClassName);
const infoText = kpxcUI.createElement('span', 'banner-info-text', {}, tr('defineChooseCustomLoginFieldText')); const infoText = kpxcUI.createElement('span', '', {}, tr('defineChooseCustomLoginFieldText'));
const separator = kpxcUI.createElement('div', 'kpxc-separator'); const separator = kpxcUI.createElement('div', 'kpxc-separator');
const secondSeparator = kpxcUI.createElement('div', 'kpxc-separator'); const secondSeparator = kpxcUI.createElement('div', 'kpxc-separator');
@ -104,7 +101,6 @@ kpxcCustomLoginFieldsBanner.create = async function() {
const passwordButton = kpxcUI.createButton(RED_BUTTON, tr('password'), kpxcCustomLoginFieldsBanner.passwordButtonClicked); const passwordButton = kpxcUI.createButton(RED_BUTTON, tr('password'), kpxcCustomLoginFieldsBanner.passwordButtonClicked);
const totpButton = kpxcUI.createButton(GREEN_BUTTON, 'TOTP', kpxcCustomLoginFieldsBanner.totpButtonClicked); const totpButton = kpxcUI.createButton(GREEN_BUTTON, 'TOTP', kpxcCustomLoginFieldsBanner.totpButtonClicked);
const stringFieldsButton = kpxcUI.createButton(BLUE_BUTTON, tr('stringFields'), kpxcCustomLoginFieldsBanner.stringFieldsButtonClicked); const stringFieldsButton = kpxcUI.createButton(BLUE_BUTTON, tr('stringFields'), kpxcCustomLoginFieldsBanner.stringFieldsButtonClicked);
const submitButton = kpxcUI.createButton(BLUE_BUTTON, tr('submitButton'), kpxcCustomLoginFieldsBanner.submitButtonClicked);
const clearDataButton = kpxcUI.createButton(RED_BUTTON, tr('defineClearData'), kpxcCustomLoginFieldsBanner.clearData); const clearDataButton = kpxcUI.createButton(RED_BUTTON, tr('defineClearData'), kpxcCustomLoginFieldsBanner.clearData);
const confirmButton = kpxcUI.createButton(GREEN_BUTTON, tr('defineConfirm'), kpxcCustomLoginFieldsBanner.confirm); const confirmButton = kpxcUI.createButton(GREEN_BUTTON, tr('defineConfirm'), kpxcCustomLoginFieldsBanner.confirm);
const closeButton = kpxcUI.createButton(RED_BUTTON, tr('defineClose'), kpxcCustomLoginFieldsBanner.closeButtonClicked); const closeButton = kpxcUI.createButton(RED_BUTTON, tr('defineClose'), kpxcCustomLoginFieldsBanner.closeButtonClicked);
@ -121,11 +117,10 @@ kpxcCustomLoginFieldsBanner.create = async function() {
kpxcCustomLoginFieldsBanner.buttons.password = passwordButton; kpxcCustomLoginFieldsBanner.buttons.password = passwordButton;
kpxcCustomLoginFieldsBanner.buttons.totp = totpButton; kpxcCustomLoginFieldsBanner.buttons.totp = totpButton;
kpxcCustomLoginFieldsBanner.buttons.stringFields = stringFieldsButton; kpxcCustomLoginFieldsBanner.buttons.stringFields = stringFieldsButton;
kpxcCustomLoginFieldsBanner.buttons.submitButton = submitButton;
bannerInfo.appendMultiple(icon, infoText); bannerInfo.appendMultiple(icon, infoText);
bannerButtons.appendMultiple(resetButton, separator, usernameButton, passwordButton, totpButton, bannerButtons.appendMultiple(resetButton, separator, usernameButton,
stringFieldsButton, submitButton, secondSeparator, clearDataButton, confirmButton, closeButton); passwordButton, totpButton, stringFieldsButton, secondSeparator, clearDataButton, confirmButton, closeButton);
banner.appendMultiple(bannerInfo, bannerButtons); banner.appendMultiple(bannerInfo, bannerButtons);
kpxcUI.makeBannerDraggable(banner); kpxcUI.makeBannerDraggable(banner);
@ -164,7 +159,6 @@ kpxcCustomLoginFieldsBanner.create = async function() {
if (!kpxcCustomLoginFieldsBanner.created) { if (!kpxcCustomLoginFieldsBanner.created) {
window.self.document.body.appendChild(wrapper); window.self.document.body.appendChild(wrapper);
kpxcUI.observeWrapper(wrapper);
kpxcCustomLoginFieldsBanner.created = true; kpxcCustomLoginFieldsBanner.created = true;
} }
@ -195,8 +189,7 @@ kpxcCustomLoginFieldsBanner.usernameButtonClicked = function(e) {
// Reset username field selection if already set // Reset username field selection if already set
if (kpxcCustomLoginFieldsBanner.selection.username) { if (kpxcCustomLoginFieldsBanner.selection.username) {
kpxcCustomLoginFieldsBanner.removeSelection(kpxcCustomLoginFieldsBanner.selection.username, kpxcCustomLoginFieldsBanner.removeSelection(kpxcCustomLoginFieldsBanner.selection.username, `div.${USERNAME_FIELD_CLASS}`);
`div.${USERNAME_FIELD_CLASS}`);
kpxcCustomLoginFieldsBanner.selection.username = undefined; kpxcCustomLoginFieldsBanner.selection.username = undefined;
} }
@ -214,8 +207,7 @@ kpxcCustomLoginFieldsBanner.passwordButtonClicked = function(e) {
// Reset password field selection if already set // Reset password field selection if already set
if (kpxcCustomLoginFieldsBanner.selection.password) { if (kpxcCustomLoginFieldsBanner.selection.password) {
kpxcCustomLoginFieldsBanner.removeSelection(kpxcCustomLoginFieldsBanner.selection.password, kpxcCustomLoginFieldsBanner.removeSelection(kpxcCustomLoginFieldsBanner.selection.password, `div.${PASSWORD_FIELD_CLASS}`);
`div.${PASSWORD_FIELD_CLASS}`);
kpxcCustomLoginFieldsBanner.selection.password = undefined; kpxcCustomLoginFieldsBanner.selection.password = undefined;
} }
@ -233,8 +225,7 @@ kpxcCustomLoginFieldsBanner.totpButtonClicked = function(e) {
// Reset TOTP field selection if already set // Reset TOTP field selection if already set
if (kpxcCustomLoginFieldsBanner.selection.totp) { if (kpxcCustomLoginFieldsBanner.selection.totp) {
kpxcCustomLoginFieldsBanner.removeSelection(kpxcCustomLoginFieldsBanner.selection.totp, kpxcCustomLoginFieldsBanner.removeSelection(kpxcCustomLoginFieldsBanner.selection.totp, `div.${TOTP_FIELD_CLASS}`);
`div.${TOTP_FIELD_CLASS}`);
kpxcCustomLoginFieldsBanner.selection.totp = undefined; kpxcCustomLoginFieldsBanner.selection.totp = undefined;
} }
@ -265,25 +256,6 @@ kpxcCustomLoginFieldsBanner.stringFieldsButtonClicked = function(e) {
sendMessageToFrames(e, 'string_field_button_clicked'); sendMessageToFrames(e, 'string_field_button_clicked');
}; };
kpxcCustomLoginFieldsBanner.submitButtonClicked = function(e) {
if (!e.isTrusted || kpxcCustomLoginFieldsBanner.dataStep === STEP_SELECT_SUBMIT_BUTTON) {
kpxcCustomLoginFieldsBanner.backToStart();
return;
}
// Reset TOTP field selection if already set
if (kpxcCustomLoginFieldsBanner.selection.submitButton) {
kpxcCustomLoginFieldsBanner.removeSelection(kpxcCustomLoginFieldsBanner.selection.submitButton,
`div.${STRING_FIELD_CLASS}`);
kpxcCustomLoginFieldsBanner.selection.submitButton = undefined;
}
kpxcCustomLoginFieldsBanner.prepareSubmitButtonSelection();
kpxcCustomLoginFieldsBanner.buttons.confirm.disabled = true;
sendMessageToFrames(e, 'submit_button_clicked');
};
kpxcCustomLoginFieldsBanner.closeButtonClicked = function(e) { kpxcCustomLoginFieldsBanner.closeButtonClicked = function(e) {
if (!e.isTrusted) { if (!e.isTrusted) {
return; return;
@ -310,8 +282,6 @@ kpxcCustomLoginFieldsBanner.updateFieldSelections = function() {
kpxcCustomLoginFieldsBanner.prepareTOTPSelection(); kpxcCustomLoginFieldsBanner.prepareTOTPSelection();
} else if (kpxcCustomLoginFieldsBanner.dataStep === STEP_SELECT_STRING_FIELDS) { } else if (kpxcCustomLoginFieldsBanner.dataStep === STEP_SELECT_STRING_FIELDS) {
kpxcCustomLoginFieldsBanner.prepareStringFieldSelection(); kpxcCustomLoginFieldsBanner.prepareStringFieldSelection();
} else if (kpxcCustomLoginFieldsBanner.dataStep === STEP_SELECT_SUBMIT_BUTTON) {
kpxcCustomLoginFieldsBanner.prepareSubmitButtonSelection();
} }
}; };
@ -344,8 +314,6 @@ kpxcCustomLoginFieldsBanner.confirm = async function(e) {
kpxc.settings[DEFINED_CUSTOM_FIELDS][location].password = undefined; kpxc.settings[DEFINED_CUSTOM_FIELDS][location].password = undefined;
} else if (currentSite.totp?.[0] === path[0]) { } else if (currentSite.totp?.[0] === path[0]) {
kpxc.settings[DEFINED_CUSTOM_FIELDS][location].totp = undefined; kpxc.settings[DEFINED_CUSTOM_FIELDS][location].totp = undefined;
} else if (currentSite.submitButton?.[0] === path[0]) {
kpxc.settings[DEFINED_CUSTOM_FIELDS][location].submitButton = undefined;
} }
}; };
@ -353,11 +321,10 @@ kpxcCustomLoginFieldsBanner.confirm = async function(e) {
const passwordPath = kpxcCustomLoginFieldsBanner.selection.password; const passwordPath = kpxcCustomLoginFieldsBanner.selection.password;
const totpPath = kpxcCustomLoginFieldsBanner.selection.totp; const totpPath = kpxcCustomLoginFieldsBanner.selection.totp;
const stringFieldsPaths = kpxcCustomLoginFieldsBanner.selection.fields; const stringFieldsPaths = kpxcCustomLoginFieldsBanner.selection.fields;
const submitButtonPath = kpxcCustomLoginFieldsBanner.selection.submitButton;
const location = kpxc.getDocumentLocation(); const location = kpxc.getDocumentLocation();
const currentSettings = kpxc.settings[DEFINED_CUSTOM_FIELDS][location]; const currentSettings = kpxc.settings[DEFINED_CUSTOM_FIELDS][location];
if (usernamePath || passwordPath || totpPath || stringFieldsPaths.length > 0 || submitButtonPath) { if (usernamePath || passwordPath || totpPath || stringFieldsPaths.length > 0) {
if (currentSettings) { if (currentSettings) {
// Update the single selection to current settings // Update the single selection to current settings
if (usernamePath) { if (usernamePath) {
@ -378,19 +345,13 @@ kpxcCustomLoginFieldsBanner.confirm = async function(e) {
if (stringFieldsPaths.length > 0) { if (stringFieldsPaths.length > 0) {
kpxc.settings[DEFINED_CUSTOM_FIELDS][location].fields = stringFieldsPaths; kpxc.settings[DEFINED_CUSTOM_FIELDS][location].fields = stringFieldsPaths;
} }
if (submitButtonPath) {
clearIdenticalField(submitButtonPath, location);
kpxc.settings[DEFINED_CUSTOM_FIELDS][location].submitButton = submitButtonPath;
}
} else { } else {
// Override all fields (default, because there's no currentSettings available) // Override all fields (default, because there's no currentSettings available)
kpxc.settings[DEFINED_CUSTOM_FIELDS][location] = { kpxc.settings[DEFINED_CUSTOM_FIELDS][location] = {
username: usernamePath, username: usernamePath,
password: passwordPath, password: passwordPath,
totp: totpPath, totp: totpPath,
fields: stringFieldsPaths, fields: stringFieldsPaths
submitButton: submitButtonPath,
}; };
} }
@ -420,8 +381,7 @@ kpxcCustomLoginFieldsBanner.resetSelection = function() {
username: undefined, username: undefined,
password: undefined, password: undefined,
totp: undefined, totp: undefined,
fields: [], fields: []
submitButton: undefined,
}; };
kpxcCustomLoginFieldsBanner.removeMarkedFields(); kpxcCustomLoginFieldsBanner.removeMarkedFields();
@ -463,24 +423,15 @@ kpxcCustomLoginFieldsBanner.prepareStringFieldSelection = function() {
kpxcCustomLoginFieldsBanner.selectStringFields(); kpxcCustomLoginFieldsBanner.selectStringFields();
}; };
kpxcCustomLoginFieldsBanner.prepareSubmitButtonSelection = function() {
kpxcCustomLoginFieldsBanner.infoText.textContent = tr('defineChooseSubmitButton');
kpxcCustomLoginFieldsBanner.dataStep = STEP_SELECT_SUBMIT_BUTTON;
kpxcCustomLoginFieldsBanner.buttons.submitButton.classList.remove(GRAY_BUTTON_CLASS);
kpxcCustomLoginFieldsBanner.selectField('submitButton');
};
kpxcCustomLoginFieldsBanner.isFieldSelected = function(field) { kpxcCustomLoginFieldsBanner.isFieldSelected = function(field) {
const currentFieldId = kpxcFields.setId(field); const currentFieldId = kpxcFields.setId(field);
const selection = kpxcCustomLoginFieldsBanner.selection;
if (kpxcCustomLoginFieldsBanner.markedFields.some(f => f === field)) { if (kpxcCustomLoginFieldsBanner.markedFields.some(f => f === field)) {
return ( return (
(selection.username && selection.usernameElement === field) (kpxcCustomLoginFieldsBanner.selection.username && kpxcCustomLoginFieldsBanner.selection.usernameElement === field)
|| (selection.password && selection.passwordElement === field) || (kpxcCustomLoginFieldsBanner.selection.password && kpxcCustomLoginFieldsBanner.selection.passwordElement === field)
|| (selection.totp && selection.totpElement === field) || (kpxcCustomLoginFieldsBanner.selection.totp && kpxcCustomLoginFieldsBanner.selection.totpElement === field)
|| (selection.submitButton && selection.submitButton === field) || kpxcCustomLoginFieldsBanner.selection.fields.some(f => f[0] === currentFieldId[0])
|| selection.fields.some(f => f[0] === currentFieldId[0])
); );
} }
@ -509,7 +460,7 @@ kpxcCustomLoginFieldsBanner.setSelectedField = function(elem) {
kpxcCustomLoginFieldsBanner.buttons.close.textContent = tr('optionsButtonCancel'); kpxcCustomLoginFieldsBanner.buttons.close.textContent = tr('optionsButtonCancel');
}; };
// Expects 'username', 'password', 'totp' or 'submitButton' // Expects 'username', 'password' or 'totp'
kpxcCustomLoginFieldsBanner.selectField = function(fieldType) { kpxcCustomLoginFieldsBanner.selectField = function(fieldType) {
kpxcCustomLoginFieldsBanner.eventFieldClick = function(e) { kpxcCustomLoginFieldsBanner.eventFieldClick = function(e) {
const field = kpxcCustomLoginFieldsBanner.getSelectedField(e); const field = kpxcCustomLoginFieldsBanner.getSelectedField(e);
@ -565,10 +516,9 @@ kpxcCustomLoginFieldsBanner.selectStringFields = function() {
kpxcCustomLoginFieldsBanner.markFields = function() { kpxcCustomLoginFieldsBanner.markFields = function() {
let firstInput; let firstInput;
const inputs = document.querySelectorAll( const inputs = document.querySelectorAll(
kpxcCustomLoginFieldsBanner.dataStep === STEP_SELECT_SUBMIT_BUTTON ? INPUT_BUTTON_QUERY_PATTERN : kpxcCustomLoginFieldsBanner.dataStep === STEP_SELECT_STRING_FIELDS
(STEP_SELECT_STRING_FIELDS ? kpxcCustomLoginFieldsBanner.inputQueryPatternStringFields
? kpxcCustomLoginFieldsBanner.inputQueryPatternStringFields : kpxcCustomLoginFieldsBanner.inputQueryPatternNormal);
: kpxcCustomLoginFieldsBanner.inputQueryPatternNormal));
const zoom = kpxcUI.bodyStyle.zoom || 1; const zoom = kpxcUI.bodyStyle.zoom || 1;
for (const i of inputs) { for (const i of inputs) {
@ -594,7 +544,7 @@ kpxcCustomLoginFieldsBanner.markFields = function() {
if (kpxcCustomLoginFieldsBanner.dataStep !== STEP_SELECT_STRING_FIELDS) { if (kpxcCustomLoginFieldsBanner.dataStep !== STEP_SELECT_STRING_FIELDS) {
field.textContent = dataStepToString(); field.textContent = dataStepToString();
} }
// Static size for the checkbox overlay // Static size for the checkbox overlay
if (i?.getLowerCaseAttribute('type') === 'checkbox') { if (i?.getLowerCaseAttribute('type') === 'checkbox') {
field.style.width = Pixels(CHECKBOX_OVERLAY_SIZE / zoom); field.style.width = Pixels(CHECKBOX_OVERLAY_SIZE / zoom);
@ -724,10 +674,7 @@ kpxcCustomLoginFieldsBanner.handleTopWindowMessage = function(args) {
kpxcCustomLoginFieldsBanner.selection.totp = selection; kpxcCustomLoginFieldsBanner.selection.totp = selection;
kpxcCustomLoginFieldsBanner.setSelectedField(); kpxcCustomLoginFieldsBanner.setSelectedField();
} else if (message === 'string_field_selected') { } else if (message === 'string_field_selected') {
kpxcCustomLoginFieldsBanner.selection.fields = selection; kpxcCustomLoginFieldsBanner.selection.stringFields = selection;
kpxcCustomLoginFieldsBanner.setSelectedField();
} else if (message === 'submitButton_selected') {
kpxcCustomLoginFieldsBanner.selection.submitButton = selection;
kpxcCustomLoginFieldsBanner.setSelectedField(); kpxcCustomLoginFieldsBanner.setSelectedField();
} else if (message === 'enable_clear_data_button') { } else if (message === 'enable_clear_data_button') {
kpxcCustomLoginFieldsBanner.buttons.clearData.style.display = 'inline-block'; kpxcCustomLoginFieldsBanner.buttons.clearData.style.display = 'inline-block';
@ -752,8 +699,6 @@ kpxcCustomLoginFieldsBanner.handleParentWindowMessage = function(args) {
kpxcCustomLoginFieldsBanner.totpButtonClicked(e); kpxcCustomLoginFieldsBanner.totpButtonClicked(e);
} else if (message === 'string_field_button_clicked') { } else if (message === 'string_field_button_clicked') {
kpxcCustomLoginFieldsBanner.stringFieldsButtonClicked(e); kpxcCustomLoginFieldsBanner.stringFieldsButtonClicked(e);
} else if (message === 'submit_button_clicked') {
kpxcCustomLoginFieldsBanner.submitButtonClicked(e);
} else if (message === 'reset_button_clicked') { } else if (message === 'reset_button_clicked') {
kpxcCustomLoginFieldsBanner.reset(); kpxcCustomLoginFieldsBanner.reset();
} else if (message === 'close_button_clicked') { } else if (message === 'close_button_clicked') {
@ -821,7 +766,5 @@ const dataStepToString = function() {
return tr('totp'); return tr('totp');
} else if (kpxcCustomLoginFieldsBanner.dataStep === STEP_SELECT_STRING_FIELDS) { } else if (kpxcCustomLoginFieldsBanner.dataStep === STEP_SELECT_STRING_FIELDS) {
return tr('defineStringField'); return tr('defineStringField');
} else if (kpxcCustomLoginFieldsBanner.dataStep === STEP_SELECT_SUBMIT_BUTTON) {
return tr('defineSubmitButton');
} }
}; };

View file

@ -9,7 +9,6 @@ const MAX_SEGMENTED_FIELD_LENGTH = 100;
* Provides methods for input field handling. * Provides methods for input field handling.
*/ */
const kpxcFields = {}; const kpxcFields = {};
kpxcFields.popoverSupported = true;
// Returns all username & password combinations detected from the inputs. // Returns all username & password combinations detected from the inputs.
// After username field is detected, first password field found after that will be saved as a combination. // After username field is detected, first password field found after that will be saved as a combination.
@ -30,7 +29,7 @@ kpxcFields.getAllCombinations = async function(inputs) {
form: input.form form: input.form
}; };
combinations.push(kpxcFields.getExistingCombination(combination)); combinations.push(combination);
usernameField = null; usernameField = null;
} else if (kpxcTOTPIcons.isValid(input)) { } else if (kpxcTOTPIcons.isValid(input)) {
// Dynamically added TOTP field // Dynamically added TOTP field
@ -94,32 +93,6 @@ kpxcFields.getCombinationFromAllInputs = function() {
return kpxc.combinations[0]; return kpxc.combinations[0];
}; };
// Checks if existing combination is found and recognized fields are added to it
kpxcFields.getExistingCombination = function(combination) {
// Lookup existing combinations that use the same form
const existingCombination = kpxc.combinations?.find(c => c.form === combination?.form);
if (existingCombination) {
// Replace values to the existing combination
existingCombination.username ??= combination.username;
existingCombination.password ??= combination.password;
if (existingCombination.passwordInputs?.length === 0) {
existingCombination.passwordInputs = combination.passwordInputs;
} else if (combination?.password) {
// If password field is found in the current combination, force assign it to the existing combination
existingCombination.password = combination.password;
}
// Remove username field from combination with certain sites (replaced by password input)
if (kpxcSites.combinationExceptionFound(existingCombination)) {
existingCombination.username = null;
}
return existingCombination;
}
return combination;
};
// Adds segmented TOTP fields to the combination if found // Adds segmented TOTP fields to the combination if found
kpxcFields.getSegmentedTOTPFields = function(inputs, combinations) { kpxcFields.getSegmentedTOTPFields = function(inputs, combinations) {
if (!kpxc.settings.showOTPIcon) { if (!kpxc.settings.showOTPIcon) {
@ -438,97 +411,6 @@ kpxcFields.isSearchField = function(target) {
return false; return false;
}; };
// :popover-open selector is supported only with Firefox >= 125 and Chrome >= 114
kpxcFields.discoverOverlays = function() {
try {
kpxcFields.overlays = document.querySelectorAll(':popover-open, [popover]');
} catch (e) {
// Ignore SyntaxError (e.g., unsupported selector)
if (!(e instanceof SyntaxError)) {
kpxcFields.popoverSupported = false;
logError(e);
}
}
};
// Checks if element has an overlay
kpxcFields.hasOverlay = function(elem) {
try {
return elem?.hasAttribute('popover') || elem?.matches(':popover-open');
} catch (e) {
// Ignore SyntaxError (e.g., unsupported selector)
if (!(e instanceof SyntaxError)) {
kpxcFields.popoverSupported = false;
logError(e);
}
}
};
// Check the visibility of existing fields
kpxcFields.checkExistingFields = function() {
if (kpxc.inputs?.some(input => !kpxcFields.isVisible(input))) {
kpxc.clearAllFromPage();
kpxc.combinations = [];
}
};
// Check for popup overlays
kpxcFields.isOverlayOnTop = function(rect) {
for (const overlay of kpxcFields.overlays ?? []) {
if (kpxcSites.overlayExceptionFound(overlay)) {
continue;
}
const overlayRect = overlay?.getBoundingClientRect();
if (overlayRect && elementsOverlap(rect, overlayRect)) {
return true;
}
}
return false;
};
/**
* Check if element is the topmost element
* @param {HTMLElement} elem Element to be checked
* @param {DOMRect} rect Precalculated DOMRect of the element
* @returns {boolean} True if element is the topmost
*/
kpxcFields.isTopElement = function(elem, rect) {
if (!elem || !rect) {
return false;
}
const rootNode = elem.getRootNode() ?? document;
// Returns the topmost element from point x, height/2
// If the input has a label as the top element and it's inside the input, allow it.
const getTopmostElement = (element, x, elementRect) => {
const topElement = rootNode.elementFromPoint(x, elementRect.top + (elementRect.height / 2));
return element?.labels &&
element.labels[0] === topElement &&
elementsOverlap(elementRect, topElement.getBoundingClientRect())
? element
: topElement;
};
// Check topmost element from three points inside the input
if (matchesWithNodeName(elem, 'INPUT') && [
getTopmostElement(elem, rect.left + (rect.width / 4), rect), // First third
getTopmostElement(elem, rect.left + (rect.width / 2), rect), // Middle
getTopmostElement(elem, rect.left + (rect.width / 1.33), rect), // Last third
].some((e) => e !== elem)) {
return false;
}
// Check if element has an overlay
if (kpxcFields.isOverlayOnTop(rect)) {
return false;
}
return true;
};
// Returns true if element is visible on the page // Returns true if element is visible on the page
kpxcFields.isVisible = function(elem) { kpxcFields.isVisible = function(elem) {
// Returns true if opacity is not set, otherwise check the limits // Returns true if opacity is not set, otherwise check the limits
@ -548,10 +430,6 @@ kpxcFields.isVisible = function(elem) {
return false; return false;
} }
if (!kpxcFields.isTopElement(elem, rect)) {
return false;
}
// Check CSS visibility // Check CSS visibility
const elemStyle = getComputedStyle(elem); const elemStyle = getComputedStyle(elem);
if (elemStyle.visibility && (elemStyle.visibility === 'hidden' || elemStyle.visibility === 'collapse') if (elemStyle.visibility && (elemStyle.visibility === 'hidden' || elemStyle.visibility === 'collapse')
@ -594,14 +472,14 @@ kpxcFields.traverseParents = function(element, predicate, resultFn = () => true,
kpxcFields.useCustomLoginFields = async function() { kpxcFields.useCustomLoginFields = async function() {
const location = kpxc.getDocumentLocation(); const location = kpxc.getDocumentLocation();
const creds = kpxc.settings['defined-custom-fields'][location]; const creds = kpxc.settings['defined-custom-fields'][location];
if (!creds.username && !creds.password && !creds.totp && creds.fields.length === 0 && !creds.submitButton) { if (!creds.username && !creds.password && !creds.totp && creds.fields.length === 0) {
return; return;
} }
// Finds the element based on the stored ID // Finds the input field based on the stored ID
const findElement = async function(fields, idArray) { const findInputField = async function(inputFields, idArray) {
if (idArray) { if (idArray) {
const input = fields.find(e => e === kpxcFields.getId(idArray, e)); const input = inputFields.find(e => e === kpxcFields.getId(idArray, e));
if (input) { if (input) {
return input; return input;
} }
@ -618,24 +496,16 @@ kpxcFields.useCustomLoginFields = async function() {
} }
}); });
const buttons = []; const [ username, password, totp ] = await Promise.all([
document.body.querySelectorAll('button, input[type=submit]').forEach(e => { await findInputField(inputFields, creds.username),
if (e.type !== 'hidden' && !e.disabled) { await findInputField(inputFields, creds.password),
buttons.push(e); await findInputField(inputFields, creds.totp)
}
});
const [ username, password, totp, submitButton ] = await Promise.all([
await findElement(inputFields, creds.username),
await findElement(inputFields, creds.password),
await findElement(inputFields, creds.totp),
await findElement(buttons, creds.submitButton),
]); ]);
// Handle StringFields // Handle StringFields
const stringFields = []; const stringFields = [];
for (const sf of creds.fields) { for (const sf of creds.fields) {
const field = await findElement(inputFields, sf); const field = await findInputField(inputFields, sf);
if (field) { if (field) {
stringFields.push(field); stringFields.push(field);
} }
@ -647,19 +517,13 @@ kpxcFields.useCustomLoginFields = async function() {
kpxcTOTPIcons.newIcon(totp, kpxc.databaseState); kpxcTOTPIcons.newIcon(totp, kpxc.databaseState);
} }
// No values found
if (!username && !password && !totp && !submitButton && stringFields?.length === 0) {
return [];
}
const combinations = []; const combinations = [];
combinations.push({ combinations.push({
username: username, username: username,
password: password, password: password,
passwordInputs: [ password ], passwordInputs: [ password ],
totp: totp, totp: totp,
fields: stringFields, fields: stringFields
submitButton: submitButton
}); });
return combinations; return combinations;

View file

@ -18,7 +18,7 @@ kpxcFill.fillAttributeToActiveElementWith = async function(attr) {
return; return;
} }
await kpxcFill.setValue(el, value[0]); kpxc.setValue(el, value[0]);
}; };
// Fill requested from the context menu. Active element is used for combination detection // Fill requested from the context menu. Active element is used for combination detection
@ -152,20 +152,20 @@ kpxcFill.fillTOTPFromUuid = async function(el, uuid) {
return; return;
} }
await kpxcFill.setTOTPValue(el, totp); kpxcFill.setTOTPValue(el, totp);
} else if (user.stringFields?.length > 0) { } else if (user.stringFields?.length > 0) {
const stringFields = user.stringFields; const stringFields = user.stringFields;
for (const s of stringFields) { for (const s of stringFields) {
const val = s['KPH: {TOTP}']; const val = s['KPH: {TOTP}'];
if (val) { if (val) {
await kpxcFill.setTOTPValue(el, val); kpxcFill.setTOTPValue(el, val);
} }
} }
} }
}; };
// Set normal or segmented TOTP value // Set normal or segmented TOTP value
kpxcFill.setTOTPValue = async function(elem, val) { kpxcFill.setTOTPValue = function(elem, val) {
if (kpxc.credentials.length === 0) { if (kpxc.credentials.length === 0) {
logDebug('Error: Credential list is empty.'); logDebug('Error: Credential list is empty.');
return; return;
@ -173,22 +173,22 @@ kpxcFill.setTOTPValue = async function(elem, val) {
for (const comb of kpxc.combinations) { for (const comb of kpxc.combinations) {
if (comb.totpInputs?.length > 0) { if (comb.totpInputs?.length > 0) {
await kpxcFill.fillSegmentedTotp(elem, val, comb.totpInputs); kpxcFill.fillSegmentedTotp(elem, val, comb.totpInputs);
return; return;
} }
} }
await kpxcFill.setValue(elem, val); kpxc.setValue(elem, val);
}; };
// Fill TOTP in parts // Fill TOTP in parts
kpxcFill.fillSegmentedTotp = async function(elem, val, totpInputs) { kpxcFill.fillSegmentedTotp = function(elem, val, totpInputs) {
if (!totpInputs.includes(elem) || val.length < totpInputs.length) { if (!totpInputs.includes(elem) || val.length < totpInputs.length) {
return; return;
} }
for (let i = 0; i < totpInputs.length; ++i) { for (let i = 0; i < totpInputs.length; ++i) {
await kpxcFill.setValue(totpInputs[i], val[i]); kpxc.setValue(totpInputs[i], val[i]);
} }
}; };
@ -217,7 +217,7 @@ kpxcFill.fillFromUsernameIcon = async function(combination) {
*/ */
kpxcFill.fillInCredentials = async function(combination, predefinedUsername, uuid, passOnly = false) { kpxcFill.fillInCredentials = async function(combination, predefinedUsername, uuid, passOnly = false) {
if (kpxc.credentials.length === 0) { if (kpxc.credentials.length === 0) {
showErrorNotification(`${tr('credentialsNoLoginsFound')} ${document.location.origin}`); kpxcUI.createNotification('error', tr('credentialsNoLoginsFound'));
return; return;
} }
@ -245,17 +245,6 @@ kpxcFill.fillInCredentials = async function(combination, predefinedUsername, uui
skipAutoSubmit = selectedCredentials.skipAutoSubmit === 'true'; skipAutoSubmit = selectedCredentials.skipAutoSubmit === 'true';
} }
// Update the password field if form has been updated with a new identical element (Moodle).
// If found, replace the new input field to the combination.
if (combination?.form && combination?.password && !combination.form.contains(combination.password)) {
const formInputs = kpxcObserverHelper.getInputs(combination.form);
const newPasswordField = formInputs?.find((formInput) =>
formInput?.getLowerCaseAttribute('type') === 'password');
if (newPasswordField && areNamedNodeMapsEqual(combination.password.attributes, newPasswordField.attributes)) {
combination.password = newPasswordField;
}
}
// Fill password // Fill password
if (combination.password && matchesWithNodeName(combination.password, 'INPUT')) { if (combination.password && matchesWithNodeName(combination.password, 'INPUT')) {
// Show a notification if password length exceeds the length defined in input // Show a notification if password length exceeds the length defined in input
@ -271,28 +260,28 @@ kpxcFill.fillInCredentials = async function(combination, predefinedUsername, uui
return; return;
} }
await kpxcFill.setValueWithChange(combination.password, selectedCredentials.password); kpxc.setValueWithChange(combination.password, selectedCredentials.password);
await kpxc.setPasswordFilled(true); await kpxc.setPasswordFilled(true);
} }
// Fill username // Fill username
if (combination.username && usernameValue && combination.username !== combination.password && if (combination.username && usernameValue &&
(!combination.username.value || combination.username.value !== usernameValue)) { (!combination.username.value || combination.username.value !== usernameValue)) {
if (!passOnly) { if (!passOnly) {
await kpxcFill.setValueWithChange(combination.username, usernameValue); kpxc.setValueWithChange(combination.username, usernameValue);
} }
} }
// Fill StringFields // Fill StringFields
if (selectedCredentials.stringFields?.length > 0) { if (selectedCredentials.stringFields?.length > 0) {
await kpxcFill.fillInStringFields(combination.fields, selectedCredentials.stringFields); kpxcFill.fillInStringFields(combination.fields, selectedCredentials.stringFields);
} }
// Fill TOTP // Fill TOTP
if (kpxc.settings.autoFillSingleTotp && kpxc.entryHasTotp(selectedCredentials)) { if (kpxc.settings.autoFillSingleTotp && kpxc.entryHasTotp(selectedCredentials)) {
const totpCombination = combination?.totp || kpxc.combinations?.find(c => c.totp); const totpCombination = combination?.totp || kpxc.combinations?.find(c => c.totp);
if (totpCombination?.totp) { if (totpCombination?.totp) {
await kpxcFill.fillTOTPFromUuid(totpCombination.totp, selectedCredentials.uuid); kpxcFill.fillTOTPFromUuid(totpCombination.totp, selectedCredentials.uuid);
} }
} }
@ -306,7 +295,7 @@ kpxcFill.fillInCredentials = async function(combination, predefinedUsername, uui
}; };
// Fills StringFields defined in Custom Fields // Fills StringFields defined in Custom Fields
kpxcFill.fillInStringFields = async function(fields, stringFields) { kpxcFill.fillInStringFields = function(fields, stringFields) {
const filledInFields = []; const filledInFields = [];
if (fields && stringFields && fields?.length > 0 && stringFields?.length > 0) { if (fields && stringFields && fields?.length > 0 && stringFields?.length > 0) {
for (let i = 0; i < fields.length; i++) { for (let i = 0; i < fields.length; i++) {
@ -318,7 +307,7 @@ kpxcFill.fillInStringFields = async function(fields, stringFields) {
const currentField = fields[i]; const currentField = fields[i];
if (currentField && stringFieldValue[0]) { if (currentField && stringFieldValue[0]) {
await kpxcFill.setValue(currentField, stringFieldValue[0], true); kpxc.setValue(currentField, stringFieldValue[0], true);
filledInFields.push(currentField); filledInFields.push(currentField);
} }
} }
@ -340,8 +329,7 @@ kpxcFill.performAutoSubmit = async function(combination, skipAutoSubmit) {
if (!skipAutoSubmit && !autoSubmitIgnoredForSite) { if (!skipAutoSubmit && !autoSubmitIgnoredForSite) {
await sendMessage('page_set_autosubmit_performed'); await sendMessage('page_set_autosubmit_performed');
// Use submit button from Custom Login Fields or detect it from the form const submitButton = kpxcForm.getFormSubmitButton(combination.form);
const submitButton = combination?.submitButton ?? kpxcForm.getFormSubmitButton(combination.form);
if (submitButton !== undefined) { if (submitButton !== undefined) {
submitButton.click(); submitButton.click();
} else if (combination.form) { } else if (combination.form) {
@ -352,79 +340,6 @@ kpxcFill.performAutoSubmit = async function(combination, skipAutoSubmit) {
} }
}; };
// Special handling for setting value to select and checkbox elements
kpxcFill.setValue = async function(field, value, forced = false) {
if (field.matches('select')) {
value = value.toLowerCase().trim();
const options = field.querySelectorAll('option');
for (const o of options) {
if (o.textContent.toLowerCase().trim() === value) {
await kpxcFill.setValueWithChange(field, o.value);
return false;
}
}
return;
} else if (field.getLowerCaseAttribute('type') === 'checkbox' && value?.toLowerCase() === 'true') {
field.checked = true;
}
// Make sure the input is not wrapped inside another element (custom INPUT element)
if (field?.nodeName !== 'INPUT' && field?.nodeName?.includes('INPUT')) {
const childInput = field?.querySelector('input');
const fieldsFromShadowDOM = kpxcObserverHelper.findInputsFromShadowDOM(field);
field = childInput ?? fieldsFromShadowDOM[0];
}
await kpxcFill.setValueWithChange(field, value, forced);
};
// Sets a new value to input field and triggers necessary events
kpxcFill.setValueWithChange = async function(field, value, forced = false) {
if (!field || (field?.readOnly && !forced)) {
return;
}
// Check for overlays before fill
kpxcFields.discoverOverlays();
const rect = field.getBoundingClientRect();
if (kpxcFields.isOverlayOnTop(rect)) {
return;
}
const dispatchLegacyEvent = function(elem, eventName) {
const legacyEvent = elem.ownerDocument.createEvent('Event');
legacyEvent.initEvent(eventName, true, false);
elem.dispatchEvent(legacyEvent);
};
field.focus();
// Use a delay to allow focus events to trigger and to give some
// breathing room to frameworks that rely on promises to update their
// state, like React. Not doing so can break OTP input, see issue #2215.
await Promise.resolve();
field.dispatchEvent(new FocusEvent('focus', { bubbles: false, cancelable: false }));
field.dispatchEvent(new FocusEvent('focusin', { bubbles: true, cancelable: false }));
// https://w3c.github.io/uievents/#keypress-event-order
field.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, cancelable: false, key: value }));
field.dispatchEvent(new InputEvent('beforeinput', { bubbles: true, cancelable: false, inputType: 'insertText', data: value }));
field.dispatchEvent(new KeyboardEvent('keypress', { bubbles: true, cancelable: false, key: value }));
field.value = value;
field.dispatchEvent(new Event('input', { bubbles: true, cancelable: false }));
field.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true, cancelable: false, key: value }));
field.dispatchEvent(new Event('change', { bubbles: true, cancelable: false }));
// Some pages will not accept the value change without dispatching events directly to the document
dispatchLegacyEvent(field, 'input');
dispatchLegacyEvent(field, 'change');
};
// Check if password fill is done to a plain text field // Check if password fill is done to a plain text field
const passwordFillIsAllowed = function(elem) { const passwordFillIsAllowed = function(elem) {
const elementIsPasswordField = const elementIsPasswordField =
@ -441,35 +356,9 @@ const passwordFillIsAllowed = function(elem) {
// Show a specific error notification if current database is not connected // Show a specific error notification if current database is not connected
const showErrorNotification = async function(errorMessage, notificationType = 'error') { const showErrorNotification = async function(errorMessage, notificationType = 'error') {
const connectedDatabase = await sendMessage('get_connected_database'); const connectedDatabase = await sendMessage('get_connected_database');
if (!connectedDatabase?.identifier && kpxc.databaseState === DatabaseState.UNLOCKED) { if (!connectedDatabase?.identifier) {
kpxcUI.createNotification('error', tr('errorCurrentDatabaseNotConnected')); kpxcUI.createNotification('error', tr('errorCurrentDatabaseNotConnected'));
} else if (!await isIframeAllowed()) {
// Special error if we are blocking due to iframe
kpxcUI.createNotification('error', tr('credentialsBlockedInIframe'));
} else { } else {
kpxcUI.createNotification(notificationType, errorMessage); kpxcUI.createNotification(notificationType, errorMessage);
} }
}; };
// Checks if two NamedNodeMaps (attribute lists) are equal
const areNamedNodeMapsEqual = function(currentNodeMap, newNodeMap) {
if (!currentNodeMap || !newNodeMap) {
return false;
}
const fieldAttributes = Array.from(currentNodeMap);
const newFieldAttributes = Array.from(newNodeMap);
if (fieldAttributes.length !== newFieldAttributes.length) {
return false;
}
for (const attr of fieldAttributes) {
const newAttr = newFieldAttributes.find((newAttr) => newAttr?.name === attr?.name);
if (!newAttr || newAttr?.value !== attr?.value) {
return false;
}
}
return true;
};

View file

@ -27,7 +27,7 @@ kpxcForm.activateCredentialBanner = async function(usernameValue, passwordInputs
return; return;
} }
if (passwordField && kpxcFields.isVisible(passwordField)) { if (passwordField) {
await kpxc.setPasswordFilled(true); await kpxc.setPasswordFilled(true);
} }
@ -66,9 +66,6 @@ kpxcForm.getFormSubmitButton = function(form) {
return; return;
} }
const hasPasswordClassOrId = (button) => button
&& (button?.classList.value?.toLowerCase()?.includes('password')
|| button?.id?.toLowerCase()?.includes('password'));
const action = kpxc.submitUrl || form.action; const action = kpxc.submitUrl || form.action;
// Check if the site needs a special handling for retrieving the form submit button // Check if the site needs a special handling for retrieving the form submit button
@ -91,19 +88,13 @@ kpxcForm.getFormSubmitButton = function(form) {
b => !b.getAttribute('formAction') b => !b.getAttribute('formAction')
); );
if (buttons.length > 0) { if (buttons.length > 0) {
const lastButton = buttons.at(-1); return buttons.at(-1);
// Accept button if it has no indication for password
if (!hasPasswordClassOrId(lastButton)) {
return buttons.at(-1);
}
} }
// Try to find similar buttons outside the form which are added via 'form' property // Try to find similar buttons outside the form which are added via 'form' property
for (const e of form.elements) { for (const e of form.elements) {
const isSubmitButton = matchesWithNodeName(e, 'BUTTON') if ((matchesWithNodeName(e, 'BUTTON') && (e.type === 'button' || e.type === 'submit' || e.type === ''))
&& (e.type === 'button' || e.type === 'submit' || e.type === ''); || (matchesWithNodeName(e, 'INPUT') && (e.type === 'button' || e.type === 'submit'))) {
const isInputButton = matchesWithNodeName(e, 'INPUT') && (e.type === 'button' || e.type === 'submit');
if ((isSubmitButton || isInputButton) && !hasPasswordClassOrId(e)) {
return e; return e;
} }
} }
@ -125,9 +116,9 @@ kpxcForm.getNewPassword = function(passwordInputs = []) {
} }
// Choose the last three password fields. The first ones are almost always for something else // Choose the last three password fields. The first ones are almost always for something else
const current = passwordInputs[passwordInputs.length - 3]?.value; const current = passwordInputs[passwordInputs.length - 3].value;
const newPass = passwordInputs[passwordInputs.length - 2]?.value; const newPass = passwordInputs[passwordInputs.length - 2].value;
const repeatNew = passwordInputs[passwordInputs.length - 1]?.value; const repeatNew = passwordInputs[passwordInputs.length - 1].value;
if ((newPass === repeatNew && current !== newPass && current !== repeatNew) if ((newPass === repeatNew && current !== newPass && current !== repeatNew)
|| (current === newPass && repeatNew !== newPass && repeatNew !== current)) { || (current === newPass && repeatNew !== newPass && repeatNew !== current)) {
@ -175,8 +166,6 @@ kpxcForm.initForm = function(form, credentialFields) {
if (submitButton) { if (submitButton) {
submitButton.addEventListener('click', kpxcForm.onSubmit); submitButton.addEventListener('click', kpxcForm.onSubmit);
} }
kpxcUI.pageObserver.observe(form, OBSERVER_OPTIONS);
} }
}; };

View file

@ -1,248 +0,0 @@
'use strict';
/**
* @Object kpxcIcons
* Icon handling.
*/
const kpxcIcons = {};
kpxcIcons.icons = [];
kpxcIcons.iconTypes = {
DEFAULT: 0, // Username icon
PASSWORD: 1,
TOTP: 2
};
// Adds an icon to input field
kpxcIcons.addIcon = async function(field, iconType) {
if (!field || !Object.values(kpxcIcons.iconTypes).includes(iconType)) {
return;
}
let iconSet = false;
if (iconType === kpxcIcons.iconTypes.DEFAULT && kpxcUsernameIcons.isValid(field)) {
kpxcUsernameIcons.newIcon(field, kpxc.databaseState);
iconSet = true;
} else if (iconType === kpxcIcons.iconTypes.PASSWORD && kpxcPasswordIcons.isValid(field)) {
kpxcPasswordIcons.newIcon(field, kpxc.databaseState);
iconSet = true;
} else if (iconType === kpxcIcons.iconTypes.TOTP && kpxcTOTPIcons.isValid(field)) {
kpxcTOTPIcons.newIcon(field, kpxc.databaseState);
iconSet = true;
}
if (iconSet) {
kpxcIcons.icons.push({
field: field,
iconType: iconType
});
}
};
// Adds all icons from a form struct
kpxcIcons.addIconsFromForm = async function(form) {
const addUsernameIcons = async function(c) {
if (kpxc.settings.showLoginFormIcon && await kpxc.passwordFilledWithExceptions(c) === false) {
// Special case where everything else has been hidden, but a single password field is now displayed.
// For example PayPal and Amazon is handled like this.
if (c.username && !c.password && c.passwordInputs.length === 1) {
// Use password input directly from form if found (Epicgames)
const passwordField = c.form?.querySelector('input[type=password]');
if (c.form && passwordField) {
kpxcIcons.addIcon(passwordField, kpxcIcons.iconTypes.DEFAULT);
} else {
kpxcIcons.addIcon(c.passwordInputs[0], kpxcIcons.iconTypes.DEFAULT);
}
}
if (c.username && !c.username.readOnly) {
kpxcIcons.addIcon(c.username, kpxcIcons.iconTypes.DEFAULT);
} else if (c.password && (!c.username || (c.username && c.username.readOnly))) {
// Single password field
kpxcIcons.addIcon(c.password, kpxcIcons.iconTypes.DEFAULT);
}
}
};
const addPasswordIcons = async function(c) {
// Show password icons also with forms without any username field
if (kpxc.settings.usePasswordGeneratorIcons
&& ((c.username && c.password) || (!c.username && c.passwordInputs.length > 0))) {
for (const input of c.passwordInputs) {
kpxcIcons.addIcon(input, kpxcIcons.iconTypes.PASSWORD);
}
}
};
const addTOTPIcons = async function(c) {
if (c.totp && kpxc.settings.showOTPIcon) {
kpxcIcons.addIcon(c.totp, kpxcIcons.iconTypes.TOTP);
}
};
await Promise.all([
await addUsernameIcons(form),
await addPasswordIcons(form),
await addTOTPIcons(form)
]);
};
kpxcIcons.calculateIconOffset = function(field, size) {
const offset = Math.floor((field.offsetHeight / 2) - (size / 2) - 1);
return (offset < 0) ? 0 : offset;
};
// Delete all icons that have been hidden from the page view
kpxcIcons.deleteAllHiddenIcons = function() {
kpxcIcons.deleteIcons(kpxcUsernameIcons.icons);
kpxcIcons.deleteIcons(kpxcPasswordIcons.icons);
kpxcIcons.deleteIcons(kpxcTOTPIcons.icons);
};
// Delete hidden icons from the list
kpxcIcons.deleteIcons = function(iconList) {
const deletedIcons = [];
for (const icon of iconList) {
if (icon.inputField && !kpxcFields.isVisible(icon.inputField)) {
const index = iconList.indexOf(icon);
icon.removeIcon();
iconList.splice(index, 1);
deletedIcons.push(icon.inputField);
// Delete the input field from detected fields so the icon can be detected again
const inputFieldIndex = kpxc.inputs.indexOf(icon.inputField);
if (inputFieldIndex >= 0) {
kpxc.inputs.splice(inputFieldIndex, 1);
}
}
}
// Remove the same icons from kpxcIcons.icons array
for (const input of deletedIcons) {
const index = kpxcIcons.icons.findIndex(e => e.field === input);
if (index >= 0) {
kpxcIcons.icons.splice(index, 1);
}
}
};
// Initializes all icons needed to be shown
kpxcIcons.initIcons = async function(combinations = []) {
if (combinations.length === 0) {
return;
}
for (const form of kpxcForm.savedForms) {
await kpxcIcons.addIconsFromForm(form);
}
// Check for other combinations that are not in any form,
// or there's a form that wasn't present in savedForms (and it's not null)
for (const c of combinations) {
if (!c.form || (c.form && !kpxcForm.savedForms.some(sf => sf.form === c.form))) {
await kpxcIcons.addIconsFromForm(c);
}
}
};
kpxcIcons.hasIcon = function(field) {
return !field ? false : kpxcIcons.icons.some(i => i.field === field);
};
kpxcIcons.monitorIconPosition = function(iconClass) {
// Handle icon position on resize
window.addEventListener('resize', function(e) {
kpxcIcons.updateIconPosition(iconClass);
});
// Handle icon position on scroll
window.addEventListener('scroll', function(e) {
kpxcIcons.updateIconPosition(iconClass);
});
window.addEventListener('transitionend', function(e) {
if (matchesWithNodeName(e.target, 'INPUT') || matchesWithNodeName(e.target, 'TEXTAREA')) {
kpxcIcons.updateIconPosition(iconClass);
}
});
};
kpxcIcons.setIconPosition = function(icon, field, rtl = false, segmented = false) {
const rect = field.getBoundingClientRect();
const size = Number(icon.getAttribute('size'));
const offset = kpxcIcons.calculateIconOffset(field, size);
const zoom = kpxcUI.bodyStyle.zoom || 1;
let left = kpxcUI.getRelativeLeftPosition(rect) / zoom;
let top = kpxcUI.getRelativeTopPosition(rect) / zoom;
// Add more space for the icon to show it at the right side of the field if TOTP fields are segmented
if (segmented) {
left += size + 10;
}
// Adjusts the icon offset for certain sites
const iconOffset = kpxcSites.iconOffset(left, top, size, field?.getLowerCaseAttribute('type'));
if (iconOffset) {
left = iconOffset[0];
top = iconOffset[1];
}
const scrollTop = kpxcUI.getScrollTop() / zoom;
const scrollLeft = kpxcUI.getScrollLeft() / zoom;
icon.style.top = Pixels(top + scrollTop + offset + 1);
icon.style.left = rtl
? Pixels(left + scrollLeft + offset)
: Pixels(left + scrollLeft + field.offsetWidth - size - offset);
};
// Sets the icons to corresponding database lock status
kpxcIcons.switchIcons = async function() {
const uuid = await sendMessage('page_get_login_id');
kpxcUsernameIcons.switchIcon(kpxc.databaseState, uuid);
kpxcPasswordIcons.switchIcon(kpxc.databaseState, uuid);
kpxcTOTPIcons.switchIcon(kpxc.databaseState, uuid);
};
/**
* Detects if the input field appears or disappears -> show/hide the icon
* - boundingClientRect with slightly (< -10) negative values -> hidden
* - intersectionRatio === 0 -> hidden
* - isIntersecting === false -> hidden
* - intersectionRatio > 0 -> shown
* - isIntersecting === true -> shown
*/
kpxcIcons.updateFromIntersectionObserver = function(iconClass, entries) {
for (const entry of entries) {
const rect = DOMRectToArray(entry.boundingClientRect);
if ((entry.intersectionRatio === 0 && !entry.isIntersecting) || (rect.some(x => x < -10))) {
iconClass.icon.style.display = 'none';
} else if (entry.intersectionRatio > 0 && entry.isIntersecting) {
iconClass.icon.style.display = 'block';
// Wait for possible DOM animations
setTimeout(() => {
kpxcIcons.setIconPosition(iconClass.icon, entry.target, iconClass.rtl, iconClass.segmented);
}, 400);
}
}
};
kpxcIcons.updateIconPosition = function(iconClass) {
if (iconClass.inputField && iconClass.icon) {
kpxcIcons.setIconPosition(iconClass.icon, iconClass.inputField, iconClass.rtl, iconClass.segmented);
}
};
const DOMRectToArray = function (domRect) {
return [
domRect.bottom,
domRect.height,
domRect.left,
domRect.right,
domRect.top,
domRect.width,
domRect.x,
domRect.y,
];
};

View file

@ -1,67 +0,0 @@
'use strict';
const MIN_ICON_SIZE = 14;
const MAX_ICON_SIZE = 24;
// Basic icon class
class Icon {
constructor(field, databaseState = DatabaseState.DISCONNECTED, segmented = false) {
this.databaseState = databaseState;
this.icon = null;
this.inputField = null;
this.rtl = kpxcUI.isRTL(field);
this.segmented = segmented;
try {
this.observer = new IntersectionObserver((entries) => {
kpxcIcons.updateFromIntersectionObserver(this, entries);
});
} catch (err) {
logError(err);
}
}
// Size the icon dynamically, but not greater than 24 or smaller than 14
calculateIconSize(field) {
return Math.max(Math.min(MAX_ICON_SIZE, field.offsetHeight - 4), MIN_ICON_SIZE);
}
// Creates a wrapper div that has the icon in Shadow DOM
createWrapper(styleSheetFilename) {
const styleSheet = createStylesheet(styleSheetFilename);
const wrapper = document.createElement('div');
wrapper.style.all = 'unset';
wrapper.style.display = 'none';
// Make sure the wrapper is positioned correctly without CSS styles affecting to it
wrapper.style.position = 'absolute';
wrapper.style.top = Pixels(0);
wrapper.style.left = Pixels(0);
// Waits for stylesheet to load before displaying the element
styleSheet.addEventListener('load', () => wrapper.style.display = 'block');
this.shadowRoot = wrapper.attachShadow({ mode: 'closed' });
this.shadowRoot.append(styleSheet);
this.shadowRoot.append(this.icon);
document.body.append(wrapper);
kpxcUI.observeWrapper(wrapper);
}
removeIcon() {
this.shadowRoot.removeChild(this.icon);
document.body.removeChild(this.shadowRoot.host);
}
switchIcon(state, uuid) {
if (!this.icon) {
return;
}
if (state === DatabaseState.UNLOCKED) {
this.icon.style.filter = kpxc.credentials.length === 0 && !uuid ? 'saturate(0%)' : 'saturate(100%)';
} else {
this.icon.style.filter = 'saturate(0%)';
}
}
}

View file

@ -0,0 +1,116 @@
'use strict';
/**
* @Object kpxcIcons
* Icon handling.
*/
const kpxcIcons = {};
kpxcIcons.icons = [];
kpxcIcons.iconTypes = { USERNAME: 0, PASSWORD: 1, TOTP: 2 };
// Adds an icon to input field
kpxcIcons.addIcon = async function(field, iconType) {
if (!field || iconType < 0 || iconType > 2) {
return;
}
let iconSet = false;
if (iconType === kpxcIcons.iconTypes.USERNAME && kpxcUsernameIcons.isValid(field)) {
kpxcUsernameIcons.newIcon(field, kpxc.databaseState);
iconSet = true;
} else if (iconType === kpxcIcons.iconTypes.PASSWORD && kpxcPasswordIcons.isValid(field)) {
kpxcPasswordIcons.newIcon(field, kpxc.databaseState);
iconSet = true;
} else if (iconType === kpxcIcons.iconTypes.TOTP && kpxcTOTPIcons.isValid(field)) {
kpxcTOTPIcons.newIcon(field, kpxc.databaseState);
iconSet = true;
}
if (iconSet) {
kpxcIcons.icons.push({
field: field,
iconType: iconType
});
}
};
// Adds all icons from a form struct
kpxcIcons.addIconsFromForm = async function(form) {
const addUsernameIcons = async function(c) {
if (kpxc.settings.showLoginFormIcon && await kpxc.passwordFilledWithExceptions(c) === false) {
// Special case where everything else has been hidden, but a single password field is now displayed.
// For example PayPal and Amazon is handled like this.
if (c.username && !c.password && c.passwordInputs.length === 1) {
kpxcIcons.addIcon(c.passwordInputs[0], kpxcIcons.iconTypes.USERNAME);
}
if (c.username && !c.username.readOnly) {
kpxcIcons.addIcon(c.username, kpxcIcons.iconTypes.USERNAME);
} else if (c.password && (!c.username || (c.username && c.username.readOnly))) {
// Single password field
kpxcIcons.addIcon(c.password, kpxcIcons.iconTypes.USERNAME);
}
}
};
const addPasswordIcons = async function(c) {
// Show password icons also with forms without any username field
if (kpxc.settings.usePasswordGeneratorIcons
&& ((c.username && c.password) || (!c.username && c.passwordInputs.length > 0))) {
for (const input of c.passwordInputs) {
kpxcIcons.addIcon(input, kpxcIcons.iconTypes.PASSWORD);
}
}
};
const addTOTPIcons = async function(c) {
if (c.totp && kpxc.settings.showOTPIcon) {
kpxcIcons.addIcon(c.totp, kpxcIcons.iconTypes.TOTP);
}
};
await Promise.all([
await addUsernameIcons(form),
await addPasswordIcons(form),
await addTOTPIcons(form)
]);
};
// Delete all icons that have been hidden from the page view
kpxcIcons.deleteHiddenIcons = function() {
kpxcUsernameIcons.deleteHiddenIcons();
kpxcPasswordIcons.deleteHiddenIcons();
kpxcTOTPIcons.deleteHiddenIcons();
};
// Initializes all icons needed to be shown
kpxcIcons.initIcons = async function(combinations = []) {
if (combinations.length === 0) {
return;
}
for (const form of kpxcForm.savedForms) {
await kpxcIcons.addIconsFromForm(form);
}
// Check for other combinations that are not in any form,
// or there's a form that wasn't present in savedForms (and it's not null)
for (const c of combinations) {
if (!c.form || (c.form && !kpxcForm.savedForms.some(sf => sf.form === c.form))) {
await kpxcIcons.addIconsFromForm(c);
}
}
};
kpxcIcons.hasIcon = function(field) {
return !field ? false : kpxcIcons.icons.some(i => i.field === field);
};
// Sets the icons to corresponding database lock status
kpxcIcons.switchIcons = async function() {
const uuid = await sendMessage('page_get_login_id');
kpxcUsernameIcons.switchIcon(kpxc.databaseState, uuid);
kpxcPasswordIcons.switchIcon(kpxc.databaseState, uuid);
kpxcTOTPIcons.switchIcon(kpxc.databaseState, uuid);
};

View file

@ -32,7 +32,7 @@ kpxc.addToSitePreferences = async function(optionName, addWildcard = false) {
let site; let site;
try { try {
site = trimURL(window.top.location.href); site = trimURL(window.top.location.href);
} catch (_err) { } catch (err) {
logDebug('Adding to Site Preferences denied from iframe.'); logDebug('Adding to Site Preferences denied from iframe.');
return; return;
} }
@ -62,10 +62,10 @@ kpxc.addToSitePreferences = async function(optionName, addWildcard = false) {
await sendMessage('save_settings', kpxc.settings); await sendMessage('save_settings', kpxc.settings);
if (optionName === SitePreferences.ALLOW_IFRAMES) { if (optionName === 'allowIframes') {
await sendMessage('page_set_allow_iframes', [ true, site ]); await sendMessage('page_set_allow_iframes', [ true, site ]);
await sendMessage('iframe_detected', false); await sendMessage('iframe_detected', false);
} else if (optionName === SitePreferences.USERNAME_ONLY) { } else if (optionName === 'usernameOnly') {
await sendMessage('username_field_detected', false); await sendMessage('username_field_detected', false);
} }
}; };
@ -81,9 +81,8 @@ kpxc.clearAllFromPage = function() {
kpxcUserAutocomplete.closeList(); kpxcUserAutocomplete.closeList();
} }
// Clear logins from background and switch back to default popup // Switch back to default popup
sendMessage('page_clear_logins'); sendMessage('get_status', [ true ]); // This is an internal function call
sendMessage('get_status', [ true, false, true ]); // This is an internal function call, forceShowDefault
}; };
// Creates a new combination manually from active element // Creates a new combination manually from active element
@ -208,8 +207,6 @@ kpxc.getSite = function(sites) {
kpxc.identifyFormInputs = async function() { kpxc.identifyFormInputs = async function() {
const forms = []; const forms = [];
const documentForms = document.forms; // Cache the value just in case const documentForms = document.forms; // Cache the value just in case
// Used for overlay security detection
kpxcFields.discoverOverlays();
for (const form of documentForms) { for (const form of documentForms) {
if (!kpxcFields.isVisible(form)) { if (!kpxcFields.isVisible(form)) {
@ -361,7 +358,7 @@ kpxc.initCredentialFields = async function() {
// Search all remaining inputs from the page, ignore the previous input fields // Search all remaining inputs from the page, ignore the previous input fields
const pageInputs = await kpxcFields.getAllPageInputs(formInputs); const pageInputs = await kpxcFields.getAllPageInputs(formInputs);
if (formInputs.length === 0 && pageInputs.length === 0) { if (formInputs.length === 0 && pageInputs.length === 0 && !kpxcFields.isCustomLoginFieldsUsed()) {
// Run 'redetect_credentials' manually if no fields are found after a page load // Run 'redetect_credentials' manually if no fields are found after a page load
setTimeout(async function() { setTimeout(async function() {
if (_called.automaticRedetectCompleted) { if (_called.automaticRedetectCompleted) {
@ -519,7 +516,7 @@ kpxc.prepareCredentials = async function() {
kpxc.initAutocomplete(); kpxc.initAutocomplete();
if (kpxc.settings.autoFillRelevantCredential) { if (kpxc.settings.autoFillRelevantCredential) {
const pageUuid = await sendMessage('page_get_login_id', false); const pageUuid = await sendMessage('page_get_login_id');
if (pageUuid) { if (pageUuid) {
const relevantCredential = kpxc.credentials.find(c => c.uuid === pageUuid); const relevantCredential = kpxc.credentials.find(c => c.uuid === pageUuid);
const combination = kpxc.combinations?.at(-1); const combination = kpxc.combinations?.at(-1);
@ -649,14 +646,11 @@ kpxc.rememberCredentialsFromContextMenu = async function() {
// Credential Banner can force the retrieval for reloading new/modified credentials. // Credential Banner can force the retrieval for reloading new/modified credentials.
kpxc.retrieveCredentials = async function(force = false) { kpxc.retrieveCredentials = async function(force = false) {
if (!await isIframeAllowed()) { if (!await isIframeAllowed()) {
return; return [];
} }
kpxc.url = document.location.href; kpxc.url = document.location.href;
kpxc.submitUrl = kpxc.getFormActionUrl(kpxc.combinations[0]);
// Search for first combination that has username or password input set
const firstCombination = kpxc.combinations?.find((combination) => combination?.username || combination?.password);
kpxc.submitUrl = kpxc.getFormActionUrl(firstCombination);
if (kpxc.settings.autoRetrieveCredentials && kpxc.url && kpxc.submitUrl) { if (kpxc.settings.autoRetrieveCredentials && kpxc.url && kpxc.submitUrl) {
await kpxc.retrieveCredentialsCallback( await kpxc.retrieveCredentialsCallback(
@ -721,6 +715,52 @@ kpxc.setPasswordFilled = async function(state) {
await sendMessage('password_set_filled', state); await sendMessage('password_set_filled', state);
}; };
// Special handling for setting value to select and checkbox elements
kpxc.setValue = function(field, value, forced = false) {
if (field.matches('select')) {
value = value.toLowerCase().trim();
const options = field.querySelectorAll('option');
for (const o of options) {
if (o.textContent.toLowerCase().trim() === value) {
kpxc.setValueWithChange(field, o.value);
return false;
}
}
return;
} else if (field.getLowerCaseAttribute('type') === 'checkbox' && value?.toLowerCase() === 'true') {
field.checked = true;
}
kpxc.setValueWithChange(field, value, forced);
};
// Sets a new value to input field and triggers necessary events
kpxc.setValueWithChange = function(field, value, forced = false) {
if (!forced && field.readOnly) {
return;
}
const dispatchLegacyEvent = function(elem, eventName) {
const legacyEvent = elem.ownerDocument.createEvent('Event');
legacyEvent.initEvent(eventName, true, false);
elem.dispatchEvent(legacyEvent);
};
field.focus();
field.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, cancelable: false }));
field.dispatchEvent(new KeyboardEvent('keypress', { bubbles: true, cancelable: false }));
field.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true, cancelable: false }));
field.dispatchEvent(new Event('input', { bubbles: true, cancelable: false }));
field.dispatchEvent(new Event('change', { bubbles: true, cancelable: false }));
field.value = value;
// Some pages will not accept the value change without dispatching events directly to the document
dispatchLegacyEvent(field, 'input');
dispatchLegacyEvent(field, 'change');
};
kpxc.showGroupNameInAutocomplete = function() { kpxc.showGroupNameInAutocomplete = function() {
return !kpxc.settings.useCompactMode return !kpxc.settings.useCompactMode
|| (kpxc.settings.showGroupNameInAutocomplete && kpxc.getUniqueGroupCount(kpxc.credentials) > 1); || (kpxc.settings.showGroupNameInAutocomplete && kpxc.getUniqueGroupCount(kpxc.credentials) > 1);
@ -732,7 +772,7 @@ kpxc.siteIgnored = async function(condition) {
let currentLocation; let currentLocation;
try { try {
currentLocation = window.top.location.href; currentLocation = window.top.location.href;
} catch (_err) { } catch (err) {
// Cross-domain security error inspecting window.top.location.href. // Cross-domain security error inspecting window.top.location.href.
// This catches an error when an iframe is being accessed from another (sub)domain // This catches an error when an iframe is being accessed from another (sub)domain
// -> use the iframe URL instead. // -> use the iframe URL instead.
@ -853,7 +893,6 @@ const initContentScript = async function() {
} }
kpxc.settings = settings; kpxc.settings = settings;
kpxc.isFirefox = await sendMessage('is_firefox');
if (await kpxc.siteIgnored()) { if (await kpxc.siteIgnored()) {
logDebug('This site is ignored in Site Preferences.'); logDebug('This site is ignored in Site Preferences.');
@ -910,9 +949,9 @@ browser.runtime.onMessage.addListener(async function(req, sender) {
if (req.action === 'activated_tab') { if (req.action === 'activated_tab') {
kpxc.triggerActivatedTab(); kpxc.triggerActivatedTab();
} else if (req.action === 'add_allow_iframes_option') { } else if (req.action === 'add_allow_iframes_option') {
kpxc.addToSitePreferences(SitePreferences.ALLOW_IFRAMES); kpxc.addToSitePreferences('allowIframes');
} else if (req.action === 'add_username_only_option') { } else if (req.action === 'add_username_only_option') {
kpxc.addToSitePreferences(SitePreferences.USERNAME_ONLY, true); kpxc.addToSitePreferences('usernameOnly', true);
} else if (req.action === 'check_database_hash' && 'hash' in req) { } else if (req.action === 'check_database_hash' && 'hash' in req) {
kpxc.detectDatabaseChange(req); kpxc.detectDatabaseChange(req);
} else if (req.action === 'choose_credential_fields') { } else if (req.action === 'choose_credential_fields') {
@ -941,14 +980,9 @@ browser.runtime.onMessage.addListener(async function(req, sender) {
kpxcFill.fillAttributeToActiveElementWith(req.args); kpxcFill.fillAttributeToActiveElementWith(req.args);
} else if (req.action === 'frame_message') { } else if (req.action === 'frame_message') {
if (req.args?.[0] === 'frame_request_to_frames' && window.self !== window.top) { if (req.args?.[0] === 'frame_request_to_frames' && window.self !== window.top) {
// Handle message from top window in iframe
kpxcCustomLoginFieldsBanner.handleParentWindowMessage(req.args); kpxcCustomLoginFieldsBanner.handleParentWindowMessage(req.args);
} else if (req.args?.[0] === 'frame_request_to_parent' && window.self === window.top) { } else if (req.args?.[0] === 'frame_request_to_parent' && window.self === window.top) {
// Handle message from iframe in top window
kpxcCustomLoginFieldsBanner.handleTopWindowMessage(req.args); kpxcCustomLoginFieldsBanner.handleTopWindowMessage(req.args);
} else if (req.args?.[0] === 'notification_from_frame' && window.self === window.top) {
// Handle notification from iframe in top window
kpxcUI.createNotification(req?.args[1], req?.args[2]);
} }
} else if (req.action === 'ignore_site') { } else if (req.action === 'ignore_site') {
kpxc.ignoreSite(req.args); kpxc.ignoreSite(req.args);
@ -962,14 +996,9 @@ browser.runtime.onMessage.addListener(async function(req, sender) {
kpxc.initCredentialFields(); kpxc.initCredentialFields();
} else if (req.action === 'reload_extension') { } else if (req.action === 'reload_extension') {
sendMessage('reconnect'); sendMessage('reconnect');
} else if (req.action === 'reopen_database') {
sendMessage(
'get_status',
[ false, true ] // Set forcePopup to true
);
} else if (req.action === 'save_credentials') { } else if (req.action === 'save_credentials') {
kpxc.rememberCredentialsFromContextMenu(); kpxc.rememberCredentialsFromContextMenu();
} else if (req.action === 'retrieve_credentials_forced') { } else if (req.action === 'retrive_credentials_forced') {
await kpxc.retrieveCredentials(true); await kpxc.retrieveCredentials(true);
} else if (req.action === 'show_password_generator') { } else if (req.action === 'show_password_generator') {
kpxcPasswordGenerator.showPasswordGenerator(); kpxcPasswordGenerator.showPasswordGenerator();
@ -999,18 +1028,11 @@ kpxc.reconnect = async function() {
const isIframeAllowed = async function() { const isIframeAllowed = async function() {
sendMessage('iframe_detected', false); sendMessage('iframe_detected', false);
// Don't allow sandboxed iframes
if (self.origin === null || self.origin === 'null') {
logDebug('Error: Sandboxed iframes are not allowed');
return false;
}
try { try {
// Check for Cross-domain security error when inspecting window.top.location.href // Check for Cross-domain security error when inspecting window.top.location.href
const currentLocation = window.top.location.href; const currentLocation = window.top.location.href;
return true; return true;
} catch (_err) { } catch (err) {
// Inspect iframe using TLD and the tab's original URL // Inspect iframe using TLD and the tab's original URL
const allowed = await sendMessage('is_iframe_allowed', [ window.location.href, window.location.hostname ]); const allowed = await sendMessage('is_iframe_allowed', [ window.location.href, window.location.hostname ]);
if (allowed) { if (allowed) {

View file

@ -18,18 +18,11 @@ kpxcObserverHelper.ignoredNodeNames = [
'A', 'A',
'HEAD', 'HEAD',
'HTML', 'HTML',
'IMG',
'LINK', 'LINK',
'SCRIPT', 'SCRIPT',
'VIDEO', 'VIDEO',
]; ];
kpxcObserverHelper.ignoredPartialNodeNames = [
'REDDIT-PDP',
'RENDER-TEMPLATE',
'SHREDDIT',
];
kpxcObserverHelper.ignoredNodeTypes = [ kpxcObserverHelper.ignoredNodeTypes = [
Node.ATTRIBUTE_NODE, Node.ATTRIBUTE_NODE,
Node.TEXT_NODE, Node.TEXT_NODE,
@ -79,22 +72,15 @@ kpxcObserverHelper.initObserver = async function() {
continue; continue;
} }
if (kpxcFields.hasOverlay(mut.target)) {
kpxcFields.discoverOverlays();
kpxcFields.checkExistingFields();
continue;
}
// Cache style mutations. We only need the last style mutation of the target. // Cache style mutations. We only need the last style mutation of the target.
kpxcObserverHelper.cacheStyle(mut, styleMutations, mutations.length); kpxcObserverHelper.cacheStyle(mut, styleMutations, mutations.length);
if (mut.type === 'childList') { if (mut.type === 'childList') {
mut.addedNodes.forEach(function (node) { if (mut.addedNodes.length > 0) {
kpxcObserverHelper.handleObserverAdd(node); kpxcObserverHelper.handleObserverAdd(mut.addedNodes[0]);
}); } else if (mut.removedNodes.length > 0) {
mut.removedNodes.forEach(function (node) { kpxcObserverHelper.handleObserverRemove(mut.removedNodes[0]);
kpxcObserverHelper.handleObserverRemove(node); }
});
} else if (mut.type === 'attributes' && (mut.attributeName === 'class' || mut.attributeName === 'style')) { } else if (mut.type === 'attributes' && (mut.attributeName === 'class' || mut.attributeName === 'style')) {
// Only accept targets with forms // Only accept targets with forms
const forms = matchesWithNodeName(mut.target, 'FORM') const forms = matchesWithNodeName(mut.target, 'FORM')
@ -244,31 +230,6 @@ kpxcObserverHelper.findInputsFromShadowDOM = function(target) {
return inputFields; return inputFields;
}; };
// Detects animations and transitions. Triggers handleObserverAdd() again on animationend/transitionend.
kpxcObserverHelper.handleTransitions = function(target) {
const classList = target?.classList?.toString();
const targetHasAnimations = classList?.includes('animate');
const targetHasDurations = classList?.includes('duration') || classList?.includes('transform');
if (targetHasAnimations || targetHasDurations) {
const animations = target.getAnimations();
const transitionTime = animations[0]?.currentTime ?? 0;
// Animation found, but transition has not finished
if (animations && transitionTime === 0) {
target.addEventListener(
targetHasAnimations ? 'animationend' : 'transitionend',
() => {
kpxcObserverHelper.handleObserverAdd(target);
},
{
once: true,
},
);
}
}
};
// Adds elements to a monitor array. Identifies the input fields. // Adds elements to a monitor array. Identifies the input fields.
kpxcObserverHelper.handleObserverAdd = async function(target) { kpxcObserverHelper.handleObserverAdd = async function(target) {
if (kpxcObserverHelper.ignoredElement(target)) { if (kpxcObserverHelper.ignoredElement(target)) {
@ -281,8 +242,6 @@ kpxcObserverHelper.handleObserverAdd = async function(target) {
return; return;
} }
kpxcObserverHelper.handleTransitions(target);
const inputs = kpxcObserverHelper.getInputs(target); const inputs = kpxcObserverHelper.getInputs(target);
if (inputs.length === 0) { if (inputs.length === 0) {
return; return;
@ -300,7 +259,7 @@ kpxcObserverHelper.handleObserverAdd = async function(target) {
kpxc.prepareCredentials(); kpxc.prepareCredentials();
} }
kpxcIcons.deleteAllHiddenIcons(); kpxcIcons.deleteHiddenIcons();
}; };
// Removes monitored elements // Removes monitored elements
@ -314,7 +273,7 @@ kpxcObserverHelper.handleObserverRemove = function(target) {
return; return;
} }
kpxcIcons.deleteAllHiddenIcons(); kpxcIcons.deleteHiddenIcons();
}; };
// Handles CSS transitionend event // Handles CSS transitionend event
@ -346,7 +305,6 @@ kpxcObserverHelper.ignoredNode = function(target) {
if (!target if (!target
|| kpxcObserverHelper.ignoredNodeTypes.some(e => e === target.nodeType) || kpxcObserverHelper.ignoredNodeTypes.some(e => e === target.nodeType)
|| kpxcObserverHelper.ignoredNodeNames.some(e => e === target.nodeName) || kpxcObserverHelper.ignoredNodeNames.some(e => e === target.nodeName)
|| kpxcObserverHelper.ignoredPartialNodeNames.some(e => target.nodeName?.includes(e))
|| target.nodeName.startsWith('YTMUSIC') || target.nodeName.startsWith('YTMUSIC')
|| target.nodeName.startsWith('YT-')) { || target.nodeName.startsWith('YT-')) {
return true; return true;
@ -363,7 +321,7 @@ const getShadowDOM = function(elem) {
try { try {
return elem.openOrClosedShadowRoot ? elem.openOrClosedShadowRoot : browser.dom.openOrClosedShadowRoot(elem); return elem.openOrClosedShadowRoot ? elem.openOrClosedShadowRoot : browser.dom.openOrClosedShadowRoot(elem);
} catch (_e) { } catch (e) {
return elem.shadowRoot; return elem.shadowRoot;
} }
}; };
@ -372,9 +330,7 @@ const getShadowDOM = function(elem) {
const treeWalkerFilter = function(node) { const treeWalkerFilter = function(node) {
return !node || return !node ||
node?.disabled || node?.disabled ||
(node instanceof Element (typeof node?.getAttribute !== 'undefined' && node?.getLowerCaseAttribute('type') === 'hidden')
&& typeof node?.getAttribute === 'function'
&& node?.getLowerCaseAttribute('type') === 'hidden')
? NodeFilter.FILTER_REJECT ? NodeFilter.FILTER_REJECT
: NodeFilter.FILTER_ACCEPT; : NodeFilter.FILTER_ACCEPT;
}; };

View file

@ -8,14 +8,13 @@ const PASSKEYS_WAIT_FOR_LIFETIMER = 30;
const enablePasskeys = async function() { const enablePasskeys = async function() {
const passkeysLogDebug = function(message, extra) { const passkeysLogDebug = function(message, extra) {
if (kpxcPasskeysUtils.debugLogging) { if (kpxcPasskeysUtils.debugLogging) {
debugLogMessage(message, extra); debugLogMessage(message, extra);
} }
}; };
const passkeys = document.createElement('script'); const passkeys = document.createElement('script');
passkeys.src = chrome.runtime.getURL('content/passkeys.js'); passkeys.src = chrome.runtime.getURL('content/passkeys.js');
document.documentElement.appendChild(passkeys); document.documentElement.appendChild(passkeys);
passkeys.remove();
const startTimer = function(timeout) { const startTimer = function(timeout) {
return setTimeout(() => { return setTimeout(() => {
@ -63,14 +62,6 @@ const enablePasskeys = async function() {
} }
}; };
const isSameOriginWithAncestors = function () {
try {
return window.origin === window.top.origin;
} catch (_err) {
return false;
}
};
document.addEventListener('kpxc-passkeys-request', async (ev) => { document.addEventListener('kpxc-passkeys-request', async (ev) => {
if (!window.isSecureContext) { if (!window.isSecureContext) {
kpxcUI.createNotification('error', tr('errorMessagePasskeysContextIsNotSecure')); kpxcUI.createNotification('error', tr('errorMessagePasskeysContextIsNotSecure'));
@ -80,14 +71,14 @@ const enablePasskeys = async function() {
if (ev.detail.action === 'passkeys_create') { if (ev.detail.action === 'passkeys_create') {
const publicKey = kpxcPasskeysUtils.buildCredentialCreationOptions( const publicKey = kpxcPasskeysUtils.buildCredentialCreationOptions(
ev.detail.publicKey, ev.detail.publicKey,
isSameOriginWithAncestors(), ev.detail.sameOriginWithAncestors,
); );
passkeysLogDebug('Passkey request', publicKey); passkeysLogDebug('Passkey request', publicKey);
await sendResponse('passkeys_register', publicKey); await sendResponse('passkeys_register', publicKey);
} else if (ev.detail.action === 'passkeys_get') { } else if (ev.detail.action === 'passkeys_get') {
const publicKey = kpxcPasskeysUtils.buildCredentialRequestOptions( const publicKey = kpxcPasskeysUtils.buildCredentialRequestOptions(
ev.detail.publicKey, ev.detail.publicKey,
isSameOriginWithAncestors(), ev.detail.sameOriginWithAncestors,
); );
passkeysLogDebug('Passkey request', publicKey); passkeysLogDebug('Passkey request', publicKey);
await sendResponse('passkeys_get', publicKey); await sendResponse('passkeys_get', publicKey);
@ -108,7 +99,7 @@ const initContent = async () => {
return; return;
} }
if (await chrome.runtime.sendMessage({ action: 'is_site_ignored', args: [ window.self.location.href, true ] })) { if (await chrome.runtime.sendMessage({ action: 'is_site_ignored', args: window.self.location.href })) {
console.log('This site is ignored in Site Preferences.'); console.log('This site is ignored in Site Preferences.');
return; return;
} }

View file

@ -26,58 +26,13 @@
return kpxcStringToArrayBuffer(window.atob(str?.replaceAll('-', '+').replaceAll('_', '/'))); return kpxcStringToArrayBuffer(window.atob(str?.replaceAll('-', '+').replaceAll('_', '/')));
}; };
// From ArrayBuffer to URL encoded base64 string
const kpxcArrayBufferToBase64 = function(buf) {
const str = [ ...new Uint8Array(buf) ].map(c => String.fromCharCode(c)).join('');
return window.btoa(str).replaceAll('+', '-').replaceAll('/', '_').replaceAll('=', '');
};
// Returns the PublicKeyCredential as JSON
// See: https://w3c.github.io/webauthn/#dom-publickeycredential-tojson
const kpxcPublicKeyCredentialJson = function (credential, publicKey) {
const clientExtensionResults = credential.getClientExtensionResults();
const type = credential.type;
const authenticatorAttachment = credential.authenticatorAttachment;
let response;
if (credential.response instanceof AuthenticatorAttestationResponse) {
const responsePublicKey = credential.response.getPublicKey();
response = {
clientDataJSON: publicKey.response.clientDataJSON,
authenticatorData: publicKey.response.authenticatorData,
transports: credential.response.getTransports(),
publicKey: responsePublicKey ? kpxcArrayBufferToBase64(responsePublicKey) : null,
publicKeyAlgorithm: credential.response.getPublicKeyAlgorithm(),
attestationObject: publicKey.response.attestationObject,
};
}
if (credential.response instanceof AuthenticatorAssertionResponse) {
response = {
clientDataJSON: publicKey.response.clientDataJSON,
authenticatorData: publicKey.response.authenticatorData,
signature: publicKey.response.signature,
userHandle: publicKey.response?.userHandle || undefined,
};
}
return {
id: publicKey.id,
rawId: publicKey.id,
response,
authenticatorAttachment,
clientExtensionResults,
type,
};
};
// Wraps response to AuthenticatorAttestationResponse object // Wraps response to AuthenticatorAttestationResponse object
const createAttestationResponse = function(publicKey) { const createAttestationResponse = function(publicKey) {
const response = { const response = {
attestationObject: kpxcBase64ToArrayBuffer(publicKey.response.attestationObject), attestationObject: kpxcBase64ToArrayBuffer(publicKey.response.attestationObject),
clientDataJSON: kpxcBase64ToArrayBuffer(publicKey.response.clientDataJSON), clientDataJSON: kpxcBase64ToArrayBuffer(publicKey.response.clientDataJSON),
getAuthenticatorData: () => kpxcBase64ToArrayBuffer(publicKey.response?.authenticatorData), getAuthenticatorData: () => kpxcBase64ToArrayBuffer(publicKey.response?.authenticatorData),
getPublicKey: () => publicKey.response?.publicKey ? publicKey.response?.publicKey : null, getPublicKey: () => null,
getPublicKeyAlgorithm: () => publicKey.response?.publicKeyAlgorithm, getPublicKeyAlgorithm: () => publicKey.response?.publicKeyAlgorithm,
getTransports: () => [ 'internal' ] getTransports: () => [ 'internal' ]
}; };
@ -108,8 +63,7 @@
response: authenticatorResponse, response: authenticatorResponse,
type: publicKey.type, type: publicKey.type,
clientExtensionResults: () => publicKey?.response?.clientExtensionResults || {}, clientExtensionResults: () => publicKey?.response?.clientExtensionResults || {},
getClientExtensionResults: () => publicKey?.response?.clientExtensionResults || {}, getClientExtensionResults: () => publicKey?.response?.clientExtensionResults || {}
toJSON: () => kpxcPublicKeyCredentialJson(publicKeyCredential, publicKey)
}; };
return Object.setPrototypeOf(publicKeyCredential, PublicKeyCredential.prototype); return Object.setPrototypeOf(publicKeyCredential, PublicKeyCredential.prototype);
@ -137,6 +91,14 @@
}); });
}; };
const isSameOriginWithAncestors = function() {
try {
return window.self.origin === window.top.origin;
} catch (err) {
return false;
}
};
// Throws errors to a correct exceptions // Throws errors to a correct exceptions
const throwError = function(errorCode, errorMessage) { const throwError = function(errorCode, errorMessage) {
if ((!errorCode && !errorMessage) || errorCode === PASSKEYS_REQUEST_CANCELED) { if ((!errorCode && !errorMessage) || errorCode === PASSKEYS_REQUEST_CANCELED) {
@ -185,9 +147,11 @@
return null; return null;
} }
const sameOriginWithAncestors = isSameOriginWithAncestors();
const response = await postMessageToExtension({ const response = await postMessageToExtension({
action: 'passkeys_create', action: 'passkeys_create',
publicKey: options.publicKey, publicKey: options.publicKey,
sameOriginWithAncestors: sameOriginWithAncestors,
}); });
if (!response.publicKey) { if (!response.publicKey) {
@ -208,9 +172,11 @@
return originalCredentials.get(options); return originalCredentials.get(options);
} }
const sameOriginWithAncestors = isSameOriginWithAncestors();
const response = await postMessageToExtension({ const response = await postMessageToExtension({
action: 'passkeys_get', action: 'passkeys_get',
publicKey: options.publicKey, publicKey: options.publicKey,
sameOriginWithAncestors: sameOriginWithAncestors,
}); });
if (!response.publicKey) { if (!response.publicKey) {
@ -235,14 +201,12 @@
// select a software authenticator. This could be removed in the future. // select a software authenticator. This could be removed in the future.
try { try {
Object.defineProperty(navigator, 'credentials', { value: passkeysCredentials }); Object.defineProperty(navigator, 'credentials', { value: passkeysCredentials });
if (window.PublicKeyCredential) { Object.defineProperty(window.PublicKeyCredential, 'isConditionalMediationAvailable', {
Object.defineProperty(window.PublicKeyCredential, 'isConditionalMediationAvailable', { value: isConditionalMediationAvailable,
value: isConditionalMediationAvailable, });
}); Object.defineProperty(window.PublicKeyCredential, 'isUserVerifyingPlatformAuthenticatorAvailable', {
Object.defineProperty(window.PublicKeyCredential, 'isUserVerifyingPlatformAuthenticatorAvailable', { value: isUserVerifyingPlatformAuthenticatorAvailable,
value: isUserVerifyingPlatformAuthenticatorAvailable, });
});
}
} catch (err) { } catch (err) {
console.log('Cannot override navigator.credentials: ', err); console.log('Cannot override navigator.credentials: ', err);
} }

View file

@ -11,6 +11,10 @@ kpxcPasswordIcons.switchIcon = function(state) {
kpxcPasswordIcons.icons.forEach(u => u.switchIcon(state)); kpxcPasswordIcons.icons.forEach(u => u.switchIcon(state));
}; };
kpxcPasswordIcons.deleteHiddenIcons = function() {
kpxcUI.deleteHiddenIcons(kpxcPasswordIcons.icons);
};
kpxcPasswordIcons.isValid = function(field) { kpxcPasswordIcons.isValid = function(field) {
if (!field if (!field
|| field.readOnly || field.readOnly
@ -30,7 +34,7 @@ class PasswordIcon extends Icon {
this.nextFieldExists = false; this.nextFieldExists = false;
this.initField(field); this.initField(field);
kpxcIcons.monitorIconPosition(this); kpxcUI.monitorIconPosition(this);
} }
} }
@ -45,22 +49,19 @@ PasswordIcon.prototype.initField = function(field) {
}; };
PasswordIcon.prototype.createIcon = function(field) { PasswordIcon.prototype.createIcon = function(field) {
const className = getIconClass('key'); const className = (isFirefox() ? 'key-moz' : 'key');
const size = this.calculateIconSize(field); const size = (field.offsetHeight > 28) ? 24 : 16;
const offset = kpxcUI.calculateIconOffset(field, size);
const icon = kpxcUI.createElement('div', 'kpxc kpxc-pwgen-icon ' + className, const icon = kpxcUI.createElement('div', 'kpxc kpxc-pwgen-icon ' + className,
{ {
'title': tr('passwordGeneratorGenerateText'), 'title': tr('passwordGeneratorGenerateText'),
'size': size, 'size': size,
'kpxc-pwgen-field-id': field.getAttribute('data-kpxc-id'), 'offset': offset,
'popover': 'manual' 'kpxc-pwgen-field-id': field.getAttribute('data-kpxc-id') // Needed?
}); });
if (kpxcFields.popoverSupported) { icon.style.zIndex = '10000000';
icon.style.margin = 0;
} else {
icon.style.zIndex = '10000000';
}
icon.style.width = Pixels(size); icon.style.width = Pixels(size);
icon.style.height = Pixels(size); icon.style.height = Pixels(size);
@ -74,11 +75,7 @@ PasswordIcon.prototype.createIcon = function(field) {
} }
if (e.shiftKey) { if (e.shiftKey) {
if (kpxcFields.popoverSupported) { icon.style.display = 'none';
icon.hidePopover();
} else {
icon.style.display = 'none';
}
return; return;
} }
@ -89,12 +86,9 @@ PasswordIcon.prototype.createIcon = function(field) {
icon.addEventListener('mousedown', ev => ev.stopPropagation()); icon.addEventListener('mousedown', ev => ev.stopPropagation());
icon.addEventListener('mouseup', ev => ev.stopPropagation()); icon.addEventListener('mouseup', ev => ev.stopPropagation());
kpxcIcons.setIconPosition(icon, field, this.rtl); kpxcUI.setIconPosition(icon, field, this.rtl);
this.icon = icon; this.icon = icon;
this.createWrapper('css/pwgen.css'); this.createWrapper('css/pwgen.css');
if (kpxcFields.popoverSupported) {
icon.showPopover();
}
}; };
@ -157,7 +151,13 @@ kpxcPasswordGenerator.fill = function(elem, password) {
const isPasswordGeneratorSupported = async function() { const isPasswordGeneratorSupported = async function() {
const response = await browser.runtime.sendMessage({ const response = await browser.runtime.sendMessage({
action: 'get_features_list' action: 'get_keepassxc_versions'
}); });
return response?.passwordGenerator;
const result = await browser.runtime.sendMessage({
action: 'compare_versions',
args: [ [ '2.7.0' ], response.current ]
});
return result['2.7.0'] || false;
}; };

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
const ignoreRegex = /(bank|coupon|post(al)?|user|zip|promo).*code|(en|de)code(d|r)*|comment|author|error/i; const ignoreRegex = /(bank|coupon|postal|user|zip).*code|(en|de)code(d|r)*|comment|author|error/i;
const ignoredTypes = [ 'email', 'password', 'username' ]; const ignoredTypes = [ 'email', 'password', 'username' ];
const allowedInputTypes = [ 'number', 'password', 'tel', 'text' ]; const allowedInputTypes = [ 'number', 'password', 'tel', 'text' ];
@ -13,14 +13,12 @@ const acceptedOTPFields = [
'idvpin', 'idvpin',
'mfa', 'mfa',
'one_time_password', 'one_time_password',
'otc-confirmation-input',
'otp', 'otp',
'token', 'token',
'twofa', 'twofa',
'two-factor', 'two-factor',
'twofactor', 'twofactor',
'verification_pin', 'verification_pin'
'mfaCode'
]; ];
const acceptedParents = [ const acceptedParents = [
@ -38,6 +36,10 @@ kpxcTOTPIcons.switchIcon = function(state, uuid) {
kpxcTOTPIcons.icons.forEach(u => u.switchIcon(state, uuid)); kpxcTOTPIcons.icons.forEach(u => u.switchIcon(state, uuid));
}; };
kpxcTOTPIcons.deleteHiddenIcons = function() {
kpxcUI.deleteHiddenIcons(kpxcTOTPIcons.icons);
};
kpxcTOTPIcons.autoCompleteIsOneTimeCode = function(field) { kpxcTOTPIcons.autoCompleteIsOneTimeCode = function(field) {
if (!field) { if (!field) {
return false; return false;
@ -107,7 +109,7 @@ class TOTPFieldIcon extends Icon {
super(field, databaseState, segmented); super(field, databaseState, segmented);
this.initField(field, segmented); this.initField(field, segmented);
kpxcIcons.monitorIconPosition(this); kpxcUI.monitorIconPosition(this);
} }
} }
@ -137,21 +139,19 @@ TOTPFieldIcon.prototype.initField = async function(field, segmented) {
}; };
TOTPFieldIcon.prototype.createIcon = function(field, segmented = false) { TOTPFieldIcon.prototype.createIcon = function(field, segmented = false) {
const className = getIconClass('kpxc-totp-icon'); const className = (isFirefox() ? 'moz' : 'default');
const size = this.calculateIconSize(field);
const icon = kpxcUI.createElement('div', 'kpxc ' + className, // Size the icon dynamically, but not greater than 24 or smaller than 14
const size = Math.max(Math.min(24, field.offsetHeight - 4), 14);
const offset = kpxcUI.calculateIconOffset(field, size);
const icon = kpxcUI.createElement('div', 'kpxc kpxc-totp-icon ' + className,
{ {
'title': tr('totpFieldText'), 'title': tr('totpFieldText'),
'size': size, 'size': size,
'popover': 'manual' 'offset': offset
}); });
icon.style.zIndex = '10000000';
if (kpxcFields.popoverSupported) {
icon.style.margin = 0;
} else {
icon.style.zIndex = '10000000';
}
icon.style.width = Pixels(size); icon.style.width = Pixels(size);
icon.style.height = Pixels(size); icon.style.height = Pixels(size);
@ -167,11 +167,7 @@ TOTPFieldIcon.prototype.createIcon = function(field, segmented = false) {
} }
if (e.shiftKey) { if (e.shiftKey) {
if (kpxcFields.popoverSupported) { icon.style.display = 'none';
icon.hidePopover();
} else {
icon.style.display = 'none';
}
return; return;
} }
@ -183,10 +179,7 @@ TOTPFieldIcon.prototype.createIcon = function(field, segmented = false) {
icon.addEventListener('mousedown', ev => ev.stopPropagation()); icon.addEventListener('mousedown', ev => ev.stopPropagation());
icon.addEventListener('mouseup', ev => ev.stopPropagation()); icon.addEventListener('mouseup', ev => ev.stopPropagation());
kpxcIcons.setIconPosition(icon, field, this.rtl, segmented); kpxcUI.setIconPosition(icon, field, this.rtl, segmented);
this.icon = icon; this.icon = icon;
this.createWrapper('css/totp.css'); this.createWrapper('css/totp.css');
if (kpxcFields.popoverSupported) {
icon.showPopover();
}
}; };

View file

@ -13,14 +13,6 @@ const ORANGE_BUTTON = 'kpxc-button kpxc-orange-button';
const RED_BUTTON = 'kpxc-button kpxc-red-button'; const RED_BUTTON = 'kpxc-button kpxc-red-button';
const GRAY_BUTTON_CLASS = 'kpxc-gray-button'; const GRAY_BUTTON_CLASS = 'kpxc-gray-button';
const ALLOWED_OBSERVER_NODETYPES = [
Node.ELEMENT_NODE,
Node.DOCUMENT_NODE,
Node.DOCUMENT_FRAGMENT_NODE
];
const OBSERVER_OPTIONS = { attributes: true, attributeFilter: [ 'style' ] };
const DatabaseState = { const DatabaseState = {
DISCONNECTED: 0, DISCONNECTED: 0,
LOCKED: 1, LOCKED: 1,
@ -35,15 +27,73 @@ const $ = function(elem) {
return document.querySelector(elem); return document.querySelector(elem);
}; };
// Returns a string with 'px' for CSS styles
const Pixels = function(value) {
return String(value) + 'px';
};
// Basic icon class
class Icon {
constructor(field, databaseState = DatabaseState.DISCONNECTED, segmented = false) {
this.databaseState = databaseState;
this.icon = null;
this.inputField = null;
this.rtl = kpxcUI.isRTL(field);
this.segmented = segmented;
try {
this.observer = new IntersectionObserver((entries) => {
kpxcUI.updateFromIntersectionObserver(this, entries);
});
} catch (err) {
logError(err);
}
}
// Creates a wrapper div that has the icon in Shadow DOM
createWrapper(styleSheetFilename) {
const styleSheet = createStylesheet(styleSheetFilename);
const wrapper = document.createElement('div');
wrapper.style.all = 'unset';
wrapper.style.display = 'none';
// Make sure the wrapper is positioned correctly without CSS styles affecting to it
wrapper.style.position = 'absolute';
wrapper.style.top = Pixels(0);
wrapper.style.left = Pixels(0);
// Waits for stylesheet to load before displaying the element
styleSheet.addEventListener('load', () => wrapper.style.display = 'block');
this.shadowRoot = wrapper.attachShadow({ mode: 'closed' });
this.shadowRoot.append(styleSheet);
this.shadowRoot.append(this.icon);
document.body.append(wrapper);
}
switchIcon(state, uuid) {
if (!this.icon) {
return;
}
if (state === DatabaseState.UNLOCKED) {
this.icon.style.filter = kpxc.credentials.length === 0 && !uuid ? 'saturate(0%)' : 'saturate(100%)';
} else {
this.icon.style.filter = 'saturate(0%)';
}
}
removeIcon() {
this.shadowRoot.removeChild(this.icon);
document.body.removeChild(this.shadowRoot.host);
}
}
const kpxcUI = {}; const kpxcUI = {};
kpxcUI.mouseDown = false; kpxcUI.mouseDown = false;
if (document.body) { if (document.body) {
const bodyRect = document.body.getBoundingClientRect(); kpxcUI.bodyRect = document.body.getBoundingClientRect();
kpxcUI.bodyRect = {
left: bodyRect.left + window.pageXOffset,
top: bodyRect.top + window.pageYOffset
};
kpxcUI.bodyStyle = getComputedStyle(document.body); kpxcUI.bodyStyle = getComputedStyle(document.body);
} }
@ -71,6 +121,63 @@ kpxcUI.createElement = function(type, classes, attributes, textContent) {
return element; return element;
}; };
kpxcUI.monitorIconPosition = function(iconClass) {
// Handle icon position on resize
window.addEventListener('resize', function(e) {
kpxcUI.updateIconPosition(iconClass);
});
// Handle icon position on scroll
window.addEventListener('scroll', function(e) {
kpxcUI.updateIconPosition(iconClass);
});
window.addEventListener('transitionend', function(e) {
if (matchesWithNodeName(e.target, 'INPUT') || matchesWithNodeName(e.target, 'TEXTAREA')) {
kpxcUI.updateIconPosition(iconClass);
}
});
};
kpxcUI.updateIconPosition = function(iconClass) {
if (iconClass.inputField && iconClass.icon) {
kpxcUI.setIconPosition(iconClass.icon, iconClass.inputField, iconClass.rtl, iconClass.segmented);
}
};
kpxcUI.calculateIconOffset = function(field, size) {
const offset = Math.floor((field.offsetHeight / 2) - (size / 2) - 1);
return (offset < 0) ? 0 : offset;
};
kpxcUI.setIconPosition = function(icon, field, rtl = false, segmented = false) {
const rect = field.getBoundingClientRect();
const size = Number(icon.getAttribute('size'));
const offset = kpxcUI.calculateIconOffset(field, size);
const zoom = kpxcUI.bodyStyle.zoom || 1;
let left = kpxcUI.getRelativeLeftPosition(rect) / zoom;
let top = kpxcUI.getRelativeTopPosition(rect) / zoom;
// Add more space for the icon to show it at the right side of the field if TOTP fields are segmented
if (segmented) {
left += size + 10;
}
// Adjusts the icon offset for certain sites
const iconOffset = kpxcSites.iconOffset(left, top, size, field?.getLowerCaseAttribute('type'));
if (iconOffset) {
left = iconOffset[0];
top = iconOffset[1];
}
const scrollTop = kpxcUI.getScrollTop() / zoom;
const scrollLeft = kpxcUI.getScrollLeft() / zoom;
icon.style.top = Pixels(top + scrollTop + offset + 1);
icon.style.left = rtl
? Pixels(left + scrollLeft + offset)
: Pixels(left + scrollLeft + field.offsetWidth - size - offset);
};
kpxcUI.getScrollTop = function() { kpxcUI.getScrollTop = function() {
return document.defaultView?.scrollY ?? document.scrollingElement?.scrollTop ?? 0; return document.defaultView?.scrollY ?? document.scrollingElement?.scrollTop ?? 0;
}; };
@ -87,6 +194,32 @@ kpxcUI.getRelativeTopPosition = function(rect) {
return kpxcUI.bodyStyle.position.toLowerCase() === 'relative' ? rect.top - kpxcUI.bodyRect.top : rect.top; return kpxcUI.bodyStyle.position.toLowerCase() === 'relative' ? rect.top - kpxcUI.bodyRect.top : rect.top;
}; };
kpxcUI.deleteHiddenIcons = function(iconList) {
const deletedIcons = [];
for (const icon of iconList) {
if (icon.inputField && !kpxcFields.isVisible(icon.inputField)) {
const index = iconList.indexOf(icon);
icon.removeIcon();
iconList.splice(index, 1);
deletedIcons.push(icon.inputField);
// Delete the input field from detected fields so the icon can be detected again
const inputFieldIndex = kpxc.inputs.indexOf(icon.inputField);
if (inputFieldIndex >= 0) {
kpxc.inputs.splice(inputFieldIndex, 1);
}
}
}
// Remove the same icons from kpxcIcons.icons array
for (const input of deletedIcons) {
const index = kpxcIcons.icons.findIndex(e => e.field === input);
if (index >= 0) {
kpxcIcons.icons.splice(index, 1);
}
}
};
kpxcUI.isRTL = function(field) { kpxcUI.isRTL = function(field) {
if (!field) { if (!field) {
return false; return false;
@ -157,29 +290,48 @@ kpxcUI.makeBannerDraggable = function(banner) {
}); });
}; };
/**
* Detects if the input field appears or disappears -> show/hide the icon
* - boundingClientRect with slightly (< -10) negative values -> hidden
* - intersectionRatio === 0 -> hidden
* - isIntersecting === false -> hidden
* - intersectionRatio > 0 -> shown
* - isIntersecting === true -> shown
*/
kpxcUI.updateFromIntersectionObserver = function(iconClass, entries) {
for (const entry of entries) {
const rect = DOMRectToArray(entry.boundingClientRect);
if ((entry.intersectionRatio === 0 && !entry.isIntersecting) || (rect.some(x => x < -10))) {
iconClass.icon.style.display = 'none';
} else if (entry.intersectionRatio > 0 && entry.isIntersecting) {
iconClass.icon.style.display = 'block';
// Wait for possible DOM animations
setTimeout(() => {
kpxcUI.setIconPosition(iconClass.icon, entry.target, iconClass.rtl, iconClass.segmented);
}, 400);
}
}
};
/** /**
* Creates a self-disappearing notification banner to DOM * Creates a self-disappearing notification banner to DOM
* @param {string} type Notification type: (success, info, warning, error) * @param {string} type Notification type: (success, info, warning, error)
* @param {string} message The message shown * @param {string} message The message shown
*/ */
kpxcUI.createNotification = async function(type, message) { kpxcUI.createNotification = function(type, message) {
if (!kpxc.settings.showNotifications || !type || !message) { if (!kpxc.settings.showNotifications || !type || !message) {
return; return;
} }
// Send the notification to top window from iframe
if (window.self !== window.top) {
await sendMessage('frame_message', [ 'notification_from_frame', type, message ]);
return;
}
// Removes notification from the body element // Removes notification from the body element
const removeNotification = function() { const removeNotification = function() {
// Catch cross-domain exception // Catch cross-domain exception
let parentBody; let parentBody;
try { try {
parentBody = window.parent.document.body; parentBody = window.parent.document.body;
} catch(_e) { } catch(e) {
parentBody = window.document.body; parentBody = window.document.body;
} }
@ -201,7 +353,7 @@ kpxcUI.createNotification = async function(type, message) {
const notification = kpxcUI.createElement('div', 'kpxc-notification kpxc-notification-' + type, {}); const notification = kpxcUI.createElement('div', 'kpxc-notification kpxc-notification-' + type, {});
type = type.charAt(0).toUpperCase() + type.slice(1) + '!'; type = type.charAt(0).toUpperCase() + type.slice(1) + '!';
const className = getIconClass('kpxc-banner-icon'); const className = (isFirefox() ? 'kpxc-banner-icon-moz' : 'kpxc-banner-icon');
const icon = kpxcUI.createElement('span', className, { 'alt': 'logo' }); const icon = kpxcUI.createElement('span', className, { 'alt': 'logo' });
const label = kpxcUI.createElement('span', 'kpxc-label', {}, type); const label = kpxcUI.createElement('span', 'kpxc-label', {}, type);
const msg = kpxcUI.createElement('span', '', {}, message); const msg = kpxcUI.createElement('span', '', {}, message);
@ -242,39 +394,8 @@ kpxcUI.createButton = function(color, textContent, callback) {
return button; return button;
}; };
// Observe and prevent style changes to wrapper div elements const DOMRectToArray = function(domRect) {
kpxcUI.createWrapperObserver = function() { return [ domRect.bottom, domRect.height, domRect.left, domRect.right, domRect.top, domRect.width, domRect.x, domRect.y ];
kpxcUI.wrapperObserver = new MutationObserver(function(mutations, obs) {
for (const mut of mutations) {
if (mut?.target && mut.target.style?.cssText !== 'all: unset;') {
mut.target.removeAttribute('style');
mut.target.style.all = 'unset';
}
}
});
};
kpxcUI.observeWrapper = function(elem) {
kpxcUI.wrapperObserver?.observe(elem, OBSERVER_OPTIONS);
};
// Observer <html> and <body> style changes
kpxcUI.createPageObserver = function() {
kpxcUI.pageObserver = new MutationObserver(function(mutations, obs) {
for (const mut of mutations) {
const currentStyle = getComputedStyle(mut?.target);
if (currentStyle.opacity && currentStyle.opacity < MIN_OPACITY) {
kpxc.clearAllFromPage();
}
}
});
if (document?.documentElement && ALLOWED_OBSERVER_NODETYPES.includes(document.documentElement.nodeType)) {
kpxcUI.pageObserver.observe(document.documentElement, OBSERVER_OPTIONS);
}
if (document?.body && ALLOWED_OBSERVER_NODETYPES.includes(document.body.nodeType)) {
kpxcUI.pageObserver.observe(document.body, OBSERVER_OPTIONS);
}
}; };
const initColorTheme = function(elem) { const initColorTheme = function(elem) {
@ -302,11 +423,6 @@ const logDebug = function(message, extra) {
} }
}; };
const initObservers = function() {
kpxcUI.createWrapperObserver();
kpxcUI.createPageObserver();
};
document.addEventListener('mousedown', function(e) { document.addEventListener('mousedown', function(e) {
if (!e.isTrusted) { if (!e.isTrusted) {
return; return;
@ -323,12 +439,6 @@ document.addEventListener('mouseup', function(e) {
kpxcUI.mouseDown = false; kpxcUI.mouseDown = false;
}); });
if (document.readyState === 'complete' || (document.readyState !== 'loading' && !document.documentElement.doScroll)) {
initObservers();
} else {
document.addEventListener('DOMContentLoaded', initObservers);
}
HTMLDivElement.prototype.appendMultiple = function(...args) { HTMLDivElement.prototype.appendMultiple = function(...args) {
for (const a of args) { for (const a of args) {
this.append(a); this.append(a);

View file

@ -12,6 +12,10 @@ kpxcUsernameIcons.switchIcon = function(state) {
kpxcUsernameIcons.icons.forEach(u => u.switchIcon(state)); kpxcUsernameIcons.icons.forEach(u => u.switchIcon(state));
}; };
kpxcUsernameIcons.deleteHiddenIcons = function() {
kpxcUI.deleteHiddenIcons(kpxcUsernameIcons.icons);
};
kpxcUsernameIcons.isValid = function(field) { kpxcUsernameIcons.isValid = function(field) {
if (!field if (!field
|| field.offsetWidth < MIN_INPUT_FIELD_OFFSET_WIDTH || field.offsetWidth < MIN_INPUT_FIELD_OFFSET_WIDTH
@ -30,7 +34,7 @@ class UsernameFieldIcon extends Icon {
super(field, databaseState); super(field, databaseState);
this.initField(field); this.initField(field);
kpxcIcons.monitorIconPosition(this); kpxcUI.monitorIconPosition(this);
} }
switchIcon(state) { switchIcon(state) {
@ -64,7 +68,9 @@ UsernameFieldIcon.prototype.initField = function(field) {
UsernameFieldIcon.prototype.createIcon = function(field) { UsernameFieldIcon.prototype.createIcon = function(field) {
const className = getIconClassName(this.databaseState); const className = getIconClassName(this.databaseState);
const size = this.calculateIconSize(field);
// Size the icon dynamically, but not greater than 24 or smaller than 14
const size = Math.max(Math.min(24, field.offsetHeight - 4), 14);
// Don't create the icon if the input field is too small // Don't create the icon if the input field is too small
if (field.offsetWidth < (size * 1.5) || field.offsetHeight < size) { if (field.offsetWidth < (size * 1.5) || field.offsetHeight < size) {
@ -72,19 +78,16 @@ UsernameFieldIcon.prototype.createIcon = function(field) {
return; return;
} }
const offset = kpxcUI.calculateIconOffset(field, size);
const icon = kpxcUI.createElement('div', 'kpxc kpxc-username-icon ' + className, const icon = kpxcUI.createElement('div', 'kpxc kpxc-username-icon ' + className,
{ {
'title': getIconText(this.databaseState), 'title': getIconText(this.databaseState),
'size': size, 'size': size,
'kpxc-pwgen-field-id': field.getAttribute('data-kpxc-id'), 'offset': offset,
'popover': 'manual' 'kpxc-pwgen-field-id': field.getAttribute('data-kpxc-id')
}); });
icon.style.zIndex = '10000000';
if (kpxcFields.popoverSupported) {
icon.style.margin = 0;
} else {
icon.style.zIndex = '10000000';
}
icon.style.width = Pixels(size); icon.style.width = Pixels(size);
icon.style.height = Pixels(size); icon.style.height = Pixels(size);
@ -94,11 +97,7 @@ UsernameFieldIcon.prototype.createIcon = function(field) {
} }
if (e.shiftKey) { if (e.shiftKey) {
if (kpxcFields.popoverSupported) { icon.style.display = 'none';
icon.hidePopover();
} else {
icon.style.display = 'none';
}
return; return;
} }
@ -109,12 +108,9 @@ UsernameFieldIcon.prototype.createIcon = function(field) {
icon.addEventListener('mousedown', ev => ev.stopPropagation()); icon.addEventListener('mousedown', ev => ev.stopPropagation());
icon.addEventListener('mouseup', ev => ev.stopPropagation()); icon.addEventListener('mouseup', ev => ev.stopPropagation());
kpxcIcons.setIconPosition(icon, field, this.rtl); kpxcUI.setIconPosition(icon, field, this.rtl);
this.icon = icon; this.icon = icon;
this.createWrapper('css/username.css'); this.createWrapper('css/username.css');
if (kpxcFields.popoverSupported) {
icon.showPopover();
}
}; };
const iconClicked = async function(field, icon) { const iconClicked = async function(field, icon) {
@ -143,12 +139,12 @@ const iconClicked = async function(field, icon) {
const getIconClassName = function(state = DatabaseState.UNLOCKED) { const getIconClassName = function(state = DatabaseState.UNLOCKED) {
if (state === DatabaseState.LOCKED) { if (state === DatabaseState.LOCKED) {
return getIconClass('lock'); return (isFirefox() ? 'lock-moz' : 'lock');
} else if (state === DatabaseState.DISCONNECTED) { } else if (state === DatabaseState.DISCONNECTED) {
return getIconClass('disconnected'); return (isFirefox() ? 'disconnected-moz' : 'disconnected');
} }
return getIconClass('unlock'); return (isFirefox() ? 'unlock-moz' : 'unlock');
}; };
const getIconText = function(state) { const getIconText = function(state) {

View file

@ -13,7 +13,7 @@ div.kpxc-banner {
margin: 0 auto !important; margin: 0 auto !important;
min-height: 2em !important; min-height: 2em !important;
max-height: 4em !important; max-height: 4em !important;
overflow-x: auto !important; overflow-x: hidden !important;
padding: 4px !important; padding: 4px !important;
position: fixed !important; position: fixed !important;
width: 100% !important; width: 100% !important;
@ -49,10 +49,6 @@ div.kpxc-banner .banner-info > span {
margin: 4px; margin: 4px;
} }
div.kpxc-banner .banner-info-text {
text-wrap: nowrap;
}
div.kpxc-banner div.banner-info, div.banner-buttons { div.kpxc-banner div.banner-info, div.banner-buttons {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
@ -81,14 +77,6 @@ div.kpxc-banner .kpxc-banner-icon-moz {
background-size: contain; background-size: contain;
} }
div.kpxc-banner .kpxc-banner-icon-safari {
width: 24px;
height: 24px;
overflow: hidden;
background: url('safari-web-extension://__MSG_@@extension_id__/icons/keepassxc.svg') right no-repeat;
background-size: contain;
}
div.kpxc-banner .kpxc-help-icon { div.kpxc-banner .kpxc-help-icon {
width: 24px; width: 24px;
height: 24px; height: 24px;
@ -105,14 +93,6 @@ div.kpxc-banner .kpxc-help-icon-moz {
background-size: contain; background-size: contain;
} }
div.kpxc-banner .kpxc-help-icon-safari {
width: 24px;
height: 24px;
overflow: hidden;
background: url('safari-web-extension://__MSG_@@extension_id__/icons/help.svg') right no-repeat;
background-size: contain;
}
.kpxc-separator { .kpxc-separator {
border-left: 1px solid #ccc; border-left: 1px solid #ccc;
height: 100% !important; height: 100% !important;
@ -133,7 +113,6 @@ div.kpxc-banner label {
font-size: 12px !important; font-size: 12px !important;
font-weight: normal !important; font-weight: normal !important;
margin: 4px !important; margin: 4px !important;
text-wrap: nowrap;
} }
div.kpxc-banner-dialog { div.kpxc-banner-dialog {

View file

@ -8,7 +8,6 @@
height: 28px !important; height: 28px !important;
margin: .2em !important; margin: .2em !important;
padding: 1px 7px 2px !important; padding: 1px 7px 2px !important;
text-wrap: nowrap;
} }
.kpxc-white-button { .kpxc-white-button {

View file

@ -4,7 +4,6 @@
--kpxc-autocomplete-menu-border: 1px solid #ddd; --kpxc-autocomplete-menu-border: 1px solid #ddd;
--kpxc-background-color: #fff; --kpxc-background-color: #fff;
--kpxc-box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); --kpxc-box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
--kpxc-box-shadow-strong: 0 20px 25px -5px rgb(0 0 0 / 0.8), 0 8px 10px -6px rgb(0 0 0 / 0.8);
--kpxc-card-background-color: #fff; --kpxc-card-background-color: #fff;
--kpxc-card-border-color: rgba(0, 0, 0, .125); --kpxc-card-border-color: rgba(0, 0, 0, .125);
--kpxc-card-header-color: #fafafa; --kpxc-card-header-color: #fafafa;
@ -30,6 +29,7 @@
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
:root, :root,
:host { :host {
--kpxc-autocomplete-footer-color: #2b2a2a; --kpxc-autocomplete-footer-color: #2b2a2a;
@ -114,3 +114,4 @@
--kpxc-lighter-text-color: rgba(0, 0, 0, 0.8); --kpxc-lighter-text-color: rgba(0, 0, 0, 0.8);
--kpxc-light-text-color: rgba(0, 0, 0, 0.5); --kpxc-light-text-color: rgba(0, 0, 0, 0.5);
} }
}

View file

@ -43,16 +43,6 @@
background-size: contain; background-size: contain;
} }
.kpxc-notification .kpxc-banner-icon-safari {
width: 24px;
height: 24px;
padding: 10px;
margin-right: 4px;
overflow: hidden;
background: url('safari-web-extension://__MSG_@@extension_id__/icons/keepassxc.svg') right no-repeat;
background-size: contain;
}
.kpxc-notification .kpxc-label { .kpxc-notification .kpxc-label {
font-weight: bold; font-weight: bold;
} }

View file

@ -1,7 +1,5 @@
.kpxc-pwgen-icon { .kpxc-pwgen-icon {
border: 0;
cursor: pointer; cursor: pointer;
padding: 0 !important;
position: absolute; position: absolute;
} }
@ -14,8 +12,3 @@
background: url('moz-extension://__MSG_@@extension_id__/icons/key.svg') right no-repeat; background: url('moz-extension://__MSG_@@extension_id__/icons/key.svg') right no-repeat;
background-size: contain; background-size: contain;
} }
.kpxc-pwgen-icon.key-safari {
background: url('safari-web-extension://__MSG_@@extension_id__/icons/key.svg') right no-repeat;
background-size: contain;
}

View file

@ -1,21 +1,14 @@
.kpxc-totp-icon { .kpxc-totp-icon {
border: 0;
cursor: pointer;
padding: 0 !important;
position: absolute; position: absolute;
cursor: pointer;
} }
.kpxc-totp-icon { .kpxc-totp-icon.default {
background: url('chrome-extension://__MSG_@@extension_id__/icons/otp.svg') right no-repeat; background: url('chrome-extension://__MSG_@@extension_id__/icons/otp.svg') right no-repeat;
background-size: contain; background-size: contain;
} }
.kpxc-totp-icon-moz { .kpxc-totp-icon.moz {
background: url('moz-extension://__MSG_@@extension_id__/icons/otp.svg') right no-repeat; background: url('moz-extension://__MSG_@@extension_id__/icons/otp.svg') right no-repeat;
background-size: contain; background-size: contain;
} }
.kpxc-totp-icon.safari {
background: url('safari-web-extension://__MSG_@@extension_id__/icons/otp.svg') right no-repeat;
background-size: contain;
}

View file

@ -1,8 +1,6 @@
.kpxc-username-icon { .kpxc-username-icon {
border: 0;
cursor: pointer;
padding: 0 !important;
position: absolute; position: absolute;
cursor: pointer;
} }
.kpxc-username-icon.disconnected { .kpxc-username-icon.disconnected {
@ -15,11 +13,6 @@
background-size: contain; background-size: contain;
} }
.kpxc-username-icon.disconnected-safari {
background: url('safari-web-extension://__MSG_@@extension_id__/icons/disconnected.svg') right no-repeat;
background-size: contain;
}
.kpxc-username-icon.lock { .kpxc-username-icon.lock {
background: url('chrome-extension://__MSG_@@extension_id__/icons/locked.svg') right no-repeat; background: url('chrome-extension://__MSG_@@extension_id__/icons/locked.svg') right no-repeat;
background-size: contain; background-size: contain;
@ -30,11 +23,6 @@
background-size: contain; background-size: contain;
} }
.kpxc-username-icon.lock-safari {
background: url('safari-web-extension://__MSG_@@extension_id__/icons/locked.svg') right no-repeat;
background-size: contain;
}
.kpxc-username-icon.unlock { .kpxc-username-icon.unlock {
background: url('chrome-extension://__MSG_@@extension_id__/icons/keepassxc.svg') right no-repeat; background: url('chrome-extension://__MSG_@@extension_id__/icons/keepassxc.svg') right no-repeat;
background-size: contain; background-size: contain;
@ -44,8 +32,3 @@
background: url('moz-extension://__MSG_@@extension_id__/icons/keepassxc.svg') right no-repeat; background: url('moz-extension://__MSG_@@extension_id__/icons/keepassxc.svg') right no-repeat;
background-size: contain; background-size: contain;
} }
.kpxc-username-icon.unlock-safari {
background: url('safari-web-extension://__MSG_@@extension_id__/icons/keepassxc.svg') right no-repeat;
background-size: contain;
}

View file

@ -1,9 +1,9 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "KeePassXC-Browser", "name": "KeePassXC-Browser",
"version": "1.10.0.1", "version": "1.9.9.2",
"version_name": "1.10.0.1", "version_name": "1.9.9.2",
"minimum_chrome_version": "124", "minimum_chrome_version": "93",
"description": "__MSG_extensionDescription__", "description": "__MSG_extensionDescription__",
"author": "KeePassXC Team", "author": "KeePassXC Team",
"icons": { "icons": {
@ -53,8 +53,7 @@
"content/fields.js", "content/fields.js",
"content/fill.js", "content/fill.js",
"content/form.js", "content/form.js",
"content/icon.js", "content/icons.js",
"content/icon-handler.js",
"content/keepassxc-browser.js", "content/keepassxc-browser.js",
"content/observer-helper.js", "content/observer-helper.js",
"content/pwgen.js", "content/pwgen.js",
@ -119,15 +118,12 @@
"choose_credential_fields": { "choose_credential_fields": {
"description": "__MSG_popupChooseCredentialsText__" "description": "__MSG_popupChooseCredentialsText__"
}, },
"retrieve_credentials_forced": { "retrive_credentials_forced": {
"description": "__MSG_credentialsRetrieveButton__" "description": "__MSG_popupReopenButton__"
}, },
"request_autotype": { "request_autotype": {
"description": "__MSG_contextMenuRequestGlobalAutoType__" "description": "__MSG_contextMenuRequestGlobalAutoType__"
}, },
"reopen_database": {
"description": "__MSG_popupReopenButton__"
},
"reload_extension": { "reload_extension": {
"description": "__MSG_popupReloadButton__" "description": "__MSG_popupReloadButton__"
} }
@ -170,7 +166,8 @@
"tabs", "tabs",
"webNavigation", "webNavigation",
"webRequest", "webRequest",
"webRequestAuthProvider" "webRequestAuthProvider",
"webRequestBlocking"
], ],
"optional_permissions": [ "optional_permissions": [
"privacy" "privacy"

View file

@ -82,10 +82,6 @@ pre {
white-space: pre-line; white-space: pre-line;
} }
.no-transitions .form-check-input {
transition: none !important;
}
.table > caption { .table > caption {
color: var(--kpxc-text-color); color: var(--kpxc-text-color);
} }
@ -109,6 +105,12 @@ tbody {
color: var(--kpxc-text-color); color: var(--kpxc-text-color);
} }
.table-striped > tbody > tr:nth-of-type(odd) input[type="checkbox"] {
background-color: var(--kpxc-card-background-color) !important;
border-color: var(--kpxc-input-main-border-color) !important;
color: var(--kpxc-text-color) !important;
}
.table-striped > tbody > tr:nth-of-type(odd) .form-check-input:checked { .table-striped > tbody > tr:nth-of-type(odd) .form-check-input:checked {
background-color: var(--kpxc-checkbox-background-color) !important; background-color: var(--kpxc-checkbox-background-color) !important;
} }
@ -134,14 +136,14 @@ table tbody tr.empty:not(:nth-last-child(2)) {
display: none; display: none;
} }
#tab-site-preferences td:nth-of-type(3), #tab-site-preferences td:nth-of-type(2),
#tab-site-preferences td:nth-of-type(3) select { #tab-site-preferences td:nth-of-type(2) select {
width: 200px; width: 200px;
} }
#tab-site-preferences td:nth-of-type(2),
#tab-site-preferences td:nth-of-type(3), #tab-site-preferences td:nth-of-type(3),
#tab-site-preferences td:nth-of-type(4), #tab-site-preferences td:nth-of-type(4),
#tab-site-preferences td:nth-of-type(5),
table td:last-of-type { table td:last-of-type {
width: 1px; width: 1px;
} }
@ -231,26 +233,6 @@ table td:last-of-type {
color: var(--kpxc-text-color); color: var(--kpxc-text-color);
} }
.non-clickable {
pointer-events: none;
}
.settings-dropdown {
box-shadow: var(--kpxc-box-shadow-strong);
overflow: hidden;
position: absolute;
}
.settings-dropdown-body {
background-color: var(--bs-table-bg);
}
.dropdown-divider {
border-top: 1px solid var(--kpxc-table-odd-color);
height: 0.5rem;
margin-top: 0.3rem;
}
.site-preferences-input { .site-preferences-input {
border: 0; border: 0;
border-bottom-right-radius: 4px !important; border-bottom-right-radius: 4px !important;

View file

@ -19,7 +19,7 @@
<script src="options.js"></script> <script src="options.js"></script>
<script src="../common/translate.js" defer></script> <script src="../common/translate.js" defer></script>
</head> </head>
<body class="pt-3 pb-5 no-transitions"> <body class="pt-3 pb-5">
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<nav class="col-md-3 col-lg-2 sidebar"> <nav class="col-md-3 col-lg-2 sidebar">
@ -31,7 +31,7 @@
<ul class="nav flex-column mb-2 text-uppercase"> <ul class="nav flex-column mb-2 text-uppercase">
<li class="active nav-item"> <li class="active nav-item">
<a class="nav-link text-light rounded-sm" href="#general-settings"> <a class="nav-link text-light rounded-sm" href="#general-settings">
<i class="fa fa-cog fa-lg pe-2" aria-hidden="true"></i> <i class="fa fa-ellipsis-h fa-lg pe-2" aria-hidden="true"></i>
<span class="menu-item" data-i18n="optionsMenuGeneral"></span> <span class="menu-item" data-i18n="optionsMenuGeneral"></span>
</a> </a>
</li> </li>
@ -49,7 +49,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-light rounded-sm" href="#site-preferences"> <a class="nav-link text-light rounded-sm" href="#site-preferences">
<i class="fa fa-list-alt fa-lg pe-2" aria-hidden="true"></i> <i class="fa fa-wrench fa-lg pe-2" aria-hidden="true"></i>
<span class="menu-item" data-i18n="optionsMenuSitePreferences"></span> <span class="menu-item" data-i18n="optionsMenuSitePreferences"></span>
</a> </a>
</li> </li>
@ -81,12 +81,6 @@
</div> </div>
<div class="card-body"> <div class="card-body">
<!-- Version warning -->
<div class="alert alert-warning mt-3 col-lg-9" role="alert" id="minimumVersionAlert" style="display: none;">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
<span data-i18n="optionsMinimumKeePassXCVersionRequired" data-i18n-placeholder="2.6.0"></span>
</div>
<!-- Color theme --> <!-- Color theme -->
<div class="form-group col-sm-3 pb-2"> <div class="form-group col-sm-3 pb-2">
<label for="colorTheme" class="form-label" data-i18n="optionsThemeSelectionHeader"></label> <label for="colorTheme" class="form-label" data-i18n="optionsThemeSelectionHeader"></label>
@ -160,7 +154,7 @@
</div> </div>
<!-- Keyboard shortcuts --> <!-- Keyboard shortcuts -->
<div class="card my-4 shadow" id="keyboardShortcuts"> <div class="card my-4 shadow">
<div class="card-header h6 rounded-0"> <div class="card-header h6 rounded-0">
<i class="fa fa-keyboard-o" aria-hidden="true"></i> <i class="fa fa-keyboard-o" aria-hidden="true"></i>
<span data-i18n="optionsKeyboardShortcutsHeader"></span> <span data-i18n="optionsKeyboardShortcutsHeader"></span>
@ -266,7 +260,7 @@
<input class="form-check-input" type="checkbox" name="autoFillSingleEntry" id="autoFillSingleEntry" value="true"> <input class="form-check-input" type="checkbox" name="autoFillSingleEntry" id="autoFillSingleEntry" value="true">
<label class="form-check-label" for="autoFillSingleEntry" data-i18n="optionsCheckboxAutoFillSingleEntry"></label> <label class="form-check-label" for="autoFillSingleEntry" data-i18n="optionsCheckboxAutoFillSingleEntry"></label>
<div class="form-text" data-i18n="optionsAutoFillSingleEntryHelpText"></div> <div class="form-text" data-i18n="optionsAutoFillSingleEntryHelpText"></div>
<div class="alert alert-warning mt-3 col-lg-9" role="alert"> <div class="alert alert-warning mt-3 col-lg-9" role="alert">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
<span data-i18n="optionsAutoFillSingleEntryWarning"></span> <span data-i18n="optionsAutoFillSingleEntryWarning"></span>
@ -284,7 +278,7 @@
</div> </div>
<!-- Autofill HTTP Auth dialogs --> <!-- Autofill HTTP Auth dialogs -->
<div class="form-group pb-1" id="autoFillHttpAuth"> <div class="form-group pb-1">
<div class="form-check form-switch"> <div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="autoFillAndSend" id="autoFillAndSend" value="true"> <input class="form-check-input" type="checkbox" name="autoFillAndSend" id="autoFillAndSend" value="true">
<label class="form-check-label" for="autoFillAndSend" data-i18n="optionsCheckboxAutoFillAndSend"></label> <label class="form-check-label" for="autoFillAndSend" data-i18n="optionsCheckboxAutoFillAndSend"></label>
@ -358,8 +352,8 @@
<!-- Number of allowed redirects --> <!-- Number of allowed redirects -->
<div class="form-group w-50 pb-2"> <div class="form-group w-50 pb-2">
<label id="redirectAllowanceLabel" class="font-weight-normal" for="redirectAllowance" data-i18n="optionsRedirectAllowance" data-i18n-placeholder="3"></label> <label id="redirectAllowanceLabel" class="font-weight-normal" for="redirectAllowance" data-i18n="optionsRedirectAllowance" data-i18n-placeholder="1"></label>
<input type="range" class="form-range" id="redirectAllowance" name="redirectAllowance" min="1" max="11" step="1" value="3"> <input type="range" class="form-range" id="redirectAllowance" name="redirectAllowance" min="1" max="11" step="1" value="1">
<div class="form-text help-text" data-i18n="optionsRedirectAllowanceHelpText"></div> <div class="form-text help-text" data-i18n="optionsRedirectAllowanceHelpText"></div>
</div> </div>
@ -565,10 +559,6 @@
<i class="fa fa-arrow-up" aria-hidden="true"></i> <i class="fa fa-arrow-up" aria-hidden="true"></i>
<span data-i18n="optionsButtonExport"></span> <span data-i18n="optionsButtonExport"></span>
</button> </button>
<button class="btn btn-sm btn-danger ms-2" id="resetSettingsButton" data-i18n="[title]optionsButtonResetSettings">
<i class="fa fa-undo" aria-hidden="true"></i>
<span data-i18n="optionsButtonResetSettings"></span>
</button>
</div> </div>
</div> </div>
</div> </div>
@ -596,30 +586,6 @@
</div> </div>
</div> </div>
</div> </div>
<div id="dialogResetSettings" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="myModalLabel" data-i18n="optionsButtonResetSettings"></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p data-i18n="optionsResetSettingsDialogText"></p>
</div>
<div class="modal-footer">
<button class="btn btn-sm btn-secondary" data-bs-dismiss="modal" aria-hidden="true">
<i class="fa fa-remove" aria-hidden="true"></i>
<span data-i18n="optionsButtonCancel"></span>
</button>
<button class="btn btn-sm yes btn-danger">
<i class="fa fa-check" aria-hidden="true"></i>
<span data-i18n="optionsButtonReset"></span>
</button>
</div>
</div>
</div>
</div>
</div> </div>
<!-- Connected Databases --> <!-- Connected Databases -->
@ -795,14 +761,16 @@
<thead> <thead>
<tr> <tr>
<th scope="col"><span data-i18n="optionsColumnPageURL"></span></th> <th scope="col"><span data-i18n="optionsColumnPageURL"></span></th>
<th scope="col"></th> <th scope="col"><span data-i18n="optionsColumnIgnore"></span></th>
<th scope="col"><span data-i18n="optionsColumnFeatures"></span></th> <th scope="col"><span data-i18n="optionsColumnUsernameOnly"></span></th>
<th scope="col"><span data-i18n="optionsColumnImprovedInputFieldDetection"></span></th>
<th scope="col"><span data-i18n="optionsColumnAllowIframes"></span></th>
<th scope="col"></th> <th scope="col"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr class="empty"> <tr class="empty">
<td colspan="4"><span data-i18n="optionsSitePreferencesNotFound"></span></td> <td colspan="5"><span data-i18n="optionsSitePreferencesNotFound"></span></td>
</tr> </tr>
<tr class="clone d-none"> <tr class="clone d-none">
<td class="text-nowrap"> <td class="text-nowrap">
@ -822,20 +790,17 @@
</button> </button>
</div> </div>
</td> </td>
<td class="text-nowrap"> <td>
<button type="button" class="btn btn-sm btn-primary container-fluid" id="settings-button"> <select class="form-select form-select-sm" name="ignore" data-i18n="[title]optionsSitePreferencesSelect">
<span class="non-clickable" data-i18n="optionsSitePreferencesSettings"></span>
</button>
</td>
<td>
<select class="form-select form-select-sm" id="ignore-select" name="ignore" data-i18n="[title]optionsSitePreferencesSelect">
<option value="ignoreNothing" data-i18n="optionsSelectionNothing"></option> <option value="ignoreNothing" data-i18n="optionsSelectionNothing"></option>
<option value="ignoreNormal" data-i18n="optionsSelectionNormal"></option> <option value="ignoreNormal" data-i18n="optionsSelectionNormal"></option>
<option value="ignoreAutoSubmit" data-i18n="optionsSelectionAutoSubmit"></option> <option value="ignoreAutoSubmit" data-i18n="optionsSelectionAutoSubmit"></option>
<option value="ignorePasskeys" data-i18n="optionsSelectionPasskeys"></option>
<option value="ignoreFull" data-i18n="optionsSelectionFull"></option> <option value="ignoreFull" data-i18n="optionsSelectionFull"></option>
</select> </select>
</td> </td>
<td><input class="form-check-input" type="checkbox" name="usernameOnly" value="false" data-i18n="[title]optionsColumnUsernameOnly"></td>
<td><input class="form-check-input" type="checkbox" name="improvedFieldDetection" value="false" data-i18n="[title]optionsColumnImprovedInputFieldDetection"></td>
<td><input class="form-check-input" type="checkbox" name="allowIframes" value="false" data-i18n="[title]optionsColumnAllowIframes"></td>
<td class="text-nowrap"> <td class="text-nowrap">
<button class="btn btn-sm delete btn-danger" data-i18n="[title]removeSitePreferencesButtonTitle"> <button class="btn btn-sm delete btn-danger" data-i18n="[title]removeSitePreferencesButtonTitle">
<i class="fa fa-remove" aria-hidden="true"></i> <i class="fa fa-remove" aria-hidden="true"></i>
@ -873,32 +838,6 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Settings dropdown -->
<div class="card settings-dropdown" style="display: none;">
<div class="card-body settings-dropdown-body">
<!-- Username only detection -->
<div class="form-check">
<input class="form-check-input" type="checkbox" id="usernameOnly" name="usernameOnly" value="false" data-i18n="[title]optionsColumnUsernameOnly">
<label class="form-check-label" for="usernameOnly" data-i18n="optionsColumnUsernameOnly"></label>
</div>
<!-- Improved input field detection -->
<div class="form-check">
<input class="form-check-input" type="checkbox" id="improvedFieldDetection" name="improvedFieldDetection" value="false" data-i18n="[title]optionsColumnImprovedInputFieldDetection">
<label class="form-check-label" for="improvedFieldDetection" data-i18n="optionsColumnImprovedInputFieldDetection"></label>
</div>
<!-- Allow iFrames -->
<div class="form-check">
<input class="form-check-input" type="checkbox" id="allowIframes" name="allowIframes" value="false" data-i18n="[title]optionsColumnAllowIframes">
<label class="form-check-label" for="allowIframes" data-i18n="optionsColumnAllowIframes"></label>
</div>
<!-- Add new options below -->
<!--<hr class="dropdown-divider">-->
</div>
</div>
</div> </div>
<!-- About --> <!-- About -->

View file

@ -1,8 +1,6 @@
'use strict'; 'use strict';
const options = {}; const options = {};
options.dropdownButton = null;
options.isFirefox = false;
const $ = function(elem) { const $ = function(elem) {
return document.querySelector(elem); return document.querySelector(elem);
@ -208,7 +206,7 @@ options.initGeneralSettings = async function() {
}); });
$('#configureCommands').addEventListener('click', function() { $('#configureCommands').addEventListener('click', function() {
if (options.isFirefox) { if (isFirefox()) {
if (typeof(browser.commands.openShortcutSettings) === 'function') { if (typeof(browser.commands.openShortcutSettings) === 'function') {
browser.commands.openShortcutSettings(); browser.commands.openShortcutSettings();
} else { } else {
@ -287,7 +285,7 @@ options.initGeneralSettings = async function() {
// Verify the import // Verify the import
temporarySettings = contents; temporarySettings = contents;
dialogImportSettingsModal.show(); dialogImportSettingsModal.show();
} catch (_err) { } catch (err) {
console.log('Error loading JSON settings file.'); console.log('Error loading JSON settings file.');
} }
}; };
@ -313,24 +311,6 @@ options.initGeneralSettings = async function() {
} }
}); });
// Reset all settings modal
const dialogResetSettingsModal = new bootstrap.Modal('#dialogResetSettings',
{ keyboard: true, focus: false, backdrop: true });
$('#dialogResetSettings').addEventListener('shown.bs.modal', function(modalEvent) {
modalEvent.currentTarget.querySelector('.modal-footer button.yes').focus();
});
$('#resetSettingsButton').addEventListener('click', function() {
dialogResetSettingsModal.show();
});
$('#dialogResetSettings .modal-footer button.yes').addEventListener('click', function(e) {
dialogResetSettingsModal.hide();
browser.runtime.sendMessage({ action: 'reset_all_settings' });
location.reload();
});
$('#copyVersionToClipboard').addEventListener('click', function () { $('#copyVersionToClipboard').addEventListener('click', function () {
const copyText = document.getElementById('versionInfo').innerText; const copyText = document.getElementById('versionInfo').innerText;
navigator.clipboard.writeText(copyText); navigator.clipboard.writeText(copyText);
@ -366,23 +346,38 @@ options.showKeePassXCVersions = async function(response) {
$('#tab-about span.kpxcVersion').textContent = response.current; $('#tab-about span.kpxcVersion').textContent = response.current;
$('#tab-general-settings button.checkUpdateKeePassXC').disabled = false; $('#tab-general-settings button.checkUpdateKeePassXC').disabled = false;
const featureList = await browser.runtime.sendMessage({ action: 'get_features_list' }); const versionResults = await browser.runtime.sendMessage({
if (featureList?.requiredKeePassXCVersionFound) { action: 'compare_versions',
args: [
[
'2.6.0',
'2.7.0',
'2.7.7',
'2.7.10'
],
response.current
],
});
// Hide/disable certain options with older KeePassXC versions than 2.6.0
if (versionResults['2.6.0']) {
$('#tab-general-settings #versionRequiredAlert').hide(); $('#tab-general-settings #versionRequiredAlert').hide();
} else { } else {
$('#tab-general-settings #showGroupNameInAutocomplete').disabled = true; $('#tab-general-settings #showGroupNameInAutocomplete').disabled = true;
$('#tab-general-settings #minimumVersionAlert').show();
} }
if (!featureList?.downloadFaviconAfterSave) { // Hide certain options with older KeePassXC versions than 2.7.0
if (!versionResults['2.7.0']) {
$('#tab-general-settings #downloadFaviconAfterSaveFormGroup').hide(); $('#tab-general-settings #downloadFaviconAfterSaveFormGroup').hide();
} }
if (!featureList?.passkeys) { // Hide certain options with older KeePassXC versions than 2.7.7
if (!versionResults['2.7.7']) {
$('#tab-general-settings #passkeysOptionsCard').hide(); $('#tab-general-settings #passkeysOptionsCard').hide();
} }
if (!featureList?.passkeysDefaultGroup) { // Hide passkeys default group option with KeePassXC version < 2.7.10
if (!versionResults['2.7.10']) {
$('#tab-general-settings #passkeysDefaultGroup').hide(); $('#tab-general-settings #passkeysDefaultGroup').hide();
} }
}; };
@ -541,43 +536,6 @@ options.initSitePreferences = function() {
modalEvent.currentTarget.querySelector('.modal-footer button.yes').focus(); modalEvent.currentTarget.querySelector('.modal-footer button.yes').focus();
}); });
const settingsButtonClicked = function(e) {
e.preventDefault();
const closestTr = e.target.closest('tr');
const url = closestTr.getAttribute('url');
const sitePreferences = options.settings['sitePreferences']?.find((pref) => pref?.url === url);
const usernameOnly = sitePreferences.usernameOnly;
const improvedFieldDetection = sitePreferences.improvedFieldDetection;
const allowIframes = sitePreferences.allowIframes;
const dropdown = $('.settings-dropdown');
if (dropdown?.style?.display !== 'block'
|| (dropdown?.style?.display === 'block' && e.target !== options.dropdownButton)) {
if (options.dropdownButton) {
options.dropdownButton.classList.remove('active');
// Update number of enabled settings to the old Settings button
const checkboxValues = Array.from(dropdown?.querySelectorAll('input[type=checkbox]')).map(c => c.checked);
updateSettingsButtonText(options.dropdownButton, checkboxValues);
}
// Apply current settings to the dropdown
dropdown.querySelector('#usernameOnly').checked = usernameOnly;
dropdown.querySelector('#improvedFieldDetection').checked = improvedFieldDetection;
dropdown.querySelector('#allowIframes').checked = allowIframes;
dropdown?.show();
updateDropdownPosition(e, dropdown);
options.dropdownButton = e.target;
options.dropdownButton.classList.add('active');
} else {
dropdown?.hide();
options.dropdownButton.classList.remove('active');
updateSettingsButtonText(options.dropdownButton, [ usernameOnly, improvedFieldDetection, allowIframes ]);
options.dropdownButton = null;
}
};
const removeButtonClicked = function(e) { const removeButtonClicked = function(e) {
e.preventDefault(); e.preventDefault();
@ -643,18 +601,18 @@ options.initSitePreferences = function() {
} }
}; };
const checkboxClicked = async function(e) { const checkboxClicked = function() {
const closestTr = options?.dropdownButton?.closest('tr'); const closestTr = this.closest('tr');
const url = closestTr.getAttribute('url'); const url = closestTr.getAttribute('url');
for (const site of options.settings['sitePreferences']) { for (const site of options.settings['sitePreferences']) {
if (site.url === url) { if (site.url === url) {
if (e.target.name === SitePreferences.USERNAME_ONLY) { if (this.name === 'usernameOnly') {
site.usernameOnly = e.target.checked; site.usernameOnly = this.checked;
} else if (e.target.name === SitePreferences.IMPROVED_FIELD_DETECTION) { } else if (this.name === 'improvedFieldDetection') {
site.improvedFieldDetection = e.target.checked; site.improvedFieldDetection = this.checked;
} else if (e.target.name === SitePreferences.ALLOW_IFRAMES) { } else if (this.name === 'allowIframes') {
site.allowIframes = e.target.checked; site.allowIframes = this.checked;
} }
} }
} }
@ -675,11 +633,6 @@ options.initSitePreferences = function() {
options.saveSettings(); options.saveSettings();
}; };
const dropdown = $('.settings-dropdown');
dropdown.querySelector('#usernameOnly').addEventListener('change', checkboxClicked);
dropdown.querySelector('#improvedFieldDetection').addEventListener('change',checkboxClicked);
dropdown.querySelector('#allowIframes').addEventListener('change', checkboxClicked);
const addNewRow = function(rowClone, newIndex, url, ignore, usernameOnly, improvedFieldDetection, allowIframes) { const addNewRow = function(rowClone, newIndex, url, ignore, usernameOnly, improvedFieldDetection, allowIframes) {
const row = rowClone.cloneNode(true); const row = rowClone.cloneNode(true);
row.setAttribute('url', url); row.setAttribute('url', url);
@ -709,25 +662,19 @@ options.initSitePreferences = function() {
saveModifiedUrl(e, row, inputField, editButton, cancelButton, saveButton) saveModifiedUrl(e, row, inputField, editButton, cancelButton, saveButton)
); );
// Page URL
row.children[0].children[0].children[0].value = url; row.children[0].children[0].children[0].value = url;
row.children[0].children[0]?.addEventListener('dblclick', (e) => row.children[0].children[0]?.addEventListener('dblclick', (e) =>
enterEditMode(e, row, inputField, editButton, cancelButton, saveButton) enterEditMode(e, row, inputField, editButton, cancelButton, saveButton)
); );
row.children[1].children[0].value = ignore;
// Settings row.children[1].children[0].addEventListener('change', selectionChanged);
const settings = row.children[1]; row.children[2].children['usernameOnly'].checked = usernameOnly;
updateSettingsButtonText(settings.querySelector('#settings-button'), row.children[2].children['usernameOnly'].addEventListener('change', checkboxClicked);
[ usernameOnly, improvedFieldDetection, allowIframes ]); row.children[3].children['improvedFieldDetection'].checked = improvedFieldDetection;
settings.querySelector('#settings-button').addEventListener('click', (e) => settingsButtonClicked(e)); row.children[3].children['improvedFieldDetection'].addEventListener('change', checkboxClicked);
row.children[4].children['allowIframes'].checked = allowIframes;
// Ignore row.children[4].children['allowIframes'].addEventListener('change', checkboxClicked);
const ignoreSelect = row.children[2]; row.children[5].addEventListener('click', removeButtonClicked);
ignoreSelect.querySelector('#ignore-select').value = ignore;
ignoreSelect.querySelector('#ignore-select').addEventListener('change', selectionChanged);
// Remove button
row.children[3].addEventListener('click', removeButtonClicked);
$('#tab-site-preferences table tbody').append(row); $('#tab-site-preferences table tbody').append(row);
}; };
@ -791,11 +738,11 @@ options.initSitePreferences = function() {
$('#tab-site-preferences table tbody tr.empty').hide(); $('#tab-site-preferences table tbody tr.empty').hide();
options.settings['sitePreferences'].push({ options.settings['sitePreferences'].push({
allowIframes: false,
ignore: IGNORE_NOTHING,
improvedFieldDetection: false,
url: value, url: value,
ignore: IGNORE_NOTHING,
usernameOnly: false, usernameOnly: false,
improvedFieldDetection: false,
allowIframes: false,
}); });
options.saveSettings(); options.saveSettings();
manualUrl.value = ''; manualUrl.value = '';
@ -830,7 +777,7 @@ options.initAbout = function() {
$('#tab-about span.versionCIP').textContent = version; $('#tab-about span.versionCIP').textContent = version;
$('#tab-about span.kpxcbrVersion').textContent = version; $('#tab-about span.kpxcbrVersion').textContent = version;
$('#tab-about span.kpxcbrOS').textContent = platform; $('#tab-about span.kpxcbrOS').textContent = platform;
$('#tab-about span.kpxcbrBrowser').textContent = getBrowserId(navigator.userAgent); $('#tab-about span.kpxcbrBrowser').textContent = getBrowserId();
}; };
options.updateTheme = function() { options.updateTheme = function() {
@ -858,110 +805,24 @@ options.createWarning = function(elem, text) {
}, 5000); }, 5000);
}; };
options.hideUnsupportedFeatures = function() { const getBrowserId = function() {
if (isSafari()) { if (navigator.userAgent.indexOf('Firefox') > -1) {
$('#tab-general-settings div#keyboardShortcuts').hide(); return 'Mozilla Firefox ' + navigator.userAgent.substr(navigator.userAgent.lastIndexOf('/') + 1);
$('#tab-general-settings div#autoFillHttpAuth').hide(); } else if (navigator.userAgent.indexOf('Edg') > -1) {
} let startPos = navigator.userAgent.indexOf('Edg');
}; startPos = navigator.userAgent.indexOf('/', startPos) + 1;
const version = navigator.userAgent.substring(startPos);
const getBrowserId = function(userAgent) { return 'Microsoft Edge ' + version;
const browserQueries = [ } else if (navigator.userAgent.indexOf('Chrome') > -1) {
{ findStr: 'Firefox', name: 'Mozilla Firefox' }, let startPos = navigator.userAgent.indexOf('Chrome');
{ findStr: 'Edg', name: 'Microsoft Edge' }, startPos = navigator.userAgent.indexOf('/', startPos) + 1;
{ findStr: 'OPR', name: 'Opera' }, const version = navigator.userAgent.substring(startPos, navigator.userAgent.indexOf('Safari'));
{ findStr: 'Chrome', name: 'Chrome/Chromium' }, return 'Chrome/Chromium ' + version;
{ findStr: 'Version/', name: 'Safari' }
];
const getVersion = (agent, findStr) => {
const match = agent?.match(new RegExp(`(?:${findStr})\/([\\d.]+)`));
return match ? match[1] : 'Unknown version';
};
for (const query of browserQueries) {
if (userAgent?.indexOf(query.findStr) > -1) {
return `${query.name} ${getVersion(userAgent, query.findStr)}`;
}
} }
return 'Other/Unknown'; return 'Other/Unknown';
}; };
// Update the number of enabled settings to the button text
const updateSettingsButtonText = function(buttonElement, enabledOptions = []) {
const numberOfEnabledOptions = enabledOptions.filter(o => o === true).length;
const buttonText = buttonElement.querySelector('span');
if (numberOfEnabledOptions > 0) {
buttonText.textContent =
`${browser.i18n.getMessage('optionsSitePreferencesSettings')} (${numberOfEnabledOptions})`;
} else {
buttonText.textContent = browser.i18n.getMessage('optionsSitePreferencesSettings');
}
};
// Updates settings dropdown menu position
const updateDropdownPosition = function(e, dropdown) {
if (!dropdown) {
dropdown = $('.settings-dropdown');
}
const settingsButton = e?.target ?? options.dropdownButton;
const rect = settingsButton?.getClientRects()?.[0];
if (!rect) {
return;
}
const zoom = getComputedStyle(document.body).zoom || 1;
const scrollTop = document.defaultView.scrollY / zoom;
const scrollLeft = document.defaultView?.scrollX / zoom;
// If dropdown does not fit to the bottom of the screen -> show it at the top of the settings button
const dropdownRect = dropdown.getBoundingClientRect();
const totalHeight = dropdownRect.height + rect.height;
const offset = (totalHeight + rect.y) / zoom > window.self.visualViewport.height ? totalHeight / zoom : 0;
dropdown.style.left = Pixels(rect.left / zoom + scrollLeft);
dropdown.style.top = Pixels(rect.bottom / zoom + scrollTop - offset);
};
// Hides the settings dropdown when clicked outside of it
document.addEventListener('mouseup', function(e) {
if (!e.isTrusted) {
return;
}
const dropdown = $('.settings-dropdown');
if (dropdown?.style?.display !== 'block') {
return;
}
const rect = dropdown?.getClientRects()?.[0];
if (!rect) {
return;
}
if ((e.x > rect.right || e.x < rect.x) || (e.y > rect.bottom || e.y < rect.y)
&& e.target.nodeName !== 'BUTTON') {
dropdown?.hide();
const checkboxValues = Array.from(dropdown?.querySelectorAll('input[type=checkbox]')).map(c => c.checked);
updateSettingsButtonText(options.dropdownButton, checkboxValues);
options.dropdownButton.classList.remove('active');
options.dropdownButton = null;
}
});
// Handle dropdown position on window resize
window.addEventListener('resize', function() {
updateDropdownPosition();
});
// Handle dropdown position on scroll
window.addEventListener('scroll', function() {
updateDropdownPosition();
});
(async() => { (async() => {
try { try {
// We eagerly load the theme here to avoid a white flash // We eagerly load the theme here to avoid a white flash
@ -976,20 +837,12 @@ window.addEventListener('scroll', function() {
const keyRing = await browser.runtime.sendMessage({ action: 'load_keyring' }); const keyRing = await browser.runtime.sendMessage({ action: 'load_keyring' });
options.keyRing = keyRing; options.keyRing = keyRing;
options.isFirefox = isFirefox();
options.initMenu(); options.initMenu();
await options.initGeneralSettings(); await options.initGeneralSettings();
options.initConnectedDatabases(); options.initConnectedDatabases();
options.initCustomLoginFields(); options.initCustomLoginFields();
options.initSitePreferences(); options.initSitePreferences();
options.initAbout(); options.initAbout();
options.hideUnsupportedFeatures();
// The form-switch transitions should complete in 150 ms
setTimeout(() => {
document.body.classList.remove('no-transitions');
}, 200);
} catch (err) { } catch (err) {
console.log('Error loading options page: ' + err); console.log('Error loading options page: ' + err);
} }

View file

@ -153,15 +153,6 @@ code {
width: 2.5rem; width: 2.5rem;
} }
#choose-custom-login-fields-button-safari {
background-image: url('safari-web-extension://__MSG_@@extension_id__/icons/custom_login_fields.svg');
background-position: center;
background-repeat: no-repeat;
background-size: 70%;
height: 31px;
width: 2.5rem;
}
#lock-database-button { #lock-database-button {
display: none; display: none;
width: 2.5rem; width: 2.5rem;

View file

@ -87,7 +87,7 @@ const sendMessageToTab = async function(message) {
}); });
// This does not work with Firefox because of https://bugzilla.mozilla.org/show_bug.cgi?id=1665380 // This does not work with Firefox because of https://bugzilla.mozilla.org/show_bug.cgi?id=1665380
await sendMessageToTab('retrieve_credentials_forced'); await sendMessageToTab('retrive_credentials_forced');
close(); close();
}); });

View file

@ -16,7 +16,9 @@ async function initSettings() {
}); });
const customLoginFieldsButton = document.body.querySelector('#settings #choose-custom-login-fields-button'); const customLoginFieldsButton = document.body.querySelector('#settings #choose-custom-login-fields-button');
customLoginFieldsButton.id = getIconClass('choose-custom-login-fields-button'); if (isFirefox()) {
customLoginFieldsButton.id = 'choose-custom-login-fields-button-moz';
}
customLoginFieldsButton.addEventListener('click', async () => { customLoginFieldsButton.addEventListener('click', async () => {
const tab = await getCurrentTab(); const tab = await getCurrentTab();

1185
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,13 +1,12 @@
{ {
"name": "keepassxc-browser", "name": "keepassxc-browser",
"version": "1.10.0.1", "version": "1.9.9.2",
"description": "KeePassXC-Browser", "description": "KeePassXC-Browser",
"main": "build.js", "main": "build.js",
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.39.1", "@playwright/test": "^1.45.1",
"@playwright/test": "^1.56.1",
"@types/node": "^20.14.10", "@types/node": "^20.14.10",
"eslint": "^9.39.1" "eslint": "^8.49.0"
}, },
"dependencies": { "dependencies": {
"@npmcli/fs": "^2.1.0" "@npmcli/fs": "^2.1.0"
@ -16,7 +15,7 @@
"build": "node build.js", "build": "node build.js",
"debug:chromium": "cp dist/manifest_chromium.json keepassxc-browser/manifest.json", "debug:chromium": "cp dist/manifest_chromium.json keepassxc-browser/manifest.json",
"debug:firefox": "cp dist/manifest_firefox.json keepassxc-browser/manifest.json", "debug:firefox": "cp dist/manifest_firefox.json keepassxc-browser/manifest.json",
"lint": "npx eslint --no-warn-ignored keepassxc-browser/**/*.js", "lint": "npx eslint keepassxc-browser/**/*.js",
"tests": "npx playwright test" "tests": "npx playwright test"
}, },
"repository": { "repository": {

8
tests/.eslintrc Normal file
View file

@ -0,0 +1,8 @@
{
"env": {
"node": true
},
"parserOptions": {
"sourceType": "module"
}
}

View file

@ -1,7 +1,6 @@
import { test, expect } from '@playwright/test'; import { test, expect } from '@playwright/test';
import { import {
compareVersion, compareVersion,
elementsOverlap,
matchesWithNodeName, matchesWithNodeName,
siteMatch, siteMatch,
slashNeededForUrl, slashNeededForUrl,
@ -90,48 +89,3 @@ test('Test trimURL()', async ({ page }) => {
expect(trimURL('https://example.com/path/')).toBe('https://example.com/path/'); expect(trimURL('https://example.com/path/')).toBe('https://example.com/path/');
expect(trimURL('https://example.com/path/#extra')).toBe('https://example.com/path/#extra'); expect(trimURL('https://example.com/path/#extra')).toBe('https://example.com/path/#extra');
}); });
// Check if different popups/overlays partially covers or touches the input field
test('Test elementsOverlap()', async ({ page }) => {
const inputRect = { left: 0, top: 5, right: 200, bottom: 28 }
// Fully covered
expect(elementsOverlap(inputRect, { left: -2, top: 0, right: 220, bottom: 40 })).toBe(true);
// Top side is covered
expect(elementsOverlap(inputRect, { left: 0, top: 0, right: 220, bottom: 20 })).toBe(true);
// Bottom side is covered
expect(elementsOverlap(inputRect, { left: -2, top: 25, right: 220, bottom: 40 })).toBe(true);
// Left side is covered
expect(elementsOverlap(inputRect, { left: -2, top: 0, right: 100, bottom: 40 })).toBe(true);
// Right side is covered
expect(elementsOverlap(inputRect, { left: 100, top: 0, right: 220, bottom: 40 })).toBe(true);
// Top-left corner is covered
expect(elementsOverlap(inputRect, { left: -2, top: 0, right: 40, bottom: 10 })).toBe(true);
// Top-right corner is covered
expect(elementsOverlap(inputRect, { left: 180, top: 0, right: 220, bottom: 10 })).toBe(true);
// Bottom-left corner is covered
expect(elementsOverlap(inputRect, { left: -2, top: 10, right: 100, bottom: 40 })).toBe(true);
// Bottom-right corner is covered
expect(elementsOverlap(inputRect, { left: 180, top: 10, right: 220, bottom: 40 })).toBe(true);
// Input field is covered with identical size
expect(elementsOverlap(inputRect, { left: 0, top: 5, right: 200, bottom: 28 })).toBe(true);
// Overlay is inside the input field
expect(elementsOverlap(inputRect, { left: 2, top: 10, right: 180, bottom: 26 })).toBe(true);
// Overlay is partially inside the input field, comes outside from the left
expect(elementsOverlap(inputRect, { left: -2, top: 10, right: 180, bottom: 26 })).toBe(true);
// Overlay is outside the input field
expect(elementsOverlap(inputRect, { left: 210, top: 0, right: 240, bottom: 40 })).toBe(false);
});

View file

@ -26,10 +26,10 @@ async function testInputFields() {
[ 'basic4', 3 ], // Username/passwd/TOTP fields [ 'basic4', 3 ], // Username/passwd/TOTP fields
[ 'div1', 2, '#toggle1' ], // Fields are behind a button that must be pressed [ 'div1', 2, '#toggle1' ], // Fields are behind a button that must be pressed
[ 'div2', 2, '#toggle2' ], // Fields are behind a button that must be pressed behind a JavaScript [ 'div2', 2, '#toggle2' ], // Fields are behind a button that must be pressed behind a JavaScript
//[ 'div3', 2, '#toggle3' ], // Fields are behind a button that must be pressed [ 'div3', 2, '#toggle3' ], // Fields are behind a button that must be pressed
//[ 'div4', 2, '#toggle4' ], // Fields are behind a button that must be pressed [ 'div4', 2, '#toggle4' ], // Fields are behind a button that must be pressed
[ 'hiddenFields1', 0 ], // Two hidden fields [ 'hiddenFields1', 0 ], // Two hidden fields
//[ 'hiddenFields2', 1 ], // Two hidden fields with one visible [ 'hiddenFields2', 1 ], // Two hidden fields with one visible
]; ];
for (const div of testDivs) { for (const div of testDivs) {
@ -60,10 +60,6 @@ async function testTotpFields() {
[ '', { id: '2fa', type: 'text', maxLength: '6' }, 'Generic 2FA field', true ], [ '', { id: '2fa', type: 'text', maxLength: '6' }, 'Generic 2FA field', true ],
[ '', { id: '2fa', type: 'text', maxLength: '4' }, 'Ignore if field maxLength too small', false ], [ '', { id: '2fa', type: 'text', maxLength: '4' }, 'Ignore if field maxLength too small', false ],
[ '', { id: '2fa', type: 'text', maxLength: '12' }, 'Ignore if field maxLength too long', false ], [ '', { id: '2fa', type: 'text', maxLength: '12' }, 'Ignore if field maxLength too long', false ],
[ '', { id: 'promocode', type: 'text', }, 'promocode id is not acceptable', false ],
[ '', { id: 'Promotional Code', type: 'text', }, 'Promotional Code id is not acceptable', false ],
[ '', { id: 'postcode', type: 'text', }, 'postcode id is not acceptable', false ],
[ '', { id: 'postalcode', type: 'text', }, 'postalcode id is not acceptable', false ],
[ '', { id: 'encode', type: 'text', }, 'encode id is not acceptable', false ], [ '', { id: 'encode', type: 'text', }, 'encode id is not acceptable', false ],
[ '', { id: 'encodedText', type: 'text', }, 'encodedText is not acceptable', false ], [ '', { id: 'encodedText', type: 'text', }, 'encodedText is not acceptable', false ],
[ '', { id: 'decoder', type: 'text', }, 'decoder id is not acceptable', false ], [ '', { id: 'decoder', type: 'text', }, 'decoder id is not acceptable', false ],