Merge branch 'master' of github.com:bitwarden/desktop into feature/bump-electron

# Conflicts:
#	package-lock.json
This commit is contained in:
Hinton 2022-04-05 17:42:20 +02:00
commit 11fce4af89
133 changed files with 5631 additions and 762 deletions

View File

@ -2,6 +2,7 @@
build
dist
dist-safari
desktop_native
jslib

View File

@ -16,7 +16,11 @@ The Bitwarden desktop app is written using Electron and Angular. The application
- [Node.js](https://nodejs.org) v16.13.1 (LTS) or greater
- NPM v8
- Windows users: To compile the native node modules used in the app you will need the _Visual C++ toolset_, available through the standard Visual Studio installer. You will also need to install the _Microsoft Build Tools 2015_ and _Windows 10 SDK 17134_ as additional dependencies in the Visual Studio installer.
- Rust (https://www.rust-lang.org/tools/install)
- Windows:
- To compile the native node modules used in the app you will need the _Visual C++ toolset_, available through the standard Visual Studio installer. You will also need to install the _Microsoft Build Tools 2015_ and _Windows 10 SDK 17134_ as additional dependencies in the Visual Studio installer.
- Linux:
- The following packages `build-essential libsecret-1-dev libglib2.0-dev`
**Run the app**

5
desktop_native/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
target
index.node
**/node_modules
**/.DS_Store
npm-debug.log*

946
desktop_native/Cargo.lock generated Normal file
View File

@ -0,0 +1,946 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bytes"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-expr"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e068cb2806bbc15b439846dc16c5f89f8599f2c3e4d73d4449d38f9b2f0b6c5"
dependencies = [
"smallvec",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "codespan-reporting"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
dependencies = [
"termcolor",
"unicode-width",
]
[[package]]
name = "convert_case"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8"
[[package]]
name = "core-foundation"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "ctor"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "cxx"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce2295fe8865279f404147e9b2328e5af0ad11a2c016e58c13acfd48a07d8a55"
dependencies = [
"cc",
"cxxbridge-flags",
"cxxbridge-macro",
"link-cplusplus",
]
[[package]]
name = "cxx-build"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aaaa055d4908326f1b4524b23ae53758019b806c0c4f382ea240982e9766b26"
dependencies = [
"cc",
"codespan-reporting",
"once_cell",
"proc-macro2",
"quote",
"scratch",
"syn",
]
[[package]]
name = "cxxbridge-flags"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a670224c6686471df12560a0b97a08145082e70bd38e2b0b5383b79e46c3da7"
[[package]]
name = "cxxbridge-macro"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b700096ca0dece28d9535fdb17ab784a8ae155d7f29d39c273643e6292c9620"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "desktop_native"
version = "0.0.0"
dependencies = [
"anyhow",
"core-foundation",
"gio",
"keytar",
"libsecret",
"napi",
"napi-build",
"napi-derive",
"scopeguard",
"security-framework",
"security-framework-sys",
"tokio",
"widestring",
"windows 0.32.0",
]
[[package]]
name = "futures-channel"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
[[package]]
name = "futures-executor"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
[[package]]
name = "futures-task"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
[[package]]
name = "futures-util"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
dependencies = [
"futures-core",
"futures-task",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "gio"
version = "0.15.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96efd8a1c00d890f6b45671916e165b5e43ccec61957d443aff6d7e44f62d348"
dependencies = [
"bitflags",
"futures-channel",
"futures-core",
"futures-io",
"gio-sys",
"glib",
"libc",
"once_cell",
"thiserror",
]
[[package]]
name = "gio-sys"
version = "0.15.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d0fa5052773f5a56b8ae47dab09d040f5d9ce1311f4f99006e16e9a08269296"
dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
"winapi",
]
[[package]]
name = "glib"
version = "0.15.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa570813c504bdf7539a9400180c2dd4b789a819556fb86da7226d7d1b037b49"
dependencies = [
"bitflags",
"futures-channel",
"futures-core",
"futures-executor",
"futures-task",
"glib-macros",
"glib-sys",
"gobject-sys",
"libc",
"once_cell",
"smallvec",
"thiserror",
]
[[package]]
name = "glib-macros"
version = "0.15.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41bfd8d227dead0829ac142454e97531b93f576d0805d779c42bfd799c65c572"
dependencies = [
"anyhow",
"heck",
"proc-macro-crate",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "glib-sys"
version = "0.15.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4366377bd56697de8aaee24e673c575d2694d72e7756324ded2b0428829a7b8"
dependencies = [
"libc",
"system-deps",
]
[[package]]
name = "gobject-sys"
version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df6859463843c20cf3837e3a9069b6ab2051aeeadf4c899d33344f4aea83189a"
dependencies = [
"glib-sys",
"libc",
"system-deps",
]
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "keytar"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d361c55fba09829ac620b040f5425bf239b1030c3d6820a84acac8da867dca4d"
dependencies = [
"keytar-sys",
]
[[package]]
name = "keytar-sys"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe908c6896705a1cb516cd6a5d956c63f08d95ace81b93253a98cd93e1e6a65a"
dependencies = [
"cc",
"cxx",
"cxx-build",
"pkg-config",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
[[package]]
name = "libsecret"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b8d814edb0cb306ffded3f1bfe72d6689529f95f7313a718331802723a73e5a"
dependencies = [
"bitflags",
"gio",
"glib",
"libc",
"libsecret-sys",
"once_cell",
]
[[package]]
name = "libsecret-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "287d2a0fcd95e4d7b0ac6fc9f802691a790d7e522138713b0cacebc4e63cab91"
dependencies = [
"gio-sys",
"glib-sys",
"gobject-sys",
"libc",
"pkg-config",
"system-deps",
]
[[package]]
name = "link-cplusplus"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8cae2cd7ba2f3f63938b9c724475dfb7b9861b545a90324476324ed21dbc8c8"
dependencies = [
"cc",
]
[[package]]
name = "lock_api"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "mio"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2"
dependencies = [
"libc",
"log",
"miow",
"ntapi",
"winapi",
]
[[package]]
name = "miow"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
dependencies = [
"winapi",
]
[[package]]
name = "napi"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17ec66e60f000c78dd7c6215b6fa260e0591e09805024332bc5b3f55acc12244"
dependencies = [
"ctor",
"lazy_static",
"napi-sys",
"tokio",
"windows 0.30.0",
]
[[package]]
name = "napi-build"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebd4419172727423cf30351406c54f6cc1b354a2cfb4f1dba3e6cd07f6d5522b"
[[package]]
name = "napi-derive"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74ac5287a5e94a8728fc82d16c5127acc5eb5b8ad6404ef5f82d6a4ce8d5bdd2"
dependencies = [
"convert_case",
"napi-derive-backend",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "napi-derive-backend"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "427f4f04525635cdf22005d1be62d6d671bcb5550d694a1efb480a315422b4af"
dependencies = [
"convert_case",
"once_cell",
"proc-macro2",
"quote",
"regex",
"syn",
]
[[package]]
name = "napi-sys"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a385494dac3c52cbcacb393bb3b42669e7db8ab240c7ad5115f549eb061f2cc"
[[package]]
name = "ntapi"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
dependencies = [
"winapi",
]
[[package]]
name = "num_cpus"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
[[package]]
name = "parking_lot"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
]
[[package]]
name = "pin-project-lite"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
[[package]]
name = "proc-macro-crate"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
dependencies = [
"thiserror",
"toml",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "scratch"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96311ef4a16462c757bb6a39152c40f58f31cd2602a40fceb937e2bc34e6cbab"
[[package]]
name = "security-framework"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc"
dependencies = [
"bitflags",
"core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "serde"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
[[package]]
name = "slab"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
[[package]]
name = "smallvec"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
[[package]]
name = "socket2"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "syn"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "system-deps"
version = "6.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709"
dependencies = [
"cfg-expr",
"heck",
"pkg-config",
"toml",
"version-compare",
]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
dependencies = [
"bytes",
"libc",
"memchr",
"mio",
"num_cpus",
"once_cell",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"winapi",
]
[[package]]
name = "tokio-macros"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "toml"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [
"serde",
]
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "version-compare"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "widestring"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b749ebd2304aa012c5992d11a25d07b406bdbe5f79d371cb7a918ce501a19eb0"
dependencies = [
"windows_aarch64_msvc 0.30.0",
"windows_i686_gnu 0.30.0",
"windows_i686_msvc 0.30.0",
"windows_x86_64_gnu 0.30.0",
"windows_x86_64_msvc 0.30.0",
]
[[package]]
name = "windows"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbedf6db9096bc2364adce0ae0aa636dcd89f3c3f2cd67947062aaf0ca2a10ec"
dependencies = [
"windows_aarch64_msvc 0.32.0",
"windows_i686_gnu 0.32.0",
"windows_i686_msvc 0.32.0",
"windows_x86_64_gnu 0.32.0",
"windows_x86_64_msvc 0.32.0",
]
[[package]]
name = "windows-sys"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6"
dependencies = [
"windows_aarch64_msvc 0.32.0",
"windows_i686_gnu 0.32.0",
"windows_i686_msvc 0.32.0",
"windows_x86_64_gnu 0.32.0",
"windows_x86_64_msvc 0.32.0",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca"
[[package]]
name = "windows_aarch64_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
[[package]]
name = "windows_i686_gnu"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8"
[[package]]
name = "windows_i686_gnu"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
[[package]]
name = "windows_i686_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6"
[[package]]
name = "windows_i686_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
[[package]]
name = "windows_x86_64_gnu"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"

43
desktop_native/Cargo.toml Normal file
View File

@ -0,0 +1,43 @@
[package]
edition = "2021"
exclude = ["index.node"]
license = "GPL-3.0"
name = "desktop_native"
version = "0.0.0"
[lib]
crate-type = ["cdylib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0"
napi = {version = "2", features = ["async"]}
napi-derive = "2"
scopeguard = "1.1.0"
tokio = {version = "1.17.0", features = ["full"]}
[build-dependencies]
napi-build = "1"
[target.'cfg(windows)'.dependencies]
widestring = "0.5.1"
windows = {version = "0.32.0", features = [
"alloc",
"Foundation",
"Storage_Streams",
"Win32_Foundation",
"Win32_Security_Credentials",
]}
[target.'cfg(windows)'.dev-dependencies]
keytar = "0.1.6"
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9.3"
security-framework = "2.6.1"
security-framework-sys = "2.6.1"
[target.'cfg(target_os = "linux")'.dependencies]
gio = "0.15.6"
libsecret = "0.1.3"

5
desktop_native/build.rs Normal file
View File

@ -0,0 +1,5 @@
extern crate napi_build;
fn main() {
napi_build::setup();
}

15
desktop_native/index.d.ts vendored Normal file
View File

@ -0,0 +1,15 @@
/* tslint:disable */
/* eslint-disable */
/* auto-generated by NAPI-RS */
export namespace passwords {
/** Fetch the stored password from the keychain. */
export function getPassword(service: string, account: string): Promise<string>
/** Fetch the stored password from the keychain that was stored with Keytar. */
export function getPasswordKeytar(service: string, account: string): Promise<string>
/** Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry. */
export function setPassword(service: string, account: string, password: string): Promise<void>
/** Delete the stored password from the keychain. */
export function deletePassword(service: string, account: string): Promise<void>
}

57
desktop_native/package-lock.json generated Normal file
View File

@ -0,0 +1,57 @@
{
"name": "desktop_native",
"version": "0.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "desktop_native",
"version": "0.1.0",
"hasInstallScript": true,
"license": "GPL-3.0",
"devDependencies": {
"@napi-rs/cli": "^2.4.4",
"cargo-cp-artifact": "^0.1"
}
},
"node_modules/@napi-rs/cli": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.4.4.tgz",
"integrity": "sha512-f+tvwCv1ka24dBqI2DgBhR7Oxl3DKHOp4onxLXwyBFt6iCADnr3YZIr1/2Iq5r3uqxFgaf01bfPsRQZPkEp0kQ==",
"dev": true,
"bin": {
"napi": "scripts/index.js"
},
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/cargo-cp-artifact": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.6.tgz",
"integrity": "sha512-CQw0doK/aaF7j041666XzuilHxqMxaKkn+I5vmBsd8SAwS0cO5CqVEVp0xJwOKstyqWZ6WK4Ww3O6p26x/Goyg==",
"dev": true,
"bin": {
"cargo-cp-artifact": "bin/cargo-cp-artifact.js"
}
}
},
"dependencies": {
"@napi-rs/cli": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.4.4.tgz",
"integrity": "sha512-f+tvwCv1ka24dBqI2DgBhR7Oxl3DKHOp4onxLXwyBFt6iCADnr3YZIr1/2Iq5r3uqxFgaf01bfPsRQZPkEp0kQ==",
"dev": true
},
"cargo-cp-artifact": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.6.tgz",
"integrity": "sha512-CQw0doK/aaF7j041666XzuilHxqMxaKkn+I5vmBsd8SAwS0cO5CqVEVp0xJwOKstyqWZ6WK4Ww3O6p26x/Goyg==",
"dev": true
}
}
}

View File

@ -0,0 +1,19 @@
{
"name": "desktop_native",
"version": "0.1.0",
"description": "",
"main": "index.node",
"scripts": {
"build": "napi build --release --js true",
"build-debug": "npm run build --",
"build-release": "npm run build -- --release",
"install": "npm run build-release",
"test": "cargo test"
},
"author": "",
"license": "GPL-3.0",
"devDependencies": {
"@napi-rs/cli": "^2.4.4",
"cargo-cp-artifact": "^0.1"
}
}

39
desktop_native/src/lib.rs Normal file
View File

@ -0,0 +1,39 @@
#[macro_use]
extern crate napi_derive;
mod password;
#[napi]
pub mod passwords {
/// Fetch the stored password from the keychain.
#[napi]
pub async fn get_password(service: String, account: String) -> napi::Result<String> {
super::password::get_password(&service, &account)
.map_err(|e| napi::Error::from_reason(e.to_string()))
}
/// Fetch the stored password from the keychain that was stored with Keytar.
#[napi]
pub async fn get_password_keytar(service: String, account: String) -> napi::Result<String> {
super::password::get_password_keytar(&service, &account)
.map_err(|e| napi::Error::from_reason(e.to_string()))
}
/// Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry.
#[napi]
pub async fn set_password(
service: String,
account: String,
password: String,
) -> napi::Result<()> {
super::password::set_password(&service, &account, &password)
.map_err(|e| napi::Error::from_reason(e.to_string()))
}
/// Delete the stored password from the keychain.
#[napi]
pub async fn delete_password(service: String, account: String) -> napi::Result<()> {
super::password::delete_password(&service, &account)
.map_err(|e| napi::Error::from_reason(e.to_string()))
}
}

View File

@ -0,0 +1,59 @@
use anyhow::Result;
use security_framework::passwords::{
delete_generic_password, get_generic_password, set_generic_password,
};
pub fn get_password(service: &str, account: &str) -> Result<String> {
let result = String::from_utf8(get_generic_password(&service, &account)?)?;
Ok(result)
}
pub fn get_password_keytar(service: &str, account: &str) -> Result<String> {
get_password(service, account)
}
pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> {
let result = set_generic_password(&service, &account, password.as_bytes())?;
Ok(result)
}
pub fn delete_password(service: &str, account: &str) -> Result<()> {
let result = delete_generic_password(&service, &account)?;
Ok(result)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({}););
set_password("BitwardenTest", "BitwardenTest", "Random").unwrap();
assert_eq!(
"Random",
get_password("BitwardenTest", "BitwardenTest").unwrap()
);
delete_password("BitwardenTest", "BitwardenTest").unwrap();
// Ensure password is deleted
match get_password("BitwardenTest", "BitwardenTest") {
Ok(_) => panic!("Got a result"),
Err(e) => assert_eq!(
"The specified item could not be found in the keychain.",
e.to_string()
),
}
}
#[test]
fn test_error_no_password() {
match get_password("Unknown", "Unknown") {
Ok(_) => panic!("Got a result"),
Err(e) => assert_eq!(
"The specified item could not be found in the keychain.",
e.to_string()
),
}
}
}

View File

@ -0,0 +1,5 @@
#[cfg_attr(target_os = "linux", path = "unix.rs")]
#[cfg_attr(target_os = "windows", path = "windows.rs")]
#[cfg_attr(target_os = "macos", path = "macos.rs")]
mod password;
pub use password::*;

View File

@ -0,0 +1,91 @@
use anyhow::{anyhow, Result};
use libsecret::{password_clear_sync, password_lookup_sync, password_store_sync, Schema};
use std::collections::HashMap;
pub fn get_password(service: &str, account: &str) -> Result<String> {
let res = password_lookup_sync(
Some(&get_schema()),
build_attributes(service, account),
gio::Cancellable::NONE,
)?;
match res {
Some(s) => Ok(String::from(s)),
None => Err(anyhow!("No password found")),
}
}
pub fn get_password_keytar(service: &str, account: &str) -> Result<String> {
get_password(service, account)
}
pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> {
let result = password_store_sync(
Some(&get_schema()),
build_attributes(service, account),
Some(&libsecret::COLLECTION_DEFAULT),
&format!("{}/{}", service, account),
password,
gio::Cancellable::NONE,
)?;
Ok(result)
}
pub fn delete_password(service: &str, account: &str) -> Result<()> {
let result = password_clear_sync(
Some(&get_schema()),
build_attributes(service, account),
gio::Cancellable::NONE,
)?;
Ok(result)
}
fn get_schema() -> Schema {
let mut attributes = std::collections::HashMap::new();
attributes.insert("service", libsecret::SchemaAttributeType::String);
attributes.insert("account", libsecret::SchemaAttributeType::String);
libsecret::Schema::new(
"org.freedesktop.Secret.Generic",
libsecret::SchemaFlags::NONE,
attributes,
)
}
fn build_attributes<'a>(service: &'a str, account: &'a str) -> HashMap<&'a str, &'a str> {
let mut attributes = HashMap::new();
attributes.insert("service", service);
attributes.insert("account", account);
attributes
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({}););
set_password("BitwardenTest", "BitwardenTest", "Random").unwrap();
assert_eq!(
"Random",
get_password("BitwardenTest", "BitwardenTest").unwrap()
);
delete_password("BitwardenTest", "BitwardenTest").unwrap();
// Ensure password is deleted
match get_password("BitwardenTest", "BitwardenTest") {
Ok(_) => panic!("Got a result"),
Err(e) => assert_eq!("No password found", e.to_string()),
}
}
#[test]
fn test_error_no_password() {
match get_password("BitwardenTest", "BitwardenTest") {
Ok(_) => panic!("Got a result"),
Err(e) => assert_eq!("No password found", e.to_string()),
}
}
}

