mirror of
https://github.com/bitwarden/browser
synced 2026-02-17 09:59:41 +00:00
Merge branch 'master' into feature/i18n-component-template
This commit is contained in:
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "التعبئة التلقائية"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "إنشاء كلمة مرور (تم النسخ)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "لا توجد تسجيلات دخول مطابقة."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "افتح خزنتك"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Avto-doldurma"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Giriş avto-doldurma"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Kart avto-doldurma"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Kimlik avto-doldurma"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Parol yarat (kopyalandı)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Uyğun gələn hesab yoxdur."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Kart yoxdur"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Kimlik yoxdur"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Giriş əlavə et"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Kart əlavə et"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Kimlik əlavə et"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Anbarın kilidini açın"
|
||||
},
|
||||
@@ -671,7 +695,7 @@
|
||||
"description": "'Solarized' is a noun and the name of a color scheme. It should not be translated."
|
||||
},
|
||||
"exportVault": {
|
||||
"message": "Anbarı ixrac et"
|
||||
"message": "Anbarı xaricə köçür"
|
||||
},
|
||||
"fileFormat": {
|
||||
"message": "Fayl formatı"
|
||||
@@ -681,19 +705,19 @@
|
||||
"description": "WARNING (should stay in capitalized letters if the language permits)"
|
||||
},
|
||||
"confirmVaultExport": {
|
||||
"message": "Anbarın ixracını təsdiqləyin"
|
||||
"message": "Anbarın xaricə köçürülməsini təsdiqləyin"
|
||||
},
|
||||
"exportWarningDesc": {
|
||||
"message": "Bu ixrac faylındakı anbar verilənləriniz şifrələnməmiş formatdadır. İxrac edilən faylı, güvənli olmayan kanallar üzərində saxlamamalı və ya göndərməməlisiniz (e-poçt kimi). Bu faylı işiniz bitdikdən sonra dərhal silin."
|
||||
"message": "Xaricə köçürdüyünüz bu fayldakı datanız şifrələnməmiş formatdadır. Bu faylı güvənli olmayan kanallar (e-poçt kimi) üzərində saxlamamalı və ya göndərməməlisiniz. İşiniz bitdikdən sonra faylı dərhal silin."
|
||||
},
|
||||
"encExportKeyWarningDesc": {
|
||||
"message": "Bu ixrac faylı, hesabınızın şifrələmə açarını istifadə edərək verilənlərinizi şifrələyir. Hesabınızın şifrələmə açarını döndərsəniz, bu ixrac faylının şifrəsini aça bilməyəcəyiniz üçün yenidən ixrac etməli olacaqsınız."
|
||||
"message": "Xaricə köçürdüyünüz bu fayldakı data, hesabınızın şifrələmə açarı istifadə edilərək şifrələnir. Hesabınızın şifrələmə açarını dəyişdirsəniz, bu faylın şifrəsini aça bilməyəcəksiniz və onu yenidən xaricə köçürməli olacaqsınız."
|
||||
},
|
||||
"encExportAccountWarningDesc": {
|
||||
"message": "Hesab şifrələmə açarları, hər Bitwarden istifadəçi hesabı üçün unikaldır, buna görə də şifrələnmiş bir ixracı, fərqli bir hesaba idxal edə bilməzsiniz."
|
||||
},
|
||||
"exportMasterPassword": {
|
||||
"message": "Anbar verilənlərinizi ixrac etmək üçün ana parolunuzu daxil edin."
|
||||
"message": "Anbar datanızı xaricə köçürmək üçün ana parolunuzu daxil edin."
|
||||
},
|
||||
"shared": {
|
||||
"message": "Paylaşılan"
|
||||
@@ -799,7 +823,7 @@
|
||||
"message": "YubiKey və Duo kimi mülkiyyətçi iki addımlı giriş seçimləri."
|
||||
},
|
||||
"ppremiumSignUpReports": {
|
||||
"message": "Anbarınızın təhlükəsiyini təmin etmək üçün parol gigiyenası, hesab sağlamlığı və verilənlərin pozulması hesabatları."
|
||||
"message": "Anbarınızın təhlükəsizliyini təmin etmək üçün parol gigiyenası, hesab sağlamlığı və data pozuntusu hesabatları."
|
||||
},
|
||||
"ppremiumSignUpTotp": {
|
||||
"message": "Anbarınızdakı hesablar üçün TOTP təsdiqləmə kodu (2FA) yaradıcısı."
|
||||
@@ -2408,18 +2432,18 @@
|
||||
"description": "Toggling an expand/collapse state."
|
||||
},
|
||||
"aliasDomain": {
|
||||
"message": "Alias domain"
|
||||
"message": "Domen ləqəbi"
|
||||
},
|
||||
"passwordRepromptDisabledAutofillOnPageLoad": {
|
||||
"message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.",
|
||||
"message": "\"Ana parolu təkrar soruş\" özəlliyi olan elementlər səhifə yüklənəndə avto-doldurulmur. \"Səhifə yüklənəndə avto-doldurma\" özəlliyi söndürülüb.",
|
||||
"description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load."
|
||||
},
|
||||
"autofillOnPageLoadSetToDefault": {
|
||||
"message": "Auto-fill on page load set to use default setting.",
|
||||
"message": "\"Səhifə yüklənəndə avto-doldurma\" özəlliyi ilkin tənzimləməni istifadə etmək üzrə tənzimləndi.",
|
||||
"description": "Toast message for informing the user that auto-fill on page load has been set to the default setting."
|
||||
},
|
||||
"turnOffMasterPasswordPromptToEditField": {
|
||||
"message": "Turn off master password re-prompt to edit this field",
|
||||
"message": "Bu sahəyə düzəliş etmək üçün \"Ana parolu təkrar soruş\"u söndürün",
|
||||
"description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Аўтазапаўненне"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Генерыраваць пароль (з капіяваннем)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Няма адпаведных лагінаў."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Разблакіраваць сховішча"
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"message": "Впишете се или създайте нов абонамент, за да достъпите защитен трезор."
|
||||
},
|
||||
"createAccount": {
|
||||
"message": "Създаване на абонамент"
|
||||
"message": "Създаване на акаунт"
|
||||
},
|
||||
"login": {
|
||||
"message": "Вписване"
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Автоматично дописване"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Авт. попълване на данни за вход"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Самопопълваща се карта"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Самопопълваща се самоличност"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Генериране на парола (копирана)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Няма съвпадащи записи."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Няма карти"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Няма самоличности"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Добавяне на запис за вход"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Добавяне на карта"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Добавяне на самоличност"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Отключете трезора си"
|
||||
},
|
||||
@@ -467,7 +491,7 @@
|
||||
"message": "Грешен код за потвърждаване"
|
||||
},
|
||||
"valueCopied": {
|
||||
"message": "$VALUE$ — копирано",
|
||||
"message": "Копирано е $VALUE$",
|
||||
"description": "Value has been copied to the clipboard.",
|
||||
"placeholders": {
|
||||
"value": {
|
||||
@@ -537,7 +561,7 @@
|
||||
"message": "Копирана парола"
|
||||
},
|
||||
"uri": {
|
||||
"message": "Адрес"
|
||||
"message": "Унифициран идентификатор на ресурс"
|
||||
},
|
||||
"uriPosition": {
|
||||
"message": "Адрес $POSITION$",
|
||||
@@ -550,7 +574,7 @@
|
||||
}
|
||||
},
|
||||
"newUri": {
|
||||
"message": "Нов адрес"
|
||||
"message": "Нов унифициран идентификатор на ресурс"
|
||||
},
|
||||
"addedItem": {
|
||||
"message": "Елементът е добавен"
|
||||
@@ -631,7 +655,7 @@
|
||||
"message": "Да се обнови ли паролата в Bitwarden?"
|
||||
},
|
||||
"notificationChangeSave": {
|
||||
"message": "Да, нека се обнови сега"
|
||||
"message": "Осъвременяване"
|
||||
},
|
||||
"notificationUnlockDesc": {
|
||||
"message": "Отключете трезора си в Битуорден, за да завършите заявката за автоматично попълване."
|
||||
@@ -684,7 +708,7 @@
|
||||
"message": "Потвърждаване на изнасянето на трезора"
|
||||
},
|
||||
"exportWarningDesc": {
|
||||
"message": "Данните от трезора ви ще се изнесат в незащитен формат. Не го пращайте по незащитени канали като е-поща. Изтрийте файла незабавно след като свършите работата си с него."
|
||||
"message": "Този износ съдържа данни на трезора ви в некриптиран формат. Не трябва да съхранявате или изпращате износния файл през незащитени канали (като имейл). Изтрийте файла моментално след като свършите работата си с него."
|
||||
},
|
||||
"encExportKeyWarningDesc": {
|
||||
"message": "При изнасяне данните се шифрират с ключа ви. Ако го смените, ще трябва наново да ги изнесете, защото няма да може да дешифрирате настоящия файл."
|
||||
@@ -699,10 +723,10 @@
|
||||
"message": "Споделено"
|
||||
},
|
||||
"learnOrg": {
|
||||
"message": "Разберете повече за организациите"
|
||||
"message": "Научете за организациите"
|
||||
},
|
||||
"learnOrgConfirmation": {
|
||||
"message": "Битуорден позволява да споделяте части от трезора си чрез използването на организация. Искате ли да научите повече от сайта bitwarden.com?"
|
||||
"message": "Битуорден позволява да споделяте елементи от трезора си а други, използвайки организация. Бихте ли посетили сайта bitwarden.com, за да научите повече?"
|
||||
},
|
||||
"moveToOrganization": {
|
||||
"message": "Преместване в организация"
|
||||
@@ -781,7 +805,7 @@
|
||||
"message": "Управление на абонамента"
|
||||
},
|
||||
"premiumManageAlert": {
|
||||
"message": "Можете да управлявате абонамента си през сайта bitwarden.com. Искате ли да го посетите сега?"
|
||||
"message": "Може да управлявате членството си в мрежата на трезора в bitwarden.com. Искате ли да посетите уебсайта сега?"
|
||||
},
|
||||
"premiumRefresh": {
|
||||
"message": "Опресняване на абонамента"
|
||||
@@ -901,7 +925,7 @@
|
||||
"message": "Регистрацията е защитена с двустепенно удостоверяване, но никой от настроените доставчици на удостоверяване не се поддържа от този браузър."
|
||||
},
|
||||
"noTwoStepProviders2": {
|
||||
"message": "Пробвайте с поддържан уеб браузър (като Chrome или Firefox) и други доставчици на удостоверяване, които се поддържат от браузърите (като специални програми за удостоверяване)."
|
||||
"message": "Употребявайте поддържан браузър (като Chrome, Firefox) и/или добавете други доставчици на удостоверяване, които се поддържат по-добре от браузърите (като специални програми за удостоверяване)."
|
||||
},
|
||||
"twoStepOptions": {
|
||||
"message": "Настройки на двустепенното удостоверяване"
|
||||
@@ -920,10 +944,10 @@
|
||||
"description": "'Authy' and 'Google Authenticator' are product names and should not be translated."
|
||||
},
|
||||
"yubiKeyTitle": {
|
||||
"message": "Устройство YubiKey OTP"
|
||||
"message": "Ключ за сигурност YubiKey OTP"
|
||||
},
|
||||
"yubiKeyDesc": {
|
||||
"message": "Използвайте устройство на YubiKey, за да влезете в абонамента си. Поддържат се моделите YubiKey 4, 4 Nano, 4C и NEO."
|
||||
"message": "Използвайте ключа за сигурност YubiKey, за да влезете в акаунта си. Работи с устройствата YubiKey 4, 4 Nano, 4C и NEO."
|
||||
},
|
||||
"duoDesc": {
|
||||
"message": "Удостоверяване чрез Duo Security, с ползване на приложението Duo Mobile, SMS, телефонен разговор или устройство U2F.",
|
||||
@@ -2096,7 +2120,7 @@
|
||||
"message": "собствен хостинг"
|
||||
},
|
||||
"thirdParty": {
|
||||
"message": "Third-party"
|
||||
"message": "Трета страна"
|
||||
},
|
||||
"thirdPartyServerMessage": {
|
||||
"message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.",
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "স্বতঃপূরণ"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "পাসওয়ার্ড তৈরি করুন (অনুলিপিকৃত)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "কোনও মিলত লগইন নেই।"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-fill"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Emplenament automàtic"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Genera contrasenya (copiada)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No hi ha inicis de sessió coincidents."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "1. Desbloquegeu la caixa forta."
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Automatické vyplňování"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Automaticky vyplnit přihlášení"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Automaticky vyplnit kartu"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Automaticky vyplnit identitu"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Vygenerovat heslo a zkopírovat do schránky"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Žádné odpovídající přihlašovací údaje"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Žádné karty"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Žádné identity"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Přidat přihlašovací údaje"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Přidat kartu"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Přidat identitu"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Odemknout Váš trezor"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Llenwi'n awtomatig"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Cynhyrchu cyfrinair (wedi'i gopïo)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Datgloi'ch cell"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-udfyld"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Autoudfyld login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Autoudfyld kort"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Autoudfyld identitet"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generér adgangskode (kopieret)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Ingen matchende logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Ingen kort"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Ingen identiteter"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Tilføj login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Tilføj kort"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Tilføj identitet"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Lås din boks op"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-Ausfüllen"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Zugangsdaten automatisch ausfüllen"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Karte automatisch ausfüllen"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Identität automatisch ausfüllen"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Passwort generieren (kopiert)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Keine passenden Zugangsdaten"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Keine Karten"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Keine Identitäten"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Zugangsdaten hinzufügen"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Karte hinzufügen"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Identität hinzufügen"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Entsperre deinen Tresor"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Αυτόματη συμπλήρωση"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Δημιουργία Κωδικού (αντιγράφηκε)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Δεν υπάρχουν αντιστοιχίσεις σύνδεσης."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Ξεκλειδώστε το vault σας"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-fill"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-fill"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Autorellenar"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generar contraseña (copiada)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Sin entradas coincidentes."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Desbloquea la caja fuerte"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Automaatne täitmine"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Täida konto andmed"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Täida kaardi andmed"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Täida identiteet"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Genereeri parool (kopeeritakse)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Sobivaid kontoandmeid ei leitud."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Kaardid puuduvad"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Identiteedid puuduvad"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Lisa konto andmed"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Lisa kaart"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Lisa identiteet"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Lukusta hoidla lahti"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-betetzea"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Sortu pasahitza (kopiatuta)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Bat datozen saio-hasierarik gabe"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Desblokeatu kutxa gotorra"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "پر کردن خودکار"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "پر کردن خودکار ورود"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "پر کردن خودکار کارت"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "پر کردن خودکار هویت"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "ساخت کلمه عبور (کپی شد)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "ورودیها منتطبق نیست"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "کارتی وجود ندارد"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "هویتی وجود ندارد"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "افزودن ورود"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "افزودن کارت"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "افزودن هویت"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "قفل گاوصندوق خود را باز کنید"
|
||||
},
|
||||
@@ -637,7 +661,7 @@
|
||||
"message": "برای پر کردن خودکار گاوصندوق Bitwarden خود را باز کنید."
|
||||
},
|
||||
"notificationUnlock": {
|
||||
"message": "بازگشایی"
|
||||
"message": "باز کردن قفل"
|
||||
},
|
||||
"enableContextMenuItem": {
|
||||
"message": "نمایش گزینههای منوی زمینه"
|
||||
@@ -772,7 +796,7 @@
|
||||
"message": "ویژگی موجود نیست"
|
||||
},
|
||||
"encryptionKeyMigrationRequired": {
|
||||
"message": "Encryption key migration required. Please login through the web vault to update your encryption key."
|
||||
"message": "انتقال کلید رمزگذاری مورد نیاز است. لطفاً از طریق گاوصندوق وب وارد شوید تا کلید رمزگذاری خود را به روز کنید."
|
||||
},
|
||||
"premiumMembership": {
|
||||
"message": "عضویت پرمیوم"
|
||||
@@ -1606,10 +1630,10 @@
|
||||
"message": "بیومتریک مرورگر در این دستگاه پشتیبانی نمیشود."
|
||||
},
|
||||
"biometricsFailedTitle": {
|
||||
"message": "زیستسنجی ناتمام ماند"
|
||||
"message": "زیستسنجی ناموفق بود"
|
||||
},
|
||||
"biometricsFailedDesc": {
|
||||
"message": "زیستسنجی نمی تواند انجام شود، استفاده از کلمه عبور اصلی یا خروج را در نظر بگیرید. اگر این مشکل ادامه یافت لطفا با پشتیبانی Bitwarden تماس بگیرید."
|
||||
"message": "زیستسنجی نمیتواند انجام شود، استفاده از کلمه عبور اصلی یا خروج را در نظر بگیرید. اگر این مشکل ادامه یافت لطفاً با پشتیبانی Bitwarden تماس بگیرید."
|
||||
},
|
||||
"nativeMessaginPermissionErrorTitle": {
|
||||
"message": "مجوز ارائه نشده است"
|
||||
@@ -1992,7 +2016,7 @@
|
||||
"message": "برون ریزی گاوصندوق شخصی"
|
||||
},
|
||||
"exportingIndividualVaultDescription": {
|
||||
"message": "Only the individual vault items associated with $EMAIL$ will be exported. Organization vault items will not be included. Only vault item information will be exported and will not include associated attachments.",
|
||||
"message": "فقط موارد شخصی گاوصندوق مرتبط با $EMAIL$ برون ریزی خواهند شد. موارد گاوصندوق سازمان شامل نخواهد شد. فقط اطلاعات مورد گاوصندوق برون ریزی خواهد شد و شامل تاریخچه کلمه عبور مرتبط یا پیوست نمیشود.",
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"content": "$1",
|
||||
@@ -2234,28 +2258,28 @@
|
||||
}
|
||||
},
|
||||
"loggingInOn": {
|
||||
"message": "ورود به عنوان"
|
||||
"message": "ورود با"
|
||||
},
|
||||
"opensInANewWindow": {
|
||||
"message": "در پنجره جدید باز میشود"
|
||||
},
|
||||
"deviceApprovalRequired": {
|
||||
"message": "تایید دستگاه لازم است. یک روش تایید برگزینید:"
|
||||
"message": "تأیید دستگاه لازم است. یک روش تأیید انتخاب کنید:"
|
||||
},
|
||||
"rememberThisDevice": {
|
||||
"message": "این دستگاه را به خاطر بسپار"
|
||||
},
|
||||
"uncheckIfPublicDevice": {
|
||||
"message": "بردارید اگر از دستگاه عمومی استفاده میکنید"
|
||||
"message": "اگر از دستگاه عمومی استفاده میکنید علامت را بردارید"
|
||||
},
|
||||
"approveFromYourOtherDevice": {
|
||||
"message": "تایید با دستگاه دیگرتان"
|
||||
"message": "تأیید با دستگاه دیگرتان"
|
||||
},
|
||||
"requestAdminApproval": {
|
||||
"message": "درخواست تایید مدیر"
|
||||
"message": "درخواست تأیید مدیر"
|
||||
},
|
||||
"approveWithMasterPassword": {
|
||||
"message": "تایید با کلمه عبور اصلی"
|
||||
"message": "تأیید با کلمه عبور اصلی"
|
||||
},
|
||||
"ssoIdentifierRequired": {
|
||||
"message": "شناسه سازمان SSO مورد نیاز است."
|
||||
@@ -2283,37 +2307,37 @@
|
||||
"message": "حساب کاربری با موفقیت ایجاد شد!"
|
||||
},
|
||||
"adminApprovalRequested": {
|
||||
"message": "تایید مدیر در خواست شد"
|
||||
"message": "تأیید مدیر درخواست شد"
|
||||
},
|
||||
"adminApprovalRequestSentToAdmins": {
|
||||
"message": "درخواست شما به مدیرتان فرستاده شد."
|
||||
},
|
||||
"youWillBeNotifiedOnceApproved": {
|
||||
"message": "به محض تایید مطلع خواهید شد."
|
||||
"message": "به محض تأیید مطلع خواهید شد."
|
||||
},
|
||||
"troubleLoggingIn": {
|
||||
"message": "در ورود مشکلی دارید؟"
|
||||
},
|
||||
"loginApproved": {
|
||||
"message": "ورود تایید شد"
|
||||
"message": "ورود تأیید شد"
|
||||
},
|
||||
"userEmailMissing": {
|
||||
"message": "رایانامه کاربر کم است"
|
||||
"message": "ایمیل کاربر وجود ندارد"
|
||||
},
|
||||
"deviceTrusted": {
|
||||
"message": "دستگاه مورد اعتماد است"
|
||||
},
|
||||
"inputRequired": {
|
||||
"message": "ورودی مورد نیاز است."
|
||||
"message": "ورودی ضروری است."
|
||||
},
|
||||
"required": {
|
||||
"message": "الزامی"
|
||||
"message": "ضروری"
|
||||
},
|
||||
"search": {
|
||||
"message": "جستجو"
|
||||
},
|
||||
"inputMinLength": {
|
||||
"message": "ورودی باید حداقل $COUNT$ نشانه داشته باشد.",
|
||||
"message": "ورودی باید حداقل $COUNT$ کاراکتر داشته باشد.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@@ -2322,7 +2346,7 @@
|
||||
}
|
||||
},
|
||||
"inputMaxLength": {
|
||||
"message": "اندازه ورودی نباید بیش از $COUNT$ نشانه باشد.",
|
||||
"message": "طول ورودی نباید بیش از $COUNT$ کاراکتر باشد.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@@ -2331,7 +2355,7 @@
|
||||
}
|
||||
},
|
||||
"inputForbiddenCharacters": {
|
||||
"message": "نشانه های زیر مجاز نیستند: $CHARACTERS$",
|
||||
"message": "کاراکترهای زیر مجاز نیستند: $CHARACTERS$",
|
||||
"placeholders": {
|
||||
"characters": {
|
||||
"content": "$1",
|
||||
@@ -2340,7 +2364,7 @@
|
||||
}
|
||||
},
|
||||
"inputMinValue": {
|
||||
"message": "مقدار ورودی باید دست کم $MIN$ باشد.",
|
||||
"message": "مقدار ورودی باید حداقل $MIN$ باشد.",
|
||||
"placeholders": {
|
||||
"min": {
|
||||
"content": "$1",
|
||||
@@ -2349,7 +2373,7 @@
|
||||
}
|
||||
},
|
||||
"inputMaxValue": {
|
||||
"message": "مقدار ورودی نباید بیش از $MAX$ باشد.",
|
||||
"message": "مقدار ورودی نباید از $MAX$ تجاوز کند.",
|
||||
"placeholders": {
|
||||
"max": {
|
||||
"content": "$1",
|
||||
@@ -2358,17 +2382,17 @@
|
||||
}
|
||||
},
|
||||
"multipleInputEmails": {
|
||||
"message": "یک یا چند رایانامه نامعتبر است"
|
||||
"message": "یک یا چند ایمیل نامعتبر است"
|
||||
},
|
||||
"inputTrimValidator": {
|
||||
"message": "ورودی نباید فقط فاصله باشد.",
|
||||
"message": "ورودی نباید فقط حاوی فضای خالی باشد.",
|
||||
"description": "Notification to inform the user that a form's input can't contain only whitespace."
|
||||
},
|
||||
"inputEmail": {
|
||||
"message": "ورودی یک نشانی رایانامه نیست."
|
||||
"message": "ورودی یک نشانی ایمیل نیست."
|
||||
},
|
||||
"fieldsNeedAttention": {
|
||||
"message": "بخش (های) $COUNT$ در بالا نیازمند توجه شما است.",
|
||||
"message": "فیلد $COUNT$ در بالا به توجه شما نیاز دارد.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@@ -2380,16 +2404,16 @@
|
||||
"message": "-- انتخاب --"
|
||||
},
|
||||
"multiSelectPlaceholder": {
|
||||
"message": "-- برای گزینش چیزی بنویسید --"
|
||||
"message": "-- برای فیلتر تایپ کنید --"
|
||||
},
|
||||
"multiSelectLoading": {
|
||||
"message": "در حال بازیابی گزینهها..."
|
||||
},
|
||||
"multiSelectNotFound": {
|
||||
"message": "موردی پیدا نشد"
|
||||
"message": "موردی یافت نشد"
|
||||
},
|
||||
"multiSelectClearAll": {
|
||||
"message": "پاک کردن همه"
|
||||
"message": "پاککردن همه"
|
||||
},
|
||||
"plusNMore": {
|
||||
"message": "+ $QUANTITY$ بیشتر",
|
||||
@@ -2401,25 +2425,25 @@
|
||||
}
|
||||
},
|
||||
"submenu": {
|
||||
"message": "زیرفهرست"
|
||||
"message": "زیرمنو"
|
||||
},
|
||||
"toggleCollapse": {
|
||||
"message": "باز و بسته کردن",
|
||||
"message": "دکمه بستن",
|
||||
"description": "Toggling an expand/collapse state."
|
||||
},
|
||||
"aliasDomain": {
|
||||
"message": "Alias domain"
|
||||
"message": "دامنه مستعار"
|
||||
},
|
||||
"passwordRepromptDisabledAutofillOnPageLoad": {
|
||||
"message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.",
|
||||
"message": "موارد با درخواست مجدد کلمه عبور اصلی را نمیتوان در بارگذاری صفحه بهصورت خودکار پر کرد. پر کردن خودکار در بارگیری صفحه خاموش شد.",
|
||||
"description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load."
|
||||
},
|
||||
"autofillOnPageLoadSetToDefault": {
|
||||
"message": "Auto-fill on page load set to use default setting.",
|
||||
"message": "پر کردن خودکار در بارگیری صفحه برای استفاده از تنظیمات پیشفرض تنظیم شده است.",
|
||||
"description": "Toast message for informing the user that auto-fill on page load has been set to the default setting."
|
||||
},
|
||||
"turnOffMasterPasswordPromptToEditField": {
|
||||
"message": "Turn off master password re-prompt to edit this field",
|
||||
"message": "برای ویرایش این فیلد، درخواست مجدد کلمه عبور اصلی را خاموش کنید",
|
||||
"description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Automaattinen täyttö"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Täytä kirjautumistieto automaattisesti"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Täytä kortti automaattisesti"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Täytä identiteetti automaattisesti"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Luo salasana (leikepöydälle)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Ei tunnistettuja kirjautumistietoja."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Kortteja ei ole"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Identiteettejä ei ole"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Lisää kirjautumistieto"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Lisää kortti"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Lisää identiteetti"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Avaa holvisi"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-fill sa Filipino ay Awtomatikong Pagpuno"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Maglagay ng Password"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Walang tumutugmang mga login"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Buksan ang iyong kahadeyero"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Saisie automatique"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Saisie automatique de l'identifiant"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Saisie automatique de la carte"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Saisie automatique de l'identité"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Générer un mot de passe (copié)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Aucun identifiant correspondant."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Aucune carte"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Aucune identité"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Ajouter un identifiant"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Ajouter une carte"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Ajouter une identité"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Déverrouillez votre coffre"
|
||||
},
|
||||
@@ -634,7 +658,7 @@
|
||||
"message": "Mettre à jour"
|
||||
},
|
||||
"notificationUnlockDesc": {
|
||||
"message": "Unlock your Bitwarden vault to complete the auto-fill request."
|
||||
"message": "Déverrouillez votre coffre Bitwarden pour terminer la demande de saisie automatique."
|
||||
},
|
||||
"notificationUnlock": {
|
||||
"message": "Déverrouiller"
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-fill"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "השלמה אוטומטית"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "צור סיסמה (העתק)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "לא נמצאו פרטי כניסה תואמים."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "שחרור הכספת שלך"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "स्वत:भरण"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate Password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "कोई मेल-मिला लॉगिन नहीं |"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "आपकी तिजोरी का ताला खोलें"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-ispuna"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generiraj lozinku (i kopiraj)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Nema podudarajućih prijava"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Otključaj svoj trezor"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Automatikus kitöltés"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Automatikus kitöltés bejelentkezés"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Automatikus kitöltés kártya"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Automatikus kitöltés személyazonosság"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Jelszó generálás (másolt)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Nincsenek egyező bejelentkezések."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Nincsenek kártyák"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Nincsenek személyazonosságok"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Bejelentkezés hozzáadása"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Kártya hozzáadása"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Személyazonossság hozzáadása"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Széf kinyitása"
|
||||
},
|
||||
@@ -143,7 +167,7 @@
|
||||
"message": "A folytatáshoz meg kell erősíteni a személyazonosságot."
|
||||
},
|
||||
"account": {
|
||||
"message": "Felhasználó"
|
||||
"message": "Fiók"
|
||||
},
|
||||
"changeMasterPassword": {
|
||||
"message": "Mesterjelszó módosítása"
|
||||
@@ -513,7 +537,7 @@
|
||||
"message": "A kétlépcsős bejelentkezés biztonságosabbá teszi a fiókot azáltal, hogy ellenőrizni kell a bejelentkezést egy másik olyan eszközzel mint például biztonsági kulcs, hitelesítő alkalmazás, SMS, telefon hívás vagy email. A kétlépcsős bejelentkezést a bitwarden.com webes széfben lehet engedélyezni. Felkeressük a webhelyet most?"
|
||||
},
|
||||
"editedFolder": {
|
||||
"message": "A mappa módosításra került."
|
||||
"message": "A mappa mentésre került."
|
||||
},
|
||||
"deleteFolderConfirmation": {
|
||||
"message": "Biztos, hogy törölni akarod ezt a mappát?"
|
||||
@@ -562,7 +586,7 @@
|
||||
"message": "Biztosan törlésre kerüljön ezt az elem?"
|
||||
},
|
||||
"deletedItem": {
|
||||
"message": "Az elem törlésre került."
|
||||
"message": "Az elem a lomtárba került."
|
||||
},
|
||||
"overwritePassword": {
|
||||
"message": "Jelszó felülírása"
|
||||
@@ -769,7 +793,7 @@
|
||||
"message": "A naximális fájlméret 500 MB."
|
||||
},
|
||||
"featureUnavailable": {
|
||||
"message": "Ez a funkció nem érhető el."
|
||||
"message": "A funkció nem érhető el."
|
||||
},
|
||||
"encryptionKeyMigrationRequired": {
|
||||
"message": "Titkosítási kulcs migráció szükséges. Jelentkezzünk be a webes széfen keresztül a titkosítási kulcs frissítéséhez."
|
||||
@@ -787,7 +811,7 @@
|
||||
"message": "Tagság frissítése"
|
||||
},
|
||||
"premiumNotCurrentMember": {
|
||||
"message": "Jelenleg nincs prémium tagság."
|
||||
"message": "Jelenleg nem vagyunk prémium tag."
|
||||
},
|
||||
"premiumSignUpAndGet": {
|
||||
"message": "Regisztráció a prémium tagságra az alábbi funkciókért:"
|
||||
@@ -796,7 +820,7 @@
|
||||
"message": "1 GB titkosított tárhely a fájlmellékleteknek."
|
||||
},
|
||||
"premiumSignUpTwoStepOptions": {
|
||||
"message": "Proprietary two-step login options such as YubiKey and Duo."
|
||||
"message": "Saját kétlépcsős bejelentkezési lehetőségek mint a YubiKey és a Duo."
|
||||
},
|
||||
"ppremiumSignUpReports": {
|
||||
"message": "Jelszó higiénia, fiók biztonság és adatszivárgási jelentések a széf biztonsága érdekében."
|
||||
@@ -817,7 +841,7 @@
|
||||
"message": "A prémium tagság megvásárolható a bitwarden.com webes széfben. Szeretnénk felkeresni a webhelyet most?"
|
||||
},
|
||||
"premiumCurrentMember": {
|
||||
"message": "Jelenleg a prémium tagság érvényben van."
|
||||
"message": "Prémium tag vagyunk!"
|
||||
},
|
||||
"premiumCurrentMemberThanks": {
|
||||
"message": "Köszönjük a Bitwarden támogatását."
|
||||
@@ -994,7 +1018,7 @@
|
||||
"message": "Alapértelmezett beállítások bejelentkezési elemekhez"
|
||||
},
|
||||
"defaultAutoFillOnPageLoadDesc": {
|
||||
"message": "Az Automatikus kitöltés engedélyezése az oldalbetöltéskor engedélyezheti vagy letilthatja a funkciót az egyes bejelentkezési elemeknél. Ez az alapértelmezett beállítás a bejelentkezési elemeknéll, amelyek nincsenek külön konfigurálva."
|
||||
"message": "Az egyes bejelentkezési elemeknél kikapcsolhatjuk oldalbetöltéskor az automatikus kitöltést az elem Szerkesztés nézetében."
|
||||
},
|
||||
"itemAutoFillOnPageLoad": {
|
||||
"message": "Automatikus kitöltés oldal betöltésnél (Ha engedélyezett az opcióknál)"
|
||||
@@ -1905,7 +1929,7 @@
|
||||
"message": "Perc"
|
||||
},
|
||||
"vaultTimeoutPolicyInEffect": {
|
||||
"message": "A szervezeti házirendek hatással vannak a széf időkorlátjára. A széf időkorlátja legfeljebb $HOURS$ óra és $MINUTES$ perc lehet.",
|
||||
"message": "A szervezeti szabályzata $HOURS$ órára és $MINUTES$ percre állította be a maximálisan megengedett széf időtúllépést.",
|
||||
"placeholders": {
|
||||
"hours": {
|
||||
"content": "$1",
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Isi otomatis"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Membuat Kata Sandi (tersalin)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Tidak ada info masuk yang cocok."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Buka brankas Anda"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Riempimento automatico"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Riempi automaticamente login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Riempi automaticamente carta"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Riempi automaticamente identità"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Genera password e copiala"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Nessun login corrispondente"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Nessuna carta"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Nessuna identità"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Aggiungi login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Aggiungi carta"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Aggiungi identità"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Sblocca la tua cassaforte"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "自動入力"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "自動入力ログイン"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "自動入力カード"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "自動入力 ID"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "パスワードを生成 (コピー)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "一致するログインがありません。"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "カードなし"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "ID なし"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "ログイン情報を追加"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "カードを追加"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "ID を追加"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "保管庫のロックを解除"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "თვითშევსება"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-fill"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "ಸ್ವಯಂ ಭರ್ತಿ"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "ಪಾಸ್ವರ್ಡ್ ರಚಿಸಿ (ನಕಲಿಸಲಾಗಿದೆ)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "ಹೊಂದಾಣಿಕೆಯ ಲಾಗಿನ್ಗಳು ಇಲ್ಲ."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "자동 완성"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "비밀번호 생성 및 클립보드에 복사"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "사용할 수 있는 로그인이 없습니다."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "보관함 잠금 해제"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Automatinis užpildymas"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Automatinio užpildymo prisijungimas"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Automatinio užpildymo kortelė"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Automatinio užpildymo tapatybė"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Kurti slaptažodį (paruoštas įterpti)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Nėra atitinkančių prisijungimų."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Nėra kortelių"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Nėra tapatybių"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Pridėti prisijungimą"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Pridėti kortelę"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Pridėti tapatybę"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Atrakinti saugyklą"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Automātiskā aizpildīšana"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Automātiski aizpildīt pieteikšanos"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Automātiski aizpildīt karti"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Automātiski aizpildīt identitāti"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Izveidot paroli (tiks ievietota starpliktuvē)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Nav atbilstošu pieteikšanās vienumu"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Nav karšu"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Nav identitāšu"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Pievienot pieteikšanās vienumu"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Pievienot karti"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Pievienot identitāti"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Atslēgt glabātavu"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "ഓട്ടോഫിൽ"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "പാസ്വേഡ് സൃഷ്ടിക്കുക (പകർത്തുക )"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "പൊരുത്തപ്പെടുന്ന ലോഗിനുകളൊന്നുമില്ല."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "स्वयंभरण"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "तिजोरी उघडा"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-fill"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-utfylling"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generer et passord (kopiert)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Ingen samsvarende innlogginger."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Lås opp hvelvet ditt"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-fill"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-invullen"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Login automatisch invullen"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Kaart automatisch invullen"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Identiteit automatisch invullen"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Wachtwoord genereren (op klembord)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Geen overeenkomstige logins."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Geen kaarten"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Geen identiteiten"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Login toevoegen"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Kaart toevoegen"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Identiteit toevoegen"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Ontgrendel je kluis"
|
||||
},
|
||||
@@ -772,7 +796,7 @@
|
||||
"message": "Functionaliteit niet beschikbaar"
|
||||
},
|
||||
"encryptionKeyMigrationRequired": {
|
||||
"message": "Encryption key migration required. Please login through the web vault to update your encryption key."
|
||||
"message": "Migratie van de encryptiesleutel vereist. Login via de website om je sleutel te bij te werken."
|
||||
},
|
||||
"premiumMembership": {
|
||||
"message": "Premium-abonnement"
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-fill"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-fill"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Autouzupełnianie"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Autouzupełnianie logowania"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Autouzupełnianie karty"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Autouzupełnianie tożsamości"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Wygeneruj hasło (do schowka)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Brak pasujących danych logowania"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Brak kart"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Brak tożsamości"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Dodaj dane logowania"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Dodaj kartę"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Dodaj tożsamość"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Odblokuj sejf"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Autopreencher"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Gerar Senha (copiada)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Sem credenciais correspondentes."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Desbloqueie seu cofre"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Preenchimento automático"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Preenchimento automático da credencial"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Preenchimento automático do cartão"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Preenchimento automático da identidade"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Gerar palavra-passe (copiada)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Sem credenciais correspondentes"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Sem cartões"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Sem identidades"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Adicionar credencial"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Adicionar cartão"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Adicionar identidade"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Desbloquear o cofre"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-completare"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generare parolă (s-a copiat)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Nu există potrivire de autentificări"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Deblocați-vă seiful"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Автозаполнение"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Автозаполнение логина"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Автозаполнение карты"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Автозаполнение личности"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Сгенерировать пароль (с копированием)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Нет подходящих логинов."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Нет карт"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Нет личностей"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Добавить логин"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Добавить карту"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Добавить личность"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Разблокировать хранилище"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "ස්වයං-පිරවීම"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "මුරපදය ජනනය (පිටපත්)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "ගැලපෙන පිවිසුම් නොමැත."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Automatické vypĺňanie"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Automatické vyplnenie prihlasovacích údajov"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Automatické vyplnenie karty"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Automatické vyplnenie identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Vygenerovať heslo (skopírované)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Žiadne zodpovedajúce prihlasovacie údaje."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Žiadne karty"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Žiadne identity"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Pridať prihlasovacie údaje"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Pridať kartu"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Pridať identitu"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Odomknúť trezor"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Samodejno izpolnjevanje"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generiraj geslo (kopirano)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Ni ustreznih prijav."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Odkleni svoj trezor"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Аутоматско допуњавање"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Генериши Лозинку (копирано)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Нема одговарајућих пријављивања."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Откључај свој сеф"
|
||||
},
|
||||
@@ -2408,7 +2432,7 @@
|
||||
"description": "Toggling an expand/collapse state."
|
||||
},
|
||||
"aliasDomain": {
|
||||
"message": "Alias domain"
|
||||
"message": "Домен алијаса"
|
||||
},
|
||||
"passwordRepromptDisabledAutofillOnPageLoad": {
|
||||
"message": "Ставке са упитом за поновно постављање главне лозинке не могу се ауто-попунити при учитавању странице. Ауто-попуњавање при учитавању странице је искључено.",
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Fyll i automatiskt"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Skapa lösenord (kopierad)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Inga matchande inloggningar"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Inga kort"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Inga identiteter"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Lägg till inloggning"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Lägg till kort"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Lägg till identitet"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Lås upp ditt valv"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Auto-fill"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Unlock your vault"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "กรอกข้อมูลอัตโนมัติ"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate Password (copied)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "ไม่พบข้อมูลล็อกอินที่ตรงกัน"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "ปลดล็อกกตู้นิรภัยของคุณ"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Otomatik doldur"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Hesabı otomatik doldur"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Kartı otomatik doldur"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Kimliği otomatik doldur"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Parola oluştur (ve kopyala)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Eşleşen hesap yok"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Kart yok"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Kimlik yok"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Hesap ekle"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Kart ekle"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Kimlik ekle"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Kasanızın kilidini açın"
|
||||
},
|
||||
@@ -1609,7 +1633,7 @@
|
||||
"message": "Biyometri doğrulanamadı"
|
||||
},
|
||||
"biometricsFailedDesc": {
|
||||
"message": "Biometrics cannot be completed, consider using a master password or logging out. If this persists, please contact Bitwarden support."
|
||||
"message": "Biyometri doğrulaması tamamlanamadı. Ana parolanızı kullanabilir veya çıkış yapabilirsiniz. Sorun devam ederse Bitwarden destek ekibiyle iletişime geçin."
|
||||
},
|
||||
"nativeMessaginPermissionErrorTitle": {
|
||||
"message": "İzin verilmedi"
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Автозаповнення"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Автозаповнення входу"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Автозаповнення картки"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Автозаповнення особистих даних"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Генерувати пароль (з копіюванням)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Немає відповідних записів"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "Немає карток"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "Немає особистих даних"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Додати запис входу"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Додати картку"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Додати особисті дані"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Розблокуйте сховище"
|
||||
},
|
||||
@@ -2408,18 +2432,18 @@
|
||||
"description": "Toggling an expand/collapse state."
|
||||
},
|
||||
"aliasDomain": {
|
||||
"message": "Alias domain"
|
||||
"message": "Псевдонім домену"
|
||||
},
|
||||
"passwordRepromptDisabledAutofillOnPageLoad": {
|
||||
"message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.",
|
||||
"message": "Записи з повторним запитом головного пароля не можна автоматично заповнювати під час завантаження сторінки. Автозаповнення на сторінці вимкнено.",
|
||||
"description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load."
|
||||
},
|
||||
"autofillOnPageLoadSetToDefault": {
|
||||
"message": "Auto-fill on page load set to use default setting.",
|
||||
"message": "Автозаповнення на сторінці налаштовано з типовими параметрами.",
|
||||
"description": "Toast message for informing the user that auto-fill on page load has been set to the default setting."
|
||||
},
|
||||
"turnOffMasterPasswordPromptToEditField": {
|
||||
"message": "Turn off master password re-prompt to edit this field",
|
||||
"message": "Вимкніть повторний запит головного пароля, щоб редагувати це поле",
|
||||
"description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "Tự động điền"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Tạo mật khẩu (đã sao chép)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "Không có thông tin đăng nhập phù hợp."
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "Mở khoá kho lưu trữ của bạn"
|
||||
},
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "自动填充"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "自动填充登录"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "自动填充支付卡"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "自动填充身份"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "生成密码(并复制)"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "无匹配的登录项目"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "无支付卡"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "无身份"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "添加登录项目"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "添加支付卡"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "添加身份"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "解锁您的密码库"
|
||||
},
|
||||
@@ -850,7 +874,7 @@
|
||||
"message": "使用此功能需要高级会员资格。"
|
||||
},
|
||||
"enterVerificationCodeApp": {
|
||||
"message": "请输入您的验证器应用中的 6 位验证码。"
|
||||
"message": "请输入您的验证器应用中的 6 位数验证码。"
|
||||
},
|
||||
"enterVerificationCodeEmail": {
|
||||
"message": "请输入发送给电子邮件 $EMAIL$ 的 6 位数验证码。",
|
||||
@@ -2117,7 +2141,7 @@
|
||||
}
|
||||
},
|
||||
"loginWithMasterPassword": {
|
||||
"message": "主密码登录"
|
||||
"message": "使用主密码登录"
|
||||
},
|
||||
"loggingInAs": {
|
||||
"message": "正登录为"
|
||||
@@ -2132,7 +2156,7 @@
|
||||
"message": "记住电子邮件地址"
|
||||
},
|
||||
"loginWithDevice": {
|
||||
"message": "设备登录"
|
||||
"message": "使用设备登录"
|
||||
},
|
||||
"loginWithDeviceEnabledInfo": {
|
||||
"message": "设备登录必须在 Bitwarden 应用程序的设置中启用。需要其他登录选项吗?"
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
"autoFill": {
|
||||
"message": "自動填入"
|
||||
},
|
||||
"autoFillLogin": {
|
||||
"message": "Auto-fill login"
|
||||
},
|
||||
"autoFillCard": {
|
||||
"message": "Auto-fill card"
|
||||
},
|
||||
"autoFillIdentity": {
|
||||
"message": "Auto-fill identity"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "產生及複製密碼"
|
||||
},
|
||||
@@ -100,6 +109,21 @@
|
||||
"noMatchingLogins": {
|
||||
"message": "無符合的登入資料"
|
||||
},
|
||||
"noCards": {
|
||||
"message": "No cards"
|
||||
},
|
||||
"noIdentities": {
|
||||
"message": "No identities"
|
||||
},
|
||||
"addLoginMenu": {
|
||||
"message": "Add login"
|
||||
},
|
||||
"addCardMenu": {
|
||||
"message": "Add card"
|
||||
},
|
||||
"addIdentityMenu": {
|
||||
"message": "Add identity"
|
||||
},
|
||||
"unlockVaultMenu": {
|
||||
"message": "解鎖您的密碼庫"
|
||||
},
|
||||
|
||||
@@ -148,7 +148,7 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
throw new Error("Nothing to auto-fill.");
|
||||
}
|
||||
|
||||
let totpPromise: Promise<string> = null;
|
||||
let totp: string | null = null;
|
||||
|
||||
const canAccessPremium = await this.stateService.getCanAccessPremium();
|
||||
const defaultUriMatch = (await this.stateService.getDefaultUriMatch()) ?? UriMatchType.Domain;
|
||||
@@ -205,15 +205,14 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
|
||||
if (
|
||||
options.cipher.type !== CipherType.Login ||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
totpPromise ||
|
||||
totp !== null ||
|
||||
!options.cipher.login.totp ||
|
||||
(!canAccessPremium && !options.cipher.organizationUseTotp)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
totpPromise = this.stateService.getDisableAutoTotpCopy().then((disabled) => {
|
||||
totp = await this.stateService.getDisableAutoTotpCopy().then((disabled) => {
|
||||
if (!disabled) {
|
||||
return this.totpService.getCode(options.cipher.login.totp);
|
||||
}
|
||||
@@ -224,8 +223,8 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
|
||||
if (didAutofill) {
|
||||
this.eventCollectionService.collect(EventType.Cipher_ClientAutofilled, options.cipher.id);
|
||||
if (totpPromise != null) {
|
||||
return await totpPromise;
|
||||
if (totp !== null) {
|
||||
return totp;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ Bitwarden, parolları iş yoldaşlarınızla təhlükəsiz paylaşa bilməyiniz
|
||||
Nəyə görə Bitwarden-i seçməliyik:
|
||||
|
||||
Yüksək səviyyə şifrələmə
|
||||
Parollarınız qabaqcıl bir ucdan digərinə kimi şifrələmə (AES-256 bit, salted hashtag və PBKDF2 SHA-256) ilə qorunur, beləcə verilənlərinizin güvənli və gizli qalmasını təmin edir.
|
||||
Parollarınız qabaqcıl ucdan-uca şifrələmə (AES-256 bit, salted hashtag və PBKDF2 SHA-256) ilə qorunur, beləcə datanızın güvənli və gizli qalmasını təmin edir.
|
||||
|
||||
Daxili parol yaradıcı
|
||||
Çox istifadə etdiyiniz hər veb sayt üçün təhlükəsizlik tələblərinə görə güclü, unikal və təsadüfi şifrələr yaradın.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"**/node_modules/@bitwarden/desktop-native/index.js",
|
||||
"**/node_modules/@bitwarden/desktop-native/desktop_native.${platform}-${arch}*.node"
|
||||
],
|
||||
"electronVersion": "24.8.5",
|
||||
"electronVersion": "26.3.0",
|
||||
"generateUpdatesFilesForAllChannels": true,
|
||||
"publish": {
|
||||
"provider": "generic",
|
||||
|
||||
@@ -476,7 +476,7 @@
|
||||
"message": "بیشترین حجم پرونده ۵۰۰ مگابایت است."
|
||||
},
|
||||
"encryptionKeyMigrationRequired": {
|
||||
"message": "Encryption key migration required. Please login through the web vault to update your encryption key."
|
||||
"message": "انتقال کلید رمزگذاری مورد نیاز است. لطفاً از طریق گاوصندوق وب وارد شوید تا کلید رمزگذاری خود را به روز کنید."
|
||||
},
|
||||
"editedFolder": {
|
||||
"message": "پوشه ذخیره شد"
|
||||
@@ -1078,7 +1078,7 @@
|
||||
"message": "۱ گیگابایت فضای ذخیرهسازی رمزنگاری شده برای پروندههای پیوست."
|
||||
},
|
||||
"premiumSignUpTwoStepOptions": {
|
||||
"message": "Proprietary two-step login options such as YubiKey and Duo."
|
||||
"message": "گزینه های ورود اضافی دو مرحله ای مانند YubiKey و Duo."
|
||||
},
|
||||
"premiumSignUpReports": {
|
||||
"message": "گزارشهای بهداشت رمز عبور، سلامت حساب و نقض دادهها برای ایمن نگهداشتن گاوصندوق شما."
|
||||
@@ -1493,7 +1493,7 @@
|
||||
"message": "یک گاوصندوق خارج شده درخواست احراز هویت مجدد را برای دسترسی آن میدهد."
|
||||
},
|
||||
"unlockMethodNeededToChangeTimeoutActionDesc": {
|
||||
"message": "Set up an unlock method to change your vault timeout action."
|
||||
"message": "یک روش بازگشایی برای پایان زمان مجاز تنظیم کنید."
|
||||
},
|
||||
"lock": {
|
||||
"message": "قفل",
|
||||
@@ -1985,7 +1985,7 @@
|
||||
"message": "برون ریزی گاوصندوق شخصی"
|
||||
},
|
||||
"exportingIndividualVaultDescription": {
|
||||
"message": "Only the individual vault items associated with $EMAIL$ will be exported. Organization vault items will not be included. Only vault item information will be exported and will not include associated attachments.",
|
||||
"message": "فقط موارد شخصی گاوصندوق مرتبط با $EMAIL$ برون ریزی خواهند شد. موارد گاوصندوق سازمان شامل نخواهد شد. فقط اطلاعات مورد گاوصندوق برون ریزی خواهد شد و شامل تاریخچه کلمه عبور مرتبط یا پیوست نمیشود.",
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"content": "$1",
|
||||
@@ -2110,7 +2110,7 @@
|
||||
"message": "با دستگاه دیگری وارد شوید"
|
||||
},
|
||||
"loginInitiated": {
|
||||
"message": "Login initiated"
|
||||
"message": "ورود به سیستم آغاز شد"
|
||||
},
|
||||
"notificationSentDevice": {
|
||||
"message": "یک اعلان به دستگاه شما ارسال شده است."
|
||||
@@ -2250,35 +2250,35 @@
|
||||
"message": "بهروز رسانی تنظیمات توصیه شده"
|
||||
},
|
||||
"deviceApprovalRequired": {
|
||||
"message": "Device approval required. Select an approval option below:"
|
||||
"message": "تأیید دستگاه لازم است. یک روش تأیید انتخاب کنید:"
|
||||
},
|
||||
"rememberThisDevice": {
|
||||
"message": "Remember this device"
|
||||
"message": "این دستگاه را به خاطر بسپار"
|
||||
},
|
||||
"uncheckIfPublicDevice": {
|
||||
"message": "Uncheck if using a public device"
|
||||
"message": "اگر از دستگاه عمومی استفاده میکنید علامت را بردارید"
|
||||
},
|
||||
"approveFromYourOtherDevice": {
|
||||
"message": "Approve from your other device"
|
||||
"message": "تأیید با دستگاه دیگرتان"
|
||||
},
|
||||
"requestAdminApproval": {
|
||||
"message": "Request admin approval"
|
||||
"message": "درخواست تأیید مدیر"
|
||||
},
|
||||
"approveWithMasterPassword": {
|
||||
"message": "Approve with master password"
|
||||
"message": "تأیید با کلمه عبور اصلی"
|
||||
},
|
||||
"region": {
|
||||
"message": "Region"
|
||||
"message": "منطقه"
|
||||
},
|
||||
"ssoIdentifierRequired": {
|
||||
"message": "Organization SSO identifier is required."
|
||||
"message": "شناسه سازمان SSO مورد نیاز است."
|
||||
},
|
||||
"eu": {
|
||||
"message": "EU",
|
||||
"message": "اروپا",
|
||||
"description": "European Union"
|
||||
},
|
||||
"loggingInOn": {
|
||||
"message": "Logging in on"
|
||||
"message": "ورود با"
|
||||
},
|
||||
"usDomain": {
|
||||
"message": "bitwarden.com"
|
||||
@@ -2287,46 +2287,46 @@
|
||||
"message": "bitwarden.eu"
|
||||
},
|
||||
"selfHostedServer": {
|
||||
"message": "self-hosted"
|
||||
"message": "خود میزبان"
|
||||
},
|
||||
"accessDenied": {
|
||||
"message": "دسترسی رد شد. شما اجازه مشاهده این صفحه را ندارید."
|
||||
},
|
||||
"accountSuccessfullyCreated": {
|
||||
"message": "Account successfully created!"
|
||||
"message": "حساب کاربری با موفقیت ایجاد شد!"
|
||||
},
|
||||
"adminApprovalRequested": {
|
||||
"message": "Admin approval requested"
|
||||
"message": "تأیید مدیر درخواست شد"
|
||||
},
|
||||
"adminApprovalRequestSentToAdmins": {
|
||||
"message": "Your request has been sent to your admin."
|
||||
"message": "درخواست شما به مدیرتان فرستاده شد."
|
||||
},
|
||||
"youWillBeNotifiedOnceApproved": {
|
||||
"message": "You will be notified once approved."
|
||||
"message": "به محض تأیید مطلع خواهید شد."
|
||||
},
|
||||
"troubleLoggingIn": {
|
||||
"message": "Trouble logging in?"
|
||||
"message": "در ورود مشکلی دارید؟"
|
||||
},
|
||||
"loginApproved": {
|
||||
"message": "Login approved"
|
||||
"message": "ورود تأیید شد"
|
||||
},
|
||||
"userEmailMissing": {
|
||||
"message": "User email missing"
|
||||
"message": "ایمیل کاربر وجود ندارد"
|
||||
},
|
||||
"deviceTrusted": {
|
||||
"message": "Device trusted"
|
||||
"message": "دستگاه مورد اعتماد است"
|
||||
},
|
||||
"inputRequired": {
|
||||
"message": "Input is required."
|
||||
"message": "ورودی ضروری است."
|
||||
},
|
||||
"required": {
|
||||
"message": "required"
|
||||
"message": "ضروری"
|
||||
},
|
||||
"search": {
|
||||
"message": "Search"
|
||||
"message": "جستجو"
|
||||
},
|
||||
"inputMinLength": {
|
||||
"message": "Input must be at least $COUNT$ characters long.",
|
||||
"message": "ورودی باید حداقل $COUNT$ کاراکتر داشته باشد.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@@ -2335,7 +2335,7 @@
|
||||
}
|
||||
},
|
||||
"inputMaxLength": {
|
||||
"message": "Input must not exceed $COUNT$ characters in length.",
|
||||
"message": "طول ورودی نباید بیش از $COUNT$ کاراکتر باشد.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@@ -2344,7 +2344,7 @@
|
||||
}
|
||||
},
|
||||
"inputForbiddenCharacters": {
|
||||
"message": "The following characters are not allowed: $CHARACTERS$",
|
||||
"message": "کاراکترهای زیر مجاز نیستند: $CHARACTERS$",
|
||||
"placeholders": {
|
||||
"characters": {
|
||||
"content": "$1",
|
||||
@@ -2353,7 +2353,7 @@
|
||||
}
|
||||
},
|
||||
"inputMinValue": {
|
||||
"message": "Input value must be at least $MIN$.",
|
||||
"message": "مقدار ورودی باید حداقل $MIN$ باشد.",
|
||||
"placeholders": {
|
||||
"min": {
|
||||
"content": "$1",
|
||||
@@ -2362,7 +2362,7 @@
|
||||
}
|
||||
},
|
||||
"inputMaxValue": {
|
||||
"message": "Input value must not exceed $MAX$.",
|
||||
"message": "مقدار ورودی نباید از $MAX$ تجاوز کند.",
|
||||
"placeholders": {
|
||||
"max": {
|
||||
"content": "$1",
|
||||
@@ -2371,17 +2371,17 @@
|
||||
}
|
||||
},
|
||||
"multipleInputEmails": {
|
||||
"message": "1 or more emails are invalid"
|
||||
"message": "یک یا چند ایمیل نامعتبر است"
|
||||
},
|
||||
"inputTrimValidator": {
|
||||
"message": "Input must not contain only whitespace.",
|
||||
"message": "ورودی نباید فقط حاوی فضای خالی باشد.",
|
||||
"description": "Notification to inform the user that a form's input can't contain only whitespace."
|
||||
},
|
||||
"inputEmail": {
|
||||
"message": "Input is not an email address."
|
||||
"message": "ورودی یک نشانی ایمیل نیست."
|
||||
},
|
||||
"fieldsNeedAttention": {
|
||||
"message": "$COUNT$ field(s) above need your attention.",
|
||||
"message": "فیلد $COUNT$ در بالا به توجه شما نیاز دارد.",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"content": "$1",
|
||||
@@ -2390,22 +2390,22 @@
|
||||
}
|
||||
},
|
||||
"selectPlaceholder": {
|
||||
"message": "-- Select --"
|
||||
"message": "-- انتخاب --"
|
||||
},
|
||||
"multiSelectPlaceholder": {
|
||||
"message": "-- Type to filter --"
|
||||
"message": "-- برای فیلتر تایپ کنید --"
|
||||
},
|
||||
"multiSelectLoading": {
|
||||
"message": "Retrieving options..."
|
||||
"message": "در حال بازیابی گزینهها..."
|
||||
},
|
||||
"multiSelectNotFound": {
|
||||
"message": "No items found"
|
||||
"message": "موردی یافت نشد"
|
||||
},
|
||||
"multiSelectClearAll": {
|
||||
"message": "Clear all"
|
||||
"message": "پاککردن همه"
|
||||
},
|
||||
"plusNMore": {
|
||||
"message": "+ $QUANTITY$ more",
|
||||
"message": "+ $QUANTITY$ بیشتر",
|
||||
"placeholders": {
|
||||
"quantity": {
|
||||
"content": "$1",
|
||||
@@ -2414,9 +2414,9 @@
|
||||
}
|
||||
},
|
||||
"submenu": {
|
||||
"message": "Submenu"
|
||||
"message": "زیرمنو"
|
||||
},
|
||||
"aliasDomain": {
|
||||
"message": "Alias domain"
|
||||
"message": "دامنه مستعار"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2417,6 +2417,6 @@
|
||||
"message": "Под-мени"
|
||||
},
|
||||
"aliasDomain": {
|
||||
"message": "Alias domain"
|
||||
"message": "Домен алијаса"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2417,6 +2417,6 @@
|
||||
"message": "Підменю"
|
||||
},
|
||||
"aliasDomain": {
|
||||
"message": "Alias domain"
|
||||
"message": "Псевдонім домену"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,7 +594,7 @@
|
||||
"message": "继续"
|
||||
},
|
||||
"enterVerificationCodeApp": {
|
||||
"message": "请输入您的身份验证器应用中的 6 位验证码。"
|
||||
"message": "请输入您的验证器应用中的 6 位数验证码。"
|
||||
},
|
||||
"enterVerificationCodeEmail": {
|
||||
"message": "请输入发送给电子邮件 $EMAIL$ 的 6 位数验证码。",
|
||||
@@ -2083,7 +2083,7 @@
|
||||
"message": "密码库"
|
||||
},
|
||||
"loginWithMasterPassword": {
|
||||
"message": "主密码登录"
|
||||
"message": "使用主密码登录"
|
||||
},
|
||||
"loggingInAs": {
|
||||
"message": "正登录为"
|
||||
|
||||
@@ -2119,7 +2119,7 @@
|
||||
"message": "Please make sure your vault is unlocked and Fingerprint phrase matches the other device."
|
||||
},
|
||||
"fingerprintPhraseHeader": {
|
||||
"message": "Fingerprint phrase"
|
||||
"message": "指紋短語"
|
||||
},
|
||||
"needAnotherOption": {
|
||||
"message": "Log in with device must be set up in the settings of the Bitwarden app. Need another option?"
|
||||
|
||||
12
apps/web/src/app/auth/auth.module.ts
Normal file
12
apps/web/src/app/auth/auth.module.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
|
||||
import { CoreAuthModule } from "./core";
|
||||
import { SettingsModule } from "./settings/settings.module";
|
||||
|
||||
@NgModule({
|
||||
imports: [CoreAuthModule, SettingsModule],
|
||||
declarations: [],
|
||||
providers: [],
|
||||
exports: [SettingsModule],
|
||||
})
|
||||
export class AuthModule {}
|
||||
15
apps/web/src/app/auth/core/core.module.ts
Normal file
15
apps/web/src/app/auth/core/core.module.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { NgModule, Optional, SkipSelf } from "@angular/core";
|
||||
|
||||
import { WebauthnLoginApiService } from "./services/webauthn-login/webauthn-login-api.service";
|
||||
import { WebauthnLoginService } from "./services/webauthn-login/webauthn-login.service";
|
||||
|
||||
@NgModule({
|
||||
providers: [WebauthnLoginService, WebauthnLoginApiService],
|
||||
})
|
||||
export class CoreAuthModule {
|
||||
constructor(@Optional() @SkipSelf() parentModule?: CoreAuthModule) {
|
||||
if (parentModule) {
|
||||
throw new Error("CoreAuthModule is already loaded. Import it in AuthModule only");
|
||||
}
|
||||
}
|
||||
}
|
||||
2
apps/web/src/app/auth/core/index.ts
Normal file
2
apps/web/src/app/auth/core/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./services";
|
||||
export * from "./core.module";
|
||||
1
apps/web/src/app/auth/core/services/index.ts
Normal file
1
apps/web/src/app/auth/core/services/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./webauthn-login";
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./webauthn-login.service";
|
||||
@@ -0,0 +1,18 @@
|
||||
import { WebauthnLoginAttestationResponseRequest } from "./webauthn-login-attestation-response.request";
|
||||
|
||||
/**
|
||||
* Request sent to the server to save a newly created webauthn login credential.
|
||||
*/
|
||||
export class SaveCredentialRequest {
|
||||
/** The response recieved from the authenticator. This contains the public key */
|
||||
deviceResponse: WebauthnLoginAttestationResponseRequest;
|
||||
|
||||
/** Nickname chosen by the user to identify this credential */
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Token required by the server to complete the creation.
|
||||
* It contains encrypted information that the server needs to verify the credential.
|
||||
*/
|
||||
token: string;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
|
||||
import { WebauthnLoginAuthenticatorResponseRequest } from "./webauthn-login-authenticator-response.request";
|
||||
|
||||
/**
|
||||
* The response recieved from an authentiator after a successful attestation.
|
||||
* This request is used to save newly created webauthn login credentials to the server.
|
||||
*/
|
||||
export class WebauthnLoginAttestationResponseRequest extends WebauthnLoginAuthenticatorResponseRequest {
|
||||
response: {
|
||||
attestationObject: string;
|
||||
clientDataJson: string;
|
||||
};
|
||||
|
||||
constructor(credential: PublicKeyCredential) {
|
||||
super(credential);
|
||||
|
||||
if (!(credential.response instanceof AuthenticatorAttestationResponse)) {
|
||||
throw new Error("Invalid authenticator response");
|
||||
}
|
||||
|
||||
this.response = {
|
||||
attestationObject: Utils.fromBufferToB64(credential.response.attestationObject),
|
||||
clientDataJson: Utils.fromBufferToB64(credential.response.clientDataJSON),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
|
||||
/**
|
||||
* An abstract class that represents responses recieved from the webauthn authenticator.
|
||||
* It contains data that is commonly returned during different types of authenticator interactions.
|
||||
*/
|
||||
export abstract class WebauthnLoginAuthenticatorResponseRequest {
|
||||
id: string;
|
||||
rawId: string;
|
||||
type: string;
|
||||
extensions: Record<string, unknown>;
|
||||
|
||||
constructor(credential: PublicKeyCredential) {
|
||||
this.id = credential.id;
|
||||
this.rawId = Utils.fromBufferToB64(credential.rawId);
|
||||
this.type = credential.type;
|
||||
this.extensions = {}; // Extensions are handled client-side
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { ChallengeResponse } from "@bitwarden/common/auth/models/response/two-factor-web-authn.response";
|
||||
import { BaseResponse } from "@bitwarden/common/models/response/base.response";
|
||||
|
||||
/**
|
||||
* Options provided by the server to be used during attestation (i.e. creation of a new webauthn credential)
|
||||
*/
|
||||
export class WebauthnLoginCredentialCreateOptionsResponse extends BaseResponse {
|
||||
/** Options to be provided to the webauthn authenticator */
|
||||
options: ChallengeResponse;
|
||||
|
||||
/**
|
||||
* Contains an encrypted version of the {@link options}.
|
||||
* Used by the server to validate the attestation response of newly created credentials.
|
||||
*/
|
||||
token: string;
|
||||
|
||||
constructor(response: unknown) {
|
||||
super(response);
|
||||
this.options = new ChallengeResponse(this.getResponseProperty("options"));
|
||||
this.token = this.getResponseProperty("token");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { BaseResponse } from "@bitwarden/common/models/response/base.response";
|
||||
|
||||
/**
|
||||
* A webauthn login credential recieved from the server.
|
||||
*/
|
||||
export class WebauthnLoginCredentialResponse extends BaseResponse {
|
||||
id: string;
|
||||
name: string;
|
||||
prfSupport: boolean;
|
||||
|
||||
constructor(response: unknown) {
|
||||
super(response);
|
||||
this.id = this.getResponseProperty("id");
|
||||
this.name = this.getResponseProperty("name");
|
||||
this.prfSupport = this.getResponseProperty("prfSupport");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { Verification } from "@bitwarden/common/types/verification";
|
||||
|
||||
import { SaveCredentialRequest } from "./request/save-credential.request";
|
||||
import { WebauthnLoginCredentialCreateOptionsResponse } from "./response/webauthn-login-credential-create-options.response";
|
||||
import { WebauthnLoginCredentialResponse } from "./response/webauthn-login-credential.response";
|
||||
|
||||
@Injectable()
|
||||
export class WebauthnLoginApiService {
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
private userVerificationService: UserVerificationService
|
||||
) {}
|
||||
|
||||
async getCredentialCreateOptions(
|
||||
verification: Verification
|
||||
): Promise<WebauthnLoginCredentialCreateOptionsResponse> {
|
||||
const request = await this.userVerificationService.buildRequest(verification);
|
||||
const response = await this.apiService.send("POST", "/webauthn/options", request, true, true);
|
||||
return new WebauthnLoginCredentialCreateOptionsResponse(response);
|
||||
}
|
||||
|
||||
async saveCredential(request: SaveCredentialRequest): Promise<boolean> {
|
||||
await this.apiService.send("POST", "/webauthn", request, true, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
getCredentials(): Promise<ListResponse<WebauthnLoginCredentialResponse>> {
|
||||
return this.apiService.send("GET", "/webauthn", null, true, true);
|
||||
}
|
||||
|
||||
async deleteCredential(credentialId: string, verification: Verification): Promise<void> {
|
||||
const request = await this.userVerificationService.buildRequest(verification);
|
||||
await this.apiService.send("POST", `/webauthn/${credentialId}/delete`, request, true, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { CredentialCreateOptionsView } from "../../views/credential-create-options.view";
|
||||
|
||||
import { WebauthnLoginApiService } from "./webauthn-login-api.service";
|
||||
import { WebauthnLoginService } from "./webauthn-login.service";
|
||||
|
||||
describe("WebauthnService", () => {
|
||||
let apiService!: MockProxy<WebauthnLoginApiService>;
|
||||
let credentials: MockProxy<CredentialsContainer>;
|
||||
let webauthnService!: WebauthnLoginService;
|
||||
|
||||
beforeAll(() => {
|
||||
// Polyfill missing class
|
||||
window.PublicKeyCredential = class {} as any;
|
||||
window.AuthenticatorAttestationResponse = class {} as any;
|
||||
apiService = mock<WebauthnLoginApiService>();
|
||||
credentials = mock<CredentialsContainer>();
|
||||
webauthnService = new WebauthnLoginService(apiService, credentials);
|
||||
});
|
||||
|
||||
describe("createCredential", () => {
|
||||
it("should return undefined when navigator.credentials throws", async () => {
|
||||
credentials.create.mockRejectedValue(new Error("Mocked error"));
|
||||
const options = createCredentialCreateOptions();
|
||||
|
||||
const result = await webauthnService.createCredential(options);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should return credential when navigator.credentials does not throw", async () => {
|
||||
const credential = createDeviceResponse();
|
||||
credentials.create.mockResolvedValue(credential as PublicKeyCredential);
|
||||
const options = createCredentialCreateOptions();
|
||||
|
||||
const result = await webauthnService.createCredential(options);
|
||||
|
||||
expect(result).toBe(credential);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createCredentialCreateOptions(): CredentialCreateOptionsView {
|
||||
return new CredentialCreateOptionsView(Symbol() as any, Symbol() as any);
|
||||
}
|
||||
|
||||
function createDeviceResponse(): PublicKeyCredential {
|
||||
const credential = {
|
||||
id: "dGVzdA==",
|
||||
rawId: new Uint8Array([0x74, 0x65, 0x73, 0x74]),
|
||||
type: "public-key",
|
||||
response: {
|
||||
attestationObject: new Uint8Array([0, 0, 0]),
|
||||
clientDataJSON: "eyJ0ZXN0IjoidGVzdCJ9",
|
||||
},
|
||||
} as any;
|
||||
|
||||
Object.setPrototypeOf(credential, PublicKeyCredential.prototype);
|
||||
Object.setPrototypeOf(credential.response, AuthenticatorAttestationResponse.prototype);
|
||||
|
||||
return credential;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
import { Injectable, Optional } from "@angular/core";
|
||||
import { BehaviorSubject, filter, from, map, Observable, shareReplay, switchMap, tap } from "rxjs";
|
||||
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { Verification } from "@bitwarden/common/types/verification";
|
||||
|
||||
import { CredentialCreateOptionsView } from "../../views/credential-create-options.view";
|
||||
import { WebauthnCredentialView } from "../../views/webauth-credential.view";
|
||||
|
||||
import { SaveCredentialRequest } from "./request/save-credential.request";
|
||||
import { WebauthnLoginAttestationResponseRequest } from "./request/webauthn-login-attestation-response.request";
|
||||
import { WebauthnLoginApiService } from "./webauthn-login-api.service";
|
||||
|
||||
@Injectable()
|
||||
export class WebauthnLoginService {
|
||||
private navigatorCredentials: CredentialsContainer;
|
||||
private _refresh$ = new BehaviorSubject<void>(undefined);
|
||||
private _loading$ = new BehaviorSubject<boolean>(true);
|
||||
private readonly credentials$ = this._refresh$.pipe(
|
||||
tap(() => this._loading$.next(true)),
|
||||
switchMap(() => this.fetchCredentials$()),
|
||||
tap(() => this._loading$.next(false)),
|
||||
shareReplay({ bufferSize: 1, refCount: true })
|
||||
);
|
||||
|
||||
readonly loading$ = this._loading$.asObservable();
|
||||
|
||||
constructor(
|
||||
private apiService: WebauthnLoginApiService,
|
||||
@Optional() navigatorCredentials?: CredentialsContainer,
|
||||
@Optional() private logService?: LogService
|
||||
) {
|
||||
// Default parameters don't work when used with Angular DI
|
||||
this.navigatorCredentials = navigatorCredentials ?? navigator.credentials;
|
||||
}
|
||||
|
||||
async getCredentialCreateOptions(
|
||||
verification: Verification
|
||||
): Promise<CredentialCreateOptionsView> {
|
||||
const response = await this.apiService.getCredentialCreateOptions(verification);
|
||||
return new CredentialCreateOptionsView(response.options, response.token);
|
||||
}
|
||||
|
||||
async createCredential(
|
||||
credentialOptions: CredentialCreateOptionsView
|
||||
): Promise<PublicKeyCredential | undefined> {
|
||||
const nativeOptions: CredentialCreationOptions = {
|
||||
publicKey: credentialOptions.options,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await this.navigatorCredentials.create(nativeOptions);
|
||||
if (!(response instanceof PublicKeyCredential)) {
|
||||
return undefined;
|
||||
}
|
||||
return response;
|
||||
} catch (error) {
|
||||
this.logService?.error(error);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async saveCredential(
|
||||
credentialOptions: CredentialCreateOptionsView,
|
||||
deviceResponse: PublicKeyCredential,
|
||||
name: string
|
||||
) {
|
||||
const request = new SaveCredentialRequest();
|
||||
request.deviceResponse = new WebauthnLoginAttestationResponseRequest(deviceResponse);
|
||||
request.token = credentialOptions.token;
|
||||
request.name = name;
|
||||
await this.apiService.saveCredential(request);
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* List of webauthn credentials saved on the server.
|
||||
*
|
||||
* **Note:**
|
||||
* - Subscribing might trigger a network request if the credentials haven't been fetched yet.
|
||||
* - The observable is shared and will not create unnecessary duplicate requests.
|
||||
* - The observable will automatically re-fetch if the user adds or removes a credential.
|
||||
* - The observable is lazy and will only fetch credentials when subscribed to.
|
||||
* - Don't subscribe to this in the constructor of a long-running service, as it will keep the observable alive.
|
||||
*/
|
||||
getCredentials$(): Observable<WebauthnCredentialView[]> {
|
||||
return this.credentials$;
|
||||
}
|
||||
|
||||
getCredential$(credentialId: string): Observable<WebauthnCredentialView> {
|
||||
return this.credentials$.pipe(
|
||||
map((credentials) => credentials.find((c) => c.id === credentialId)),
|
||||
filter((c) => c !== undefined)
|
||||
);
|
||||
}
|
||||
|
||||
async deleteCredential(credentialId: string, verification: Verification): Promise<void> {
|
||||
await this.apiService.deleteCredential(credentialId, verification);
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
private fetchCredentials$(): Observable<WebauthnCredentialView[]> {
|
||||
return from(this.apiService.getCredentials()).pipe(map((response) => response.data));
|
||||
}
|
||||
|
||||
private refresh() {
|
||||
this._refresh$.next();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { ChallengeResponse } from "@bitwarden/common/auth/models/response/two-factor-web-authn.response";
|
||||
|
||||
export class CredentialCreateOptionsView {
|
||||
constructor(readonly options: ChallengeResponse, readonly token: string) {}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export class WebauthnCredentialView {
|
||||
id: string;
|
||||
name: string;
|
||||
prfSupport: boolean;
|
||||
}
|
||||
2
apps/web/src/app/auth/index.ts
Normal file
2
apps/web/src/app/auth/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./auth.module";
|
||||
export * from "./core";
|
||||
@@ -6,7 +6,14 @@
|
||||
<auth-password-callout [policy]="enforcedPolicyOptions" *ngIf="enforcedPolicyOptions">
|
||||
</auth-password-callout>
|
||||
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate autocomplete="off">
|
||||
<form
|
||||
#form
|
||||
(ngSubmit)="submit()"
|
||||
[appApiAction]="formPromise"
|
||||
ngNativeValidate
|
||||
autocomplete="off"
|
||||
class="tw-mb-14"
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
@@ -118,3 +125,7 @@
|
||||
{{ "changeMasterPassword" | i18n }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<app-webauthn-login-settings
|
||||
*ngIf="showWebauthnLoginSettings$ | async"
|
||||
></app-webauthn-login-settings>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { firstValueFrom, Observable } from "rxjs";
|
||||
|
||||
import { ChangePasswordComponent as BaseChangePasswordComponent } from "@bitwarden/angular/auth/components/change-password.component";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
@@ -11,12 +11,13 @@ import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-conso
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { EmergencyAccessStatusType } from "@bitwarden/common/auth/enums/emergency-access-status-type";
|
||||
import { EmergencyAccessUpdateRequest } from "@bitwarden/common/auth/models/request/emergency-access-update.request";
|
||||
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { UpdateKeyRequest } from "@bitwarden/common/models/request/update-key.request";
|
||||
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
@@ -50,6 +51,8 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
checkForBreaches = true;
|
||||
characterMinimumMessage = "";
|
||||
|
||||
protected showWebauthnLoginSettings$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
cryptoService: CryptoService,
|
||||
@@ -65,13 +68,13 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
private apiService: ApiService,
|
||||
private sendService: SendService,
|
||||
private organizationService: OrganizationService,
|
||||
private keyConnectorService: KeyConnectorService,
|
||||
private router: Router,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private organizationUserService: OrganizationUserService,
|
||||
dialogService: DialogService,
|
||||
private userVerificationService: UserVerificationService,
|
||||
private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction
|
||||
private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||
private configService: ConfigServiceAbstraction
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
@@ -86,6 +89,10 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.showWebauthnLoginSettings$ = this.configService.getFeatureFlag$(
|
||||
FeatureFlag.PasswordlessLogin
|
||||
);
|
||||
|
||||
if (!(await this.userVerificationService.hasMasterPassword())) {
|
||||
this.router.navigate(["/settings/security/two-factor"]);
|
||||
}
|
||||
|
||||
16
apps/web/src/app/auth/settings/settings.module.ts
Normal file
16
apps/web/src/app/auth/settings/settings.module.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
|
||||
import { PasswordCalloutComponent } from "@bitwarden/auth";
|
||||
|
||||
import { SharedModule } from "../../shared";
|
||||
|
||||
import { ChangePasswordComponent } from "./change-password.component";
|
||||
import { WebauthnLoginSettingsModule } from "./webauthn-login-settings";
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule, WebauthnLoginSettingsModule, PasswordCalloutComponent],
|
||||
declarations: [ChangePasswordComponent],
|
||||
providers: [],
|
||||
exports: [WebauthnLoginSettingsModule, ChangePasswordComponent],
|
||||
})
|
||||
export class SettingsModule {}
|
||||
@@ -0,0 +1,70 @@
|
||||
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
||||
<bit-dialog dialogSize="large">
|
||||
<span bitDialogTitle
|
||||
>{{ "loginWithPasskey" | i18n }}
|
||||
<span class="tw-text-sm tw-normal-case tw-text-muted">{{ "newPasskey" | i18n }}</span>
|
||||
</span>
|
||||
<ng-container bitDialogContent>
|
||||
<ng-container *ngIf="currentStep === 'userVerification'">
|
||||
<p bitTypography="body1">
|
||||
{{ "passkeyEnterMasterPassword" | i18n }}
|
||||
</p>
|
||||
<bit-form-field disableMargin formGroupName="userVerification">
|
||||
<bit-label>{{ "masterPassword" | i18n }}</bit-label>
|
||||
<input type="password" bitInput formControlName="masterPassword" appAutofocus />
|
||||
<button type="button" bitIconButton bitSuffix bitPasswordInputToggle></button>
|
||||
<bit-hint>{{ "confirmIdentity" | i18n }}</bit-hint>
|
||||
</bit-form-field>
|
||||
</ng-container>
|
||||
|
||||
<div *ngIf="currentStep === 'credentialCreation'" class="tw-flex tw-flex-col tw-items-center">
|
||||
<bit-icon [icon]="Icons.CreatePasskeyIcon" class="tw-mb-6"></bit-icon>
|
||||
<h3 bitTypography="h3">{{ "creatingPasskeyLoading" | i18n }}</h3>
|
||||
<p bitTypography="body1">{{ "creatingPasskeyLoadingInfo" | i18n }}</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
*ngIf="currentStep === 'credentialCreationFailed'"
|
||||
class="tw-flex tw-flex-col tw-items-center"
|
||||
>
|
||||
<bit-icon [icon]="Icons.CreatePasskeyFailedIcon" class="tw-mb-6"></bit-icon>
|
||||
<h3 bitTypography="h3">{{ "errorCreatingPasskey" | i18n }}</h3>
|
||||
<p bitTypography="body1">{{ "errorCreatingPasskeyInfo" | i18n }}</p>
|
||||
</div>
|
||||
|
||||
<div *ngIf="currentStep === 'credentialNaming'">
|
||||
<h3 bitTypography="h3">{{ "passkeySuccessfullyCreated" | i18n }}</h3>
|
||||
<p bitTypography="body1">
|
||||
{{ "customPasskeyNameInfo" | i18n }}
|
||||
</p>
|
||||
<bit-form-field disableMargin formGroupName="credentialNaming">
|
||||
<bit-label>{{ "customName" | i18n }}</bit-label>
|
||||
<input type="text" bitInput formControlName="name" appAutofocus />
|
||||
<bit-hint>{{
|
||||
"charactersCurrentAndMaximum"
|
||||
| i18n : formGroup.value.credentialNaming.name.length : NameMaxCharacters
|
||||
}}</bit-hint>
|
||||
</bit-form-field>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container bitDialogFooter>
|
||||
<button type="submit" bitButton bitFormButton buttonType="primary">
|
||||
<ng-container *ngIf="currentStep === 'userVerification'">
|
||||
{{ "continue" | i18n }}
|
||||
</ng-container>
|
||||
<ng-container *ngIf="currentStep === 'credentialCreation'">
|
||||
{{ "continue" | i18n }}
|
||||
</ng-container>
|
||||
<ng-container *ngIf="currentStep === 'credentialCreationFailed'">
|
||||
{{ "tryAgain" | i18n }}
|
||||
</ng-container>
|
||||
<ng-container *ngIf="currentStep === 'credentialNaming'">
|
||||
{{ ((hasPasskeys$ | async) ? "save" : "enable") | i18n }}
|
||||
</ng-container>
|
||||
</button>
|
||||
<button type="button" bitButton bitFormButton buttonType="secondary" bitDialogClose>
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</bit-dialog>
|
||||
</form>
|
||||
@@ -0,0 +1,178 @@
|
||||
import { DialogConfig, DialogRef } from "@angular/cdk/dialog";
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { firstValueFrom, map, Observable } from "rxjs";
|
||||
|
||||
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { WebauthnLoginService } from "../../../core";
|
||||
import { CredentialCreateOptionsView } from "../../../core/views/credential-create-options.view";
|
||||
|
||||
import { CreatePasskeyFailedIcon } from "./create-passkey-failed.icon";
|
||||
import { CreatePasskeyIcon } from "./create-passkey.icon";
|
||||
|
||||
export enum CreateCredentialDialogResult {
|
||||
Success,
|
||||
}
|
||||
|
||||
type Step =
|
||||
| "userVerification"
|
||||
| "credentialCreation"
|
||||
| "credentialCreationFailed"
|
||||
| "credentialNaming";
|
||||
|
||||
@Component({
|
||||
templateUrl: "create-credential-dialog.component.html",
|
||||
})
|
||||
export class CreateCredentialDialogComponent implements OnInit {
|
||||
protected readonly NameMaxCharacters = 50;
|
||||
protected readonly CreateCredentialDialogResult = CreateCredentialDialogResult;
|
||||
protected readonly Icons = { CreatePasskeyIcon, CreatePasskeyFailedIcon };
|
||||
|
||||
protected currentStep: Step = "userVerification";
|
||||
protected formGroup = this.formBuilder.group({
|
||||
userVerification: this.formBuilder.group({
|
||||
masterPassword: ["", [Validators.required]],
|
||||
}),
|
||||
credentialNaming: this.formBuilder.group({
|
||||
name: ["", Validators.maxLength(50)],
|
||||
}),
|
||||
});
|
||||
protected credentialOptions?: CredentialCreateOptionsView;
|
||||
protected deviceResponse?: PublicKeyCredential;
|
||||
protected hasPasskeys$?: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private formBuilder: FormBuilder,
|
||||
private dialogRef: DialogRef,
|
||||
private webauthnService: WebauthnLoginService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private logService: LogService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.hasPasskeys$ = this.webauthnService
|
||||
.getCredentials$()
|
||||
.pipe(map((credentials) => credentials.length > 0));
|
||||
}
|
||||
|
||||
protected submit = async () => {
|
||||
this.dialogRef.disableClose = true;
|
||||
|
||||
try {
|
||||
switch (this.currentStep) {
|
||||
case "userVerification":
|
||||
return await this.submitUserVerification();
|
||||
case "credentialCreationFailed":
|
||||
return await this.submitCredentialCreationFailed();
|
||||
case "credentialCreation":
|
||||
return await this.submitCredentialCreation();
|
||||
case "credentialNaming":
|
||||
return await this.submitCredentialNaming();
|
||||
}
|
||||
} finally {
|
||||
this.dialogRef.disableClose = false;
|
||||
}
|
||||
};
|
||||
|
||||
protected async submitUserVerification() {
|
||||
this.formGroup.controls.userVerification.markAllAsTouched();
|
||||
if (this.formGroup.controls.userVerification.invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.credentialOptions = await this.webauthnService.getCredentialCreateOptions({
|
||||
type: VerificationType.MasterPassword,
|
||||
secret: this.formGroup.value.userVerification.masterPassword,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof ErrorResponse && error.statusCode === 400) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("error"),
|
||||
this.i18nService.t("invalidMasterPassword")
|
||||
);
|
||||
} else {
|
||||
this.logService?.error(error);
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("unexpectedError"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentStep = "credentialCreation";
|
||||
await this.submitCredentialCreation();
|
||||
}
|
||||
|
||||
protected async submitCredentialCreation() {
|
||||
this.deviceResponse = await this.webauthnService.createCredential(this.credentialOptions);
|
||||
if (this.deviceResponse === undefined) {
|
||||
this.currentStep = "credentialCreationFailed";
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentStep = "credentialNaming";
|
||||
}
|
||||
|
||||
protected async submitCredentialCreationFailed() {
|
||||
this.currentStep = "credentialCreation";
|
||||
await this.submitCredentialCreation();
|
||||
}
|
||||
|
||||
protected async submitCredentialNaming() {
|
||||
this.formGroup.controls.credentialNaming.markAllAsTouched();
|
||||
if (this.formGroup.controls.credentialNaming.invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const name = this.formGroup.value.credentialNaming.name;
|
||||
try {
|
||||
await this.webauthnService.saveCredential(
|
||||
this.credentialOptions,
|
||||
this.deviceResponse,
|
||||
this.formGroup.value.credentialNaming.name
|
||||
);
|
||||
} catch (error) {
|
||||
this.logService?.error(error);
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("unexpectedError"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (await firstValueFrom(this.hasPasskeys$)) {
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("passkeySaved", name)
|
||||
);
|
||||
} else {
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("loginWithPasskeyEnabled")
|
||||
);
|
||||
}
|
||||
|
||||
this.dialogRef.close(CreateCredentialDialogResult.Success);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Strongly typed helper to open a CreateCredentialDialog
|
||||
* @param dialogService Instance of the dialog service that will be used to open the dialog
|
||||
* @param config Configuration for the dialog
|
||||
*/
|
||||
export const openCreateCredentialDialog = (
|
||||
dialogService: DialogService,
|
||||
config: DialogConfig<unknown>
|
||||
) => {
|
||||
return dialogService.open<CreateCredentialDialogResult | undefined, unknown>(
|
||||
CreateCredentialDialogComponent,
|
||||
config
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
import { svgIcon } from "@bitwarden/components";
|
||||
|
||||
export const CreatePasskeyFailedIcon = svgIcon`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="163" height="115" fill="none">
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" d="M31 19.46H9v22h22v-22Zm-24-2v26h26v-26H7Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd"
|
||||
d="M0 43.46a4 4 0 0 1 4-4h32a4 4 0 0 1 4 4v7h-4v-7H4v16.747l1.705 2.149a4 4 0 0 1 .866 2.486v22.205a4 4 0 0 1-1 2.645L4 91.475v17.985h32V91.475l-1.572-1.783a4 4 0 0 1-1-2.645V64.842a4 4 0 0 1 .867-2.486L36 60.207V56.46h4v3.747a4 4 0 0 1-.867 2.487l-1.704 2.148v22.205L39 88.83a4 4 0 0 1 1 2.645v17.985a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V91.475a4 4 0 0 1 1-2.645l1.571-1.783V64.842L.867 62.694A4 4 0 0 1 0 60.207V43.46Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd"
|
||||
d="M19.74 63.96a.5.5 0 0 1 .355.147l2.852 2.866a.5.5 0 0 1 .146.353V77.56c2.585 1.188 4.407 3.814 4.407 6.865 0 4.183-3.357 7.534-7.5 7.534-4.144 0-7.5-3.376-7.5-7.534a7.546 7.546 0 0 1 4.478-6.894v-1.443a.5.5 0 0 1 .146-.353l1.275-1.281-1.322-1.33a.5.5 0 0 1 0-.705l.332-.334-.262-.263a.5.5 0 0 1-.005-.7l1.332-1.377-1.445-1.452a.5.5 0 0 1-.145-.352v-1.114a.5.5 0 0 1 .145-.352l2.357-2.369a.5.5 0 0 1 .355-.147Zm-1.856 3.075v.7l1.645 1.654a.5.5 0 0 1 .005.7l-1.332 1.377.267.268a.5.5 0 0 1 0 .705l-.333.334 1.323 1.329a.5.5 0 0 1 0 .705l-1.48 1.488v1.57a.5.5 0 0 1-.32.466 6.545 6.545 0 0 0-4.159 6.095c0 3.61 2.913 6.534 6.5 6.534 3.588 0 6.5-2.901 6.5-6.534 0-2.749-1.707-5.105-4.095-6.074a.5.5 0 0 1-.312-.463V67.532L19.74 65.17l-1.857 1.866ZM20 85.623a1.27 1.27 0 0 0-1.268 1.276c0 .702.56 1.276 1.268 1.276.712 0 1.268-.555 1.268-1.276A1.27 1.27 0 0 0 20 85.623Zm-2.268 1.276A2.27 2.27 0 0 1 20 84.623a2.27 2.27 0 0 1 2.268 2.276c0 1.269-1 2.276-2.268 2.276a2.27 2.27 0 0 1-2.268-2.276ZM57.623 114a1 1 0 0 1 1-1h63.048a1 1 0 0 1 0 2H58.623a1 1 0 0 1-1-1Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd"
|
||||
d="M78.022 114V95.654h2V114h-2ZM98.418 114V95.654h2V114h-2Z" clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd"
|
||||
d="M16 14.46c0-7.732 6.268-14 14-14h119c7.732 0 14 6.268 14 14v68c0 7.732-6.268 14-14 14H39.5v-4H149c5.523 0 10-4.477 10-10v-68c0-5.523-4.477-10-10-10H30c-5.523 0-10 4.477-10 10v5h-4v-5Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd"
|
||||
d="M25 15.46a6 6 0 0 1 6-6h117a6 6 0 0 1 6 6v66a6 6 0 0 1-6 6H36.5v-2H148a4 4 0 0 0 4-4v-66a4 4 0 0 0-4-4H31a4 4 0 0 0-4 4v3h-2v-3Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500"
|
||||
d="M104.269 32.86a1.42 1.42 0 0 0-1.007-.4h-25.83c-.39 0-.722.132-1.007.4a1.26 1.26 0 0 0-.425.947v16.199c0 1.207.25 2.407.75 3.597a13.22 13.22 0 0 0 1.861 3.165c.74.919 1.62 1.817 2.646 2.69a30.93 30.93 0 0 0 2.834 2.172c.868.577 1.77 1.121 2.712 1.636.942.516 1.612.862 2.007 1.043.394.181.714.326.95.42.18.083.373.128.583.128.21 0 .403-.041.582-.128.241-.099.557-.239.956-.42.394-.181 1.064-.532 2.006-1.043a36.595 36.595 0 0 0 2.712-1.636c.867-.576 1.813-1.302 2.838-2.171a19.943 19.943 0 0 0 2.646-2.69 13.24 13.24 0 0 0 1.862-3.166 9.19 9.19 0 0 0 .749-3.597V33.812c.005-.367-.14-.684-.425-.952Zm-3.329 17.298c0 5.864-10.593 10.916-10.593 10.916V35.93h10.593v14.228Z" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" d="M18 24.46h-5v-2h5v2ZM27 24.46h-5v-2h5v2Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-danger-500"
|
||||
d="M51.066 66.894a2.303 2.303 0 0 1-2.455-.5l-10.108-9.797L28.375 66.4l-.002.002a2.294 2.294 0 0 1-3.185.005 2.24 2.24 0 0 1-.506-2.496c.117-.27.286-.518.503-.728l10.062-9.737-9.945-9.623a2.258 2.258 0 0 1-.698-1.6c-.004-.314.06-.619.176-.894a2.254 2.254 0 0 1 1.257-1.222 2.305 2.305 0 0 1 1.723.014c.267.11.518.274.732.486l10.01 9.682 9.995-9.688.009-.008a2.292 2.292 0 0 1 3.159.026c.425.411.68.98.684 1.59a2.242 2.242 0 0 1-.655 1.6l-.01.01-9.926 9.627 10.008 9.7.029.027a2.237 2.237 0 0 1 .53 2.496l-.002.004a2.258 2.258 0 0 1-1.257 1.222Z" />
|
||||
</svg>
|
||||
`;
|
||||
@@ -0,0 +1,26 @@
|
||||
import { svgIcon } from "@bitwarden/components";
|
||||
|
||||
export const CreatePasskeyIcon = svgIcon`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="163" height="116" fill="none">
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" d="M31 19.58H9v22h22v-22Zm-24-2v26h26v-26H7Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd"
|
||||
d="M0 43.58a4 4 0 0 1 4-4h32a4 4 0 0 1 4 4v7h-4v-7H4v16.747l1.705 2.149a4 4 0 0 1 .866 2.486v22.204a4 4 0 0 1-1 2.646L4 91.595v17.985h32V91.595l-1.572-1.783a4 4 0 0 1-1-2.646V64.962a4 4 0 0 1 .867-2.486L36 60.327V56.58h4v3.747a4 4 0 0 1-.867 2.486l-1.704 2.149v22.204L39 88.95a4 4 0 0 1 1 2.646v17.985a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V91.595a4 4 0 0 1 1-2.646l1.571-1.783V64.962L.867 62.813A4 4 0 0 1 0 60.327V43.58Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd"
|
||||
d="M19.74 64.08a.5.5 0 0 1 .355.147l2.852 2.866a.5.5 0 0 1 .146.352V77.68c2.585 1.189 4.407 3.814 4.407 6.865 0 4.183-3.357 7.535-7.5 7.535-4.144 0-7.5-3.377-7.5-7.535a7.546 7.546 0 0 1 4.478-6.894V76.21a.5.5 0 0 1 .146-.353l1.275-1.282-1.322-1.329a.5.5 0 0 1 0-.705l.332-.334-.262-.263a.5.5 0 0 1-.005-.7l1.332-1.377-1.445-1.452a.5.5 0 0 1-.145-.353v-1.113a.5.5 0 0 1 .145-.353l2.357-2.368a.5.5 0 0 1 .355-.147Zm-1.856 3.074v.7l1.645 1.654a.5.5 0 0 1 .005.7l-1.332 1.377.267.268a.5.5 0 0 1 0 .706l-.333.334 1.323 1.329a.5.5 0 0 1 0 .705l-1.48 1.488v1.57a.5.5 0 0 1-.32.466 6.545 6.545 0 0 0-4.159 6.094c0 3.61 2.913 6.535 6.5 6.535 3.588 0 6.5-2.902 6.5-6.535 0-2.748-1.707-5.104-4.095-6.073a.5.5 0 0 1-.312-.463V67.651l-2.352-2.364-1.857 1.866ZM20 85.742a1.27 1.27 0 0 0-1.268 1.277c0 .701.56 1.276 1.268 1.276.712 0 1.268-.555 1.268-1.276A1.27 1.27 0 0 0 20 85.742Zm-2.268 1.277A2.27 2.27 0 0 1 20 84.742a2.27 2.27 0 0 1 2.268 2.277c0 1.268-1 2.276-2.268 2.276a2.27 2.27 0 0 1-2.268-2.276ZM41.796 42.844a1 1 0 0 1 1.413.058l5.526 6A1 1 0 0 1 48 50.58H27a1 1 0 1 1 0-2h18.72l-3.982-4.323a1 1 0 0 1 .058-1.413ZM33.315 62.315a1 1 0 0 1-1.413-.058l-5.526-6a1 1 0 0 1 .735-1.677h21a1 1 0 1 1 0 2h-18.72l3.982 4.322a1 1 0 0 1-.058 1.413ZM57.623 114.12a1 1 0 0 1 1-1h63.048a1 1 0 1 1 0 2H58.623a1 1 0 0 1-1-1Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd"
|
||||
d="M78.022 114.12V95.774h2v18.346h-2ZM98.418 114.12V95.774h2v18.346h-2Z" clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd"
|
||||
d="M16 14.58c0-7.732 6.268-14 14-14h119c7.732 0 14 6.268 14 14v68c0 7.732-6.268 14-14 14H39.5v-4H149c5.523 0 10-4.478 10-10v-68c0-5.523-4.477-10-10-10H30c-5.523 0-10 4.477-10 10v5h-4v-5Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd"
|
||||
d="M25 15.58a6 6 0 0 1 6-6h117a6 6 0 0 1 6 6v66a6 6 0 0 1-6 6H36.5v-2H148a4 4 0 0 0 4-4v-66a4 4 0 0 0-4-4H31a4 4 0 0 0-4 4v3h-2v-3Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-500"
|
||||
d="M104.269 32.98a1.42 1.42 0 0 0-1.007-.4h-25.83c-.39 0-.722.132-1.007.4a1.26 1.26 0 0 0-.425.947v16.199c0 1.207.25 2.406.75 3.597a13.222 13.222 0 0 0 1.861 3.165c.74.919 1.62 1.817 2.646 2.69a30.93 30.93 0 0 0 2.834 2.172c.868.577 1.77 1.121 2.712 1.636.942.515 1.612.861 2.007 1.043.394.18.714.325.95.42.18.082.373.128.583.128.21 0 .403-.042.582-.128.241-.099.557-.24.956-.42.394-.182 1.064-.532 2.006-1.043a36.56 36.56 0 0 0 2.712-1.636c.867-.577 1.813-1.302 2.838-2.172a19.943 19.943 0 0 0 2.646-2.69 13.24 13.24 0 0 0 1.862-3.165c.5-1.187.749-2.386.749-3.597V33.93c.005-.367-.14-.684-.425-.952Zm-3.329 17.298c0 5.864-10.593 10.916-10.593 10.916V36.049h10.593v14.23Z" />
|
||||
<path class="tw-fill-secondary-500" fill-rule="evenodd" d="M18 24.58h-5v-2h5v2ZM27 24.58h-5v-2h5v2Z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
`;
|
||||
@@ -0,0 +1,34 @@
|
||||
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
||||
<bit-dialog dialogSize="large">
|
||||
<span bitDialogTitle
|
||||
>{{ "removePasskey" | i18n }}
|
||||
<span *ngIf="credential" class="tw-text-sm tw-normal-case tw-text-muted">{{
|
||||
credential.name
|
||||
}}</span>
|
||||
</span>
|
||||
<ng-container bitDialogContent>
|
||||
<ng-container *ngIf="!credential">
|
||||
<i class="bwi bwi-spinner bwi-spin tw-ml-1" aria-hidden="true"></i>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="credential">
|
||||
<p bitTypography="body1">{{ "removePasskeyInfo" | i18n }}</p>
|
||||
|
||||
<bit-form-field disableMargin>
|
||||
<bit-label>{{ "masterPassword" | i18n }}</bit-label>
|
||||
<input type="password" bitInput formControlName="masterPassword" />
|
||||
<button type="button" bitIconButton bitSuffix bitPasswordInputToggle></button>
|
||||
<bit-hint>{{ "confirmIdentity" | i18n }}</bit-hint>
|
||||
</bit-form-field>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ng-container bitDialogFooter>
|
||||
<button type="submit" bitButton bitFormButton buttonType="danger">
|
||||
{{ "remove" | i18n }}
|
||||
</button>
|
||||
<button type="button" bitButton bitFormButton buttonType="secondary" bitDialogClose>
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</bit-dialog>
|
||||
</form>
|
||||
@@ -0,0 +1,95 @@
|
||||
import { DialogConfig, DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
|
||||
import { Component, Inject, OnDestroy, OnInit } from "@angular/core";
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { WebauthnLoginService } from "../../../core";
|
||||
import { WebauthnCredentialView } from "../../../core/views/webauth-credential.view";
|
||||
|
||||
export interface DeleteCredentialDialogParams {
|
||||
credentialId: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
templateUrl: "delete-credential-dialog.component.html",
|
||||
})
|
||||
export class DeleteCredentialDialogComponent implements OnInit, OnDestroy {
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
protected formGroup = this.formBuilder.group({
|
||||
masterPassword: ["", [Validators.required]],
|
||||
});
|
||||
protected credential?: WebauthnCredentialView;
|
||||
|
||||
constructor(
|
||||
@Inject(DIALOG_DATA) private params: DeleteCredentialDialogParams,
|
||||
private formBuilder: FormBuilder,
|
||||
private dialogRef: DialogRef,
|
||||
private webauthnService: WebauthnLoginService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private logService: LogService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.webauthnService
|
||||
.getCredential$(this.params.credentialId)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((credential) => (this.credential = credential));
|
||||
}
|
||||
|
||||
submit = async () => {
|
||||
if (this.credential === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dialogRef.disableClose = true;
|
||||
try {
|
||||
await this.webauthnService.deleteCredential(this.credential.id, {
|
||||
type: VerificationType.MasterPassword,
|
||||
secret: this.formGroup.value.masterPassword,
|
||||
});
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("passkeyRemoved"));
|
||||
} catch (error) {
|
||||
if (error instanceof ErrorResponse && error.statusCode === 400) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("error"),
|
||||
this.i18nService.t("invalidMasterPassword")
|
||||
);
|
||||
} else {
|
||||
this.logService.error(error);
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("unexpectedError"));
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
this.dialogRef.disableClose = false;
|
||||
}
|
||||
|
||||
this.dialogRef.close();
|
||||
};
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Strongly typed helper to open a DeleteCredentialDialogComponent
|
||||
* @param dialogService Instance of the dialog service that will be used to open the dialog
|
||||
* @param config Configuration for the dialog
|
||||
*/
|
||||
export const openDeleteCredentialDialogComponent = (
|
||||
dialogService: DialogService,
|
||||
config: DialogConfig<DeleteCredentialDialogParams>
|
||||
) => {
|
||||
return dialogService.open<unknown>(DeleteCredentialDialogComponent, config);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./webauthn-login-settings.module";
|
||||
@@ -0,0 +1,71 @@
|
||||
<h2 bitTypography="h2">
|
||||
{{ "loginWithPasskey" | i18n }}
|
||||
<ng-container *ngIf="hasData">
|
||||
<span *ngIf="hasCredentials" bitBadge badgeType="success" class="!tw-align-middle">{{
|
||||
"on" | i18n
|
||||
}}</span>
|
||||
<span *ngIf="!hasCredentials" bitBadge badgeType="secondary" class="!tw-align-middle">{{
|
||||
"off" | i18n
|
||||
}}</span>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="loading">
|
||||
<i class="bwi bwi-spinner bwi-spin tw-ml-1" aria-hidden="true"></i>
|
||||
</ng-container>
|
||||
</h2>
|
||||
<p bitTypography="body1">
|
||||
{{ "loginWithPasskeyInfo" | i18n }}
|
||||
<a bitLink href="https://bitwarden.com/help/login-with-passkeys">{{
|
||||
"learnMoreAboutPasswordless" | i18n
|
||||
}}</a>
|
||||
</p>
|
||||
|
||||
<table *ngIf="hasCredentials" class="tw-mb-5">
|
||||
<tr *ngFor="let credential of credentials">
|
||||
<td class="tw-p-2 tw-pl-0 tw-font-semibold">{{ credential.name }}</td>
|
||||
<td class="tw-p-2 tw-pr-0">
|
||||
<ng-container *ngIf="credential.prfSupport">
|
||||
<i class="bwi bwi-lock-encrypted"></i>
|
||||
{{ "supportsEncryption" | i18n }}
|
||||
</ng-container>
|
||||
<span bitTypography="body1" class="tw-text-muted">
|
||||
{{ "encryptionNotSupported" | i18n }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="tw-py-2 tw-pl-10 tw-pr-0">
|
||||
<button
|
||||
type="button"
|
||||
bitLink
|
||||
[disabled]="loading"
|
||||
[attr.aria-label]="('remove' | i18n) + ' ' + credential.name"
|
||||
(click)="deleteCredential(credential.id)"
|
||||
>
|
||||
{{ "remove" | i18n }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p bitTypography="body2" *ngIf="limitReached">{{ "passkeyLimitReachedInfo" | i18n }}</p>
|
||||
|
||||
<ng-container *ngIf="hasData && !limitReached">
|
||||
<button
|
||||
*ngIf="hasCredentials"
|
||||
type="button"
|
||||
bitButton
|
||||
[disabled]="loading"
|
||||
(click)="createCredential()"
|
||||
>
|
||||
{{ "newPasskey" | i18n }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
*ngIf="!hasCredentials"
|
||||
type="button"
|
||||
bitButton
|
||||
[attr.aria-label]="('enable' | i18n) + ' ' + ('loginWithPasskey' | i18n)"
|
||||
[disabled]="loading"
|
||||
(click)="createCredential()"
|
||||
>
|
||||
{{ "enable" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Component, HostBinding, OnDestroy, OnInit } from "@angular/core";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { WebauthnLoginService } from "../../core";
|
||||
import { WebauthnCredentialView } from "../../core/views/webauth-credential.view";
|
||||
|
||||
import { openCreateCredentialDialog } from "./create-credential-dialog/create-credential-dialog.component";
|
||||
import { openDeleteCredentialDialogComponent } from "./delete-credential-dialog/delete-credential-dialog.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-webauthn-login-settings",
|
||||
templateUrl: "webauthn-login-settings.component.html",
|
||||
host: {
|
||||
"aria-live": "polite",
|
||||
},
|
||||
})
|
||||
export class WebauthnLoginSettingsComponent implements OnInit, OnDestroy {
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
protected readonly MaxCredentialCount = 5;
|
||||
|
||||
protected credentials?: WebauthnCredentialView[];
|
||||
protected loading = true;
|
||||
|
||||
constructor(
|
||||
private webauthnService: WebauthnLoginService,
|
||||
private dialogService: DialogService
|
||||
) {}
|
||||
|
||||
@HostBinding("attr.aria-busy")
|
||||
get ariaBusy() {
|
||||
return this.loading ? "true" : "false";
|
||||
}
|
||||
|
||||
get hasCredentials() {
|
||||
return this.credentials && this.credentials.length > 0;
|
||||
}
|
||||
|
||||
get hasData() {
|
||||
return this.credentials !== undefined;
|
||||
}
|
||||
|
||||
get limitReached() {
|
||||
return this.credentials?.length >= this.MaxCredentialCount;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.webauthnService
|
||||
.getCredentials$()
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((credentials) => (this.credentials = credentials));
|
||||
|
||||
this.webauthnService.loading$
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((loading) => (this.loading = loading));
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
protected createCredential() {
|
||||
openCreateCredentialDialog(this.dialogService, {});
|
||||
}
|
||||
|
||||
protected deleteCredential(credentialId: string) {
|
||||
openDeleteCredentialDialogComponent(this.dialogService, { data: { credentialId } });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
|
||||
import { SharedModule } from "../../../shared/shared.module";
|
||||
|
||||
import { CreateCredentialDialogComponent } from "./create-credential-dialog/create-credential-dialog.component";
|
||||
import { DeleteCredentialDialogComponent } from "./delete-credential-dialog/delete-credential-dialog.component";
|
||||
import { WebauthnLoginSettingsComponent } from "./webauthn-login-settings.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule, FormsModule, ReactiveFormsModule],
|
||||
declarations: [
|
||||
WebauthnLoginSettingsComponent,
|
||||
CreateCredentialDialogComponent,
|
||||
DeleteCredentialDialogComponent,
|
||||
],
|
||||
exports: [WebauthnLoginSettingsComponent],
|
||||
})
|
||||
export class WebauthnLoginSettingsModule {}
|
||||
@@ -6,9 +6,10 @@ import { FormFieldModule } from "@bitwarden/components";
|
||||
|
||||
import { OrganizationCreateModule } from "../../admin-console/organizations/create/organization-create.module";
|
||||
import { RegisterFormModule } from "../../auth/register-form/register-form.module";
|
||||
import { PaymentComponent, TaxInfoComponent } from "../../billing";
|
||||
import { BillingComponent } from "../../billing/accounts/trial-initiation/billing.component";
|
||||
import { EnvironmentSelectorModule } from "../../components/environment-selector/environment-selector.module";
|
||||
import { LooseComponentsModule, SharedModule } from "../../shared";
|
||||
import { SharedModule } from "../../shared";
|
||||
|
||||
import { ConfirmationDetailsComponent } from "./confirmation-details.component";
|
||||
import { AbmEnterpriseContentComponent } from "./content/abm-enterprise-content.component";
|
||||
@@ -37,8 +38,9 @@ import { VerticalStepperModule } from "./vertical-stepper/vertical-stepper.modul
|
||||
FormFieldModule,
|
||||
RegisterFormModule,
|
||||
OrganizationCreateModule,
|
||||
LooseComponentsModule,
|
||||
EnvironmentSelectorModule,
|
||||
PaymentComponent,
|
||||
TaxInfoComponent,
|
||||
],
|
||||
declarations: [
|
||||
TrialInitiationComponent,
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
<bit-form-control>
|
||||
<input type="checkbox" bitCheckbox formControlName="enabled" />
|
||||
<bit-label>{{ "addSecretsManager" | i18n }}</bit-label>
|
||||
<bit-label>{{ "subscribeToSecretsManager" | i18n }}</bit-label>
|
||||
<bit-hint *ngIf="upgradeOrganization">{{ "addSecretsManagerUpgradeDesc" | i18n }}</bit-hint>
|
||||
</bit-form-control>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
|
||||
import { OrganizationUserModule } from "./admin-console/organizations/users/organization-user.module";
|
||||
import { AuthModule } from "./auth";
|
||||
import { LoginModule } from "./auth/login/login.module";
|
||||
import { TrialInitiationModule } from "./auth/trial-initiation/trial-initiation.module";
|
||||
import { LooseComponentsModule, SharedModule } from "./shared";
|
||||
@@ -16,6 +17,7 @@ import { VaultFilterModule } from "./vault/individual-vault/vault-filter/vault-f
|
||||
OrganizationBadgeModule,
|
||||
OrganizationUserModule,
|
||||
LoginModule,
|
||||
AuthModule,
|
||||
],
|
||||
exports: [
|
||||
SharedModule,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user