View File

@ -0,0 +1,180 @@
use anyhow::{anyhow, Result};
use widestring::{U16CString, U16String};
use windows::Win32::{
Foundation::{GetLastError, ERROR_NOT_FOUND, FILETIME, PWSTR, WIN32_ERROR},
Security::Credentials::{
CredDeleteW, CredFree, CredReadW, CredWriteW, CREDENTIALW, CRED_FLAGS,
CRED_PERSIST_ENTERPRISE, CRED_TYPE_GENERIC,
},
};
const CRED_FLAGS_NONE: u32 = 0;
pub fn get_password<'a>(service: &str, account: &str) -> Result<String> {
let target_name = U16CString::from_str(target_name(service, account))?;
let mut credential: *mut CREDENTIALW = std::ptr::null_mut();
let credential_ptr = &mut credential;
let result = unsafe {
CredReadW(
PWSTR(target_name.as_ptr()),
CRED_TYPE_GENERIC.0,
CRED_FLAGS_NONE,
credential_ptr,
)
};
scopeguard::defer!({
unsafe { CredFree(credential as *mut _) };
});
if !result.as_bool() {
return Err(anyhow!(convert_error(unsafe { GetLastError() })));
}
let password = unsafe {
U16String::from_ptr(
(*credential).CredentialBlob as *const u16,
(*credential).CredentialBlobSize as usize / 2,
)
.to_string_lossy()
};
Ok(String::from(password))
}
// Remove this after sufficient releases
pub fn get_password_keytar<'a>(service: &str, account: &str) -> Result<String> {
let target_name = U16CString::from_str(target_name(service, account))?;
let mut credential: *mut CREDENTIALW = std::ptr::null_mut();
let credential_ptr = &mut credential;
let result = unsafe {
CredReadW(
PWSTR(target_name.as_ptr()),
CRED_TYPE_GENERIC.0,
CRED_FLAGS_NONE,
credential_ptr,
)
};
scopeguard::defer!({
unsafe { CredFree(credential as *mut _) };
});
if !result.as_bool() {
return Err(anyhow!(unsafe { GetLastError() }.0.to_string()));
}
let password = unsafe {
std::str::from_utf8_unchecked(std::slice::from_raw_parts(
(*credential).CredentialBlob,
(*credential).CredentialBlobSize as usize,
))
};
Ok(String::from(password))
}
pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> {
let target_name = U16CString::from_str(target_name(service, account))?;
let user_name = U16CString::from_str(account)?;
let last_written = FILETIME {
dwLowDateTime: 0,
dwHighDateTime: 0,
};
let credential = U16CString::from_str(password)?;
let credential_len = password.len() as u32 * 2;
let credential = CREDENTIALW {
Flags: CRED_FLAGS(CRED_FLAGS_NONE),
Type: CRED_TYPE_GENERIC,
TargetName: PWSTR(target_name.as_ptr()),
Comment: PWSTR::default(),
LastWritten: last_written,
CredentialBlobSize: credential_len,
CredentialBlob: credential.as_ptr() as *mut u8,
Persist: CRED_PERSIST_ENTERPRISE,
AttributeCount: 0,
Attributes: std::ptr::null_mut(),
TargetAlias: PWSTR::default(),
UserName: PWSTR(user_name.as_ptr()),
};
let result = unsafe { CredWriteW(&credential, 0) };
if !result.as_bool() {
return Err(anyhow!(unsafe { GetLastError() }.0.to_string()));
}
Ok(())
}
pub fn delete_password(service: &str, account: &str) -> Result<()> {
let target_name = U16CString::from_str(target_name(service, account))?;
unsafe {
CredDeleteW(
PWSTR(target_name.as_ptr()),
CRED_TYPE_GENERIC.0,
CRED_FLAGS_NONE,
)
.ok()?
};
Ok(())
}
fn target_name(service: &str, account: &str) -> String {
format!("{}/{}", service, account)
}
// Convert the internal WIN32 errors to descriptive messages
fn convert_error(code: WIN32_ERROR) -> String {
match code {
ERROR_NOT_FOUND => String::from("Password not found."),
_ => code.0.to_string(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({}););
set_password("BitwardenTest", "BitwardenTest", "Random").unwrap();
assert_eq!(
"Random",
get_password("BitwardenTest", "BitwardenTest").unwrap()
);
delete_password("BitwardenTest", "BitwardenTest").unwrap();
// Ensure password is deleted
match get_password("BitwardenTest", "BitwardenTest") {
Ok(_) => panic!("Got a result"),
Err(e) => assert_eq!("Password not found.", e.to_string()),
}
}
#[test]
fn test_get_password_keytar() {
scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({}););
keytar::set_password("BitwardenTest", "BitwardenTest", "HelloFromKeytar").unwrap();
assert_eq!(
"HelloFromKeytar",
get_password_keytar("BitwardenTest", "BitwardenTest").unwrap()
);
}
#[test]
fn test_error_no_password() {
match get_password("BitwardenTest", "BitwardenTest") {
Ok(_) => panic!("Got a result"),
Err(e) => assert_eq!("Password not found.", e.to_string()),
}
}
}

2
jslib

@ -1 +1 @@
Subproject commit fa73c13b8c9ed35cbb9909e342b143fa8a57f1a0
Subproject commit f3a4fde513dc16779e85597bd00027b160671db7

728
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,7 @@
"build:renderer:dev": "cross-env NODE_ENV=development webpack --config webpack.renderer.js",
"build:renderer:watch": "cross-env NODE_ENV=development webpack --config webpack.renderer.js --watch",
"electron": "npm run build:main:dev && concurrently -k -n Main,Rend -c yellow,cyan \"electron --inspect=5858 ./build --watch\" \"npm run build:renderer:watch\"",
"electron:ignore": "npm run build:main:dev && concurrently -k -n Main,Rend -c yellow,cyan \"electron --inspect=5858 --ignore-certificate-errors ./build --watch\" \"npm run build:renderer:watch\"",
"clean:dist": "rimraf ./dist/*",
"clean:l10n": "git push origin --delete l10n_master",
"pack:dir": "npm run clean:dist && electron-builder --dir -p never",
@ -79,6 +80,10 @@
"asarUnpack": [
"**/*.node"
],
"files": [
"**/*",
"!**/node_modules/@bitwarden/desktop-native/**/*"
],
"mac": {
"electronUpdaterCompatibility": ">=0.0.1",
"category": "public.app-category.productivity",
@ -187,7 +192,9 @@
"entitlements": "resources/entitlements.mas.plist",
"entitlementsInherit": "resources/entitlements.mas.inherit.plist",
"hardenedRuntime": false,
"minimumSystemVersion": "10.14"
"extendInfo": {
"LSMinimumSystemVersion": "10.14.0"
}
},
"nsisWeb": {
"oneClick": false,
@ -301,9 +308,12 @@
"@angular/platform-browser": "^12.2.13",
"@angular/platform-browser-dynamic": "^12.2.13",
"@angular/router": "^12.2.13",
"@bitwarden/desktop-native": "file:desktop_native",
"@bitwarden/jslib-angular": "file:jslib/angular",
"@bitwarden/jslib-common": "file:jslib/common",
"@bitwarden/jslib-electron": "file:jslib/electron",
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
"forcefocus": "^1.1.0",
"ngx-toastr": "14.1.4",
"node-ipc": "^9.1.4",
"nord": "^0.2.1",

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 KiB

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 B

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -25,11 +25,7 @@
</div>
<div class="box">
<div class="box-header">
<button
type="button"
(click)="toggleCustom()"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
>
<button type="button" (click)="toggleCustom()" [attr.aria-expanded]="showCustom">
<i class="bwi bwi-plus-square" [hidden]="showCustom" aria-hidden="true"></i>
<i class="bwi bwi-minus-square" [hidden]="!showCustom" aria-hidden="true"></i>
{{ "customEnvironment" | i18n }}

View File

@ -37,6 +37,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePassword()"
>
<i

View File

@ -55,6 +55,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePassword()"
>
<i

View File

@ -47,6 +47,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePassword(false)"
>
<i
@ -97,6 +98,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePassword(true)"
>
<i

View File

@ -63,6 +63,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePassword(false)"
>
<i
@ -115,6 +116,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePassword(true)"
>
<i

View File

@ -3,7 +3,9 @@
<div class="modal-content">
<div class="modal-body form">
<div class="box">
<label class="settingsTitle">{{ "settingsTitle" | i18n: currentUserEmail }} </label>
<div class="box-header">
{{ "settingsTitle" | i18n: currentUserEmail }}
</div>
<div class="box-content box-content-padded">
<h2>
<button

View File

@ -43,6 +43,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePassword(false)"
>
<i
@ -90,6 +91,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePassword(true)"
>
<i

View File

@ -37,14 +37,14 @@ import { TokenService } from "jslib-common/abstractions/token.service";
import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service";
import { CipherType } from "jslib-common/enums/cipherType";
import { MenuUpdateRequest } from "src/main/menu.updater";
import { MenuUpdateRequest } from "../main/menu/menu.updater";
import { PremiumComponent } from "./accounts/premium.component";
import { SettingsComponent } from "./accounts/settings.component";
import { ExportComponent } from "./vault/export.component";
import { FolderAddEditComponent } from "./vault/folder-add-edit.component";
import { GeneratorComponent } from "./vault/generator.component";
import { PasswordGeneratorHistoryComponent } from "./vault/password-generator-history.component";
import { PasswordGeneratorComponent } from "./vault/password-generator.component";
const BroadcasterSubscriptionId = "AppComponent";
const IdleTimeout = 60000 * 10; // 10 minutes
@ -65,7 +65,7 @@ const systemTimeoutOptions = {
<ng-template #passwordHistory></ng-template>
<ng-template #appFolderAddEdit></ng-template>
<ng-template #exportVault></ng-template>
<ng-template #appPasswordGenerator></ng-template>
<ng-template #appGenerator></ng-template>
<app-header></app-header>
<div id="container">
<div class="loading" *ngIf="loading">
@ -84,8 +84,8 @@ export class AppComponent implements OnInit {
exportVaultModalRef: ViewContainerRef;
@ViewChild("appFolderAddEdit", { read: ViewContainerRef, static: true })
folderAddEditModalRef: ViewContainerRef;
@ViewChild("appPasswordGenerator", { read: ViewContainerRef, static: true })
passwordGeneratorModalRef: ViewContainerRef;
@ViewChild("appGenerator", { read: ViewContainerRef, static: true })
generatorModalRef: ViewContainerRef;
loading = false;
@ -317,10 +317,10 @@ export class AppComponent implements OnInit {
case "newFolder":
await this.addFolder();
break;
case "openPasswordGenerator":
// openPasswordGenerator has extended functionality if called in the vault
case "openGenerator":
// openGenerator has extended functionality if called in the vault
if (!this.router.url.includes("vault")) {
await this.openPasswordGenerator();
await this.openGenerator();
}
break;
case "convertAccountToKeyConnector":
@ -402,15 +402,15 @@ export class AppComponent implements OnInit {
});
}
async openPasswordGenerator() {
async openGenerator() {
if (this.modal != null) {
this.modal.close();
}
[this.modal] = await this.modalService.openViewRef(
PasswordGeneratorComponent,
this.folderAddEditModalRef,
(comp) => (comp.showSelect = false)
GeneratorComponent,
this.generatorModalRef,
(comp) => (comp.comingFromAddEdit = false)
);
this.modal.onClosed.subscribe(() => {

View File

@ -99,9 +99,9 @@ import { CiphersComponent } from "./vault/ciphers.component";
import { CollectionsComponent } from "./vault/collections.component";
import { ExportComponent } from "./vault/export.component";
import { FolderAddEditComponent } from "./vault/folder-add-edit.component";
import { GeneratorComponent } from "./vault/generator.component";
import { GroupingsComponent } from "./vault/groupings.component";
import { PasswordGeneratorHistoryComponent } from "./vault/password-generator-history.component";
import { PasswordGeneratorComponent } from "./vault/password-generator.component";
import { PasswordHistoryComponent } from "./vault/password-history.component";
import { ShareComponent } from "./vault/share.component";
import { VaultComponent } from "./vault/vault.component";
@ -193,7 +193,7 @@ registerLocaleData(localeZhTw, "zh-TW");
LockComponent,
LoginComponent,
NavComponent,
PasswordGeneratorComponent,
GeneratorComponent,
PasswordGeneratorHistoryComponent,
PasswordHistoryComponent,
PasswordRepromptComponent,

View File

@ -26,6 +26,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePassword()"
>
<i

View File

@ -28,6 +28,7 @@
appStopClick
appBlurClick
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPin"
(click)="toggleVisibility()"
>
<i

View File

@ -164,6 +164,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePasswordVisible()"
[disabled]="disableSend"
>

View File

@ -85,6 +85,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="f.showValue"
(click)="toggleFieldValue(f)"
>
<i

View File

@ -27,15 +27,30 @@
</div>
<!-- Login -->
<div *ngIf="cipher.type === cipherType.Login">
<div class="box-content-row" appBoxRow>
<label for="loginUsername">{{ "username" | i18n }}</label>
<input
id="loginUsername"
type="text"
name="Login.Username"
[(ngModel)]="cipher.login.username"
appInputVerbatim
/>
<div class="box-content-row box-content-row-flex" appBoxRow>
<div class="row-main">
<label for="loginUsername">{{ "username" | i18n }}</label>
<input
id="loginUsername"
type="text"
name="Login.Username"
[(ngModel)]="cipher.login.username"
appInputVerbatim
/>
</div>
<div class="action-buttons">
<a
class="row-btn"
href="#"
appStopClick
appBlurClick
role="button"
appA11yTitle="{{ 'generateUsername' | i18n }}"
(click)="generateUsername()"
>
<i class="bwi bwi-lg bwi-generate" aria-hidden="true"></i>
</a>
</div>
</div>
<div class="box-content-row box-content-row-flex" appBoxRow>
<div class="row-main">
@ -79,6 +94,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePassword()"
>
<i
@ -144,6 +160,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showCardNumber"
(click)="toggleCardNumber()"
>
<i
@ -198,6 +215,7 @@
appBlurClick
role="button"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showCardCode"
(click)="toggleCardCode()"
>
<i

View File

@ -0,0 +1,481 @@
<div
class="modal fade"
role="dialog"
aria-modal="true"
attr.aria-label="{{ 'generatePassword' | i18n }}"
>
<div class="modal-dialog modal-md" role="document">
<div class="modal-content">
<div class="modal-body">
<div class="modal-title">
{{ "generator" | i18n }}
</div>
<app-callout
type="info"
*ngIf="enforcedPasswordPolicyOptions?.inEffect() && type === 'password'"
>
{{ "passwordGeneratorPolicyInEffect" | i18n }}
</app-callout>
<div class="generated-block" *ngIf="type === 'password'">
<div class="generated-wrapper" [innerHTML]="password | colorPassword" appSelectCopy></div>
<div class="action-buttons">
<button
type="button"
class="icon-btn primary"
appStopClick
appA11yTitle="{{ 'copyPassword' | i18n }}"
(click)="copy()"
>
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
</button>
<button
type="button"
class="icon-btn primary"
appStopClick
appA11yTitle="{{ 'regeneratePassword' | i18n }}"
(click)="regenerate()"
>
<i class="bwi bwi-lg bwi-generate" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="generated-block" *ngIf="type === 'username'">
<div class="generated-wrapper" [innerHTML]="username | colorPassword" appSelectCopy></div>
<div class="action-buttons">
<button
type="button"
class="icon-btn primary"
appStopClick
appA11yTitle="{{ 'copyUsername' | i18n }}"
(click)="copy()"
>
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
</button>
<button
type="button"
class="icon-btn primary"
appStopClick
appA11yTitle="{{ 'regenerateUsername' | i18n }}"
(click)="regenerate()"
>
<i class="bwi bwi-lg bwi-generate" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="box">
<div class="box-content condensed">
<div class="box-content-row box-content-row-radio">
<label class="radio-header">{{ "whatWouldYouLikeToGenerate" | i18n }}</label>
<div
class="radio-group text-default"
appBoxRow
name="TypeOptions"
*ngFor="let o of typeOptions"
>
<input
type="radio"
class="radio"
[(ngModel)]="type"
name="Type_{{ o.value }}"
id="type_{{ o.value }}"
[value]="o.value"
(change)="typeChanged()"
[checked]="type === o.value"
[disabled]="comingFromAddEdit"
/>
<label class="unstyled" for="type_{{ o.value }}">
{{ o.name }}
</label>
</div>
</div>
</div>
</div>
<ng-container *ngIf="type === 'password'">
<div class="box">
<div class="box-header">
<button
type="button"
(click)="toggleOptions()"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-expanded]="showOptions"
>
<i class="bwi bwi-plus-square" aria-hidden="true" [hidden]="showOptions"></i>
<i class="bwi bwi-minus-square" aria-hidden="true" [hidden]="!showOptions"></i>
{{ "options" | i18n }}
</button>
</div>
<div class="box-content condensed" [hidden]="!showOptions">
<div class="box-content-row box-content-row-radio">
<label class="radio-header">{{ "passwordType" | i18n }}</label>
<div
class="radio-group text-default"
appBoxRow
name="PassTypeOptions"
*ngFor="let o of passTypeOptions"
>
<input
type="radio"
class="radio"
[(ngModel)]="passwordOptions.type"
name="PasswordType_{{ o.value }}"
id="passwordType_{{ o.value }}"
[value]="o.value"
(change)="savePasswordOptions()"
[checked]="passwordOptions.type === o.value"
/>
<label class="unstyled" for="passwordType_{{ o.value }}">
{{ o.name }}
</label>
</div>
</div>
</div>
</div>
<div class="box" [hidden]="!showOptions" *ngIf="passwordOptions.type === 'passphrase'">
<div class="box-content condensed">
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="num-words">{{ "numWords" | i18n }}</label>
<input
id="num-words"
type="number"
min="3"
max="20"
(blur)="savePasswordOptions()"
[(ngModel)]="passwordOptions.numWords"
/>
</div>
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="word-separator">{{ "wordSeparator" | i18n }}</label>
<input
id="word-separator"
type="text"
maxlength="1"
(input)="savePasswordOptions()"
[(ngModel)]="passwordOptions.wordSeparator"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="capitalize">{{ "capitalize" | i18n }}</label>
<input
id="capitalize"
type="checkbox"
(change)="savePasswordOptions()"
[(ngModel)]="passwordOptions.capitalize"
[disabled]="enforcedPasswordPolicyOptions?.capitalize"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="include-number">{{ "includeNumber" | i18n }}</label>
<input
id="include-number"
type="checkbox"
(change)="savePasswordOptions()"
[(ngModel)]="passwordOptions.includeNumber"
[disabled]="enforcedPasswordPolicyOptions?.includeNumber"
/>
</div>
</div>
</div>
<ng-container *ngIf="passwordOptions.type === 'password'">
<div class="box" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row box-content-row-slider" appBoxRow>
<label for="length">{{ "length" | i18n }}</label>
<input
id="length"
type="number"
min="5"
max="128"
[(ngModel)]="passwordOptions.length"
(blur)="savePasswordOptions()"
/>
<input
id="lengthRange"
type="range"
min="5"
max="128"
step="1"
[(ngModel)]="passwordOptions.length"
(change)="sliderChanged()"
(input)="sliderInput()"
attr.aria-label="{{ 'length' | i18n }}"
tabindex="-1"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="uppercase">A-Z</label>
<input
id="uppercase"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useUppercase"
[(ngModel)]="passwordOptions.uppercase"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="lowercase">a-z</label>
<input
id="lowercase"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useLowercase"
[(ngModel)]="passwordOptions.lowercase"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="numbers">0-9</label>
<input
id="numbers"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useNumbers"
[(ngModel)]="passwordOptions.number"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="special">!@#$%^&*</label>
<input
id="special"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useSpecial"
[(ngModel)]="passwordOptions.special"
/>
</div>
</div>
</div>
<div class="box" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="min-number">{{ "minNumbers" | i18n }}</label>
<input
id="min-number"
type="number"
min="0"
max="9"
(blur)="savePasswordOptions()"
[(ngModel)]="passwordOptions.minNumber"
/>
</div>
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="min-special">{{ "minSpecial" | i18n }}</label>
<input
id="min-special"
type="number"
min="0"
max="9"
(blur)="savePasswordOptions()"
[(ngModel)]="passwordOptions.minSpecial"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="ambiguous">{{ "ambiguous" | i18n }}</label>
<input
id="ambiguous"
type="checkbox"
(change)="savePasswordOptions()"
[(ngModel)]="avoidAmbiguous"
/>
</div>
</div>
</div>
</ng-container>
</ng-container>
<ng-container *ngIf="type === 'username'">
<div class="box">
<div class="box-header">
<button
type="button"
(click)="toggleOptions()"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-expanded]="showOptions"
>
<i class="bwi bwi-plus-square" aria-hidden="true" [hidden]="showOptions"></i>
<i class="bwi bwi-minus-square" aria-hidden="true" [hidden]="!showOptions"></i>
{{ "options" | i18n }}
</button>
</div>
<div class="box-content condensed" [hidden]="!showOptions">
<div class="box-content-row box-content-row-radio">
<label class="radio-header">
{{ "usernameType" | i18n }}
<a
href="#"
appStopClick
appBlurClick
(click)="usernameTypesLearnMore()"
appA11yTitle="{{ 'learnMore' | i18n }}"
>
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
</a>
</label>
<div
class="radio-group align-start text-default"
appBoxRow
name="UsernameTypeOptions"
*ngFor="let o of usernameTypeOptions"
>
<input
type="radio"
class="radio"
[(ngModel)]="usernameOptions.type"
name="UsernameType_{{ o.value }}"
id="usernameType_{{ o.value }}"
[value]="o.value"
(change)="saveUsernameOptions()"
[checked]="usernameOptions.type === o.value"
/>
<label class="unstyled" for="usernameType_{{ o.value }}">
{{ o.name }}
<div class="small text-muted" *ngIf="o.desc">{{ o.desc }}</div>
</label>
</div>
</div>
</div>
</div>
<div class="box" *ngIf="usernameOptions.type === 'forwarded'" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row">
<label class="radio-header">{{ "service" | i18n }}</label>
<div class="radio-group text-default" appBoxRow *ngFor="let o of forwardOptions">
<input
type="radio"
[(ngModel)]="usernameOptions.forwardedService"
name="ForwardType_{{ o.value }}"
id="forwardtype_{{ o.value }}"
[value]="o.value"
(change)="saveUsernameOptions()"
[checked]="usernameOptions.forwardedService === o.value"
/>
<label for="forwardtype_{{ o.value }}">
{{ o.name }}
</label>
</div>
</div>
</div>
</div>
<div class="box" *ngIf="usernameOptions.type === 'subaddress'" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row" appBoxRow>
<label for="subaddress-email">{{ "emailAddress" | i18n }}</label>
<input
id="subaddress-email"
type="text"
name="SubaddressEmail"
[(ngModel)]="usernameOptions.subaddressEmail"
(blur)="saveUsernameOptions()"
/>
</div>
<div class="box-content-row" *ngIf="subaddressOptions.length > 1">
<label class="radio-header">{{ "type" | i18n }}</label>
<div class="radio-group text-default" appBoxRow *ngFor="let o of subaddressOptions">
<input
type="radio"
[(ngModel)]="usernameOptions.subaddressType"
name="SubaddressType_{{ o.value }}"
id="subaddresstype_{{ o.value }}"
[value]="o.value"
(change)="saveUsernameOptions()"
[checked]="usernameOptions.subaddressType === o.value"
/>
<label for="subaddresstype_{{ o.value }}">
{{ o.name }}
</label>
</div>
</div>
<div class="box-content-row" appBoxRow *ngIf="usernameWebsite">
<label for="subaddress-website">{{ "website" | i18n }}</label>
<input
id="subaddress-website"
type="text"
name="SubaddressWebsite"
[value]="usernameOptions.website"
disabled
readonly
/>
</div>
</div>
</div>
<div class="box" *ngIf="usernameOptions.type === 'catchall'" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row" appBoxRow>
<label for="catchall-domain">{{ "domainName" | i18n }}</label>
<input
id="catchall-domain"
type="text"
name="CatchallDomain"
[(ngModel)]="usernameOptions.catchallDomain"
(blur)="saveUsernameOptions()"
/>
</div>
<div class="box-content-row" *ngIf="catchallOptions.length > 1">
<label class="radio-header">{{ "type" | i18n }}</label>
<div class="radio-group text-default" appBoxRow *ngFor="let o of catchallOptions">
<input
type="radio"
[(ngModel)]="usernameOptions.catchallType"
name="CatchallType_{{ o.value }}"
id="catchalltype_{{ o.value }}"
[value]="o.value"
(change)="saveUsernameOptions()"
[checked]="usernameOptions.catchallType === o.value"
/>
<label for="catchalltype_{{ o.value }}">
{{ o.name }}
</label>
</div>
</div>
<div class="box-content-row" appBoxRow *ngIf="usernameWebsite">
<label for="catchall-website">{{ "website" | i18n }}</label>
<input
id="catchall-website"
type="text"
name="CatchallWebsite"
[value]="usernameOptions.website"
disabled
readonly
/>
</div>
</div>
</div>
<div class="box" *ngIf="usernameOptions.type === 'word'" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="capitalize">{{ "capitalize" | i18n }}</label>
<input
id="capitalize"
type="checkbox"
(change)="saveUsernameOptions()"
[(ngModel)]="usernameOptions.wordCapitalize"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="include-number">{{ "includeNumber" | i18n }}</label>
<input
id="include-number"
type="checkbox"
(change)="saveUsernameOptions()"
[(ngModel)]="usernameOptions.wordIncludeNumber"
/>
</div>
</div>
</div>
</ng-container>
</div>
<div class="modal-footer">
<button
type="button"
class="primary"
appBlurClick
*ngIf="comingFromAddEdit"
(click)="select()"
appA11yTitle="{{ 'select' | i18n }}"
>
<i class="bwi bwi-lg bwi-fw bwi-check" aria-hidden="true"></i>
</button>
<button type="button" data-dismiss="modal">
{{ (comingFromAddEdit ? "cancel" : "close") | i18n }}
</button>
</div>
</div>
</div>
</div>

View File

@ -1,7 +1,7 @@
import { Component } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { PasswordGeneratorComponent as BasePasswordGeneratorComponent } from "jslib-angular/components/password-generator.component";
import { GeneratorComponent as BaseGeneratorComponent } from "jslib-angular/components/generator.component";
import { I18nService } from "jslib-common/abstractions/i18n.service";
import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service";
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
@ -9,10 +9,10 @@ import { StateService } from "jslib-common/abstractions/state.service";
import { UsernameGenerationService } from "jslib-common/abstractions/usernameGeneration.service";
@Component({
selector: "app-password-generator",
templateUrl: "password-generator.component.html",
selector: "app-generator",
templateUrl: "generator.component.html",
})
export class PasswordGeneratorComponent extends BasePasswordGeneratorComponent {
export class GeneratorComponent extends BaseGeneratorComponent {
constructor(
passwordGenerationService: PasswordGenerationService,
usernameGenerationService: UsernameGenerationService,
@ -31,4 +31,8 @@ export class PasswordGeneratorComponent extends BasePasswordGeneratorComponent {
window
);
}
usernameTypesLearnMore() {
this.platformUtilsService.launchUri("https://bitwarden.com/help/generator/#username-types");
}
}

View File

@ -10,7 +10,7 @@
<div class="box-content-row box-content-row-flex" *ngFor="let h of history">
<div class="row-main">
<div
class="password-wrapper monospaced"
class="generated-wrapper monospaced"
appSelectCopy
[innerHTML]="h.password | colorPassword"
></div>

View File

@ -1,230 +0,0 @@
<div
class="modal fade"
role="dialog"
aria-modal="true"
attr.aria-label="{{ 'generatePassword' | i18n }}"
>
<div class="modal-dialog modal-sm" role="document">
<div class="modal-content">
<div class="modal-body">
<app-callout type="info" *ngIf="enforcedPasswordPolicyOptions?.inEffect()">
{{ "passwordGeneratorPolicyInEffect" | i18n }}
</app-callout>
<div class="password-block">
<div class="password-wrapper" [innerHTML]="password | colorPassword" appSelectCopy></div>
</div>
<div class="box">
<div class="box-content condensed">
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="regenerate()">
<i class="bwi bwi-fw bwi-generate" aria-hidden="true"></i>
{{ "regeneratePassword" | i18n }}
</a>
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="copy()">
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i> {{ "copyPassword" | i18n }}
</a>
</div>
</div>
<div class="box">
<div class="box-header">
<button
type="button"
(click)="toggleOptions()"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
>
<i class="bwi bwi-plus-square" aria-hidden="true" [hidden]="showOptions"></i>
<i class="bwi bwi-minus-square" aria-hidden="true" [hidden]="!showOptions"></i>
{{ "options" | i18n }}
</button>
</div>
<div class="box-content condensed" [hidden]="!showOptions">
<div class="box-content-row box-content-row-radio">
<label class="sr-only radio-header">{{ "type" | i18n }}</label>
<div
class="radio-group text-default"
appBoxRow
name="PassTypeOptions"
*ngFor="let o of passTypeOptions"
>
<input
type="radio"
class="radio"
[(ngModel)]="passwordOptions.type"
name="Type_{{ o.value }}"
id="type_{{ o.value }}"
[value]="o.value"
(change)="savePasswordOptions()"
[checked]="passwordOptions.type === o.value"
/>
<label class="unstyled" for="type_{{ o.value }}">
{{ o.name }}
</label>
</div>
</div>
</div>
</div>
<div class="box" [hidden]="!showOptions" *ngIf="passwordOptions.type === 'passphrase'">
<div class="box-content condensed">
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="num-words">{{ "numWords" | i18n }}</label>
<input
id="num-words"
type="number"
min="3"
max="20"
(blur)="savePasswordOptions()"
[(ngModel)]="passwordOptions.numWords"
/>
</div>
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="word-separator">{{ "wordSeparator" | i18n }}</label>
<input
id="word-separator"
type="text"
maxlength="1"
(input)="savePasswordOptions()"
[(ngModel)]="passwordOptions.wordSeparator"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="capitalize">{{ "capitalize" | i18n }}</label>
<input
id="capitalize"
type="checkbox"
(change)="savePasswordOptions()"
[(ngModel)]="passwordOptions.capitalize"
[disabled]="enforcedPasswordPolicyOptions?.capitalize"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="include-number">{{ "includeNumber" | i18n }}</label>
<input
id="include-number"
type="checkbox"
(change)="savePasswordOptions()"
[(ngModel)]="passwordOptions.includeNumber"
[disabled]="enforcedPasswordPolicyOptions?.includeNumber"
/>
</div>
</div>
</div>
<ng-container *ngIf="passwordOptions.type === 'password'">
<div class="box" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row box-content-row-slider" appBoxRow>
<label for="length">{{ "length" | i18n }}</label>
<input
id="length"
type="number"
min="5"
max="128"
[(ngModel)]="passwordOptions.length"
(blur)="savePasswordOptions()"
/>
<input
id="lengthRange"
type="range"
min="5"
max="128"
step="1"
[(ngModel)]="passwordOptions.length"
(change)="sliderChanged()"
(input)="sliderInput()"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="uppercase">A-Z</label>
<input
id="uppercase"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useUppercase"
[(ngModel)]="passwordOptions.uppercase"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="lowercase">a-z</label>
<input
id="lowercase"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useLowercase"
[(ngModel)]="passwordOptions.lowercase"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="numbers">0-9</label>
<input
id="numbers"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useNumbers"
[(ngModel)]="passwordOptions.number"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="special">!@#$%^&*</label>
<input
id="special"
type="checkbox"
(change)="savePasswordOptions()"
[disabled]="enforcedPasswordPolicyOptions?.useSpecial"
[(ngModel)]="passwordOptions.special"
/>
</div>
</div>
</div>
<div class="box" [hidden]="!showOptions">
<div class="box-content condensed">
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="min-number">{{ "minNumbers" | i18n }}</label>
<input
id="min-number"
type="number"
min="0"
max="9"
(blur)="savePasswordOptions()"
[(ngModel)]="passwordOptions.minNumber"
/>
</div>
<div class="box-content-row box-content-row-input" appBoxRow>
<label for="min-special">{{ "minSpecial" | i18n }}</label>
<input
id="min-special"
type="number"
min="0"
max="9"
(blur)="savePasswordOptions()"
[(ngModel)]="passwordOptions.minSpecial"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="ambiguous">{{ "ambiguous" | i18n }}</label>
<input
id="ambiguous"
type="checkbox"
(change)="savePasswordOptions()"
[(ngModel)]="avoidAmbiguous"
/>
</div>
</div>
</div>
</ng-container>
</div>
<div class="modal-footer">
<button
type="button"
class="primary"
appBlurClick
*ngIf="showSelect"
(click)="select()"
appA11yTitle="{{ 'select' | i18n }}"
>
<i class="bwi bwi-lg bwi-fw bwi-check" aria-hidden="true"></i>
</button>
<button type="button" data-dismiss="modal">
{{ (showSelect ? "cancel" : "close") | i18n }}
</button>
</div>
</div>
</div>
</div>

View File

@ -37,7 +37,8 @@
(onCancelled)="cancelledAddEdit($event)"
(onShareCipher)="shareCipher($event)"
(onEditCollections)="cipherCollections($event)"
(onGeneratePassword)="openPasswordGenerator(true)"
(onGeneratePassword)="openGenerator(true, true)"
(onGenerateUsername)="openGenerator(true, false)"
>
</app-vault-add-edit>
<div
@ -65,7 +66,7 @@
>
</app-vault-groupings>
</div>
<ng-template #passwordGenerator></ng-template>
<ng-template #generator></ng-template>
<ng-template #attachments></ng-template>
<ng-template #collections></ng-template>
<ng-template #share></ng-template>

View File

@ -35,8 +35,8 @@ import { AttachmentsComponent } from "./attachments.component";
import { CiphersComponent } from "./ciphers.component";
import { CollectionsComponent } from "./collections.component";
import { FolderAddEditComponent } from "./folder-add-edit.component";
import { GeneratorComponent } from "./generator.component";
import { GroupingsComponent } from "./groupings.component";
import { PasswordGeneratorComponent } from "./password-generator.component";
import { PasswordHistoryComponent } from "./password-history.component";
import { ShareComponent } from "./share.component";
import { ViewComponent } from "./view.component";
@ -52,8 +52,8 @@ export class VaultComponent implements OnInit, OnDestroy {
@ViewChild(AddEditComponent) addEditComponent: AddEditComponent;
@ViewChild(CiphersComponent, { static: true }) ciphersComponent: CiphersComponent;
@ViewChild(GroupingsComponent, { static: true }) groupingsComponent: GroupingsComponent;
@ViewChild("passwordGenerator", { read: ViewContainerRef, static: true })
passwordGeneratorModalRef: ViewContainerRef;
@ViewChild("generator", { read: ViewContainerRef, static: true })
generatorModalRef: ViewContainerRef;
@ViewChild("attachments", { read: ViewContainerRef, static: true })
attachmentsModalRef: ViewContainerRef;
@ViewChild("passwordHistory", { read: ViewContainerRef, static: true })
@ -120,8 +120,8 @@ export class VaultComponent implements OnInit, OnDestroy {
(document.querySelector("#search") as HTMLInputElement).select();
detectChanges = false;
break;
case "openPasswordGenerator":
await this.openPasswordGenerator(false);
case "openGenerator":
await this.openGenerator(false);
break;
case "syncCompleted":
await this.load();
@ -599,28 +599,38 @@ export class VaultComponent implements OnInit, OnDestroy {
this.go();
}
async openPasswordGenerator(showSelect: boolean) {
async openGenerator(comingFromAddEdit: boolean, passwordType = true) {
if (this.modal != null) {
this.modal.close();
}
const cipher = this.addEditComponent?.cipher;
const loginType = cipher != null && cipher.type === CipherType.Login && cipher.login != null;
const [modal, childComponent] = await this.modalService.openViewRef(
PasswordGeneratorComponent,
this.passwordGeneratorModalRef,
(comp) => (comp.showSelect = showSelect)
GeneratorComponent,
this.generatorModalRef,
(comp) => {
comp.comingFromAddEdit = comingFromAddEdit;
if (comingFromAddEdit) {
comp.type = passwordType ? "password" : "username";
if (loginType && cipher.login.hasUris && cipher.login.uris[0].hostname != null) {
comp.usernameWebsite = cipher.login.uris[0].hostname;
}
}
}
);
this.modal = modal;
childComponent.onSelected.subscribe((password: string) => {
childComponent.onSelected.subscribe((value: string) => {
this.modal.close();
if (
this.addEditComponent != null &&
this.addEditComponent.cipher != null &&
this.addEditComponent.cipher.type === CipherType.Login &&
this.addEditComponent.cipher.login != null
) {
if (loginType) {
this.addEditComponent.markPasswordAsDirty();
this.addEditComponent.cipher.login.password = password;
if (passwordType) {
this.addEditComponent.cipher.login.password = value;
} else {
this.addEditComponent.cipher.login.username = value;
}
}
});

View File

@ -47,7 +47,7 @@
</div>
<div
*ngIf="showPassword"
class="monospaced password-wrapper"
class="monospaced generated-wrapper"
appSelectCopy
[innerHTML]="cipher.login.password | colorPassword"
></div>
@ -79,6 +79,7 @@
href="#"
appStopClick
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showPassword"
(click)="togglePassword()"
role="button"
>
@ -161,6 +162,7 @@
href="#"
appStopClick
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showCardNumber"
(click)="toggleCardNumber()"
role="button"
>
@ -202,6 +204,7 @@
href="#"
appStopClick
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
[attr.aria-pressed]="showCardCode"
(click)="toggleCardCode()"
role="button"
>

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Is u seker u wil oor die huidige wagwoord skryf?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Geen Vouer",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Hierdie wagwoord is in geen bekende databreuke gevind nie. Dit behoort veilig vir gebruik te wees."
},
"baseDomain": {
"message": "Basisdomein"
"message": "Basisdomein",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Gasheer",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Hazırkı parolun üzərinə yazmaq istədiyinizə əminsiniz?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Qovluq yoxdur",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Bu parol, məlumat pozuntularında qeydə alınmayıb. Rahatlıqla istifadə edə bilərsiniz."
},
"baseDomain": {
"message": "Baza domeni"
"message": "Baza domeni",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Вы ўпэўнены, што хочаце перазапісаць бягучы пароль?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Без папкі",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Гэты пароль не быў знойдзены ў вядомых базах уцечак. Можна працягваць яго выкарыстоўваць."
},
"baseDomain": {
"message": "Асноўны дамен"
"message": "Асноўны дамен",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Хост",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Сигурни ли сте, че искате да обновите текущата парола?"
},
"overwriteUsername": {
"message": "Замяна на потребителското име"
},
"overwriteUsernameConfirmation": {
"message": "Наостина ли искате да замените текущото потребителско име?"
},
"noneFolder": {
"message": "Няма папка",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Паролата не е била разкрита в известните пробиви. Засега ползването ѝ изглежда безопасно."
},
"baseDomain": {
"message": "Основен домейн"
"message": "Основен домейн",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Име на домейн",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Сървър",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Генератор"
},
"whatWouldYouLikeToGenerate": {
"message": "Какво бихте искали да генерирате?"
},
"passwordType": {
"message": "Тип парола"
},
"regenerateUsername": {
"message": "Повторно генериране на потр. име"
},
"generateUsername": {
"message": "Генериране на потр. име"
},
"usernameType": {
"message": "Тип потребителско име"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Използвайте възможностите за под-адресиране на е-поща на своя доставчик."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Произволно"
},
"randomWord": {
"message": "Произволна дума"
},
"websiteName": {
"message": "Име на уеб сайт"
},
"service": {
"message": "Услуга"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "আপনি কি নিশ্চিত যে আপনি বর্তমান পাসওয়ার্ডটি ওভাররাইট করতে চান?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "কোন ফোল্ডার নেই",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "এই পাসওয়ার্ডটি কোনও পরিচিত তথ্য লঙ্ঘনে পাওয়া যায় নি। এটি ব্যবহার করা নিরাপদ হওয়া উচিত।"
},
"baseDomain": {
"message": "ভিত্তি ডোমেইন"
"message": "ভিত্তি ডোমেইন",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "নিয়ন্ত্রণকর্তা",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Da li ste sigurni da želite da zamijenite trenutnu lozinku?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Nema foldera",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "This password was not found in any known data breaches. It should be safe to use."
},
"baseDomain": {
"message": "Base domain"
"message": "Base domain",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Esteu segur que voleu sobreescriure la contrasenya actual?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Cap carpeta",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Aquesta contrasenya no s'ha trobat en cap filtració de dades coneguda. Hauries de poder utilitzar-la de manera segura."
},
"baseDomain": {
"message": "Domini base"
"message": "Domini base",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Amfitrió",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Opravdu chcete přepsat aktuální heslo?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Žádná složka",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": " V žádném ze známých případů nedošlo k úniku tohoto hesla. Mělo by být bezpečné používat jej i nadále."
},
"baseDomain": {
"message": "Základní doména"
"message": "Základní doména",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Er du sikker på, at du vil overskrive den aktuelle adgangskode?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Ingen mappe",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Denne adgangskode er ikke fundet i nogen kendte datalæk. Den burde være sikker at bruge."
},
"baseDomain": {
"message": "Grund-domæne"
"message": "Grund-domæne",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Vært",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Bist du sicher, dass du das Passwort überschreiben möchtest?"
},
"overwriteUsername": {
"message": "Benutzername überschreiben"
},
"overwriteUsernameConfirmation": {
"message": "Bist du sicher, dass du den aktuellen Benutzernamen überschreiben möchtest?"
},
"noneFolder": {
"message": "Kein Ordner",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Dieses Kennwort wurde in keinen bekannten Datensätzen gefunden. Es sollte sicher sein."
},
"baseDomain": {
"message": "Basis-Domäne"
"message": "Basis-Domäne",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain-Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Server",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "Was möchtest du generieren?"
},
"passwordType": {
"message": "Passworttyp"
},
"regenerateUsername": {
"message": "Benutzername neu generieren"
},
"generateUsername": {
"message": "Benutzernamen generieren"
},
"usernameType": {
"message": "Benutzernamentyp"
},
"plusAddressedEmail": {
"message": "Mit Plus adressierte E-Mail"
},
"plusAddressedEmailDesc": {
"message": "Verwende die Unteradressierungsmöglichkeiten deines E-Mail-Providers."
},
"catchallEmail": {
"message": "Catch-All E-Mail-Adresse"
},
"catchallEmailDesc": {
"message": "Verwende den konfigurierten Catch-All-Posteingang deiner Domain."
},
"random": {
"message": "Zufällig"
},
"randomWord": {
"message": "Zufälliges Wort"
},
"websiteName": {
"message": "Webseiten-Name"
},
"service": {
"message": "Dienst"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Είστε βέβαιοι ότι θέλετε να αντικαταστήσετε τον τρέχον κωδικό πρόσβασης;"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Χωρίς Φάκελο",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Αυτός ο κωδικός δεν βρέθηκε σε κάποια γνωστή διαρροή δεδομένων. Θα πρέπει να είναι ασφαλής για χρήση."
},
"baseDomain": {
"message": "Βασικός τομέας"
"message": "Βασικός τομέας",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "No Folder",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "This password was not found in any known data breaches. It should be safe to use."
},
"baseDomain": {
"message": "Base domain"
"message": "Base domain",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "No folder",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "This password was not found in any known data breaches. It should be safe to use."
},
"baseDomain": {
"message": "Base domain"
"message": "Base domain",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "No Folder",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "This password was not found in any known data breaches. It should be safe to use."
},
"baseDomain": {
"message": "Base domain"
"message": "Base domain",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "¿Estás seguro de que quieres sobreescribir la contraseña actual?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Sin carpeta",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Esta contraseña no fue encontrada en ninguna filtración de datos conocida. Deberías poder utilizarla de forma segura."
},
"baseDomain": {
"message": "Dominio base"
"message": "Dominio base",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Servidor",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Oled kindel, et soovid olemasolevat parooli üle kirjutada?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Kaust puudub",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Seda parooli ei õnnestu andmeleketest leida. Parooli edasi kasutamine peaks olema turvaline."
},
"baseDomain": {
"message": "Baasdomeen"
"message": "Baasdomeen",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "آیا از بازنویسی بر روی پسورد فعلی مطمئن هستید؟"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "بدون پوشه",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "این کلمه عبور در هیچ رخنه داده‌ای شناخته نشده است. باید برای استفاده امن باشد."
},
"baseDomain": {
"message": "دامنه پایه"
"message": "دامنه پایه",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "میزبان",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Haluatko varmasti korvata nykyisen salasanan?"
},
"overwriteUsername": {
"message": "Korvaa käyttäjätunnus"
},
"overwriteUsernameConfirmation": {
"message": "Haluatko varmasti korvata nykyisen käyttäjätunnuksen?"
},
"noneFolder": {
"message": "Ei kansiota",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Salasanaa ei löytynyt tunnetuista tietovuodoista. Sen pitäisi olla turvallinen."
},
"baseDomain": {
"message": "Pääverkkotunnus"
"message": "Pääverkkotunnus",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Verkkotunnus",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Isäntä",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generaattori"
},
"whatWouldYouLikeToGenerate": {
"message": "Mitä haluat luoda?"
},
"passwordType": {
"message": "Salasanan tyyppi"
},
"regenerateUsername": {
"message": "Luo uusi käyttäjätunnus"
},
"generateUsername": {
"message": "Luo käyttäjätunnus"
},
"usernameType": {
"message": "Käyttäjätunnuksen tyyppi"
},
"plusAddressedEmail": {
"message": "Plus-osoitteinen sähköposti"
},
"plusAddressedEmailDesc": {
"message": "Käytä sähköpostipalvelusi aliosoiteominaisuuksia."
},
"catchallEmail": {
"message": "Catch-all-sähköpostiosoite"
},
"catchallEmailDesc": {
"message": "Käytä verkkotunnuksellesi määritettyä catch-all-postilaatikkoa."
},
"random": {
"message": "Satunnainen"
},
"randomWord": {
"message": "Satunnainen sana"
},
"websiteName": {
"message": "Verkkosivuston nimi"
},
"service": {
"message": "Palvelu"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "No Folder",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "This password was not found in any known data breaches. It should be safe to use."
},
"baseDomain": {
"message": "Base domain"
"message": "Base domain",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Êtes-vous sûr de vouloir écraser le mot de passe actuel ?"
},
"overwriteUsername": {
"message": "Remplacer le nom d'utilisateur"
},
"overwriteUsernameConfirmation": {
"message": "Êtes-vous sûr(e) de vouloir remplacer le mot de passe actuel ?"
},
"noneFolder": {
"message": "Aucun dossier",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Ce mot de passe n'a été trouvé dans aucune fuite de données connue. Il semble sécurisé."
},
"baseDomain": {
"message": "Domaine de base"
"message": "Domaine de base",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Nom du domaine",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Hôte",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Générateur"
},
"whatWouldYouLikeToGenerate": {
"message": "Que souhaitez-vous générer ?"
},
"passwordType": {
"message": "Type de mot de passe"
},
"regenerateUsername": {
"message": "Régénérer le nom d'utilisateur"
},
"generateUsername": {
"message": "Générer le nom d'utilisateur"
},
"usernameType": {
"message": "Type de nom d'utilisateur"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Utilisez les capacités de sous-adressage de votre fournisseur de courriel."
},
"catchallEmail": {
"message": "Collecteur d'email"
},
"catchallEmailDesc": {
"message": "Utilisez la boîte de réception du collecteur configurée de votre domaine."
},
"random": {
"message": "Aléatoire"
},
"randomWord": {
"message": "Mots aléatoire"
},
"websiteName": {
"message": "Nom du site Web"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "האם אתה בטוח שברצונך לדרוס את הסיסמה הנוכחית?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "ללא תיקיה",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "הסיסמה לא נמצאה בפריצות אבטחה ידועות. היא בטוחה לשימוש."
},
"baseDomain": {
"message": "שם בסיס הדומיין"
"message": "שם בסיס הדומיין",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "שרת",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "No Folder",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "This password was not found in any known data breaches. It should be safe to use."
},
"baseDomain": {
"message": "Base domain"
"message": "Base domain",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Sigurno želiš prebrisati trenutnu lozinku?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Nema mape",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Lozinka nije pronađena niti u jednoj krađi podataka. Sigurna je za korištenje."
},
"baseDomain": {
"message": "Primarna domena"
"message": "Primarna domena",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Biztosan felülírásra kerüljön a jelenlegi jelszó?"
},
"overwriteUsername": {
"message": "Felhasználónév felülírása"
},
"overwriteUsernameConfirmation": {
"message": "Biztosan felülírásra kerüljön az aktuális felhasználónév?"
},
"noneFolder": {
"message": "Nincs mappa",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Ez a jelszó nem található egyetlen ismert adatszivárgásban sem. Biztonságos a használata."
},
"baseDomain": {
"message": "Alap domain"
"message": "Alap domain",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Tartománynév",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Kiszolgáló",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generátor"
},
"whatWouldYouLikeToGenerate": {
"message": "Mit szeretnénk generálni?"
},
"passwordType": {
"message": "Jelszótípus"
},
"regenerateUsername": {
"message": "Felhasználónév ismételt geneálása"
},
"generateUsername": {
"message": "Felhasználónév generálása"
},
"usernameType": {
"message": "Felhasználónév típusa"
},
"plusAddressedEmail": {
"message": "További címzési email cím"
},
"plusAddressedEmailDesc": {
"message": "Használjuk az email cím szolgáltató alcímzési képességeit."
},
"catchallEmail": {
"message": "Összes email cím begyűjtése"
},
"catchallEmailDesc": {
"message": "Használjuk a tartomány konfigurált összes befogási bejövő postaládát."
},
"random": {
"message": "Véletlen"
},
"randomWord": {
"message": "Véletlenszerű szó"
},
"websiteName": {
"message": "Webhelynév"
},
"service": {
"message": "Szolgáltatás"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Anda yakin ingin menimpa sandi saat ini?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Tidak Ada Folder",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Kata sandi ini tidak di temukan di dalam pelanggaran data yang di kenal. Harusnya aman untuk di gunakan."
},
"baseDomain": {
"message": "Basis domain"
"message": "Basis domain",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Sei sicuro di voler sovrascrivere la password corrente?"
},
"overwriteUsername": {
"message": "Sovrascrivi nome utente"
},
"overwriteUsernameConfirmation": {
"message": "Sei sicuro di voler sovrascrivere il nome utente attuale?"
},
"noneFolder": {
"message": "Nessuna cartella",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Questa password non è stata trovata in dati violati noti. Dovrebbe essere sicura da usare."
},
"baseDomain": {
"message": "Dominio di base"
"message": "Dominio di base",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Nome dominio",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generatore"
},
"whatWouldYouLikeToGenerate": {
"message": "Cosa vorresti generare?"
},
"passwordType": {
"message": "Tipo di password"
},
"regenerateUsername": {
"message": "Rigenera nome utente"
},
"generateUsername": {
"message": "Genera nome utente"
},
"usernameType": {
"message": "Tipo di nome utente"
},
"plusAddressedEmail": {
"message": "Indirizzo di posta alternativo"
},
"plusAddressedEmailDesc": {
"message": "Usa le funzionalità di sub-indirizzamento del tuo fornitore di posta elettronica."
},
"catchallEmail": {
"message": "Email catch-all"
},
"catchallEmailDesc": {
"message": "Usa la casella di posta catch-all di dominio."
},
"random": {
"message": "Casuale"
},
"randomWord": {
"message": "Parola casuale"
},
"websiteName": {
"message": "Nome sito web"
},
"service": {
"message": "Servizio"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "現在のパスワードを上書きしてもよろしいですか?"
},
"overwriteUsername": {
"message": "ユーザー名を上書き"
},
"overwriteUsernameConfirmation": {
"message": "現在のユーザー名を上書きしてもよろしいですか?"
},
"noneFolder": {
"message": "フォルダーなし",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "このパスワードは過去に漏洩したデータ内にはないため、安全であると思われます。"
},
"baseDomain": {
"message": "ベースドメイン"
"message": "ベースドメイン",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "ドメイン名",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "ホスト",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "ジェネレーター"
},
"whatWouldYouLikeToGenerate": {
"message": "何を生成しますか?"
},
"passwordType": {
"message": "パスワードの種類"
},
"regenerateUsername": {
"message": "ユーザー名を再生成"
},
"generateUsername": {
"message": "ユーザー名を生成"
},
"usernameType": {
"message": "ユーザー名の種類"
},
"plusAddressedEmail": {
"message": "プラス付きのメールアドレス"
},
"plusAddressedEmailDesc": {
"message": "メールプロバイダのエイリアス機能を使用します。"
},
"catchallEmail": {
"message": "キャッチオールメール"
},
"catchallEmailDesc": {
"message": "ドメインに設定されたキャッチオール受信トレイを使用します。"
},
"random": {
"message": "ランダム"
},
"randomWord": {
"message": "ランダムな単語"
},
"websiteName": {
"message": "ウェブサイト名"
},
"service": {
"message": "サービス"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "No Folder",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "This password was not found in any known data breaches. It should be safe to use."
},
"baseDomain": {
"message": "Base domain"
"message": "Base domain",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "No Folder",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "This password was not found in any known data breaches. It should be safe to use."
},
"baseDomain": {
"message": "Base domain"
"message": "Base domain",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "ಪ್ರಸ್ತುತ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ತಿದ್ದಿಬರೆಯಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "ಫೋಲ್ಡರ್ ಇಲ್ಲ",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "ತಿಳಿದಿರುವ ಯಾವುದೇ ಡೇಟಾ ಉಲ್ಲಂಘನೆಗಳಲ್ಲಿ ಈ ಪಾಸ್‌ವರ್ಡ್ ಕಂಡುಬಂದಿಲ್ಲ. ಅದನ್ನು ಬಳಸಲು ಸುರಕ್ಷಿತವಾಗಿರಬೇಕು."
},
"baseDomain": {
"message": "ಮೂಲ ಡೊಮೇನ್"
"message": "ಮೂಲ ಡೊಮೇನ್",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "ಅತಿಥೆಯ",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "정말 현재 비밀번호를 덮어쓰시겠습니까?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "폴더 없음",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "이 비밀번호는 데이터 유출 목록에 없습니다. 사용하기에 안전한 비밀번호입니다."
},
"baseDomain": {
"message": "기본 도메인"
"message": "기본 도메인",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "호스트",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Vai tiešām pārrakstīt esošo paroli?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Nav mapes",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Šī parole netika atrasta nevienā no zināmajiem datu pārkāpumiem. Tai vajadzētu būt droši izmantojamai."
},
"baseDomain": {
"message": "Pamata domēns"
"message": "Pamata domēns",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Saimniekdators",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Jeste li sigurni da želite da zamijenite trenutnu lozinku?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Nema fascikle",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Ova lozinka nije pronađena ni u jednoj poznatoj krađi podataka. Trebala bi biti sigurna za upotrebu."
},
"baseDomain": {
"message": "Osnovni domen"
"message": "Osnovni domen",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Lokalna instalacija (HOST)",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "നിലവിലെ പാസ്‌വേഡ് പുനരാലേഖനം ചെയ്യണമെന്ന് നിങ്ങൾക്ക് ഉറപ്പാണോ?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "ഫോൾഡർ ഇല്ല",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "അറിയപ്പെടുന്ന ഡാറ്റാ ലംഘനങ്ങളിൽ ഒന്നും ഈ പാസ്‌വേഡ് കണ്ടെത്തിയില്ല. ഇത് ഉപയോഗിക്കുന്നത് സുരക്ഷിതമായിരിക്കും."
},
"baseDomain": {
"message": "അടിസ്ഥാന ഡൊമെയ്ൻ"
"message": "അടിസ്ഥാന ഡൊമെയ്ൻ",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "ഹോസ്റ്റ്",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Er du sikker på at du vil overskrive det nåværende passordet?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Ingen mappe",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Dette passordet ble ikke funnet i noen kjente databrudd. Det burde være trygt å bruke."
},
"baseDomain": {
"message": "Grunndomene"
"message": "Grunndomene",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Vert",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Weet je zeker dat je het huidige wachtwoord wilt overschrijven?"
},
"overwriteUsername": {
"message": "Gebruikersnaam overschrijven"
},
"overwriteUsernameConfirmation": {
"message": "Weet je zeker dat je de huidige gebruikersnaam wilt overschrijven?"
},
"noneFolder": {
"message": "Geen map",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Dit wachtwoord is niet gevonden in de bekende gegevenslekken. Het kan veilig gebruikt worden."
},
"baseDomain": {
"message": "Basisdomein"
"message": "Basisdomein",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domeinnaam",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Hostnaam",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "Wat wil je genereren?"
},
"passwordType": {
"message": "Type wachtwoord"
},
"regenerateUsername": {
"message": "Gebruikersnaam opnieuw genereren"
},
"generateUsername": {
"message": "Gebruikersnamen genereren"
},
"usernameType": {
"message": "Type gebruikersnaam"
},
"plusAddressedEmail": {
"message": "E-mailadres-met-plus"
},
"plusAddressedEmailDesc": {
"message": "Gebruik de subadressen van je e-mailprovider."
},
"catchallEmail": {
"message": "Catch-all e-mail"
},
"catchallEmailDesc": {
"message": "Gebruik de catch-all inbox van je domein."
},
"random": {
"message": "Willekeurig"
},
"randomWord": {
"message": "Willekeurig woord"
},
"websiteName": {
"message": "Websitenaam"
},
"service": {
"message": "Dienst"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "No Folder",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "This password was not found in any known data breaches. It should be safe to use."
},
"baseDomain": {
"message": "Base domain"
"message": "Base domain",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Czy na pewno chcesz zastąpić obecne hasło?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Nieprzypisane",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "To hasło nie znajduje się w żadnej znanej wykradzionej bazie danych. Powinno być bezpieczne w użyciu."
},
"baseDomain": {
"message": "Domena podstawowa"
"message": "Domena podstawowa",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Você tem certeza que deseja substituir a senha atual?"
},
"overwriteUsername": {
"message": "Overwrite Username"
},
"overwriteUsernameConfirmation": {
"message": "Are you sure you want to overwrite the current username?"
},
"noneFolder": {
"message": "Nenhuma Pasta",
"description": "This is the folder for uncategorized items"
@ -737,10 +743,10 @@
"message": "Gerador de Senha"
},
"contactUs": {
"message": "Contact Us"
"message": "Fale Conosco"
},
"getHelp": {
"message": "Get Help"
"message": "Obter Ajuda"
},
"fileBugReport": {
"message": "Enviar um Relatório de Bug"
@ -1188,7 +1194,12 @@
"message": "Esta senha não foi encontrada em brechas de dados conhecidas. Deve ser seguro de usar."
},
"baseDomain": {
"message": "Domínio de base"
"message": "Domínio de base",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Domain Name",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Servidor",
@ -1815,18 +1826,60 @@
"message": "Opções"
},
"sessionTimeout": {
"message": "Your session has timed out. Please go back and try logging in again."
"message": "Sua sessão expirou. Por favor, volte e tente iniciar a sessão novamente."
},
"exportingPersonalVaultTitle": {
"message": "Exporting Personal Vault"
"message": "Exportação do Cofre Pessoal"
},
"exportingPersonalVaultDescription": {
"message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.",
"message": "Apenas os itens pessoais do cofre associados com $EMAIL$ serão exportados. Os itens do cofre da organização não serão incluídos.",
"placeholders": {
"email": {
"content": "$1",
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "What would you like to generate?"
},
"passwordType": {
"message": "Password Type"
},
"regenerateUsername": {
"message": "Regenerate Username"
},
"generateUsername": {
"message": "Generate Username"
},
"usernameType": {
"message": "Username Type"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Catch-all Email"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Random"
},
"randomWord": {
"message": "Random Word"
},
"websiteName": {
"message": "Website Name"
},
"service": {
"message": "Service"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Sigur doriți să suprascrieți parola curentă?"
},
"overwriteUsername": {
"message": "Suprascrieți numele de utilizator"
},
"overwriteUsernameConfirmation": {
"message": "Sunteți sigur că doriți să suprascrieți numele de utilizator curent?"
},
"noneFolder": {
"message": "Fără dosar",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Aceasta parola nu a fost găsită în nicio breșă de date cunoscută. Ar trebui să fie sigură de utilizat."
},
"baseDomain": {
"message": "Domeniu de bază"
"message": "Domeniu de bază",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Nume de domeniu",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Gazdă",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Generator"
},
"whatWouldYouLikeToGenerate": {
"message": "Ce doriți să generați?"
},
"passwordType": {
"message": "Tip de parolă"
},
"regenerateUsername": {
"message": "Regenerare nume de utilizator"
},
"generateUsername": {
"message": "Generare nume de utilizator"
},
"usernameType": {
"message": "Tip de nume de utilizator"
},
"plusAddressedEmail": {
"message": "Plus e-mail adresat"
},
"plusAddressedEmailDesc": {
"message": "Utilizați capacitățile de subadresare ale furnizorului dvs. de e-mail."
},
"catchallEmail": {
"message": "E-mail Catch-all"
},
"catchallEmailDesc": {
"message": "Utilizați inbox-ul catch-all configurat pentru domeniul dvs."
},
"random": {
"message": "Aleatoriu"
},
"randomWord": {
"message": "Cuvânt aleatoriu"
},
"websiteName": {
"message": "Numele site-ului web"
},
"service": {
"message": "Serviciu"
}
}

View File

@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Вы уверены, что хотите переписать текущий пароль?"
},
"overwriteUsername": {
"message": "Перезаписать имя пользователя"
},
"overwriteUsernameConfirmation": {
"message": "Вы уверены, что хотите перезаписать текущее имя пользователя?"
},
"noneFolder": {
"message": "Без папки",
"description": "This is the folder for uncategorized items"
@ -1188,7 +1194,12 @@
"message": "Этот пароль не обнаружен в известных базах утечек. Можно продолжать его использовать."
},
"baseDomain": {
"message": "Основной домен"
"message": "Основной домен",
"description": "Domain name. Ex. website.com"
},
"domainName": {
"message": "Доменное имя",
"description": "Domain name. Ex. website.com"
},
"host": {
"message": "Хост",
@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
},
"generator": {
"message": "Генератор"
},
"whatWouldYouLikeToGenerate": {
"message": "Что вы хотите сгенерировать?"
},
"passwordType": {
"message": "Тип пароля"
},
"regenerateUsername": {
"message": "Восстановить имя пользователя"
},
"generateUsername": {
"message": "Создать имя пользователя"
},
"usernameType": {
"message": "Тип имени пользователя"
},
"plusAddressedEmail": {
"message": "Plus Addressed Email"
},
"plusAddressedEmailDesc": {
"message": "Use your email provider's sub-addressing capabilities."
},
"catchallEmail": {
"message": "Универсальная электронная почта"
},
"catchallEmailDesc": {
"message": "Use your domain's configured catch-all inbox."
},
"random": {
"message": "Случайно"
},
"randomWord": {
"message": "Случайное слово"
},
"websiteName": {
"message": "Название сайта"
},
"service": {
"message": "Service"
}
}

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