Compare commits

...

306 Commits
4.1.2 ... 4.1.9

Author SHA1 Message Date
J-Jamet
1b98bd740c Merge branch 'release/4.1.9' 2025-10-06 17:27:26 +02:00
J-Jamet
5adeb5cde0 fix: Tags 2025-10-06 17:20:59 +02:00
J-Jamet
b949d5d861 Merge branch 'develop' of https://hosted.weblate.org/projects/keepass-dx/strings into translations 2025-10-06 17:18:20 +02:00
J-Jamet
b4264a30a4 fix: Update description 2025-10-06 17:16:57 +02:00
J-Jamet
cf799c0f68 fix: Update to 4.1.9 2025-10-06 17:14:10 +02:00
J-Jamet
97f0ca519b fix: Killed service #2201 2025-10-06 16:59:42 +02:00
J-Jamet
cf4047b701 Merge branch 'chenxiaolong-landscape-insets' into develop 2025-10-06 13:58:39 +02:00
J-Jamet
40608a3eb5 Merge branch 'landscape-insets' of github.com:chenxiaolong/KeePassDX into chenxiaolong-landscape-insets 2025-10-06 13:58:20 +02:00
J-Jamet
99cb50d031 fix: Bug report title 2025-10-06 12:47:30 +02:00
Oğuz Ersen
b0d0c35241 Translated using Weblate (Turkish)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/tr/
2025-10-05 18:02:07 +00:00
Mekyla Credo
6044c93a4a Translated using Weblate (Filipino)
Currently translated at 46.5% (309 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fil/
2025-10-05 18:02:05 +00:00
Oğuz Ersen
b544b5d54d Translated using Weblate (Turkish)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2025-10-05 18:02:02 +00:00
Andrew Gunnerson
852378e484 Simplify inset logic, fix landscape mode, fix cutout overlapping
The commit primarily fixes a few overlapping issues caused by the window
inset handling. Previously, there were two main issues:

* Because setTransparentNavigationBar() checked for portrait mode, the
  inset logic never executed in landscape mode. This caused the app to
  overlap the status bar and navigation bar.

* The inset logic did not have handling for displayCutout insets. In
  landscape mode, this would cause the app to overlap the notch or
  camera hole punch area on phones.

In addition to fixing those issues, this commit simplifies the inset
logic a bit:

* applyWindowInsets() now accepts an EnumSet of WindowInsetPosition to
  avoid needing to duplicate logic for the various position
  combinations.

* Insets are now applied to the main container in the layout instead of
  individual elements where possible. This eliminates the need for the
  previous manual IME height handling logic in BOTTOM_IME vs
  TOP_BOTTOM_IME (for avoiding the insets being applied twice).

* Since insets are now applied to the main layout container,
  applyWindowInsets() now takes systemBars, displayCutout, and ime all
  into consideration. This should avoid all possible overlapping.

* Add support for using padding instead of margins for insets. This is
  used for GroupActivity's navigation drawer, where Material design
  intends for the drawer background to be drawn behind system bars.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2025-10-04 17:24:24 -04:00
Alonso González Chaves
711a344860 Translated using Weblate (Spanish)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/es/
2025-10-04 14:02:05 +02:00
Alonso González Chaves
72087c7e5c Translated using Weblate (Spanish)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/es/
2025-10-04 14:02:01 +02:00
J-Jamet
f17d211fbd fix: Change appearance summary #2171 2025-09-24 13:19:57 +02:00
Xo
ae903ad236 Translated using Weblate (Hebrew)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/he/
2025-09-15 09:02:00 +00:00
Milo Ivir
7c3a15ce79 Translated using Weblate (Croatian)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hr/
2025-09-12 16:01:59 +00:00
J-Jamet
2230fe66ab Merge tag '4.1.8' into develop
4.1.8
2025-09-12 16:04:08 +02:00
J-Jamet
84a62a32ff Merge branch 'release/4.1.8' 2025-09-12 16:03:59 +02:00
J-Jamet
da8ef9340c fix: Loading ViewModel 2025-09-12 15:23:32 +02:00
J-Jamet
af068349e4 fix: Upgrade to 4.1.8 2025-09-12 14:14:06 +02:00
J-Jamet
56cb5953dd fix: Deletable recycle bin #2163 2025-09-12 13:00:56 +02:00
J-Jamet
2fc2a9c7c1 fix: Delete algo during merge #1516 2025-09-11 21:19:40 +02:00
J-Jamet
69e7cdbc47 fix: Search with space #175 2025-09-11 16:43:40 +02:00
J-Jamet
39d9a74a73 fix: Warnings 2025-09-11 16:36:35 +02:00
shinebrillant
b609d4e182 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/zh_Hant/
2025-09-11 13:02:01 +00:00
J-Jamet
7212c73481 fix: Warnings 2025-09-11 14:55:37 +02:00
J-Jamet
3ee4caa153 fix: Warnings 2025-09-11 14:53:41 +02:00
J-Jamet
28e4d929bb fix: Warnings 2025-09-11 14:51:35 +02:00
Artyom Rybakov
e8ecf28f7c Translated using Weblate (Russian)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/ru/
2025-09-10 14:21:47 +02:00
shinebrillant
3d5adbfc01 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hant/
2025-09-10 14:21:46 +02:00
Matthaiks
72bfc50703 Translated using Weblate (Polish)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2025-09-10 14:21:46 +02:00
Matthaiks
a60e2e780d Translated using Weblate (Polish)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2025-09-09 12:01:58 +00:00
Retrial
9210851765 Translated using Weblate (Greek)
Currently translated at 100.0% (664 of 664 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/el/
2025-09-09 12:01:56 +00:00
J-Jamet
a46251be7b fix: Better biometric exception implementation 2025-09-09 13:37:50 +02:00
J-Jamet
e8ec27dc38 fix: Upgrade to API 35 2025-09-09 11:45:30 +02:00
J-Jamet
30dd7c567c fix: Autofill compatibility package 2025-09-08 15:17:09 +02:00
J-Jamet
b196145578 Merge branch 'milotype-croatian-translation-20250907' into translations
# Conflicts:
#	fastlane/metadata/android/hr/full_description.txt
#	fastlane/metadata/android/hr/short_description.txt
#	fastlane/metadata/android/hr/title.txt
2025-09-08 12:45:09 +02:00
J-Jamet
ac347db2d1 fix: Translations 2025-09-08 12:43:06 +02:00
J-Jamet
013c437cf7 Merge branch 'develop' of https://hosted.weblate.org/projects/keepass-dx/strings into translations 2025-09-08 12:38:51 +02:00
Milo Ivir
1f600d60e3 Translated using Weblate (Croatian)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/hr/
2025-09-08 12:33:27 +02:00
Milo Ivir
d5ecaeb331 Add Croatian translation 2025-09-07 16:29:42 +02:00
Milo Ivir
db8b0100de Translated using Weblate (Croatian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hr/
2025-09-07 15:51:05 +02:00
Ihor Hordiichuk
5f41177a1f Translated using Weblate (Ukrainian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/uk/
2025-09-06 12:01:59 +00:00
Artyom Rybakov
0db2b7023e Translated using Weblate (Russian)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/ru/
2025-09-02 14:02:02 +00:00
Artyom Rybakov
a2c2a21dde Translated using Weblate (Russian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2025-09-02 14:02:00 +00:00
scollovati
d7a3e7fedd Translated using Weblate (Italian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2025-09-02 14:01:58 +00:00
J-Jamet
5e4ee167fc Merge branch 'rmacklin-remember-last-read-only-state-of-each-database' into develop 2025-09-01 19:02:59 +02:00
J-Jamet
c911b7c511 fix: Import DatabaseFile 2025-09-01 19:01:35 +02:00
J-Jamet
c79d1f1b81 Merge branch 'Dev-ClayP-master' into develop 2025-09-01 18:19:11 +02:00
J-Jamet
daf717becd fix: Remove JELLY_BEAN_MR1 conditions and unused PRNGFixes 2025-09-01 18:15:00 +02:00
J-Jamet
48d4483484 Merge branch 'master' of github.com:Dev-ClayP/KeePassDX into Dev-ClayP-master 2025-09-01 17:34:46 +02:00
leap123
c6b0ee27df Translated using Weblate (Indonesian)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/id/
2025-08-31 17:01:54 +00:00
Priit Jõerüüt
0053726d0b Translated using Weblate (Estonian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/et/
2025-08-30 18:16:53 +02:00
leap123
1395af88d1 Translated using Weblate (Indonesian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/id/
2025-08-30 18:16:52 +02:00
Fjuro
2e3ade1b4a Translated using Weblate (Czech)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2025-08-30 18:16:52 +02:00
XiveZ
90c43acfbf Translated using Weblate (Belarusian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/be/
2025-08-30 07:03:02 +02:00
Ghost of Sparta
90b68fd972 Translated using Weblate (Hungarian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hu/
2025-08-30 07:03:02 +02:00
XiveZ
ef6aeceb20 Translated using Weblate (Belarusian)
Currently translated at 5.2% (35 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/be/
2025-08-29 07:25:41 +02:00
jonnysemon
ef8685f0e7 Translated using Weblate (Arabic)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2025-08-29 07:25:41 +02:00
XiveZ
3021ed158b Added translation using Weblate (Belarusian) 2025-08-29 07:02:51 +02:00
weblator
a57043f496 Translated using Weblate (Azerbaijani)
Currently translated at 96.8% (645 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/az/
2025-08-29 07:02:51 +02:00
weblator
fdfd124fee Translated using Weblate (Serbian)
Currently translated at 50.3% (335 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/sr/
2025-08-29 07:02:50 +02:00
weblator
71739de91a Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 19.9% (133 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/yue_Hant/
2025-08-29 07:02:50 +02:00
weblator
041b1fbf53 Translated using Weblate (Burmese)
Currently translated at 6.4% (43 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/my/
2025-08-29 07:02:50 +02:00
weblator
3a72b32b4a Translated using Weblate (Slovenian)
Currently translated at 9.7% (65 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/sl/
2025-08-29 07:02:50 +02:00
weblator
994f174300 Translated using Weblate (Marathi)
Currently translated at 1.2% (8 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/mr/
2025-08-29 07:02:49 +02:00
weblator
c0f32254bb Translated using Weblate (Esperanto)
Currently translated at 21.1% (141 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/eo/
2025-08-29 07:02:49 +02:00
109247019824
fd98dbeebe Translated using Weblate (Bulgarian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/bg/
2025-08-29 07:02:49 +02:00
weblator
69ac6e6698 Translated using Weblate (Serbian (Latin script))
Currently translated at 59.0% (393 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/sr_Latn/
2025-08-29 07:02:48 +02:00
weblator
35e224d227 Translated using Weblate (Portuguese)
Currently translated at 99.6% (664 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt/
2025-08-29 07:02:47 +02:00
weblator
2da8552a53 Translated using Weblate (Javanese)
Currently translated at 3.6% (24 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/jv/
2025-08-29 07:02:47 +02:00
weblator
a9a5047949 Translated using Weblate (Persian)
Currently translated at 43.8% (292 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fa/
2025-08-29 07:02:47 +02:00
weblator
17c98f7fea Translated using Weblate (Indonesian)
Currently translated at 99.6% (664 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/id/
2025-08-29 07:02:47 +02:00
weblator
c3bc890665 Translated using Weblate (Malayalam)
Currently translated at 56.4% (376 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ml/
2025-08-29 07:02:47 +02:00
weblator
7a295c2541 Translated using Weblate (Punjabi)
Currently translated at 48.4% (323 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pa/
2025-08-29 07:02:46 +02:00
weblator
01b1b74c6a Translated using Weblate (Bengali (Bangladesh))
Currently translated at 13.3% (89 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/bn_BD/
2025-08-29 07:02:46 +02:00
weblator
fd25d21c72 Translated using Weblate (Hindi)
Currently translated at 21.9% (146 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hi/
2025-08-29 07:02:46 +02:00
Telaneo
6b1d8d24dd Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nb_NO/
2025-08-29 07:02:46 +02:00
大王叫我来巡山
5d002f5128 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2025-08-29 07:02:45 +02:00
weblator
98314c466f Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.6% (664 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_BR/
2025-08-29 07:02:44 +02:00
Matthaiks
4f7afd7c97 Translated using Weblate (Polish)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2025-08-29 07:02:44 +02:00
weblator
a9e139ff7e Translated using Weblate (Norwegian Nynorsk)
Currently translated at 42.6% (284 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nn/
2025-08-29 07:02:44 +02:00
Stephan Paternotte
4ff483a8d2 Translated using Weblate (Dutch)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nl/
2025-08-29 07:02:44 +02:00
weblator
1916b79df1 Translated using Weblate (Lithuanian)
Currently translated at 60.2% (401 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/lt/
2025-08-29 07:02:44 +02:00
Liner Seven
98e15a7717 Translated using Weblate (Japanese)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ja/
2025-08-29 07:02:43 +02:00
Masowick
dfd18e3c7f Translated using Weblate (German)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2025-08-29 07:02:42 +02:00
weblator
8fbbaae05b Translated using Weblate (English)
Currently translated at 99.8% (665 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/en/
2025-08-29 07:02:41 +02:00
Richard Macklin
8a60056866 Remove no-longer-needed enable_read_only_* string resources
(We just removed the usages of these strings)
2025-08-26 20:10:46 -07:00
Richard Macklin
e9d20a51a5 Remove global "Write-protected" setting
This addresses J-Jamet's feedback that keeping the global setting would
potentially lead to confusion, so it should be removed now that we are
remembering each database's read-only state.
2025-08-26 20:10:42 -07:00
Richard Macklin
a28d77ba32 feat: Remember the last read-only state of each database
The app has supported a global setting for opening (all) databases in
read-only mode. But that's not particularly flexible for the use case
where you have one database that should be read-only and one that should
be read-write.

Previously, to handle this use case you could open one database in
read-only mode, but the next time you attempted to open the same
database, it would "forget" that, so you would have to toggle it to
read-only mode again manually. This commit changes that behavior so that
if you toggle a database to read-only mode, it'll be remembered the next
time you open the database. (You can still toggle it back to read-write
if you change your mind, and that, too, will be remembered the next time
you open the database.)
2025-08-26 20:08:22 -07:00
Telaneo
d143605a40 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nb_NO/
2025-08-25 17:28:06 +02:00
J-Jamet
15972efb4f Merge branch 'develop' 2025-08-23 00:40:23 +02:00
J-Jamet
dae5f65c0d Revert "fix: revert checkUnlock"
This reverts commit 564b5f10ea.
2025-08-23 00:20:48 +02:00
J-Jamet
564b5f10ea fix: revert checkUnlock 2025-08-23 00:03:59 +02:00
J-Jamet
e6e40f9bd4 fix: Update to 4.1.7 2025-08-22 23:54:03 +02:00
J-Jamet
bd15e36b52 fix: Multiple biometric prompt 2025-08-22 22:50:58 +02:00
J-Jamet
43faca3061 fix: Multiple call to check availability 2025-08-22 22:34:11 +02:00
J-Jamet
82af9bada2 fix: CipherDatabase listener and rename advanced unlock in device unlock 2025-08-22 22:05:51 +02:00
Liner Seven
2befa68c93 Translated using Weblate (Japanese)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ja/
2025-08-22 11:02:30 +02:00
Random
4034a2bfc4 Translated using Weblate (Italian)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/it/
2025-08-20 13:02:22 +00:00
Nara Huang
0d93e867cf Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hant/
2025-08-20 13:02:18 +00:00
Hosted Weblate
8cac4eb51c Merge branch 'origin/develop' into Weblate. 2025-08-19 10:32:22 +02:00
Alex Ionescu
933d34ff1d Translated using Weblate (Romanian)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ro/
2025-08-19 10:32:21 +02:00
J-Jamet
d34f460b98 fix: Remove title in template issue 2025-08-19 10:12:11 +02:00
J-Jamet
7632face63 fix: Update issue template 2025-08-19 10:09:48 +02:00
J-Jamet
c4cbd2e587 fix: tags 2025-08-19 09:28:59 +02:00
J-Jamet
ad454c2e4a Merge branch 'translations' into develop 2025-08-19 09:20:35 +02:00
J-Jamet
fbb03c3ecf Merge branch 'develop' of https://hosted.weblate.org/projects/keepass-dx/strings into translations 2025-08-19 09:19:55 +02:00
J-Jamet
1a4d963d53 fix: Background event 2025-08-18 20:57:38 +02:00
J-Jamet
0c58992c21 feat: New github templates 2025-08-18 19:47:25 +02:00
J-Jamet
0eaeb3b90b fix: Upgrade CHANGELOG 2025-08-18 18:55:37 +02:00
J-Jamet
fba8443d0a fix: logs 2025-08-18 18:45:11 +02:00
J-Jamet
601874442c fix: Better database loading 2025-08-18 18:29:48 +02:00
J-Jamet
fa34618d67 fix: Connect database 2025-08-18 16:55:39 +02:00
J-Jamet
a60fc83379 fix: old device code 2025-08-18 16:28:45 +02:00
J-Jamet
c2c9ebe4c7 fix: Orientatino change in old device 2025-08-18 16:08:14 +02:00
J-Jamet
fdd86e2b9e fix: cryptoPrompt private variable 2025-08-18 13:16:26 +02:00
J-Jamet
34f0f45862 fix: Add app in background event 2025-08-18 13:12:32 +02:00
J-Jamet
c0345d4dc4 Revert "fix: Smal fix"
This reverts commit 24e859c4ce.
2025-08-18 12:11:17 +02:00
J-Jamet
24e859c4ce fix: Smal fix 2025-08-18 12:09:31 +02:00
J-Jamet
1fff0c526c fix: Authentication error 2025-08-18 10:03:02 +02:00
J-Jamet
1ee1bb8d95 fix: Device credential operation 2025-08-18 09:55:46 +02:00
J-Jamet
b8e996a5af fix: Orientation change 2025-08-17 22:45:00 +02:00
J-Jamet
df999002af fix: DeviceUnlockManager init 2025-08-17 13:36:36 +02:00
J-Jamet
64f5a4152b fix: prompt null 2025-08-17 13:24:17 +02:00
J-Jamet
0af99d1830 fix: Orientation change 2025-08-17 13:16:21 +02:00
J-Jamet
733f337312 fix: Lock orientation change 2025-08-17 11:54:39 +02:00
J-Jamet
1f99b1f884 fix: Error Keystore #2114 2025-08-17 11:24:52 +02:00
J-Jamet
c3b5598a09 fix: Auto open biometric prompt from database list #2113 Update to 4.1.6 2025-08-17 10:09:04 +02:00
jonnysemon
26cb36ccd0 Translated using Weblate (Arabic)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2025-08-16 07:02:04 +02:00
Kaya Zeren
67e0496efc Translated using Weblate (Turkish)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2025-08-15 00:02:25 +00:00
Ihor Hordiichuk
6c4d040564 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/uk/
2025-08-15 00:02:23 +00:00
J-Jamet
cb5a725d50 Merge tag '4.1.5' into develop
4.1.5
2025-08-14 17:18:34 +02:00
J-Jamet
1c30d533ad Merge branch 'release/4.1.5' 2025-08-14 17:18:23 +02:00
J-Jamet
845d1a581b fix: warnings 2025-08-14 17:14:01 +02:00
J-Jamet
23bebf9597 fix: Auto prompt #2111 2025-08-14 17:02:40 +02:00
J-Jamet
536e038306 Merge branch 'release/4.1.4' 2025-08-14 13:04:44 +02:00
J-Jamet
9e1f6d29a5 fix: update Gemfile.lock 2025-08-14 12:28:22 +02:00
J-Jamet
7a9469e59d fix: code improvement #2105 2025-08-13 19:21:42 +02:00
J-Jamet
c12eb3d643 fix: error code 28 #2105 2025-08-13 19:03:15 +02:00
J-Jamet
da0f02e536 fix: better prompt variable management #2105 2025-08-13 18:27:51 +02:00
J-Jamet
04bcc6631c fix: open auto prompt too often #2105 2025-08-13 17:59:56 +02:00
J-Jamet
698e3b7fb1 fix: auto open prompt #2105 2025-08-13 11:49:54 +02:00
J-Jamet
6de02384c1 fix: close prompt #2105 2025-08-13 11:25:36 +02:00
J-Jamet
df3bd7e0a1 fix: cipher call #2105 2025-08-13 11:03:50 +02:00
J-Jamet
c8c232639f fix: better cipher and prompt workflow #2105 2025-08-12 19:49:31 +02:00
J-Jamet
192d6eedd0 fix: autoprompt thread #2105 2025-08-12 15:51:41 +02:00
J-Jamet
9cae3f0794 fix: initDecryptData #2105 2025-08-12 15:33:35 +02:00
J-Jamet
a680db9707 fix: initDecryptData #2105 2025-08-12 15:20:32 +02:00
J-Jamet
fe526089d7 fix: auto prompt #2105 2025-08-12 14:54:52 +02:00
J-Jamet
dfd7ade416 fix: Regression #2105 2025-08-12 13:42:57 +02:00
J-Jamet
3cd65345c5 fix: Small biometric fixes 2025-08-12 13:04:52 +02:00
J-Jamet
2d398908de fix: refresh when activate setting 2025-08-12 11:11:12 +02:00
J-Jamet
756454abc3 fix: update CHANGELOG 2025-08-12 10:52:42 +02:00
J-Jamet
b7619b45b1 fix: Transition deprecation 2025-08-12 10:51:15 +02:00
J-Jamet
1369a3cad9 fix: test dependency and gradle version 2025-08-12 10:26:32 +02:00
J-Jamet
f46c062c4e fix: Auto biometric prompt #2105 2025-08-10 22:34:48 +02:00
J-Jamet
0a0abef4d4 fix: Keystore exception 2025-08-10 21:37:41 +02:00
J-Jamet
3a8245ee74 fix: Exception as Snackbar 2025-08-10 21:32:12 +02:00
J-Jamet
7be554a378 fix: unlock manager #2098 #2101 2025-08-10 12:24:23 +02:00
Masowick
7007efa627 Translated using Weblate (German)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2025-08-07 08:01:53 +02:00
J-Jamet
6c37f7b12c fix: Update to 4.1.4 2025-08-03 18:17:56 +02:00
Mark Bengtsson
05defff5ef Translated using Weblate (Swedish)
Currently translated at 72.2% (482 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/sv/
2025-07-31 16:02:37 +02:00
ssantos
e4569662ba Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pt_PT/
2025-07-31 16:02:34 +02:00
Xo
4727f7a761 Translated using Weblate (Hebrew)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/he/
2025-07-31 16:02:32 +02:00
scollovati
89b15e715d Translated using Weblate (Italian)
Currently translated at 33.3% (1 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/it/
2025-07-29 10:24:20 +02:00
Liner Seven
ef72df02e3 Translated using Weblate (Japanese)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ja/
2025-07-29 10:24:18 +02:00
Matthaiks
b6201262f1 Translated using Weblate (Polish)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/pl/
2025-07-26 12:05:52 +00:00
Viktor Varvaruk
b99fa9ffcf Translated using Weblate (Ukrainian)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/uk/
2025-07-26 12:05:50 +00:00
scollovati
1497ab85b2 Translated using Weblate (Italian)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2025-07-26 12:05:49 +00:00
Ghost of Sparta
2ade463974 Translated using Weblate (Hungarian)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hu/
2025-07-26 12:05:47 +00:00
J-Jamet
3a67ec09d5 fix: Update CHANGELOG 2025-07-25 16:04:02 +02:00
J-Jamet
dca800b1bb Merge tag '4.1.3' into develop
4.1.3
2025-07-25 15:56:49 +02:00
J-Jamet
70665f110d Merge branch 'release/4.1.3' 2025-07-25 15:56:17 +02:00
J-Jamet
3b39cafb99 fix: Warnings 2025-07-25 14:30:47 +02:00
Priit Jõerüüt
0c1b94468d Translated using Weblate (Estonian)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/et/
2025-07-25 12:58:50 +02:00
109247019824
7a841bbf57 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/bg/
2025-07-25 12:58:50 +02:00
jonnysemon
0066f1c77a Translated using Weblate (Arabic)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2025-07-25 12:58:50 +02:00
大王叫我来巡山
14dbff603d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2025-07-25 12:58:50 +02:00
solokot
42afa93293 Translated using Weblate (Russian)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2025-07-25 12:58:50 +02:00
Matthaiks
2fa25a51ad Translated using Weblate (Polish)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2025-07-25 12:58:50 +02:00
Stephan Paternotte
2b7f41477f Translated using Weblate (Dutch)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nl/
2025-07-25 12:58:49 +02:00
Sylvain Pichon
be0d5f80c3 Translated using Weblate (French)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fr/
2025-07-25 12:58:49 +02:00
Retrial
3844188fcc Translated using Weblate (Greek)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/el/
2025-07-25 12:58:49 +02:00
VfBFan
ef81ba5a8f Translated using Weblate (German)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2025-07-25 12:58:49 +02:00
Fjuro
2871668d8f Translated using Weblate (Czech)
Currently translated at 100.0% (667 of 667 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2025-07-25 12:58:49 +02:00
J-Jamet
2b5ecb2f84 fix: Simplify query #2096 2025-07-24 22:19:39 +02:00
J-Jamet
e397b92c36 fix: Search and allow empty query #2096 2025-07-24 21:29:43 +02:00
J-Jamet
e273eb6e03 fix: Replace strong tag 2025-07-24 20:36:01 +02:00
J-Jamet
28b624afa3 fix: Descriptions 2025-07-24 20:30:14 +02:00
J-Jamet
fb1e6cdc3f Merge branch 'develop' of https://hosted.weblate.org/projects/keepass-dx/strings into translations 2025-07-24 20:23:50 +02:00
jonnysemon
8b6499d040 Translated using Weblate (Arabic)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2025-07-24 20:16:45 +02:00
Kunzisoft
054af507ad Translated using Weblate (French)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fr/
2025-07-24 20:16:44 +02:00
J-Jamet
ac9bb9b666 fix: Biometric error #2081 2025-07-24 19:41:28 +02:00
J-Jamet
809e1929e5 fix: Biometric error #2081 2025-07-24 19:21:29 +02:00
J-Jamet
a1b1338d67 fix: Biometric after orientation change #2081 2025-07-24 19:12:25 +02:00
J-Jamet
bd4cacfab1 Merge branch 'IzzySoft-fastlane' into develop 2025-07-24 18:26:32 +02:00
J-Jamet
e0343bdc55 Merge branch 'IzzySoft-iod' into develop 2025-07-24 18:23:40 +02:00
J-Jamet
b743d004e2 fix: Template EMAIL #1986 2025-07-24 18:22:11 +02:00
J-Jamet
4b20e035b2 fix: Upgrade CHANGELOG 2025-07-24 17:12:09 +02:00
J-Jamet
afe5fddc50 Merge branch 'shauser88-fix-save-copy-localtime' into develop 2025-07-24 17:09:48 +02:00
J-Jamet
d68ca1b51f Merge branch 'fix-save-copy-localtime' of github.com:shauser88/KeePassDX into shauser88-fix-save-copy-localtime 2025-07-24 17:08:55 +02:00
Jérémy JAMET
061b087229 Merge pull request #2095 from d20n/fix-en_GB-strings
Fix several incomplete en_GB strings
2025-07-24 16:59:23 +02:00
J-Jamet
bb3a379965 fix: Upgrade CHANGELOG 2025-07-24 16:42:35 +02:00
J-Jamet
593b5c6338 fix: Biometric error prompts #2081 2025-07-24 16:39:42 +02:00
J-Jamet
56f8a1bf9f fix: Upgrade version and CHANGELOG 2025-07-22 18:45:44 +02:00
J-Jamet
962b547b36 fix: Registration #2089 2025-07-22 18:40:36 +02:00
Izzy
6df8ff4310 fastlane: slight formatting adjustments to full descriptions 2025-07-20 00:31:38 +02:00
Martin Milchevski
52f17140b8 Translated using Weblate (Macedonian)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/mk/
2025-07-20 00:03:07 +02:00
ginger-co
75c2bb4a87 Translated using Weblate (Hebrew)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/he/
2025-07-20 00:03:05 +02:00
Martin Milchevski
f36f6c3155 Translated using Weblate (Macedonian)
Currently translated at 4.8% (32 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/mk/
2025-07-18 23:16:13 +02:00
Martin Milchevski
b88b92c5b0 Added translation using Weblate (Macedonian) 2025-07-18 23:00:51 +02:00
pigmentblue15
d2c569c4f0 Translated using Weblate (Japanese)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ja/
2025-07-16 17:01:50 +02:00
Izzy
cb1316564e IzzyOnDroid provides both, the Free and the Libre variants 2025-07-15 09:51:50 +02:00
VfBFan
245d3f7df2 Translated using Weblate (German)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/de/
2025-07-14 19:02:00 +02:00
Random
3729b3c5a0 Translated using Weblate (Italian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2025-07-14 19:01:52 +02:00
Random
7ce5eb3c27 Translated using Weblate (Italian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2025-07-14 19:01:50 +02:00
VfBFan
43defea85e Translated using Weblate (German)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2025-07-14 19:01:48 +02:00
d20n
8470c4e39b Fix several incomplete en_GB strings 2025-07-14 17:20:42 +02:00
Dev-ClayP
1f678fc975 Update Loupe.kt
removed old sdk checks
2025-07-09 11:24:30 -04:00
Dev-ClayP
082c839639 Update EntryEditActivity.kt
removed old sdk checks
2025-07-09 11:18:59 -04:00
Dev-ClayP
600d548fce Update BroadcastAction.kt
removed old SDK check
2025-07-09 11:15:46 -04:00
Dev-ClayP
3035f9b686 Update TimeoutHelper.kt
Removed old SDK check
2025-07-09 11:14:18 -04:00
Dev-ClayP
6eae0f02d3 Update FileDatabaseSelectActivity.kt
removed PackageManager.allowCreateDocumentByStorageAccessFramework()
2025-07-09 11:11:53 -04:00
Dev-ClayP
87be2f4b9e Update UriHelper.kt
removed PackageManager.allowCreateDocumentByStorageAccessFramework()  it will always eval to true with sdk update
2025-07-09 11:09:44 -04:00
Dev-ClayP
3b054504a1 Update UriUtil.kt
removed another kitkat check
2025-07-09 11:05:01 -04:00
Dev-ClayP
a88f6b968a Update UriUtil.kt
Removed KitKat sdk check
2025-07-09 11:04:12 -04:00
Dev-ClayP
1fc4f150bf Update item_breadcrumb.xml
Removed jelly_bean target check
2025-07-09 10:45:16 -04:00
Dev-ClayP
1f4e59cbdc Update fragment_set_otp.xml
Removed sdk target checks for jelly_bean
2025-07-09 10:44:21 -04:00
Dev-ClayP
b5dc8d9adf Update build.gradle
changed minsdk to 19
2025-07-09 10:40:38 -04:00
Dev-ClayP
43f7e08548 Update build.gradle
changed minsdk to 19
2025-07-09 10:40:13 -04:00
Dev-ClayP
05fc6f87ec Update build.gradle
changed minsdk to 19
2025-07-09 10:39:34 -04:00
Dev-ClayP
daae535fa1 Update TemplateView.kt
Removed old SDK checks
2025-07-09 10:28:27 -04:00
Dev-ClayP
90c8cb3455 Update ViewUtil.kt
Removed SDK check
2025-07-09 10:26:12 -04:00
Dev-ClayP
daeee10de9 Update TemplateEditView.kt
Removed old SDK check
2025-07-09 10:25:15 -04:00
Dev-ClayP
6c1c401a71 Update NodesAdapter.kt
Removed old SDK check
2025-07-09 10:23:44 -04:00
Dev-ClayP
fd7f0fceb2 Update UriUtil.kt
Removed Old SDK Check
2025-07-09 10:21:55 -04:00
Dev-ClayP
26b8a616be Update AboutActivity.kt
Removed old SDK Check
2025-07-09 10:19:54 -04:00
Dev-ClayP
d88882f439 Removed PRNGFixes App.kt 2025-07-09 10:15:36 -04:00
Dev-ClayP
09dc1d6baa Removed sdk checks on TextFieldView.kt
Removed SDK checks that will always resolve to true now. Since we are updating min sdk to 19, these checks are no longer necessary.
2025-07-09 09:57:23 -04:00
Clay Perry
f4f5e86979 Updated Minimum SDK to 16 2025-07-08 12:52:14 -04:00
Stephan Paternotte
a41afb7f1e Translated using Weblate (Dutch)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/nl/
2025-07-07 15:02:17 +02:00
Stephan Paternotte
32d9cfbe29 Translated using Weblate (Dutch)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/nl/
2025-07-07 15:02:15 +02:00
Masowick
7210652567 Translated using Weblate (German)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/de/
2025-07-07 15:02:13 +02:00
VfBFan
ab15967ad7 Translated using Weblate (German)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/de/
2025-07-07 15:02:11 +02:00
Stephan Paternotte
44df4ec181 Added translation using Weblate (Dutch) 2025-07-06 14:29:32 +02:00
Fjuro
7afe356082 Translated using Weblate (Czech)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/cs/
2025-07-06 14:29:32 +02:00
Fjuro
87597553b8 Translated using Weblate (Czech)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/cs/
2025-07-06 14:29:32 +02:00
Fjuro
27e5f58d5e Added translation using Weblate (Czech) 2025-07-05 23:12:59 +02:00
jonnysemon
762c946d35 Translated using Weblate (Arabic)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/ar/
2025-07-05 23:12:58 +02:00
jonnysemon
21a927e3e9 Translated using Weblate (Arabic)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/ar/
2025-07-05 23:12:58 +02:00
jonnysemon
f93bb7436a Translated using Weblate (Arabic)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/ar/
2025-07-05 23:12:58 +02:00
jonnysemon
6294fddbba Translated using Weblate (Arabic)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2025-07-05 23:12:58 +02:00
jonnysemon
c5719dfaf2 Translated using Weblate (Arabic)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ar/
2025-07-05 23:12:58 +02:00
Matthaiks
673fd67f15 Translated using Weblate (Polish)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2025-07-05 23:12:58 +02:00
Fjuro
25524c48e9 Translated using Weblate (Czech)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2025-07-05 23:12:58 +02:00
Fjuro
631b924c33 Translated using Weblate (Czech)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2025-07-05 23:12:58 +02:00
J-Jamet
fba12bc278 Merge tag '4.1.2' into develop
4.1.2
2025-07-05 17:30:44 +02:00
Tomás
bf7e014f8c Translated using Weblate (Spanish)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/es/
2025-07-05 11:40:35 +02:00
Tomás
40e1607698 Translated using Weblate (Spanish)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/es/
2025-07-05 11:40:35 +02:00
Matthaiks
4a132f06fe Translated using Weblate (Polish)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2025-07-05 11:40:35 +02:00
Tomás
0396dd975d Translated using Weblate (Spanish)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/es/
2025-07-05 02:47:45 +02:00
Yurt Page
a6b20455ef Translated using Weblate (Russian)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/ru/
2025-07-04 16:00:48 +02:00
Bora Atıcı
ca148ef546 Translated using Weblate (Turkish)
Currently translated at 66.6% (2 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/tr/
2025-07-02 19:01:48 +02:00
Priit Jõerüüt
25df86606c Translated using Weblate (Estonian)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/et/
2025-07-01 18:31:43 +02:00
Priit Jõerüüt
811f33eb3f Translated using Weblate (Estonian)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/et/
2025-07-01 18:31:43 +02:00
solokot
ca7e2ed89d Translated using Weblate (Russian)
Currently translated at 66.6% (2 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/ru/
2025-07-01 18:31:43 +02:00
solokot
6f4cd79e2c Translated using Weblate (Russian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2025-07-01 18:31:43 +02:00
solokot
da1caf4b8b Translated using Weblate (Russian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2025-07-01 18:31:43 +02:00
Stephan Paternotte
4a0a8e44ca Translated using Weblate (Dutch)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nl/
2025-07-01 18:31:43 +02:00
Stephan Paternotte
6bc2c3481b Translated using Weblate (Dutch)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nl/
2025-07-01 18:31:43 +02:00
Liner Seven
dc75837ac7 Translated using Weblate (Japanese)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/ja/
2025-07-01 09:22:50 +02:00
Liner Seven
9849b0a1da Translated using Weblate (Japanese)
Currently translated at 100.0% (3 of 3 strings)

Translation: KeePassDX/Metadata
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/metadata/ja/
2025-07-01 09:22:50 +02:00
Priit Jõerüüt
2c15a1ddd6 Translated using Weblate (Estonian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/et/
2025-07-01 09:22:50 +02:00
Priit Jõerüüt
98eb9976cf Translated using Weblate (Estonian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/et/
2025-07-01 09:22:50 +02:00
Keterion
0d9a5810b1 Translated using Weblate (Filipino)
Currently translated at 46.2% (308 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fil/
2025-07-01 09:22:50 +02:00
Besnik Bleta
1adaa137a5 Translated using Weblate (Albanian)
Currently translated at 96.5% (643 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/sq/
2025-07-01 09:22:50 +02:00
bowornsin
44a428d15a Translated using Weblate (Thai)
Currently translated at 89.3% (595 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/th/
2025-07-01 09:22:50 +02:00
Suman Garai
5416a7942a Translated using Weblate (Bengali)
Currently translated at 52.5% (350 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/bn/
2025-07-01 09:22:49 +02:00
Keterion
9e0024baf5 Translated using Weblate (English (United Kingdom))
Currently translated at 33.9% (226 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/en_GB/
2025-07-01 09:22:49 +02:00
Keterion
8d47ce38c2 Translated using Weblate (Vietnamese)
Currently translated at 98.6% (657 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/vi/
2025-07-01 09:22:49 +02:00
109247019824
80af43c0ca Translated using Weblate (Bulgarian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/bg/
2025-07-01 09:22:49 +02:00
109247019824
225f8243c2 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/bg/
2025-07-01 09:22:49 +02:00
தமிழ்நேரம்
68bc118add Translated using Weblate (Tamil)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ta/
2025-07-01 09:22:49 +02:00
தமிழ்நேரம்
abbc584402 Translated using Weblate (Tamil)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ta/
2025-07-01 09:22:49 +02:00
தமிழ்நேரம்
6635594639 Translated using Weblate (Tamil)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ta/
2025-07-01 09:22:49 +02:00
தமிழ்நேரம்
10db77d402 Translated using Weblate (Tamil)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ta/
2025-07-01 09:22:49 +02:00
Allan Nordhøy
000fd7e520 Translated using Weblate (Norwegian Bokmål)
Currently translated at 98.4% (656 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nb_NO/
2025-07-01 09:22:48 +02:00
Keterion
c8ced4ae59 Translated using Weblate (Galician)
Currently translated at 87.0% (580 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/gl/
2025-07-01 09:22:48 +02:00
hugoalh
9209ca9af7 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 99.8% (665 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hant/
2025-07-01 09:22:48 +02:00
大王叫我来巡山
c7bd90c610 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2025-07-01 09:22:47 +02:00
aasami
fceb9c3547 Translated using Weblate (Slovak)
Currently translated at 99.8% (665 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/sk/
2025-07-01 09:22:47 +02:00
Ash Ed
030c49b571 Translated using Weblate (Russian)
Currently translated at 99.8% (665 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2025-07-01 09:22:47 +02:00
Stephan Paternotte
f2d6a6a536 Translated using Weblate (Dutch)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nl/
2025-07-01 09:22:47 +02:00
Liner Seven
8f61521f05 Translated using Weblate (Japanese)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ja/
2025-07-01 09:22:47 +02:00
cc5efd7b0
89af7ec5d0 Translated using Weblate (Japanese)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ja/
2025-07-01 09:22:47 +02:00
Ghost of Sparta
362f1aebed Translated using Weblate (Hungarian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hu/
2025-07-01 09:22:46 +02:00
summoner001
5226527cec Translated using Weblate (Hungarian)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/hu/
2025-07-01 09:22:46 +02:00
Aitor Elorza
b8464cd0e5 Translated using Weblate (Basque)
Currently translated at 95.6% (637 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/eu/
2025-07-01 09:22:46 +02:00
Óscar Fernández Díaz
46e7b04d66 Translated using Weblate (Spanish)
Currently translated at 99.6% (664 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/es/
2025-07-01 09:22:46 +02:00
VfBFan
73111b770f Translated using Weblate (German)
Currently translated at 100.0% (666 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2025-07-01 09:22:46 +02:00
Keterion
995d485700 Translated using Weblate (Danish)
Currently translated at 98.6% (657 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/da/
2025-07-01 09:22:46 +02:00
pitroig
5ebbbef667 Translated using Weblate (Catalan)
Currently translated at 99.8% (665 of 666 strings)

Translation: KeePassDX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ca/
2025-07-01 09:22:45 +02:00
Stefan Hauser
a7a93fa2a2 Use local date/time in filename for saving a copy of the database 2025-01-16 09:15:32 +01:00
219 changed files with 5187 additions and 4183 deletions

View File

@@ -1,49 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**KeePass Database**
- Created with: [e.g Windows KeePass 2.42]
- Version: [e.g. 2]
- Location: [e.g. Remote file retrieved with GDrive app]
- File provider (`content://` URI): [e.g. `content://com.google.android.apps.docs.storage/5`]
- Size: [e.g. 150Mo]
- Contains attachment: [e.g. Yes]
**KeePassDX:**
- Version: [e.g. 2.5.0.0beta23]
- Build: [e.g. Free]
- Language: [e.g. French]
**Android:**
- Device: [e.g. GalaxyS8]
- Version: [e.g. 8.1]
**Additional context**
Add any other context about the problem here.
- Browser for Autofill: [e.g. Chrome version X]

62
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: Bug report
description: Report a bug.
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Please check out the [Wiki](https://github.com/Kunzisoft/KeePassDX/wiki) and [existing issues](https://github.com/Kunzisoft/KeePassDX/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) to see if your problem has already been reported.
- type: checkboxes
id: checks
attributes:
label: Checks
options:
- label: I have read the Wiki, searched the open issues, and still think this is a new bug.
required: true
- type: textarea
id: bug
attributes:
label: "Explain the problem clearly and succinctly:"
validations:
required: true
- type: textarea
id: expected
attributes:
label: "Describe what you expected to happen:"
- type: input
id: app-version
attributes:
label: "KeePassDX version:"
validations:
required: true
- type: dropdown
id: app-build
attributes:
label: "Build:"
multiple: true
options:
- Free
- Libre
validations:
required: true
- type: input
id: database-version
attributes:
label: "Database version:"
- type: input
id: file-provider
attributes:
label: "File provider (`content://` URI)"
- type: input
id: android-version
attributes:
label: "Android version:"
- type: input
id: android-device
attributes:
label: "Android device:"
- type: textarea
id: additional-context
attributes:
label: "Additional context:"

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

@@ -0,0 +1 @@
blank_issues_enabled: false

View File

@@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -0,0 +1,33 @@
name: Feature request
description: Suggest an idea.
labels: ["feature"]
body:
- type: markdown
attributes:
value: |
Please check out the [Wiki](https://github.com/Kunzisoft/KeePassDX/wiki) and [existing issues](https://github.com/Kunzisoft/KeePassDX/issues?q=is%3Aissue%20state%3Aopen%20label%3Afeature) to see if your feature has already been reported.
- type: checkboxes
id: checks
attributes:
label: Checks
options:
- label: I have read the Wiki, searched the open issues, and still think this is a new feature.
required: true
- type: textarea
id: problem
attributes:
label: "Explain the problem clearly and succinctly:"
- type: textarea
id: solution
attributes:
label: "Describe the solution you'd like:"
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: "Describe alternatives you've considered:"
- type: textarea
id: additional-context
attributes:
label: "Additional context:"

View File

@@ -1,3 +1,39 @@
KeePassDX(4.1.9)
* Fix landscape UI #2198 #2200 (@chenxiaolong)
* Fix start loop and flash screen #2201
* Small fixes
KeePassDX(4.1.8)
* Updated to API 35 minimum SDK 19 #2073 #2138 #2067 #2133 #1687 (Thx @Dev-ClayP)
* Remember last read-only state #2099 #2100 (Thx @rmacklin)
* Fix merge deletion #1516
* Fix space in search #175
* Fix deletable recycle bin #2163
* Small fixes
KeePassDX(4.1.7)
* Fix CipherDatabase for biometric states #2119
KeePassDX(4.1.6)
* Auto open biometric prompt from database list #2113
* Fix Keystore errors #2114 #2115
* Complete biometric refactoring for better compatibility
KeePassDX(4.1.5)
* Fix auto prompt #2111
KeePassDX(4.1.4)
* Fix UnlockManager #2098 #2101
* Auto device unlock prompt #2105
* Small fixes ##2066
KeePassDX(4.1.3)
* Fix Autofill Registration #2089
* Fix Biometric errors #2081
* Fixed timestamp in copy file #1981 #1983
* Fix Template Email #1986
* Fix Search #2096
KeePassDX(4.1.2)
* Fix URL search #1940 #1946 #2003 #2040 #2044
* Fix Autofill popup #2054

View File

@@ -9,31 +9,35 @@ GEM
public_suffix (>= 2.0.2, < 7.0)
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.3.0)
aws-partitions (1.1009.0)
aws-sdk-core (3.213.0)
aws-eventstream (1.4.0)
aws-partitions (1.1146.0)
aws-sdk-core (3.229.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
base64
bigdecimal
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.95.0)
aws-sdk-core (~> 3, >= 3.210.0)
logger
aws-sdk-kms (1.110.0)
aws-sdk-core (~> 3, >= 3.228.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.171.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sdk-s3 (1.196.1)
aws-sdk-core (~> 3, >= 3.228.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.10.1)
aws-sigv4 (1.12.1)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
base64 (0.2.0)
base64 (0.3.0)
bigdecimal (3.2.2)
claide (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
declarative (0.0.20)
digest-crc (0.6.5)
digest-crc (0.7.0)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.6.20240107)
dotenv (2.8.1)
@@ -55,11 +59,11 @@ GEM
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-em_synchrony (1.0.1)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-multipart (1.1.1)
multipart-post (~> 2.0)
faraday-net_http (1.0.2)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
@@ -67,8 +71,8 @@ GEM
faraday-retry (1.0.3)
faraday_middleware (1.2.1)
faraday (~> 1.0)
fastimage (2.3.1)
fastlane (2.225.0)
fastimage (2.4.0)
fastlane (2.228.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
@@ -108,7 +112,7 @@ GEM
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty (~> 0.4.1)
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
fastlane-plugin-versioning_android (0.1.1)
fastlane-sirp (1.0.0)
@@ -130,12 +134,12 @@ GEM
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.31.0)
google-apis-core (>= 0.11.0, < 2.a)
google-cloud-core (1.7.1)
google-cloud-core (1.8.0)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.4.0)
google-cloud-errors (1.5.0)
google-cloud-storage (1.47.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
@@ -151,36 +155,39 @@ GEM
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
http-cookie (1.0.7)
http-cookie (1.0.8)
domain_name (~> 0.5)
httpclient (2.8.3)
httpclient (2.9.0)
mutex_m
jmespath (1.6.2)
json (2.8.2)
jwt (2.9.3)
json (2.13.2)
jwt (2.10.2)
base64
logger (1.7.0)
mini_magick (4.13.2)
mini_mime (1.1.5)
multi_json (1.15.0)
multi_json (1.17.0)
multipart-post (2.4.1)
mutex_m (0.3.0)
nanaimo (0.4.0)
naturally (2.2.1)
naturally (2.3.0)
nkf (0.2.0)
optparse (0.6.0)
os (1.1.4)
plist (3.7.1)
public_suffix (6.0.1)
rake (13.2.1)
plist (3.7.2)
public_suffix (6.0.2)
rake (13.3.0)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.3.9)
rouge (2.0.7)
rexml (3.4.1)
rouge (3.28.0)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
rubyzip (2.4.1)
security (0.1.5)
signet (0.19.0)
signet (0.20.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
@@ -207,8 +214,8 @@ GEM
colored2 (~> 3.1)
nanaimo (~> 0.4.0)
rexml (>= 3.3.6, < 4.0)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty (0.4.1)
rouge (~> 3.28.0)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
@@ -220,4 +227,4 @@ DEPENDENCIES
fastlane-plugin-versioning_android
BUNDLED WITH
2.5.10
2.6.9

View File

@@ -54,7 +54,7 @@ Optional visual styles are accessible after a contribution (and a congratulatory
|--------|--------|---------|
| [Google Play](https://play.google.com/store/apps/details?id=com.kunzisoft.keepass.free) | ![Google Play Release](https://img.shields.io/endpoint?color=blue&logo=google-play&logoColor=green&url=https%3A%2F%2Fplay.cuzi.workers.dev%2Fplay%3Fi%3Dcom.kunzisoft.keepass.free%26gl%3DUS%26hl%3Den%26l%3DGoogle%2520Play%26m%3D%24version) | Free + [Pro](https://play.google.com/store/apps/details?id=com.kunzisoft.keepass.pro) |
| [F-Droid](https://f-droid.org/en/packages/com.kunzisoft.keepass.libre/) | ![F-Droid Version](https://img.shields.io/f-droid/v/com.kunzisoft.keepass.libre?logo=F-Droid&label=F-Droid) | Libre |
| [IzzyOnDroid](https://apt.izzysoft.de/fdroid/index/apk/com.kunzisoft.keepass.free) | ![IzzyOnDroid Version](https://img.shields.io/endpoint?&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAADAFBMVEUA0////wAA0v8A0v8A0////wD//wAFz/QA0/8A0/8A0/8A0/8A0v///wAA0/8A0/8A0/8A0/8A0//8/gEA0/8A0/8B0/4A0/8A0/8A0/+j5QGAwwIA0//C9yEA0/8A0/8A0/8A0/8A0/8A0/+n4SAA0/8A0/8A0/+o6gCw3lKt7QCv5SC+422b3wC19AC36zAA0/+d1yMA0/8A0/+W2gEA0/+w8ACz8gCKzgG7+QC+9CFLfwkA0/8A0////wAA0/8A0/8A0/8A0/+f2xym3iuHxCGq5BoA1P+m2joI0vONyiCz3mLO7oYA0/8M1Piq3Ei78CbB8EPe8LLj9Ly751G77zWQ1AC96UYC0fi37CL//wAA0/8A0////wD//wCp3jcA0/+j3SGj2i/I72Sx4zHE8FLB8zak1kYeycDI6nRl3qEA0/7V7psA0v6WzTa95mGi2RvB5XkPy9zH5YJ3uwGV1yxVihRLiwdxtQ1ZkAf//wD//wD//wD//wD//wCn5gf//wD//wD//wD//wD//wAA0/+h4A3R6p8A0/+X1w565OD6/ARg237n9csz2vPz+gNt37V/vifO8HW68B/L6ZOCwxXY8KRQsWRzhExAtG/E612a1Rd/pTBpmR9qjysduKVhmxF9mTY51aUozK+CsDSA52T//wD//wAA0////wD//wBJ1JRRxFWjzlxDyXRc0pGT1wCG0CWB3VGUzSTh8h6c0TSr5CCJ5FFxvl6s4H3m8xML0/DA5CvK51EX1N+Y2gSt4Dag3ChE3fax2ki68yO57NF10FRZnUPl88eJxhuCxgCz5EOLwEGf1DFutmahzGW98x0W1PGk3R154MHE6bOn69qv3gy92oG90o+Hn07B7rhCmiyMwECv1nO+0pQfwrCo57xF2daXsVhKrEdenQAduaee1Bsjr42z5D9RoCXy+QNovXpy2Z5MtWDO/TiSukaF3UtE1K6j3B4YwLc5wXlzpyIK0u5zy3uJqg4pu5RTpkZmpVKyAP8A0wBHcExHcEyBUSeEAAABAHRSTlP///9F9wjAAxD7FCEGzBjd08QyEL39abMd6///8P/ZWAnipIv/cC6B//7////////L/1Dz/0D///////86/vYnquY3/v///5T//v///17///////////////84S3QNB/8L/////////////7r/////NP////9l/////wPD4yis/x7Ym2lWSP+em////0n////////v///////////////////7//7pdGN3Urr6/+v/6aT////+//H/o2P/1v+7r7jp4PM/3p4g////g///K///481LxO///v////9w////8v/////9/p3J///a+P9v/5KR/+n///+p/xf//8P//wAAe7FyaAAABCZJREFUSMdj+E8iYKBUgwIHnwQ3N7cEHxcH+///VayoAE0Dh41qR7aBnCIQ8MsJKHH9/99czYYMWlA0cIkJGjMgAKfq//9RNYzIgLcBWYOTiCgDMhDn+B9bh6LebiWyH6L5UZQzONoAHWSHoqEpDkkDsyKqelv1//9rG1HUN9YihZK9AKp6BkG+/6xNqA5ajhSsCkrIipmYGGRa//9vQXVQXSySBnkWJOUMfn5Myuz/G3hR1NdEIUUchwiy+bkTsg4dbW/fu6W/e1c3XMMy5JiOZkFxUFZo74mgKTqaKXu0+2HqVwkja3BH9kFu361JwcHTfPJD4mdfe8ULAdVRyGlJAcVFfg+CQOozZ4XrJ85+JgwBsVXIGriQw5Tp4ZScezd8JiWnBupru30qwJZa+ZAjmWlC8fUZM4qB6kPnLNSPLMWqQQ5ZQ5aOzs1HmamBaQHzFs6y+qAmJCTE8f9/QgKSBg4DJPWc6zVDQkIC09JkZSPD38kukpExFpT4z67uYI/QwCOOCCK/izvu5CWl6AcEWMnKWml7LWbKZfH9/99UkknQHhGsynDz+65eWXv3/JmJrq5eXienVlRUfH/z8VvCf45soKQIH1yDEQsszrp6gwq9C73T87xcXadKl5TkFev4A/2tygmSBqYXqAYJmK+ZuoJydDR1vP09DA0NOy2kpdML81+U/heCpH1JU3jig7lJ5nKOT4i/t6ZHkqGzs4lJmIVHfrj+JR4HqLQSD0yDkCNEpGNn5ix9D03/eJdElTZdKV2TpNOhkwt8YUlNUgimgV0dLMBvf1gz1MolPd5FRcVNSkpDQ8owJeBCDyIhrIDnOD5QcuIU+3/2QKSs9laQ+noNLS0zLWdtqyP7mBAFAw88TwsJgMuJYweBGjYngtWbmeuZOW+bvNQToUFOAlFqOBk4Ov3/L7Z60/aN0p1tUhpa5nqWlub7C3p2I9QzyAghlUvczOz/1fhzPT3XSIfpSmmYAdVbmm1gV0dSz8DSilpUQsqCddIWIA3meuZaJqdMJZEzl6gRqgZIWZAxUdoizERXN8yi5MltcZTChzMaRQM3JNUWHS8rL/+yaPGvMmvr5ywoGoxtkDWwQ+Pb89ycBeWfGSJeL/la+RS1eOPnRtbQKgMRjZg+t8x6PkP273nWQAoFOPAgaeAThKXAmXMrK39Kmr5fsuBlBqoXfJGLe3VbmHjG9Mczi9T//3h7vygXtcDlQtJg44iQiIjIBRbGPO7gghPJy0ZIxT2HOLIUgwxQzsgYrUR350HSIMaJLidhgKY+mw+pflBDrX8E7OGBjPCAPc76gQFSTqAIiYrb/8dRP4CyosJ/rmwU5XIxHMilt4QBJwsSkBMClxOQULBlkRRwEONmR2kJcDGjADX2/+xO8r5iqjExqmLyrWpcPFRta1BfAwCtyN3XpuJ4RgAAAABJRU5ErkJggg==&url=https://apt.izzysoft.de/fdroid/api/v1/shield/com.kunzisoft.keepass.free&label=IzzyOnDroid) | Free |
| [IzzyOnDroid](https://apt.izzysoft.de/fdroid/index/apk/com.kunzisoft.keepass.free) | ![IzzyOnDroid Version](https://img.shields.io/endpoint?&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAADAFBMVEUA0////wAA0v8A0v8A0////wD//wAFz/QA0/8A0/8A0/8A0/8A0v///wAA0/8A0/8A0/8A0/8A0//8/gEA0/8A0/8B0/4A0/8A0/8A0/+j5QGAwwIA0//C9yEA0/8A0/8A0/8A0/8A0/8A0/+n4SAA0/8A0/8A0/+o6gCw3lKt7QCv5SC+422b3wC19AC36zAA0/+d1yMA0/8A0/+W2gEA0/+w8ACz8gCKzgG7+QC+9CFLfwkA0/8A0////wAA0/8A0/8A0/8A0/+f2xym3iuHxCGq5BoA1P+m2joI0vONyiCz3mLO7oYA0/8M1Piq3Ei78CbB8EPe8LLj9Ly751G77zWQ1AC96UYC0fi37CL//wAA0/8A0////wD//wCp3jcA0/+j3SGj2i/I72Sx4zHE8FLB8zak1kYeycDI6nRl3qEA0/7V7psA0v6WzTa95mGi2RvB5XkPy9zH5YJ3uwGV1yxVihRLiwdxtQ1ZkAf//wD//wD//wD//wD//wCn5gf//wD//wD//wD//wD//wAA0/+h4A3R6p8A0/+X1w565OD6/ARg237n9csz2vPz+gNt37V/vifO8HW68B/L6ZOCwxXY8KRQsWRzhExAtG/E612a1Rd/pTBpmR9qjysduKVhmxF9mTY51aUozK+CsDSA52T//wD//wAA0////wD//wBJ1JRRxFWjzlxDyXRc0pGT1wCG0CWB3VGUzSTh8h6c0TSr5CCJ5FFxvl6s4H3m8xML0/DA5CvK51EX1N+Y2gSt4Dag3ChE3fax2ki68yO57NF10FRZnUPl88eJxhuCxgCz5EOLwEGf1DFutmahzGW98x0W1PGk3R154MHE6bOn69qv3gy92oG90o+Hn07B7rhCmiyMwECv1nO+0pQfwrCo57xF2daXsVhKrEdenQAduaee1Bsjr42z5D9RoCXy+QNovXpy2Z5MtWDO/TiSukaF3UtE1K6j3B4YwLc5wXlzpyIK0u5zy3uJqg4pu5RTpkZmpVKyAP8A0wBHcExHcEyBUSeEAAABAHRSTlP///9F9wjAAxD7FCEGzBjd08QyEL39abMd6///8P/ZWAnipIv/cC6B//7////////L/1Dz/0D///////86/vYnquY3/v///5T//v///17///////////////84S3QNB/8L/////////////7r/////NP////9l/////wPD4yis/x7Ym2lWSP+em////0n////////v///////////////////7//7pdGN3Urr6/+v/6aT////+//H/o2P/1v+7r7jp4PM/3p4g////g///K///481LxO///v////9w////8v/////9/p3J///a+P9v/5KR/+n///+p/xf//8P//wAAe7FyaAAABCZJREFUSMdj+E8iYKBUgwIHnwQ3N7cEHxcH+///VayoAE0Dh41qR7aBnCIQ8MsJKHH9/99czYYMWlA0cIkJGjMgAKfq//9RNYzIgLcBWYOTiCgDMhDn+B9bh6LebiWyH6L5UZQzONoAHWSHoqEpDkkDsyKqelv1//9rG1HUN9YihZK9AKp6BkG+/6xNqA5ajhSsCkrIipmYGGRa//9vQXVQXSySBnkWJOUMfn5Myuz/G3hR1NdEIUUchwiy+bkTsg4dbW/fu6W/e1c3XMMy5JiOZkFxUFZo74mgKTqaKXu0+2HqVwkja3BH9kFu361JwcHTfPJD4mdfe8ULAdVRyGlJAcVFfg+CQOozZ4XrJ85+JgwBsVXIGriQw5Tp4ZScezd8JiWnBupru30qwJZa+ZAjmWlC8fUZM4qB6kPnLNSPLMWqQQ5ZQ5aOzs1HmamBaQHzFs6y+qAmJCTE8f9/QgKSBg4DJPWc6zVDQkIC09JkZSPD38kukpExFpT4z67uYI/QwCOOCCK/izvu5CWl6AcEWMnKWml7LWbKZfH9/99UkknQHhGsynDz+65eWXv3/JmJrq5eXienVlRUfH/z8VvCf45soKQIH1yDEQsszrp6gwq9C73T87xcXadKl5TkFev4A/2tygmSBqYXqAYJmK+ZuoJydDR1vP09DA0NOy2kpdML81+U/heCpH1JU3jig7lJ5nKOT4i/t6ZHkqGzs4lJmIVHfrj+JR4HqLQSD0yDkCNEpGNn5ix9D03/eJdElTZdKV2TpNOhkwt8YUlNUgimgV0dLMBvf1gz1MolPd5FRcVNSkpDQ8owJeBCDyIhrIDnOD5QcuIU+3/2QKSs9laQ+noNLS0zLWdtqyP7mBAFAw88TwsJgMuJYweBGjYngtWbmeuZOW+bvNQToUFOAlFqOBk4Ov3/L7Z60/aN0p1tUhpa5nqWlub7C3p2I9QzyAghlUvczOz/1fhzPT3XSIfpSmmYAdVbmm1gV0dSz8DSilpUQsqCddIWIA3meuZaJqdMJZEzl6gRqgZIWZAxUdoizERXN8yi5MltcZTChzMaRQM3JNUWHS8rL/+yaPGvMmvr5ywoGoxtkDWwQ+Pb89ycBeWfGSJeL/la+RS1eOPnRtbQKgMRjZg+t8x6PkP273nWQAoFOPAgaeAThKXAmXMrK39Kmr5fsuBlBqoXfJGLe3VbmHjG9Mczi9T//3h7vygXtcDlQtJg44iQiIjIBRbGPO7gghPJy0ZIxT2HOLIUgwxQzsgYrUR350HSIMaJLidhgKY+mw+pflBDrX8E7OGBjPCAPc76gQFSTqAIiYrb/8dRP4CyosJ/rmwU5XIxHMilt4QBJwsSkBMClxOQULBlkRRwEONmR2kJcDGjADX2/+xO8r5iqjExqmLyrWpcPFRta1BfAwCtyN3XpuJ4RgAAAABJRU5ErkJggg==&url=https://apt.izzysoft.de/fdroid/api/v1/shield/com.kunzisoft.keepass.free&label=IzzyOnDroid) | Free & [Libre](https://apt.izzysoft.de/fdroid/index/apk/com.kunzisoft.keepass.libre) |
| [GitHub](https://github.com/Kunzisoft/KeePassDX/releases) / [Obtainium](https://github.com/ImranR98/Obtainium) | ![GitHub Release](https://img.shields.io/github/v/release/Kunzisoft/KeePassDX?include_prereleases&logo=GitHub&label=GitHub) | Free & Libre |
## Package authenticity from GitHub

View File

@@ -5,14 +5,14 @@ apply plugin: 'kotlin-kapt'
android {
namespace 'com.kunzisoft.keepass'
compileSdkVersion 34
compileSdkVersion 36
defaultConfig {
applicationId "com.kunzisoft.keepass"
minSdkVersion 15
targetSdkVersion 34
versionCode = 134
versionName = "4.1.2"
minSdkVersion 19
targetSdkVersion 35
versionCode = 143
versionName = "4.1.9"
multiDexEnabled true
testApplicationId = "com.kunzisoft.keepass.tests"
@@ -118,6 +118,7 @@ dependencies {
implementation 'androidx.media:media:1.6.0'
// Lifecycle - LiveData - ViewModel - Coroutines
implementation "androidx.core:core-ktx:$android_core_version"
implementation "androidx.lifecycle:lifecycle-process:2.6.2"
implementation 'androidx.fragment:fragment-ktx:1.6.0'
implementation "com.google.android.material:material:$android_material_version"
// Token auto complete

View File

@@ -0,0 +1,96 @@
{
"formatVersion": 1,
"database": {
"version": 3,
"identityHash": "a20aec7cf09664b1102ec659fa51160a",
"entities": [
{
"tableName": "file_database_history",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`database_uri` TEXT NOT NULL, `database_alias` TEXT NOT NULL, `keyfile_uri` TEXT, `hardware_key` TEXT, `read_only` INTEGER, `updated` INTEGER NOT NULL, PRIMARY KEY(`database_uri`))",
"fields": [
{
"fieldPath": "databaseUri",
"columnName": "database_uri",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "databaseAlias",
"columnName": "database_alias",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keyFileUri",
"columnName": "keyfile_uri",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "hardwareKey",
"columnName": "hardware_key",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "readOnly",
"columnName": "read_only",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "updated",
"columnName": "updated",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"database_uri"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "cipher_database",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`database_uri` TEXT NOT NULL, `encrypted_value` TEXT NOT NULL, `specs_parameters` TEXT NOT NULL, PRIMARY KEY(`database_uri`))",
"fields": [
{
"fieldPath": "databaseUri",
"columnName": "database_uri",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "encryptedValue",
"columnName": "encrypted_value",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "specParameters",
"columnName": "specs_parameters",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"database_uri"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a20aec7cf09664b1102ec659fa51160a')"
]
}
}

View File

@@ -164,7 +164,7 @@
android:configChanges="keyboardHidden"
android:excludeFromRecents="true"/>
<activity
android:name="com.kunzisoft.keepass.settings.AdvancedUnlockSettingsActivity" />
android:name="com.kunzisoft.keepass.settings.DeviceUnlockSettingsActivity" />
<activity
android:name="com.kunzisoft.keepass.settings.AutofillSettingsActivity" />
<activity
@@ -221,7 +221,7 @@
android:enabled="true"
android:exported="false" />
<service
android:name="com.kunzisoft.keepass.services.AdvancedUnlockNotificationService"
android:name="com.kunzisoft.keepass.services.DeviceUnlockNotificationService"
android:foregroundServiceType="specialUse"
android:enabled="true"
android:exported="false" />

View File

@@ -359,8 +359,6 @@ class Loupe(imageView: ImageView, container: ViewGroup) : View.OnTouchListener,
isViewTranslateAnimationRunning = true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
imageView.run {
val translationY = if (velY > 0) {
originalViewBounds.top + height - top
@@ -396,41 +394,6 @@ class Loupe(imageView: ImageView, container: ViewGroup) : View.OnTouchListener,
}
})
}
} else {
ObjectAnimator.ofFloat(imageView, View.TRANSLATION_Y, if (velY > 0) {
originalViewBounds.top + imageView.height - imageView.top
} else {
originalViewBounds.top - imageView.height - imageView.top
}.toFloat()).apply {
duration = dismissAnimationDuration
interpolator = dismissAnimationInterpolator
addUpdateListener {
val amount = calcTranslationAmount()
changeBackgroundAlpha(amount)
onViewTranslateListener?.onViewTranslate(imageView, amount)
}
addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(p0: Animator) {
// no op
}
override fun onAnimationEnd(p0: Animator) {
isViewTranslateAnimationRunning = false
onViewTranslateListener?.onDismiss(imageView)
cleanup()
}
override fun onAnimationCancel(p0: Animator) {
isViewTranslateAnimationRunning = false
}
override fun onAnimationRepeat(p0: Animator) {
// no op
}
})
start()
}
}
}
private fun processFlingBitmap(velocityX: Float, velocityY: Float) {
@@ -657,8 +620,6 @@ class Loupe(imageView: ImageView, container: ViewGroup) : View.OnTouchListener,
private fun restoreViewTransform() {
val imageView = imageViewRef.get() ?: return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
imageView.run {
animate()
.setDuration(restoreAnimationDuration)
@@ -687,41 +648,12 @@ class Loupe(imageView: ImageView, container: ViewGroup) : View.OnTouchListener,
}
})
}
} else {
ObjectAnimator.ofFloat(imageView, View.TRANSLATION_Y, (originalViewBounds.top - imageView.top).toFloat()).apply {
duration = restoreAnimationDuration
interpolator = restoreAnimationInterpolator
addUpdateListener {
val amount = calcTranslationAmount()
changeBackgroundAlpha(amount)
onViewTranslateListener?.onViewTranslate(imageView, amount)
}
addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(p0: Animator) {
// no op
}
override fun onAnimationEnd(p0: Animator) {
onViewTranslateListener?.onRestore(imageView)
}
override fun onAnimationCancel(p0: Animator) {
// no op
}
override fun onAnimationRepeat(p0: Animator) {
// no op
}
})
start()
}
}
}
private fun startDragToDismissAnimation() {
val imageView = imageViewRef.get() ?: return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
imageView.run {
val translationY = if (y - initialY > 0) {
originalViewBounds.top + height - top
@@ -757,37 +689,7 @@ class Loupe(imageView: ImageView, container: ViewGroup) : View.OnTouchListener,
}
})
}
} else {
ObjectAnimator.ofFloat(imageView, View.TRANSLATION_Y, imageView.translationY).apply {
duration = dismissAnimationDuration
interpolator = AccelerateDecelerateInterpolator()
addUpdateListener {
val amount = calcTranslationAmount()
changeBackgroundAlpha(amount)
onViewTranslateListener?.onViewTranslate(imageView, amount)
}
addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(p0: Animator) {
isViewTranslateAnimationRunning = true
}
override fun onAnimationEnd(p0: Animator) {
isViewTranslateAnimationRunning = false
onViewTranslateListener?.onDismiss(imageView)
cleanup()
}
override fun onAnimationCancel(p0: Animator) {
isViewTranslateAnimationRunning = false
}
override fun onAnimationRepeat(p0: Animator) {
// no op
}
})
start()
}
}
}
private fun processFlingToDismiss(velocityY: Float) {

View File

@@ -58,7 +58,7 @@ class AboutActivity : StylishActivity() {
var version: String
var build: String
try {
version = packageManager.getPackageInfoCompat(packageName).versionName
version = packageManager.getPackageInfoCompat(packageName).versionName ?: ""
build = BuildConfig.BUILD_VERSION
} catch (e: NameNotFoundException) {
Log.w(javaClass.simpleName, "Unable to get the app or the build version", e)
@@ -78,9 +78,8 @@ class AboutActivity : StylishActivity() {
movementMethod = LinkMovementMethod.getInstance()
text = HtmlCompat.fromHtml(getString(R.string.html_about_licence, DateTime().year),
HtmlCompat.FROM_HTML_MODE_LEGACY)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
textDirection = View.TEXT_DIRECTION_ANY_RTL
}
}
findViewById<TextView>(R.id.activity_about_privacy_text).apply {

View File

@@ -124,15 +124,11 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
if (autofillComponent == null) {
setResult(Activity.RESULT_CANCELED)
finish()
} else if (!KeeAutofillService.autofillAllowedFor(
} else if (KeeAutofillService.autofillAllowedFor(
applicationId = searchInfo.applicationId,
webDomain = searchInfo.webDomain,
context = this
)) {
showBlockRestartMessage()
setResult(Activity.RESULT_CANCELED)
finish()
} else {
// If database is open
SearchHelper.checkAutoSearchInfo(this,
database,
@@ -159,6 +155,10 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
searchInfo)
}
)
} else {
showBlockRestartMessage()
setResult(Activity.RESULT_CANCELED)
finish()
}
}
@@ -170,9 +170,6 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
webDomain = searchInfo.webDomain,
context = this
)) {
showBlockRestartMessage()
setResult(Activity.RESULT_CANCELED)
} else {
val readOnly = database?.isReadOnly != false
SearchHelper.checkAutoSearchInfo(this,
database,
@@ -203,6 +200,9 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
registerInfo)
}
)
} else {
showBlockRestartMessage()
setResult(Activity.RESULT_CANCELED)
}
finish()
}

View File

@@ -23,7 +23,6 @@ import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
@@ -38,13 +37,10 @@ import androidx.activity.result.ActivityResultLauncher
import androidx.activity.viewModels
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.BlendModeColorFilterCompat
import androidx.core.graphics.BlendModeCompat
import androidx.core.graphics.ColorUtils
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.appbar.AppBarLayout
@@ -83,11 +79,13 @@ import com.kunzisoft.keepass.view.hideByFading
import com.kunzisoft.keepass.view.setTransparentNavigationBar
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
import com.kunzisoft.keepass.viewmodels.EntryViewModel
import java.util.EnumSet
import java.util.UUID
class EntryActivity : DatabaseLockActivity() {
private var footer: ViewGroup? = null
private var container: View? = null
private var coordinatorLayout: CoordinatorLayout? = null
private var collapsingToolbarLayout: CollapsingToolbarLayout? = null
private var appBarLayout: AppBarLayout? = null
@@ -139,6 +137,7 @@ class EntryActivity : DatabaseLockActivity() {
// Get views
footer = findViewById(R.id.activity_entry_footer)
container = findViewById(R.id.activity_entry_container)
coordinatorLayout = findViewById(R.id.toolbar_coordinator)
collapsingToolbarLayout = findViewById(R.id.toolbar_layout)
appBarLayout = findViewById(R.id.app_bar)
@@ -154,8 +153,12 @@ class EntryActivity : DatabaseLockActivity() {
setTransparentNavigationBar {
// To fix margin with API 27
ViewCompat.setOnApplyWindowInsetsListener(collapsingToolbarLayout!!, null)
coordinatorLayout?.applyWindowInsets(WindowInsetPosition.TOP)
footer?.applyWindowInsets(WindowInsetPosition.BOTTOM)
container?.applyWindowInsets(EnumSet.of(
WindowInsetPosition.TOP_MARGINS,
WindowInsetPosition.BOTTOM_MARGINS,
WindowInsetPosition.START_MARGINS,
WindowInsetPosition.END_MARGINS,
))
}
// Empty title

View File

@@ -100,6 +100,7 @@ import com.kunzisoft.keepass.view.showActionErrorIfNeeded
import com.kunzisoft.keepass.view.updateLockPaddingStart
import com.kunzisoft.keepass.viewmodels.ColorPickerViewModel
import com.kunzisoft.keepass.viewmodels.EntryEditViewModel
import java.util.EnumSet
import java.util.UUID
class EntryEditActivity : DatabaseLockActivity(),
@@ -180,8 +181,12 @@ class EntryEditActivity : DatabaseLockActivity(),
// To apply fit window with transparency
setTransparentNavigationBar(applyToStatusBar = true) {
container?.applyWindowInsets(WindowInsetPosition.TOP_BOTTOM_IME)
footer?.applyWindowInsets(WindowInsetPosition.BOTTOM_IME)
container?.applyWindowInsets(EnumSet.of(
WindowInsetPosition.TOP_MARGINS,
WindowInsetPosition.BOTTOM_MARGINS,
WindowInsetPosition.START_MARGINS,
WindowInsetPosition.END_MARGINS,
))
}
stopService(Intent(this, ClipboardEntryNotificationService::class.java))
@@ -604,16 +609,12 @@ class EntryEditActivity : DatabaseLockActivity(),
isVisible = isEnabled
}
menu?.findItem(R.id.menu_add_attachment)?.apply {
// Attachment not compatible below KitKat
isEnabled = !mIsTemplate
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
isVisible = isEnabled
}
menu?.findItem(R.id.menu_add_otp)?.apply {
// OTP not compatible below KitKat
isEnabled = mAllowOTP
&& !mIsTemplate
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
isVisible = isEnabled
}
return super.onPrepareOptionsMenu(menu)

View File

@@ -70,7 +70,6 @@ import com.kunzisoft.keepass.utils.MagikeyboardUtil
import com.kunzisoft.keepass.utils.MenuUtil
import com.kunzisoft.keepass.utils.UriUtil.isContributingUser
import com.kunzisoft.keepass.utils.UriUtil.openUrl
import com.kunzisoft.keepass.utils.allowCreateDocumentByStorageAccessFramework
import com.kunzisoft.keepass.utils.getParcelableCompat
import com.kunzisoft.keepass.view.asError
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
@@ -263,7 +262,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
GroupActivity.launch(
this@FileDatabaseSelectActivity,
database,
PreferencesUtil.enableReadOnlyDatabase(this@FileDatabaseSelectActivity)
false
)
}
ACTION_DATABASE_LOAD_TASK -> {
@@ -316,6 +315,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
private fun launchPasswordActivityWithPath(databaseUri: Uri) {
launchPasswordActivity(databaseUri, null, null)
// Delete flickering for kitkat <=
@Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
overridePendingTransition(0, 0)
}
@@ -329,13 +329,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
// Show open and create button or special mode
when (mSpecialMode) {
SpecialMode.DEFAULT -> {
if (packageManager.allowCreateDocumentByStorageAccessFramework()) {
// There is an activity which can handle this intent.
createDatabaseButtonView?.visibility = View.VISIBLE
} else{
// No Activity found that can handle this intent.
createDatabaseButtonView?.visibility = View.GONE
}
}
else -> {
// Disable create button if in selection mode or request for autofill

View File

@@ -48,6 +48,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.Toolbar
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.GravityCompat
import androidx.core.view.WindowInsetsCompat
@@ -116,7 +117,8 @@ import com.kunzisoft.keepass.view.showActionErrorIfNeeded
import com.kunzisoft.keepass.view.updateLockPaddingStart
import com.kunzisoft.keepass.viewmodels.GroupEditViewModel
import com.kunzisoft.keepass.viewmodels.GroupViewModel
import org.joda.time.Instant
import org.joda.time.LocalDateTime
import java.util.EnumSet
class GroupActivity : DatabaseLockActivity(),
@@ -131,6 +133,7 @@ class GroupActivity : DatabaseLockActivity(),
private var header: ViewGroup? = null
private var footer: ViewGroup? = null
private var drawerLayout: DrawerLayout? = null
private var constraintLayout: ConstraintLayout? = null
private var databaseNavView: NavigationDatabaseView? = null
private var coordinatorLayout: CoordinatorLayout? = null
private var coordinatorError: CoordinatorLayout? = null
@@ -279,6 +282,7 @@ class GroupActivity : DatabaseLockActivity(),
header = findViewById(R.id.activity_group_header)
footer = findViewById(R.id.activity_group_footer)
drawerLayout = findViewById(R.id.drawer_layout)
constraintLayout = findViewById(R.id.activity_group_container_view)
databaseNavView = findViewById(R.id.database_nav_view)
coordinatorLayout = findViewById(R.id.group_coordinator)
coordinatorError = findViewById(R.id.error_coordinator)
@@ -296,8 +300,19 @@ class GroupActivity : DatabaseLockActivity(),
// To apply fit window with transparency
setTransparentNavigationBar(applyToStatusBar = true) {
drawerLayout?.applyWindowInsets(WindowInsetPosition.TOP_BOTTOM_IME)
footer?.applyWindowInsets(WindowInsetPosition.BOTTOM_IME)
constraintLayout?.applyWindowInsets(EnumSet.of(
WindowInsetPosition.TOP_MARGINS,
WindowInsetPosition.BOTTOM_MARGINS,
WindowInsetPosition.START_MARGINS,
WindowInsetPosition.END_MARGINS,
))
// The background of the drawer is meant to overlap system bars, so use padding
databaseNavView?.applyWindowInsets(EnumSet.of(
WindowInsetPosition.TOP_PADDING,
WindowInsetPosition.BOTTOM_PADDING,
// Only on the start side, since the drawer is anchored to one side of the screen
WindowInsetPosition.START_PADDING,
))
}
lockView?.setOnClickListener {
@@ -343,7 +358,7 @@ class GroupActivity : DatabaseLockActivity(),
mExternalFileHelper?.createDocument(
getString(R.string.database_file_name_default) +
"_" +
Instant.now().toString() +
LocalDateTime.now().toString() +
mDatabase?.defaultFileExtension)
}
R.id.menu_lock_all -> {
@@ -1373,7 +1388,8 @@ class GroupActivity : DatabaseLockActivity(),
}
else -> {
// Load the previous group
loadMainGroup(mPreviousGroupsIds.removeLast())
loadMainGroup(mPreviousGroupsIds
.removeAt(mPreviousGroupsIds.lastIndex))
}
}
}

View File

@@ -32,7 +32,6 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.CompoundButton
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
@@ -43,32 +42,42 @@ import androidx.appcompat.widget.Toolbar
import androidx.biometric.BiometricManager
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.fragment.app.commit
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.google.android.material.snackbar.Snackbar
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.DuplicateUuidDialog
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.helpers.SpecialMode
import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity
import com.kunzisoft.keepass.activities.legacy.DatabaseModeActivity
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.autofill.AutofillComponent
import com.kunzisoft.keepass.autofill.AutofillHelper
import com.kunzisoft.keepass.biometric.AdvancedUnlockFragment
import com.kunzisoft.keepass.biometric.AdvancedUnlockManager
import com.kunzisoft.keepass.biometric.DeviceUnlockFragment
import com.kunzisoft.keepass.biometric.DeviceUnlockManager
import com.kunzisoft.keepass.biometric.deviceUnlockError
import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.MainCredential
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
import com.kunzisoft.keepass.database.exception.FileNotFoundDatabaseException
import com.kunzisoft.keepass.education.PasswordActivityEducation
import com.kunzisoft.keepass.hardware.HardwareKey
import com.kunzisoft.keepass.model.*
import com.kunzisoft.keepass.model.CipherDecryptDatabase
import com.kunzisoft.keepass.model.CipherEncryptDatabase
import com.kunzisoft.keepass.model.CredentialStorage
import com.kunzisoft.keepass.model.DatabaseFile
import com.kunzisoft.keepass.model.RegisterInfo
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.CIPHER_DATABASE_KEY
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.DATABASE_URI_KEY
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.MAIN_CREDENTIAL_KEY
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.READ_ONLY_KEY
import com.kunzisoft.keepass.settings.AdvancedUnlockSettingsActivity
import com.kunzisoft.keepass.settings.AppearanceSettingsActivity
import com.kunzisoft.keepass.settings.DeviceUnlockSettingsActivity
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.utils.BACK_PREVIOUS_KEYBOARD_ACTION
@@ -79,26 +88,31 @@ import com.kunzisoft.keepass.utils.getParcelableExtraCompat
import com.kunzisoft.keepass.view.MainCredentialView
import com.kunzisoft.keepass.view.asError
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
import com.kunzisoft.keepass.viewmodels.AdvancedUnlockViewModel
import com.kunzisoft.keepass.viewmodels.DatabaseFileViewModel
import com.kunzisoft.keepass.viewmodels.DeviceUnlockViewModel
import kotlinx.coroutines.launch
import java.io.FileNotFoundException
class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.BuilderListener {
class MainCredentialActivity : DatabaseModeActivity() {
// Views
private var toolbar: Toolbar? = null
private var filenameView: TextView? = null
private var logotypeButton: View? = null
private var advancedUnlockButton: View? = null
private var deviceUnlockButton: View? = null
private var mainCredentialView: MainCredentialView? = null
private var confirmButtonView: Button? = null
private var infoContainerView: ViewGroup? = null
private lateinit var coordinatorLayout: CoordinatorLayout
private var advancedUnlockFragment: AdvancedUnlockFragment? = null
private var deviceUnlockFragment: DeviceUnlockFragment? = null
private val mDatabaseFileViewModel: DatabaseFileViewModel by viewModels()
private val mAdvancedUnlockViewModel: AdvancedUnlockViewModel by viewModels()
private val mDeviceUnlockViewModel: DeviceUnlockViewModel? by lazy {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ViewModelProvider(this)[DeviceUnlockViewModel::class.java]
} else null
}
private val mPasswordActivityEducation = PasswordActivityEducation(this)
@@ -131,7 +145,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
filenameView = findViewById(R.id.filename)
logotypeButton = findViewById(R.id.activity_password_logotype)
advancedUnlockButton = findViewById(R.id.fragment_advanced_unlock_container_view)
deviceUnlockButton = findViewById(R.id.fragment_device_unlock_container_view)
mainCredentialView = findViewById(R.id.activity_password_credentials)
confirmButtonView = findViewById(R.id.activity_password_open_button)
infoContainerView = findViewById(R.id.activity_password_info_container)
@@ -140,7 +154,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
mReadOnly = if (savedInstanceState != null && savedInstanceState.containsKey(KEY_READ_ONLY)) {
savedInstanceState.getBoolean(KEY_READ_ONLY)
} else {
PreferencesUtil.enableReadOnlyDatabase(this)
false
}
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this)
mRememberHardwareKey = PreferencesUtil.rememberHardwareKey(this)
@@ -166,19 +180,13 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
}
// Listen password checkbox to init advanced unlock and confirmation button
mainCredentialView?.onPasswordChecked =
CompoundButton.OnCheckedChangeListener { _, _ ->
mAdvancedUnlockViewModel.checkUnlockAvailability()
enableConfirmationButton()
mainCredentialView?.onConditionToStoreCredentialChanged = { _, verified ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mDeviceUnlockViewModel?.checkConditionToStoreCredential(
condition = verified
)
}
mainCredentialView?.onKeyFileChecked =
CompoundButton.OnCheckedChangeListener { _, _ ->
// TODO mAdvancedUnlockViewModel.checkUnlockAvailability()
enableConfirmationButton()
}
mainCredentialView?.onHardwareKeyChecked =
CompoundButton.OnCheckedChangeListener { _, _ ->
// TODO mAdvancedUnlockViewModel.checkUnlockAvailability()
// TODO Async by ViewModel
enableConfirmationButton()
}
@@ -202,6 +210,13 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
}
mForceReadOnly = databaseFileNotExists
// Restore read-only state from database file if not forced
if (!mForceReadOnly) {
databaseFile?.readOnly?.let { savedReadOnlyState ->
mReadOnly = savedReadOnlyState
}
}
invalidateOptionsMenu()
// Post init uri with KeyFile only if needed
@@ -228,20 +243,55 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
onDatabaseFileLoaded(databaseFile?.databaseUri, keyFileUri, hardwareKey)
}
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mDeviceUnlockViewModel?.let { deviceUnlockViewModel ->
deviceUnlockViewModel.uiState.collect { uiState ->
// New value received
uiState.credentialRequiredCipher?.let { cipher ->
deviceUnlockViewModel.encryptCredential(
credential = getCredentialForEncryption(),
cipher = cipher
)
}
uiState.cipherEncryptDatabase?.let { cipherEncryptDatabase ->
onCredentialEncrypted(cipherEncryptDatabase)
deviceUnlockViewModel.consumeCredentialEncrypted()
}
uiState.cipherDecryptDatabase?.let { cipherDecryptDatabase ->
onCredentialDecrypted(cipherDecryptDatabase)
deviceUnlockViewModel.consumeCredentialDecrypted()
}
uiState.exception?.let { error ->
Snackbar.make(
coordinatorLayout,
deviceUnlockError(error, this@MainCredentialActivity),
Snackbar.LENGTH_LONG
).asError().show()
deviceUnlockViewModel.exceptionShown()
}
}
}
}
}
}
}
override fun onResume() {
super.onResume()
// Init Biometric elements only if allowed
if (PreferencesUtil.isAdvancedUnlockEnable(this)) {
advancedUnlockFragment = supportFragmentManager
.findFragmentByTag(UNLOCK_FRAGMENT_TAG) as? AdvancedUnlockFragment?
if (advancedUnlockFragment == null) {
advancedUnlockFragment = AdvancedUnlockFragment().also {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& PreferencesUtil.isDeviceUnlockEnable(this)) {
deviceUnlockFragment = supportFragmentManager
.findFragmentByTag(UNLOCK_FRAGMENT_TAG) as? DeviceUnlockFragment?
if (deviceUnlockFragment == null) {
deviceUnlockFragment = DeviceUnlockFragment().also {
supportFragmentManager.commit {
replace(
R.id.fragment_advanced_unlock_container_view,
R.id.fragment_device_unlock_container_view,
it,
UNLOCK_FRAGMENT_TAG
)
@@ -258,18 +308,9 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
sendBroadcast(Intent(BACK_PREVIOUS_KEYBOARD_ACTION))
}
// Don't allow auto open prompt if lock become when UI visible
if (DatabaseLockActivity.LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK == true) {
mAdvancedUnlockViewModel.allowAutoOpenBiometricPrompt = false
}
mDatabaseFileUri?.let { databaseFileUri ->
mDatabaseFileViewModel.loadDatabaseFile(databaseFileUri)
}
mDatabase?.let { database ->
launchGroupActivityIfLoaded(database)
}
}
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
@@ -296,9 +337,6 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
super.onDatabaseActionFinished(database, actionTask, result)
when (actionTask) {
ACTION_DATABASE_LOAD_TASK -> {
// Recheck advanced unlock if error
mAdvancedUnlockViewModel.initAdvancedUnlockMode()
if (result.isSuccess) {
launchGroupActivityIfLoaded(database)
} else {
@@ -400,23 +438,6 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
}
}
override fun retrieveCredentialForEncryption(): ByteArray {
return mainCredentialView?.retrieveCredentialForStorage(credentialStorageListener)
?: byteArrayOf()
}
override fun conditionToStoreCredential(): Boolean {
return mainCredentialView?.conditionToStoreCredential() == true
}
override fun onCredentialEncrypted(cipherEncryptDatabase: CipherEncryptDatabase) {
// Load the database if password is registered with biometric
loadDatabase(mDatabaseFileUri,
mainCredentialView?.getMainCredential(),
cipherEncryptDatabase
)
}
private val credentialStorageListener = object: MainCredentialView.CredentialStorageListener {
override fun passwordToStore(password: String?): ByteArray? {
return password?.toByteArray()
@@ -433,7 +454,20 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
}
}
override fun onCredentialDecrypted(cipherDecryptDatabase: CipherDecryptDatabase) {
private fun getCredentialForEncryption(): ByteArray {
return mainCredentialView?.retrieveCredentialForStorage(credentialStorageListener)
?: byteArrayOf()
}
private fun onCredentialEncrypted(cipherEncryptDatabase: CipherEncryptDatabase) {
// Load the database if password is registered with biometric
loadDatabase(mDatabaseFileUri,
mainCredentialView?.getMainCredential(),
cipherEncryptDatabase
)
}
private fun onCredentialDecrypted(cipherDecryptDatabase: CipherDecryptDatabase) {
// Load the database if password is retrieve from biometric
// Retrieve from biometric
val mainCredential = mainCredentialView?.getMainCredential() ?: MainCredential()
@@ -485,7 +519,9 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
loadDatabase()
} else {
// Init Biometric elements
mAdvancedUnlockViewModel.databaseFileLoaded(databaseFileUri)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mDeviceUnlockViewModel?.connect(databaseFileUri)
}
}
enableConfirmationButton()
@@ -513,13 +549,6 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
}
}
override fun onPause() {
// Reinit locking activity UI variable
DatabaseLockActivity.LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK = null
super.onPause()
}
override fun onSaveInstanceState(outState: Bundle) {
outState.putBoolean(KEY_READ_ONLY, mReadOnly)
super.onSaveInstanceState(outState)
@@ -635,7 +664,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
try {
menu.findItem(R.id.menu_open_file_read_mode_key)
} catch (e: Exception) {
Log.e(TAG, "Unable to find read mode menu")
Log.e(TAG, "Unable to find read mode menu", e)
}
performedNextEducation(menu)
},
@@ -645,17 +674,17 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& !readOnlyEducationPerformed) {
val biometricCanAuthenticate = AdvancedUnlockManager.canAuthenticate(this)
val biometricCanAuthenticate = DeviceUnlockManager.canAuthenticate(this)
if ((biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS)
&& advancedUnlockButton != null) {
&& deviceUnlockButton != null) {
mPasswordActivityEducation.checkAndPerformedBiometricEducation(
advancedUnlockButton!!,
deviceUnlockButton!!,
{
startActivity(
Intent(
this,
AdvancedUnlockSettingsActivity::class.java
DeviceUnlockSettingsActivity::class.java
)
)
},
@@ -664,7 +693,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
})
}
}
} catch (ignored: Exception) {}
} catch (_: Exception) {}
}
}
@@ -685,6 +714,12 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
R.id.menu_open_file_read_mode_key -> {
mReadOnly = !mReadOnly
changeOpenFileReadIcon(item)
// Save the read-only state to database
mDatabaseFileUri?.let { databaseUri ->
FileDatabaseHistoryAction.getInstance(applicationContext).addOrUpdateDatabaseFile(
DatabaseFile(databaseUri = databaseUri, readOnly = mReadOnly)
)
}
}
else -> MenuUtil.onDefaultMenuOptionsItemSelected(this, item)
}
@@ -692,6 +727,13 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu
return super.onOptionsItemSelected(item)
}
override fun onDestroy() {
super.onDestroy()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mDeviceUnlockViewModel?.disconnect()
}
}
companion object {
private val TAG = MainCredentialActivity::class.java.name

View File

@@ -176,21 +176,14 @@ class SortDialogFragment : DatabaseDialogFragment() {
return bundle
}
fun getInstance(sortNodeEnum: SortNodeEnum,
ascending: Boolean,
groupsBefore: Boolean): SortDialogFragment {
val bundle = buildBundle(sortNodeEnum, ascending, groupsBefore)
val fragment = SortDialogFragment()
fragment.arguments = bundle
return fragment
}
fun getInstance(sortNodeEnum: SortNodeEnum,
ascending: Boolean,
groupsBefore: Boolean,
recycleBinBottom: Boolean): SortDialogFragment {
recycleBinBottom: Boolean?): SortDialogFragment {
val bundle = buildBundle(sortNodeEnum, ascending, groupsBefore)
recycleBinBottom?.let {
bundle.putBoolean(SORT_RECYCLE_BIN_BOTTOM_BUNDLE_KEY, recycleBinBottom)
}
val fragment = SortDialogFragment()
fragment.arguments = bundle
return fragment

View File

@@ -76,9 +76,6 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
private var specialMode: SpecialMode = SpecialMode.DEFAULT
private var mRecycleBinEnable: Boolean = false
private var mRecycleBin: Group? = null
private var mRecycleViewScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
@@ -102,21 +99,14 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
R.id.menu_sort -> {
context?.let { context ->
val sortDialogFragment: SortDialogFragment =
if (mRecycleBinEnable) {
SortDialogFragment.getInstance(
PreferencesUtil.getListSort(context),
PreferencesUtil.getAscendingSort(context),
PreferencesUtil.getGroupsBeforeSort(context),
if (mDatabase?.isRecycleBinEnabled == true) {
PreferencesUtil.getRecycleBinBottomSort(context)
} else null
)
} else {
SortDialogFragment.getInstance(
PreferencesUtil.getListSort(context),
PreferencesUtil.getAscendingSort(context),
PreferencesUtil.getGroupsBeforeSort(context)
)
}
sortDialogFragment.show(childFragmentManager, "sortDialog")
}
true
@@ -165,9 +155,6 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
}
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
mRecycleBinEnable = database?.isRecycleBinEnabled == true
mRecycleBin = database?.recycleBin
context?.let { context ->
database?.let { database ->
mAdapter = NodesAdapter(context, database).apply {
@@ -312,6 +299,11 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
}
}
private fun containsRecycleBin(nodes: List<Node>): Boolean {
return mDatabase?.isRecycleBinEnabled == true
&& nodes.any { it == mDatabase?.recycleBin }
}
fun actionNodesCallback(database: ContextualDatabase,
nodes: List<Node>,
menuListener: NodesActionMenuListener?,
@@ -336,8 +328,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
// Open and Edit for a single item
if (nodes.size == 1) {
// Edition
if (database.isReadOnly
|| (mRecycleBinEnable && nodes[0] == mRecycleBin)) {
if (database.isReadOnly || containsRecycleBin(nodes)) {
menu?.removeItem(R.id.menu_edit)
}
} else {
@@ -357,8 +348,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
}
// Deletion
if (database.isReadOnly
|| (mRecycleBinEnable && nodes.any { it == mRecycleBin })) {
if (database.isReadOnly || containsRecycleBin(nodes)) {
menu?.removeItem(R.id.menu_delete)
}
}

View File

@@ -47,10 +47,14 @@ import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.timeout.TimeoutHelper
import com.kunzisoft.keepass.utils.*
import com.kunzisoft.keepass.utils.LOCK_ACTION
import com.kunzisoft.keepass.utils.LockReceiver
import com.kunzisoft.keepass.utils.closeDatabase
import com.kunzisoft.keepass.utils.registerLockReceiver
import com.kunzisoft.keepass.utils.unregisterLockReceiver
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
import com.kunzisoft.keepass.viewmodels.NodesViewModel
import java.util.*
import java.util.UUID
abstract class DatabaseLockActivity : DatabaseModeActivity(),
PasswordEncodingDialogFragment.Listener {
@@ -184,8 +188,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
mLockReceiver = LockReceiver {
mDatabase = null
closeDatabase(database)
if (LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK == null)
LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK = LOCKING_ACTIVITY_UI_VISIBLE
mExitLock = true
closeOptionsMenu()
finish()
@@ -413,8 +415,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
}
invalidateOptionsMenu()
LOCKING_ACTIVITY_UI_VISIBLE = true
}
protected fun checkTimeAndLockIfTimeoutOrResetTimeout(action: (() -> Unit)? = null) {
@@ -429,8 +429,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
}
override fun onPause() {
LOCKING_ACTIVITY_UI_VISIBLE = false
super.onPause()
if (mTimeoutEnable) {
@@ -480,9 +478,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
const val TIMEOUT_ENABLE_KEY = "TIMEOUT_ENABLE_KEY"
const val TIMEOUT_ENABLE_KEY_DEFAULT = true
private var LOCKING_ACTIVITY_UI_VISIBLE = false
var LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK: Boolean? = null
}
}

View File

@@ -22,6 +22,7 @@ package com.kunzisoft.keepass.activities.stylish
import android.content.ActivityNotFoundException
import android.content.Intent
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
@@ -77,7 +78,18 @@ abstract class StylishActivity : AppCompatActivity() {
startActivity(intent)
}
finish()
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
@Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
overrideActivityTransition(
OVERRIDE_TRANSITION_OPEN,
android.R.anim.fade_in,
android.R.anim.fade_out
)
else
overridePendingTransition(
android.R.anim.fade_in,
android.R.anim.fade_out
)
}
override fun onCreate(savedInstanceState: Bundle?) {

View File

@@ -530,9 +530,8 @@ class NodesAdapter (
holder?.otpToken?.apply {
text = otpElement?.tokenString
setTextSize(mTextSizeUnit, mOtpTokenTextDefaultDimension, mPrefSizeMultiplier)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
textDirection = View.TEXT_DIRECTION_LTR
}
}
holder?.otpContainer?.setOnClickListener {
otpElement?.token?.let { token ->

View File

@@ -19,15 +19,53 @@
*/
package com.kunzisoft.keepass.app
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.multidex.MultiDexApplication
import com.kunzisoft.keepass.activities.stylish.Stylish
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
class App : MultiDexApplication() {
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycleObserver)
Stylish.load(this)
PRNGFixes.apply()
}
}
object AppLifecycleObserver : DefaultLifecycleObserver {
var isAppInForeground: Boolean = false
private set
var lockBackgroundEvent = false
private val _appJustLaunched = MutableSharedFlow<Unit>(replay = 0)
val appJustLaunched = _appJustLaunched.asSharedFlow()
@OptIn(DelicateCoroutinesApi::class)
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
val wasPreviouslyInBackground = !isAppInForeground
isAppInForeground = true
if (!lockBackgroundEvent && wasPreviouslyInBackground) {
GlobalScope.launch {
_appJustLaunched.emit(Unit)
}
}
}
override fun onStop(owner: LifecycleOwner) {
super.onStop(owner)
isAppInForeground = false
}
}

View File

@@ -1,399 +0,0 @@
package com.kunzisoft.keepass.app;
/*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will Google be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, as long as the origin is not misrepresented.
*/
import android.os.Build;
import android.os.Process;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.SecureRandomSpi;
import java.security.Security;
import java.util.Locale;
/**
* Fixes for the output of the default PRNG having low entropy.
*
* The fixes need to be applied via {@link #apply()} before any use of Java
* Cryptography Architecture primitives. A good place to invoke them is in the
* application's {@code onCreate}.
*/
public final class PRNGFixes {
private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL =
getBuildFingerprintAndDeviceSerial();
/** Hidden constructor to prevent instantiation. */
private PRNGFixes() {}
/**
* Applies all fixes.
*
* @throws SecurityException if a fix is needed but could not be applied.
*/
public static void apply() {
try {
if (supportedOnThisDevice()) {
applyOpenSSLFix();
installLinuxPRNGSecureRandom();
}
} catch (Exception e) {
// Do nothing, do the best we can to implement the workaround
}
}
private static boolean supportedOnThisDevice() {
// Blacklist on samsung devices
if (Build.MANUFACTURER.toLowerCase(Locale.ENGLISH).contains("samsung")) {
return false;
}
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) {
return false;
}
if (onSELinuxEnforce()) {
return false;
}
File urandom = new File("/dev/urandom");
// Test permissions
if ( !(urandom.canRead() && urandom.canWrite()) ) {
return false;
}
// Test actually writing to urandom
try {
FileOutputStream fos = new FileOutputStream(urandom);
fos.write(0);
} catch (Exception e) {
return false;
}
return true;
}
private static boolean onSELinuxEnforce() {
try {
ProcessBuilder builder = new ProcessBuilder("getenforce");
builder.redirectErrorStream(true);
java.lang.Process process = builder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
process.waitFor();
String output = reader.readLine();
if (output == null) {
return false;
}
return output.toLowerCase(Locale.US).startsWith("enforcing");
} catch (Exception e) {
return false;
}
}
/**
* Applies the fix for OpenSSL PRNG having low entropy. Does nothing if the
* fix is not needed.
*
* @throws SecurityException if the fix is needed but could not be applied.
*/
private static void applyOpenSSLFix() throws SecurityException {
if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
|| (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2)) {
// No need to apply the fix
return;
}
try {
// Mix in the device- and invocation-specific seed.
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_seed", byte[].class)
.invoke(null, generateSeed());
// Mix output of Linux PRNG into OpenSSL's PRNG
int bytesRead = (Integer) Class.forName(
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_load_file", String.class, long.class)
.invoke(null, "/dev/urandom", 1024);
if (bytesRead != 1024) {
throw new IOException(
"Unexpected number of bytes read from Linux PRNG: "
+ bytesRead);
}
} catch (Exception e) {
throw new SecurityException("Failed to seed OpenSSL PRNG", e);
}
}
/**
* Installs a Linux PRNG-backed {@code SecureRandom} implementation as the
* default. Does nothing if the implementation is already the default or if
* there is not need to install the implementation.
*
* @throws SecurityException if the fix is needed but could not be applied.
*/
private static void installLinuxPRNGSecureRandom()
throws SecurityException {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) {
// No need to apply the fix
return;
}
// Install a Linux PRNG-based SecureRandom implementation as the
// default, if not yet installed.
Provider[] secureRandomProviders =
Security.getProviders("SecureRandom.SHA1PRNG");
if ((secureRandomProviders == null)
|| (secureRandomProviders.length < 1)
|| (!LinuxPRNGSecureRandomProvider.class.equals(
secureRandomProviders[0].getClass()))) {
Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1);
}
// Assert that new SecureRandom() and
// SecureRandom.getInstance("SHA1PRNG") return a SecureRandom backed
// by the Linux PRNG-based SecureRandom implementation.
SecureRandom rng1 = new SecureRandom();
if (!LinuxPRNGSecureRandomProvider.class.equals(
rng1.getProvider().getClass())) {
throw new SecurityException(
"new SecureRandom() backed by wrong Provider: "
+ rng1.getProvider().getClass());
}
SecureRandom rng2;
try {
rng2 = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
throw new SecurityException("SHA1PRNG not available", e);
}
if (!LinuxPRNGSecureRandomProvider.class.equals(
rng2.getProvider().getClass())) {
throw new SecurityException(
"SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong"
+ " Provider: " + rng2.getProvider().getClass());
}
}
/**
* {@code Provider} of {@code SecureRandom} engines which pass through
* all requests to the Linux PRNG.
*/
private static class LinuxPRNGSecureRandomProvider extends Provider {
public LinuxPRNGSecureRandomProvider() {
super("LinuxPRNG",
1.0,
"A Linux-specific random number provider that uses"
+ " /dev/urandom");
// Although /dev/urandom is not a SHA-1 PRNG, some apps
// explicitly request a SHA1PRNG SecureRandom and we thus need to
// prevent them from getting the default implementation whose output
// may have low entropy.
put("SecureRandom.SHA1PRNG", LinuxPRNGSecureRandom.class.getName());
put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
}
}
/**
* {@link SecureRandomSpi} which passes all requests to the Linux PRNG
* ({@code /dev/urandom}).
*/
public static class LinuxPRNGSecureRandom extends SecureRandomSpi {
/*
* IMPLEMENTATION NOTE: Requests to generate bytes and to mix in a seed
* are passed through to the Linux PRNG (/dev/urandom). Instances of
* this class seed themselves by mixing in the current time, PID, UID,
* build fingerprint, and hardware serial number (where available) into
* Linux PRNG.
*
* Concurrency: Read requests to the underlying Linux PRNG are
* serialized (on sLock) to ensure that multiple threads do not get
* duplicated PRNG output.
*/
private static final File URANDOM_FILE = new File("/dev/urandom");
private static final Object sLock = new Object();
/**
* Input stream for reading from Linux PRNG or {@code null} if not yet
* opened.
*
* @GuardedBy("sLock")
*/
private static DataInputStream sUrandomIn;
/**
* Output stream for writing to Linux PRNG or {@code null} if not yet
* opened.
*
* @GuardedBy("sLock")
*/
private static OutputStream sUrandomOut;
/**
* Whether this engine instance has been seeded. This is needed because
* each instance needs to seed itself if the client does not explicitly
* seed it.
*/
private boolean mSeeded;
@Override
protected void engineSetSeed(byte[] bytes) {
try {
OutputStream out;
synchronized (sLock) {
out = getUrandomOutputStream();
}
out.write(bytes);
out.flush();
mSeeded = true;
} catch (IOException e) {
throw new SecurityException(
"Failed to mix seed into " + URANDOM_FILE, e);
}
}
@Override
protected void engineNextBytes(byte[] bytes) {
if (!mSeeded) {
// Mix in the device- and invocation-specific seed.
engineSetSeed(generateSeed());
}
try {
DataInputStream in;
synchronized (sLock) {
in = getUrandomInputStream();
}
synchronized (in) {
in.readFully(bytes);
}
} catch (IOException e) {
throw new SecurityException(
"Failed to read from " + URANDOM_FILE, e);
}
}
@Override
protected byte[] engineGenerateSeed(int size) {
byte[] seed = new byte[size];
engineNextBytes(seed);
return seed;
}
private DataInputStream getUrandomInputStream() {
synchronized (sLock) {
if (sUrandomIn == null) {
// NOTE: Consider inserting a BufferedInputStream between
// DataInputStream and FileInputStream if you need higher
// PRNG output performance and can live with future PRNG
// output being pulled into this process prematurely.
try {
sUrandomIn = new DataInputStream(
new FileInputStream(URANDOM_FILE));
} catch (IOException e) {
throw new SecurityException("Failed to open "
+ URANDOM_FILE + " for reading", e);
}
}
return sUrandomIn;
}
}
private OutputStream getUrandomOutputStream() {
synchronized (sLock) {
if (sUrandomOut == null) {
try {
sUrandomOut = new FileOutputStream(URANDOM_FILE);
} catch (IOException e) {
throw new SecurityException("Failed to open "
+ URANDOM_FILE + " for writing", e);
}
}
return sUrandomOut;
}
}
}
/**
* Generates a device- and invocation-specific seed to be mixed into the
* Linux PRNG.
*/
private static byte[] generateSeed() {
try {
ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream();
DataOutputStream seedBufferOut =
new DataOutputStream(seedBuffer);
seedBufferOut.writeLong(System.currentTimeMillis());
seedBufferOut.writeLong(System.nanoTime());
seedBufferOut.writeInt(Process.myPid());
seedBufferOut.writeInt(Process.myUid());
seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL);
seedBufferOut.close();
return seedBuffer.toByteArray();
} catch (IOException e) {
throw new SecurityException("Failed to generate seed", e);
}
}
/**
* Gets the hardware serial number of this device.
*
* @return serial number or {@code null} if not available.
*/
private static String getDeviceSerialNumber() {
// We're using the Reflection API because Build.SERIAL is only available
// since API Level 9 (Gingerbread, Android 2.3).
try {
return (String) Build.class.getField("SERIAL").get(null);
} catch (Exception ignored) {
return null;
}
}
private static byte[] getBuildFingerprintAndDeviceSerial() {
StringBuilder result = new StringBuilder();
String fingerprint = Build.FINGERPRINT;
if (fingerprint != null) {
result.append(fingerprint);
}
String serial = getDeviceSerialNumber();
if (serial != null) {
result.append(serial);
}
try {
return result.toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 encoding not supported");
}
}
}

View File

@@ -26,10 +26,11 @@ import android.content.Context
import androidx.room.AutoMigration
@Database(
version = 2,
version = 3,
entities = [FileDatabaseHistoryEntity::class, CipherDatabaseEntity::class],
autoMigrations = [
AutoMigration (from = 1, to = 2)
AutoMigration (from = 1, to = 2),
AutoMigration (from = 2, to = 3)
]
)
abstract class AppDatabase : RoomDatabase() {

View File

@@ -28,9 +28,10 @@ import android.os.IBinder
import android.util.Base64
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import com.kunzisoft.keepass.database.element.binary.BinaryData.Companion.BASE64_FLAG
import com.kunzisoft.keepass.model.CipherEncryptDatabase
import com.kunzisoft.keepass.services.AdvancedUnlockNotificationService
import com.kunzisoft.keepass.services.DeviceUnlockNotificationService
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.utils.IOActionTask
import com.kunzisoft.keepass.utils.SingletonHolderParameter
@@ -43,19 +44,19 @@ class CipherDatabaseAction(context: Context) {
AppDatabase.getDatabase(applicationContext).cipherDatabaseDao()
// Temp DAO to easily remove content if object no longer in memory
private var useTempDao = PreferencesUtil.isTempAdvancedUnlockEnable(applicationContext)
private var useTempDao = PreferencesUtil.isTempDeviceUnlockEnable(applicationContext)
private var mBinder: AdvancedUnlockNotificationService.AdvancedUnlockBinder? = null
private var mBinder: DeviceUnlockNotificationService.DeviceUnlockBinder? = null
private var mServiceConnection: ServiceConnection? = null
private var mDatabaseListeners = LinkedList<CipherDatabaseListener>()
private var mAdvancedUnlockBroadcastReceiver = AdvancedUnlockNotificationService.AdvancedUnlockReceiver {
private var mDeviceUnlockBroadcastReceiver = DeviceUnlockNotificationService.DeviceUnlockReceiver {
deleteAll()
removeAllDataAndDetach()
}
fun reloadPreferences() {
useTempDao = PreferencesUtil.isTempAdvancedUnlockEnable(applicationContext)
private fun reloadPreferences() {
useTempDao = PreferencesUtil.isTempDeviceUnlockEnable(applicationContext)
}
@Synchronized
@@ -70,15 +71,15 @@ class CipherDatabaseAction(context: Context) {
@Synchronized
private fun attachService(performedAction: () -> Unit) {
ContextCompat.registerReceiver(applicationContext, mAdvancedUnlockBroadcastReceiver,
ContextCompat.registerReceiver(applicationContext, mDeviceUnlockBroadcastReceiver,
IntentFilter().apply {
addAction(AdvancedUnlockNotificationService.REMOVE_ADVANCED_UNLOCK_KEY_ACTION)
addAction(DeviceUnlockNotificationService.REMOVE_DEVICE_UNLOCK_KEY_ACTION)
}, ContextCompat.RECEIVER_EXPORTED
)
mServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) {
mBinder = (serviceBinder as AdvancedUnlockNotificationService.AdvancedUnlockBinder)
mBinder = (serviceBinder as DeviceUnlockNotificationService.DeviceUnlockBinder)
performedAction.invoke()
}
@@ -87,7 +88,7 @@ class CipherDatabaseAction(context: Context) {
}
}
try {
AdvancedUnlockNotificationService.bindService(applicationContext,
DeviceUnlockNotificationService.bindService(applicationContext,
mServiceConnection!!,
Context.BIND_AUTO_CREATE)
} catch (e: Exception) {
@@ -99,11 +100,11 @@ class CipherDatabaseAction(context: Context) {
@Synchronized
private fun detachService() {
try {
applicationContext.unregisterReceiver(mAdvancedUnlockBroadcastReceiver)
applicationContext.unregisterReceiver(mDeviceUnlockBroadcastReceiver)
} catch (_: Exception) {}
mServiceConnection?.let {
AdvancedUnlockNotificationService.unbindService(applicationContext, it)
DeviceUnlockNotificationService.unbindService(applicationContext, it)
}
}
@@ -123,23 +124,27 @@ class CipherDatabaseAction(context: Context) {
private fun onClear() {
mBinder = null
mServiceConnection = null
mDatabaseListeners.forEach {
it.onCipherDatabaseCleared()
mDatabaseListeners.forEach { listener ->
listener.onCipherDatabaseCleared()
}
}
interface CipherDatabaseListener {
fun onCipherDatabaseRetrieved(databaseUri: Uri, cipherDatabase: CipherEncryptDatabase?)
fun onCipherDatabaseAddedOrUpdated(cipherDatabase: CipherEncryptDatabase)
fun onCipherDatabaseDeleted(databaseUri: Uri)
fun onAllCipherDatabasesDeleted()
fun onCipherDatabaseCleared()
}
fun getCipherDatabase(databaseUri: Uri,
cipherDatabaseResultListener: (CipherEncryptDatabase?) -> Unit) {
cipherDatabaseResultListener: ((CipherEncryptDatabase?) -> Unit)? = null) {
if (useTempDao) {
serviceActionTask {
var cipherDatabase: CipherEncryptDatabase? = null
mBinder?.getCipherDatabase(databaseUri)?.let { cipherDatabaseEntity ->
cipherDatabase = CipherEncryptDatabase().apply {
this.databaseUri = Uri.parse(cipherDatabaseEntity.databaseUri)
this.databaseUri = cipherDatabaseEntity.databaseUri.toUri()
this.encryptedValue = Base64.decode(
cipherDatabaseEntity.encryptedValue,
BASE64_FLAG
@@ -150,7 +155,11 @@ class CipherDatabaseAction(context: Context) {
)
}
}
cipherDatabaseResultListener.invoke(cipherDatabase)
cipherDatabaseResultListener?.invoke(cipherDatabase) ?: run {
mDatabaseListeners.forEach { listener ->
listener.onCipherDatabaseRetrieved(databaseUri, cipherDatabase)
}
}
}
} else {
IOActionTask(
@@ -158,7 +167,7 @@ class CipherDatabaseAction(context: Context) {
cipherDatabaseDao.getByDatabaseUri(databaseUri.toString())
?.let { cipherDatabaseEntity ->
CipherEncryptDatabase().apply {
this.databaseUri = Uri.parse(cipherDatabaseEntity.databaseUri)
this.databaseUri = cipherDatabaseEntity.databaseUri.toUri()
this.encryptedValue = Base64.decode(
cipherDatabaseEntity.encryptedValue,
Base64.NO_WRAP
@@ -170,21 +179,29 @@ class CipherDatabaseAction(context: Context) {
}
}
},
{
cipherDatabaseResultListener.invoke(it)
{ cipherDatabase ->
cipherDatabaseResultListener?.invoke(cipherDatabase) ?: run {
mDatabaseListeners.forEach { listener ->
listener.onCipherDatabaseRetrieved(databaseUri, cipherDatabase)
}
}
}
).execute()
}
}
fun containsCipherDatabase(databaseUri: Uri,
private fun containsCipherDatabase(databaseUri: Uri?,
contains: (Boolean) -> Unit) {
if (databaseUri == null) {
contains.invoke(false)
} else {
getCipherDatabase(databaseUri) {
contains.invoke(it != null)
}
}
}
fun resetCipherParameters(databaseUri: Uri) {
fun resetCipherParameters(databaseUri: Uri?) {
containsCipherDatabase(databaseUri) { contains ->
if (contains) {
mBinder?.resetTimer()
@@ -206,7 +223,11 @@ class CipherDatabaseAction(context: Context) {
// The only case to create service (not needed to get an info)
serviceActionTask(true) {
mBinder?.addOrUpdateCipherDatabase(cipherDatabaseEntity)
cipherDatabaseResultListener?.invoke()
cipherDatabaseResultListener?.invoke() ?: run {
mDatabaseListeners.forEach { listener ->
listener.onCipherDatabaseAddedOrUpdated(cipherEncryptDatabase)
}
}
}
} else {
IOActionTask(
@@ -221,7 +242,11 @@ class CipherDatabaseAction(context: Context) {
}
},
{
cipherDatabaseResultListener?.invoke()
cipherDatabaseResultListener?.invoke() ?: run {
mDatabaseListeners.forEach { listener ->
listener.onCipherDatabaseAddedOrUpdated(cipherEncryptDatabase)
}
}
}
).execute()
}
@@ -233,7 +258,11 @@ class CipherDatabaseAction(context: Context) {
if (useTempDao) {
serviceActionTask {
mBinder?.deleteByDatabaseUri(databaseUri)
cipherDatabaseResultListener?.invoke()
cipherDatabaseResultListener?.invoke() ?: run {
mDatabaseListeners.forEach { listener ->
listener.onCipherDatabaseDeleted(databaseUri)
}
}
}
} else {
IOActionTask(
@@ -241,10 +270,15 @@ class CipherDatabaseAction(context: Context) {
cipherDatabaseDao.deleteByDatabaseUri(databaseUri.toString())
},
{
cipherDatabaseResultListener?.invoke()
cipherDatabaseResultListener?.invoke() ?: run {
mDatabaseListeners.forEach { listener ->
listener.onCipherDatabaseDeleted(databaseUri)
}
}
}
).execute()
}
reloadPreferences()
}
fun deleteAll() {
@@ -259,8 +293,12 @@ class CipherDatabaseAction(context: Context) {
cipherDatabaseDao.deleteAll()
}
).execute()
mDatabaseListeners.forEach { listener ->
listener.onAllCipherDatabasesDeleted()
}
// Unbind
removeAllDataAndDetach()
reloadPreferences()
}
companion object : SingletonHolderParameter<CipherDatabaseAction, Context>(::CipherDatabaseAction) {

View File

@@ -49,6 +49,7 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
databaseUri,
fileDatabaseHistoryEntity?.keyFileUri?.parseUri(),
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity?.hardwareKey),
fileDatabaseHistoryEntity?.readOnly,
fileDatabaseHistoryEntity?.databaseUri?.decodeUri(),
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity?.databaseAlias
?: ""),
@@ -99,6 +100,7 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
fileDatabaseHistoryEntity.databaseUri.parseUri(),
fileDatabaseHistoryEntity.keyFileUri?.parseUri(),
HardwareKey.getHardwareKeyFromString(fileDatabaseHistoryEntity.hardwareKey),
fileDatabaseHistoryEntity.readOnly,
fileDatabaseHistoryEntity.databaseUri.decodeUri(),
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity.databaseAlias),
fileDatabaseInfo.exists,
@@ -147,6 +149,8 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
?: "",
databaseFileToAddOrUpdate.keyFileUri?.toString(),
databaseFileToAddOrUpdate.hardwareKey?.value,
databaseFileToAddOrUpdate.readOnly
?: fileDatabaseHistoryRetrieve?.readOnly,
System.currentTimeMillis()
)
@@ -168,6 +172,7 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
fileDatabaseHistory.databaseUri.parseUri(),
fileDatabaseHistory.keyFileUri?.parseUri(),
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
fileDatabaseHistory.readOnly,
fileDatabaseHistory.databaseUri.decodeUri(),
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistory.databaseAlias),
fileDatabaseInfo.exists,
@@ -195,6 +200,7 @@ class FileDatabaseHistoryAction(private val applicationContext: Context) {
fileDatabaseHistory.databaseUri.parseUri(),
fileDatabaseHistory.keyFileUri?.parseUri(),
HardwareKey.getHardwareKeyFromString(fileDatabaseHistory.hardwareKey),
fileDatabaseHistory.readOnly,
fileDatabaseHistory.databaseUri.decodeUri(),
databaseFileToDelete.databaseAlias
)

View File

@@ -38,6 +38,9 @@ data class FileDatabaseHistoryEntity(
@ColumnInfo(name = "hardware_key")
var hardwareKey: String?,
@ColumnInfo(name = "read_only")
var readOnly: Boolean?,
@ColumnInfo(name = "updated")
val updated: Long
) {

View File

@@ -1,10 +0,0 @@
package com.kunzisoft.keepass.biometric
import androidx.annotation.StringRes
import javax.crypto.Cipher
data class AdvancedUnlockCryptoPrompt(var cipher: Cipher,
@StringRes var promptTitleId: Int,
@StringRes var promptDescriptionId: Int? = null,
var isDeviceCredentialOperation: Boolean,
var isBiometricOperation: Boolean)

View File

@@ -1,678 +0,0 @@
/*
* Copyright 2020 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePassDX.
*
* KeePassDX is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KeePassDX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.biometric
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.view.*
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.core.view.MenuProvider
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
import com.kunzisoft.keepass.database.exception.UnknownDatabaseLocationException
import com.kunzisoft.keepass.model.CipherDecryptDatabase
import com.kunzisoft.keepass.model.CipherEncryptDatabase
import com.kunzisoft.keepass.model.CredentialStorage
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.view.AdvancedUnlockInfoView
import com.kunzisoft.keepass.view.hideByFading
import com.kunzisoft.keepass.view.showByFading
import com.kunzisoft.keepass.viewmodels.AdvancedUnlockViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class AdvancedUnlockFragment: Fragment(), AdvancedUnlockManager.AdvancedUnlockCallback {
private var mBuilderListener: BuilderListener? = null
private var mAdvancedUnlockEnabled = false
private var mAutoOpenPromptEnabled = false
private var advancedUnlockManager: AdvancedUnlockManager? = null
private var biometricMode: Mode = Mode.BIOMETRIC_UNAVAILABLE
private var mAdvancedUnlockInfoView: AdvancedUnlockInfoView? = null
var databaseFileUri: Uri? = null
private set
// TODO Retrieve credential storage from app database
var credentialDatabaseStorage: CredentialStorage = CredentialStorage.DEFAULT
// Variable to check if the prompt can be open (if the right activity is currently shown)
// checkBiometricAvailability() allows open biometric prompt and onDestroy() removes the authorization
private var allowOpenBiometricPrompt = false
private lateinit var cipherDatabaseAction : CipherDatabaseAction
private var cipherDatabaseListener: CipherDatabaseAction.CipherDatabaseListener? = null
private val mAdvancedUnlockViewModel: AdvancedUnlockViewModel by activityViewModels()
// Only to fix multiple fingerprint menu #332
private var mAllowAdvancedUnlockMenu = false
private var mAddBiometricMenuInProgress = false
// Only keep connection when we request a device credential activity
private var keepConnection = false
private var mDeviceCredentialResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
mAdvancedUnlockViewModel.allowAutoOpenBiometricPrompt = false
// To wait resume
if (keepConnection) {
mAdvancedUnlockViewModel.deviceCredentialAuthSucceeded =
result.resultCode == Activity.RESULT_OK
}
keepConnection = false
}
private val menuProvider: MenuProvider = object: MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// biometric menu
if (mAllowAdvancedUnlockMenu)
menuInflater.inflate(R.menu.advanced_unlock, menu)
}
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
when (menuItem.itemId) {
R.id.menu_keystore_remove_key -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
deleteEncryptedDatabaseKey()
}
}
return false
}
}
override fun onAttach(context: Context) {
super.onAttach(context)
mAdvancedUnlockEnabled = PreferencesUtil.isAdvancedUnlockEnable(context)
mAutoOpenPromptEnabled = PreferencesUtil.isAdvancedUnlockPromptAutoOpenEnable(context)
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mBuilderListener = context as BuilderListener
}
} catch (e: ClassCastException) {
throw ClassCastException(context.toString()
+ " must implement " + BuilderListener::class.java.name)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
cipherDatabaseAction = CipherDatabaseAction.getInstance(requireContext().applicationContext)
mAdvancedUnlockViewModel.onInitAdvancedUnlockModeRequested.observe(this) {
initAdvancedUnlockMode()
}
mAdvancedUnlockViewModel.onUnlockAvailabilityCheckRequested.observe(this) {
checkUnlockAvailability()
}
mAdvancedUnlockViewModel.onDatabaseFileLoaded.observe(this) {
onDatabaseLoaded(it)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
val rootView = inflater.inflate(R.layout.fragment_advanced_unlock, container, false)
mAdvancedUnlockInfoView = rootView.findViewById(R.id.advanced_unlock_view)
return rootView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity?.addMenuProvider(menuProvider, viewLifecycleOwner)
}
override fun onResume() {
super.onResume()
context?.let {
mAdvancedUnlockEnabled = PreferencesUtil.isAdvancedUnlockEnable(it)
mAutoOpenPromptEnabled = PreferencesUtil.isAdvancedUnlockPromptAutoOpenEnable(it)
}
keepConnection = false
}
private fun onDatabaseLoaded(databaseUri: Uri?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// To get device credential unlock result, only if same database uri
if (databaseUri != null
&& mAdvancedUnlockEnabled) {
val deviceCredentialAuthSucceeded = mAdvancedUnlockViewModel.deviceCredentialAuthSucceeded
deviceCredentialAuthSucceeded?.let {
if (databaseUri == databaseFileUri) {
if (deviceCredentialAuthSucceeded == true) {
advancedUnlockManager?.advancedUnlockCallback?.onAuthenticationSucceeded()
} else {
advancedUnlockManager?.advancedUnlockCallback?.onAuthenticationFailed()
}
} else {
disconnect()
}
} ?: run {
if (databaseUri != databaseFileUri) {
connect(databaseUri)
}
}
} else {
disconnect()
}
mAdvancedUnlockViewModel.deviceCredentialAuthSucceeded = null
}
}
/**
* Check unlock availability and change the current mode depending of device's state
*/
private fun checkUnlockAvailability() {
context?.let { context ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
allowOpenBiometricPrompt = true
if (PreferencesUtil.isBiometricUnlockEnable(context)) {
// biometric not supported (by API level or hardware) so keep option hidden
// or manually disable
val biometricCanAuthenticate = AdvancedUnlockManager.canAuthenticate(context)
if (!PreferencesUtil.isAdvancedUnlockEnable(context)
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE) {
toggleMode(Mode.BIOMETRIC_UNAVAILABLE)
} else if (biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED) {
toggleMode(Mode.BIOMETRIC_SECURITY_UPDATE_REQUIRED)
} else {
// biometric is available but not configured, show icon but in disabled state with some information
if (biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
toggleMode(Mode.DEVICE_CREDENTIAL_OR_BIOMETRIC_NOT_CONFIGURED)
} else {
selectMode()
}
}
} else if (PreferencesUtil.isDeviceCredentialUnlockEnable(context)) {
if (AdvancedUnlockManager.isDeviceSecure(context)) {
selectMode()
} else {
toggleMode(Mode.DEVICE_CREDENTIAL_OR_BIOMETRIC_NOT_CONFIGURED)
}
}
}
}
}
@RequiresApi(Build.VERSION_CODES.M)
private fun selectMode() {
// Check if fingerprint well init (be called the first time the fingerprint is configured
// and the activity still active)
if (advancedUnlockManager?.isKeyManagerInitialized != true) {
advancedUnlockManager = AdvancedUnlockManager { requireActivity() }
// callback for fingerprint findings
advancedUnlockManager?.advancedUnlockCallback = this
}
// Recheck to change the mode
if (advancedUnlockManager?.isKeyManagerInitialized != true) {
toggleMode(Mode.KEY_MANAGER_UNAVAILABLE)
} else {
if (mBuilderListener?.conditionToStoreCredential() == true) {
// listen for encryption
toggleMode(Mode.STORE_CREDENTIAL)
} else {
databaseFileUri?.let { databaseUri ->
cipherDatabaseAction.containsCipherDatabase(databaseUri) { containsCipher ->
// biometric available but no stored password found yet for this DB so show info don't listen
toggleMode(if (containsCipher) {
// listen for decryption
Mode.EXTRACT_CREDENTIAL
} else {
// wait for typing
Mode.WAIT_CREDENTIAL
})
}
}
}
}
}
@RequiresApi(Build.VERSION_CODES.M)
private fun toggleMode(newBiometricMode: Mode) {
if (newBiometricMode != biometricMode) {
biometricMode = newBiometricMode
initAdvancedUnlockMode()
}
}
@RequiresApi(Build.VERSION_CODES.M)
private fun initNotAvailable() {
showViews(false)
mAdvancedUnlockInfoView?.setIconViewClickListener(null)
}
@RequiresApi(Build.VERSION_CODES.M)
private fun openBiometricSetting() {
mAdvancedUnlockInfoView?.setIconViewClickListener {
try {
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
context?.startActivity(Intent(Settings.ACTION_BIOMETRIC_ENROLL))
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P -> {
@Suppress("DEPRECATION") context
?.startActivity(Intent(Settings.ACTION_FINGERPRINT_ENROLL))
}
else -> {
context?.startActivity(Intent(Settings.ACTION_SECURITY_SETTINGS))
}
}
} catch (e: Exception) {
// ACTION_SECURITY_SETTINGS does not contain fingerprint enrollment on some devices...
context?.startActivity(Intent(Settings.ACTION_SETTINGS))
}
}
}
@RequiresApi(Build.VERSION_CODES.M)
private fun initSecurityUpdateRequired() {
showViews(true)
setAdvancedUnlockedTitleView(R.string.biometric_security_update_required)
openBiometricSetting()
}
@RequiresApi(Build.VERSION_CODES.M)
private fun initNotConfigured() {
showViews(true)
setAdvancedUnlockedTitleView(R.string.configure_biometric)
setAdvancedUnlockedMessageView("")
openBiometricSetting()
}
@RequiresApi(Build.VERSION_CODES.M)
private fun initKeyManagerNotAvailable() {
showViews(true)
setAdvancedUnlockedTitleView(R.string.keystore_not_accessible)
openBiometricSetting()
}
@RequiresApi(Build.VERSION_CODES.M)
private fun initWaitData() {
showViews(true)
setAdvancedUnlockedTitleView(R.string.unavailable)
setAdvancedUnlockedMessageView("")
context?.let { context ->
mAdvancedUnlockInfoView?.setIconViewClickListener {
onAuthenticationError(BiometricPrompt.ERROR_UNABLE_TO_PROCESS,
context.getString(R.string.credential_before_click_advanced_unlock_button))
}
}
}
@RequiresApi(Build.VERSION_CODES.M)
private fun openAdvancedUnlockPrompt(cryptoPrompt: AdvancedUnlockCryptoPrompt) {
lifecycleScope.launch(Dispatchers.Main) {
if (allowOpenBiometricPrompt) {
if (cryptoPrompt.isDeviceCredentialOperation)
keepConnection = true
try {
advancedUnlockManager?.openAdvancedUnlockPrompt(cryptoPrompt,
mDeviceCredentialResultLauncher)
} catch (e: Exception) {
Log.e(TAG, "Unable to open advanced unlock prompt", e)
setAdvancedUnlockedTitleView(R.string.advanced_unlock_prompt_not_initialized)
}
}
}
}
@RequiresApi(Build.VERSION_CODES.M)
private fun initEncryptData() {
showViews(true)
setAdvancedUnlockedTitleView(R.string.unlock_and_link_biometric)
setAdvancedUnlockedMessageView("")
advancedUnlockManager?.initEncryptData { cryptoPrompt ->
// Set listener to open the biometric dialog and save credential
mAdvancedUnlockInfoView?.setIconViewClickListener { _ ->
openAdvancedUnlockPrompt(cryptoPrompt)
}
} ?: throw Exception("AdvancedUnlockManager not initialized")
}
@RequiresApi(Build.VERSION_CODES.M)
private fun initDecryptData() {
showViews(true)
setAdvancedUnlockedTitleView(R.string.unlock)
setAdvancedUnlockedMessageView("")
advancedUnlockManager?.let { unlockHelper ->
databaseFileUri?.let { databaseUri ->
cipherDatabaseAction.getCipherDatabase(databaseUri) { cipherDatabase ->
cipherDatabase?.let {
unlockHelper.initDecryptData(it.specParameters) { cryptoPrompt ->
// Set listener to open the biometric dialog and check credential
mAdvancedUnlockInfoView?.setIconViewClickListener { _ ->
openAdvancedUnlockPrompt(cryptoPrompt)
}
// Auto open the biometric prompt
if (mAdvancedUnlockViewModel.allowAutoOpenBiometricPrompt
&& mAutoOpenPromptEnabled) {
mAdvancedUnlockViewModel.allowAutoOpenBiometricPrompt = false
openAdvancedUnlockPrompt(cryptoPrompt)
}
}
} ?: deleteEncryptedDatabaseKey()
}
} ?: throw UnknownDatabaseLocationException()
} ?: throw Exception("AdvancedUnlockManager not initialized")
}
private fun initAdvancedUnlockMode() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAllowAdvancedUnlockMenu = false
try {
when (biometricMode) {
Mode.BIOMETRIC_UNAVAILABLE -> initNotAvailable()
Mode.BIOMETRIC_SECURITY_UPDATE_REQUIRED -> initSecurityUpdateRequired()
Mode.DEVICE_CREDENTIAL_OR_BIOMETRIC_NOT_CONFIGURED -> initNotConfigured()
Mode.KEY_MANAGER_UNAVAILABLE -> initKeyManagerNotAvailable()
Mode.WAIT_CREDENTIAL -> initWaitData()
Mode.STORE_CREDENTIAL -> initEncryptData()
Mode.EXTRACT_CREDENTIAL -> initDecryptData()
}
} catch (e: Exception) {
onGenericException(e)
}
invalidateBiometricMenu()
}
}
private fun invalidateBiometricMenu() {
// Show fingerprint key deletion
if (!mAddBiometricMenuInProgress) {
mAddBiometricMenuInProgress = true
databaseFileUri?.let { databaseUri ->
cipherDatabaseAction.containsCipherDatabase(databaseUri) { containsCipher ->
mAllowAdvancedUnlockMenu = containsCipher
&& (biometricMode != Mode.BIOMETRIC_UNAVAILABLE
&& biometricMode != Mode.KEY_MANAGER_UNAVAILABLE)
mAddBiometricMenuInProgress = false
activity?.invalidateOptionsMenu()
}
}
}
}
@RequiresApi(Build.VERSION_CODES.M)
fun connect(databaseUri: Uri) {
showViews(true)
this.databaseFileUri = databaseUri
cipherDatabaseListener = object: CipherDatabaseAction.CipherDatabaseListener {
override fun onCipherDatabaseCleared() {
advancedUnlockManager?.closeBiometricPrompt()
checkUnlockAvailability()
}
}
cipherDatabaseAction.apply {
reloadPreferences()
cipherDatabaseListener?.let {
registerDatabaseListener(it)
}
}
checkUnlockAvailability()
}
@RequiresApi(Build.VERSION_CODES.M)
fun disconnect(hideViews: Boolean = true,
closePrompt: Boolean = true) {
this.databaseFileUri = null
// Close the biometric prompt
allowOpenBiometricPrompt = false
if (closePrompt)
advancedUnlockManager?.closeBiometricPrompt()
cipherDatabaseListener?.let {
cipherDatabaseAction.unregisterDatabaseListener(it)
}
biometricMode = Mode.BIOMETRIC_UNAVAILABLE
if (hideViews) {
showViews(false)
}
}
@RequiresApi(Build.VERSION_CODES.M)
fun deleteEncryptedDatabaseKey() {
mAllowAdvancedUnlockMenu = false
advancedUnlockManager?.closeBiometricPrompt()
databaseFileUri?.let { databaseUri ->
cipherDatabaseAction.deleteByDatabaseUri(databaseUri) {
checkUnlockAvailability()
}
} ?: checkUnlockAvailability()
}
@RequiresApi(Build.VERSION_CODES.M)
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
lifecycleScope.launch(Dispatchers.Main) {
Log.e(TAG, "Biometric authentication error. Code : $errorCode Error : $errString")
setAdvancedUnlockedMessageView(errString.toString())
}
}
@RequiresApi(Build.VERSION_CODES.M)
override fun onAuthenticationFailed() {
lifecycleScope.launch(Dispatchers.Main) {
Log.e(TAG, "Biometric authentication failed, biometric not recognized")
setAdvancedUnlockedMessageView(R.string.advanced_unlock_not_recognized)
}
}
@RequiresApi(Build.VERSION_CODES.M)
override fun onAuthenticationSucceeded() {
lifecycleScope.launch(Dispatchers.Main) {
when (biometricMode) {
Mode.BIOMETRIC_UNAVAILABLE -> {
}
Mode.BIOMETRIC_SECURITY_UPDATE_REQUIRED -> {
}
Mode.DEVICE_CREDENTIAL_OR_BIOMETRIC_NOT_CONFIGURED -> {
}
Mode.KEY_MANAGER_UNAVAILABLE -> {
}
Mode.WAIT_CREDENTIAL -> {
}
Mode.STORE_CREDENTIAL -> {
// newly store the entered password in encrypted way
mBuilderListener?.retrieveCredentialForEncryption()?.let { credential ->
advancedUnlockManager?.encryptData(credential)
}
}
Mode.EXTRACT_CREDENTIAL -> {
// retrieve the encrypted value from preferences
databaseFileUri?.let { databaseUri ->
cipherDatabaseAction.getCipherDatabase(databaseUri) { cipherDatabase ->
cipherDatabase?.encryptedValue?.let { value ->
advancedUnlockManager?.decryptData(value)
} ?: deleteEncryptedDatabaseKey()
}
} ?: run {
onAuthenticationError(-1, getString(R.string.error_database_uri_null))
}
}
}
}
}
override fun handleEncryptedResult(encryptedValue: ByteArray, ivSpec: ByteArray) {
databaseFileUri?.let { databaseUri ->
mBuilderListener?.onCredentialEncrypted(
CipherEncryptDatabase().apply {
this.databaseUri = databaseUri
this.credentialStorage = credentialDatabaseStorage
this.encryptedValue = encryptedValue
this.specParameters = ivSpec
}
)
}
}
override fun handleDecryptedResult(decryptedValue: ByteArray) {
// Load database directly with password retrieve
databaseFileUri?.let { databaseUri ->
mBuilderListener?.onCredentialDecrypted(
CipherDecryptDatabase().apply {
this.databaseUri = databaseUri
this.credentialStorage = credentialDatabaseStorage
this.decryptedValue = decryptedValue
}
)
cipherDatabaseAction.resetCipherParameters(databaseUri)
}
}
@RequiresApi(Build.VERSION_CODES.M)
override fun onUnrecoverableKeyException(e: Exception) {
setAdvancedUnlockedMessageView(R.string.advanced_unlock_invalid_key)
}
@RequiresApi(Build.VERSION_CODES.M)
override fun onInvalidKeyException(e: Exception) {
setAdvancedUnlockedMessageView(R.string.advanced_unlock_invalid_key)
}
@RequiresApi(Build.VERSION_CODES.M)
override fun onGenericException(e: Exception) {
val errorMessage = e.cause?.localizedMessage ?: e.localizedMessage ?: ""
setAdvancedUnlockedMessageView(errorMessage)
}
private fun showViews(show: Boolean) {
lifecycleScope.launch(Dispatchers.Main) {
if (show) {
if (mAdvancedUnlockInfoView?.visibility != View.VISIBLE)
mAdvancedUnlockInfoView?.showByFading()
}
else {
if (mAdvancedUnlockInfoView?.visibility == View.VISIBLE)
mAdvancedUnlockInfoView?.hideByFading()
}
}
}
@RequiresApi(Build.VERSION_CODES.M)
private fun setAdvancedUnlockedTitleView(textId: Int) {
lifecycleScope.launch(Dispatchers.Main) {
mAdvancedUnlockInfoView?.setTitle(textId)
}
}
@RequiresApi(Build.VERSION_CODES.M)
private fun setAdvancedUnlockedMessageView(textId: Int) {
lifecycleScope.launch(Dispatchers.Main) {
mAdvancedUnlockInfoView?.setMessage(textId)
}
}
@RequiresApi(Build.VERSION_CODES.M)
private fun setAdvancedUnlockedMessageView(text: CharSequence) {
lifecycleScope.launch(Dispatchers.Main) {
mAdvancedUnlockInfoView?.setMessage(text)
}
}
enum class Mode {
BIOMETRIC_UNAVAILABLE,
BIOMETRIC_SECURITY_UPDATE_REQUIRED,
DEVICE_CREDENTIAL_OR_BIOMETRIC_NOT_CONFIGURED,
KEY_MANAGER_UNAVAILABLE,
WAIT_CREDENTIAL,
STORE_CREDENTIAL,
EXTRACT_CREDENTIAL
}
interface BuilderListener {
fun retrieveCredentialForEncryption(): ByteArray
fun conditionToStoreCredential(): Boolean
fun onCredentialEncrypted(cipherEncryptDatabase: CipherEncryptDatabase)
fun onCredentialDecrypted(cipherDecryptDatabase: CipherDecryptDatabase)
}
override fun onPause() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!keepConnection) {
// If close prompt, bug "user not authenticated in Android R"
disconnect(false)
advancedUnlockManager = null
}
}
super.onPause()
}
override fun onDestroyView() {
mAdvancedUnlockInfoView = null
super.onDestroyView()
}
override fun onDestroy() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
disconnect()
advancedUnlockManager = null
mBuilderListener = null
}
super.onDestroy()
}
override fun onDetach() {
mBuilderListener = null
super.onDetach()
}
companion object {
private val TAG = AdvancedUnlockFragment::class.java.name
}
}

View File

@@ -1,506 +0,0 @@
/*
* Copyright 2020 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePassDX.
*
* KeePassDX is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KeePassDX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.biometric
import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyPermanentlyInvalidatedException
import android.security.keystore.KeyProperties
import android.util.Log
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.RequiresApi
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricManager.Authenticators.*
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
import com.kunzisoft.keepass.settings.PreferencesUtil
import java.security.KeyStore
import java.security.UnrecoverableKeyException
import java.util.concurrent.Executors
import javax.crypto.BadPaddingException
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.spec.IvParameterSpec
@RequiresApi(api = Build.VERSION_CODES.M)
class AdvancedUnlockManager(private var retrieveContext: () -> FragmentActivity) {
private var keyStore: KeyStore? = null
private var keyGenerator: KeyGenerator? = null
private var cipher: Cipher? = null
private var biometricPrompt: BiometricPrompt? = null
private var authenticationCallback = object: BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
advancedUnlockCallback?.onAuthenticationSucceeded()
}
override fun onAuthenticationFailed() {
advancedUnlockCallback?.onAuthenticationFailed()
}
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
advancedUnlockCallback?.onAuthenticationError(errorCode, errString)
}
}
var advancedUnlockCallback: AdvancedUnlockCallback? = null
private var isKeyManagerInit = false
private val biometricUnlockEnable = PreferencesUtil.isBiometricUnlockEnable(retrieveContext())
private val deviceCredentialUnlockEnable = PreferencesUtil.isDeviceCredentialUnlockEnable(retrieveContext())
val isKeyManagerInitialized: Boolean
get() {
if (!isKeyManagerInit) {
advancedUnlockCallback?.onGenericException(Exception("Biometric not initialized"))
}
return isKeyManagerInit
}
private fun isBiometricOperation(): Boolean {
return biometricUnlockEnable || isDeviceCredentialBiometricOperation()
}
// Since Android 30, device credential is also a biometric operation
private fun isDeviceCredentialOperation(): Boolean {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.R
&& deviceCredentialUnlockEnable
}
private fun isDeviceCredentialBiometricOperation(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& deviceCredentialUnlockEnable
}
init {
if (isDeviceSecure(retrieveContext())
&& (biometricUnlockEnable || deviceCredentialUnlockEnable)) {
try {
this.keyStore = KeyStore.getInstance(ADVANCED_UNLOCK_KEYSTORE)
this.keyGenerator = KeyGenerator.getInstance(ADVANCED_UNLOCK_KEY_ALGORITHM, ADVANCED_UNLOCK_KEYSTORE)
this.cipher = Cipher.getInstance(
ADVANCED_UNLOCK_KEY_ALGORITHM + "/"
+ ADVANCED_UNLOCK_BLOCKS_MODES + "/"
+ ADVANCED_UNLOCK_ENCRYPTION_PADDING)
isKeyManagerInit = (keyStore != null
&& keyGenerator != null
&& cipher != null)
} catch (e: Exception) {
Log.e(TAG, "Unable to initialize the keystore", e)
isKeyManagerInit = false
advancedUnlockCallback?.onGenericException(e)
}
} else {
// really not much to do when no fingerprint support found
isKeyManagerInit = false
}
}
@Synchronized private fun getSecretKey(): SecretKey? {
if (!isKeyManagerInitialized) {
return null
}
try {
// Create new key if needed
keyStore?.let { keyStore ->
keyStore.load(null)
try {
if (!keyStore.containsAlias(ADVANCED_UNLOCK_KEYSTORE_KEY)) {
// Set the alias of the entry in Android KeyStore where the key will appear
// and the constrains (purposes) in the constructor of the Builder
keyGenerator?.init(
KeyGenParameterSpec.Builder(
ADVANCED_UNLOCK_KEYSTORE_KEY,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(ADVANCED_UNLOCK_BLOCKS_MODES)
.setEncryptionPaddings(ADVANCED_UNLOCK_ENCRYPTION_PADDING)
.apply {
// Require the user to authenticate with a fingerprint to authorize every use
// of the key, don't use it for device credential because it's the user authentication
if (biometricUnlockEnable) {
setUserAuthenticationRequired(true)
}
// To store in the security chip
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
&& retrieveContext().packageManager.hasSystemFeature(
PackageManager.FEATURE_STRONGBOX_KEYSTORE)) {
setIsStrongBoxBacked(true)
}
}
.build())
keyGenerator?.generateKey()
}
} catch (e: Exception) {
Log.e(TAG, "Unable to create a key in keystore", e)
advancedUnlockCallback?.onGenericException(e)
}
return keyStore.getKey(ADVANCED_UNLOCK_KEYSTORE_KEY, null) as SecretKey?
}
} catch (e: Exception) {
Log.e(TAG, "Unable to retrieve the key in keystore", e)
advancedUnlockCallback?.onGenericException(e)
}
return null
}
@Synchronized fun initEncryptData(actionIfCypherInit: (cryptoPrompt: AdvancedUnlockCryptoPrompt) -> Unit,) {
initEncryptData(actionIfCypherInit, true)
}
@Synchronized private fun initEncryptData(actionIfCypherInit: (cryptoPrompt: AdvancedUnlockCryptoPrompt) -> Unit,
firstLaunch: Boolean) {
if (!isKeyManagerInitialized) {
return
}
try {
getSecretKey()?.let { secretKey ->
cipher?.let { cipher ->
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
actionIfCypherInit.invoke(
AdvancedUnlockCryptoPrompt(
cipher,
R.string.advanced_unlock_prompt_store_credential_title,
R.string.advanced_unlock_prompt_store_credential_message,
isDeviceCredentialOperation(), isBiometricOperation())
)
}
}
} catch (unrecoverableKeyException: UnrecoverableKeyException) {
Log.e(TAG, "Unable to initialize encrypt data", unrecoverableKeyException)
advancedUnlockCallback?.onUnrecoverableKeyException(unrecoverableKeyException)
} catch (invalidKeyException: KeyPermanentlyInvalidatedException) {
Log.e(TAG, "Unable to initialize encrypt data", invalidKeyException)
if (firstLaunch) {
deleteAllEntryKeysInKeystoreForBiometric(retrieveContext())
initEncryptData(actionIfCypherInit, false)
} else {
advancedUnlockCallback?.onInvalidKeyException(invalidKeyException)
}
} catch (e: Exception) {
Log.e(TAG, "Unable to initialize encrypt data", e)
advancedUnlockCallback?.onGenericException(e)
}
}
@Synchronized fun encryptData(value: ByteArray) {
if (!isKeyManagerInitialized) {
return
}
try {
val encrypted = cipher?.doFinal(value) ?: byteArrayOf()
// passes updated iv spec on to callback so this can be stored for decryption
cipher?.parameters?.getParameterSpec(IvParameterSpec::class.java)?.let{ spec ->
advancedUnlockCallback?.handleEncryptedResult(encrypted, spec.iv)
}
} catch (e: Exception) {
Log.e(TAG, "Unable to encrypt data", e)
advancedUnlockCallback?.onGenericException(e)
}
}
@Synchronized fun initDecryptData(ivSpecValue: ByteArray,
actionIfCypherInit: (cryptoPrompt: AdvancedUnlockCryptoPrompt) -> Unit) {
initDecryptData(ivSpecValue, actionIfCypherInit, true)
}
@Synchronized private fun initDecryptData(ivSpecValue: ByteArray,
actionIfCypherInit: (cryptoPrompt: AdvancedUnlockCryptoPrompt) -> Unit,
firstLaunch: Boolean = true) {
if (!isKeyManagerInitialized) {
return
}
try {
// important to restore spec here that was used for decryption
val spec = IvParameterSpec(ivSpecValue)
getSecretKey()?.let { secretKey ->
cipher?.let { cipher ->
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec)
actionIfCypherInit.invoke(
AdvancedUnlockCryptoPrompt(
cipher,
R.string.advanced_unlock_prompt_extract_credential_title,
null,
isDeviceCredentialOperation(), isBiometricOperation())
)
}
}
} catch (unrecoverableKeyException: UnrecoverableKeyException) {
Log.e(TAG, "Unable to initialize decrypt data", unrecoverableKeyException)
if (firstLaunch) {
deleteKeystoreKey()
initDecryptData(ivSpecValue, actionIfCypherInit, firstLaunch)
} else {
advancedUnlockCallback?.onUnrecoverableKeyException(unrecoverableKeyException)
}
} catch (invalidKeyException: KeyPermanentlyInvalidatedException) {
Log.e(TAG, "Unable to initialize decrypt data", invalidKeyException)
if (firstLaunch) {
deleteAllEntryKeysInKeystoreForBiometric(retrieveContext())
initDecryptData(ivSpecValue, actionIfCypherInit, firstLaunch)
} else {
advancedUnlockCallback?.onInvalidKeyException(invalidKeyException)
}
} catch (e: Exception) {
Log.e(TAG, "Unable to initialize decrypt data", e)
advancedUnlockCallback?.onGenericException(e)
}
}
@Synchronized fun decryptData(encryptedValue: ByteArray) {
if (!isKeyManagerInitialized) {
return
}
try {
// actual decryption here
cipher?.doFinal(encryptedValue)?.let { decrypted ->
advancedUnlockCallback?.handleDecryptedResult(decrypted)
}
} catch (badPaddingException: BadPaddingException) {
Log.e(TAG, "Unable to decrypt data", badPaddingException)
advancedUnlockCallback?.onInvalidKeyException(badPaddingException)
} catch (e: Exception) {
Log.e(TAG, "Unable to decrypt data", e)
advancedUnlockCallback?.onGenericException(e)
}
}
@Synchronized fun deleteKeystoreKey() {
try {
keyStore?.load(null)
keyStore?.deleteEntry(ADVANCED_UNLOCK_KEYSTORE_KEY)
} catch (e: Exception) {
Log.e(TAG, "Unable to delete entry key in keystore", e)
advancedUnlockCallback?.onGenericException(e)
}
}
@Synchronized fun openAdvancedUnlockPrompt(cryptoPrompt: AdvancedUnlockCryptoPrompt,
deviceCredentialResultLauncher: ActivityResultLauncher<Intent>
) {
// Init advanced unlock prompt
if (biometricPrompt == null) {
biometricPrompt = BiometricPrompt(retrieveContext(),
Executors.newSingleThreadExecutor(),
authenticationCallback)
}
val promptTitle = retrieveContext().getString(cryptoPrompt.promptTitleId)
val promptDescription = cryptoPrompt.promptDescriptionId?.let { descriptionId ->
retrieveContext().getString(descriptionId)
} ?: ""
if (cryptoPrompt.isBiometricOperation) {
val promptInfoExtractCredential = BiometricPrompt.PromptInfo.Builder().apply {
setTitle(promptTitle)
if (promptDescription.isNotEmpty())
setDescription(promptDescription)
setConfirmationRequired(false)
if (isDeviceCredentialBiometricOperation()) {
setAllowedAuthenticators(DEVICE_CREDENTIAL)
} else {
setNegativeButtonText(retrieveContext().getString(android.R.string.cancel))
}
}.build()
biometricPrompt?.authenticate(
promptInfoExtractCredential,
BiometricPrompt.CryptoObject(cryptoPrompt.cipher))
}
else if (cryptoPrompt.isDeviceCredentialOperation) {
val keyGuardManager = ContextCompat.getSystemService(retrieveContext(), KeyguardManager::class.java)
@Suppress("DEPRECATION")
deviceCredentialResultLauncher.launch(
keyGuardManager?.createConfirmDeviceCredentialIntent(promptTitle, promptDescription)
)
}
}
@Synchronized fun closeBiometricPrompt() {
biometricPrompt?.cancelAuthentication()
}
interface AdvancedUnlockErrorCallback {
fun onUnrecoverableKeyException(e: Exception)
fun onInvalidKeyException(e: Exception)
fun onGenericException(e: Exception)
}
interface AdvancedUnlockCallback : AdvancedUnlockErrorCallback {
fun onAuthenticationSucceeded()
fun onAuthenticationFailed()
fun onAuthenticationError(errorCode: Int, errString: CharSequence)
fun handleEncryptedResult(encryptedValue: ByteArray, ivSpec: ByteArray)
fun handleDecryptedResult(decryptedValue: ByteArray)
}
companion object {
private val TAG = AdvancedUnlockManager::class.java.name
private const val ADVANCED_UNLOCK_KEYSTORE = "AndroidKeyStore"
private const val ADVANCED_UNLOCK_KEYSTORE_KEY = "com.kunzisoft.keepass.biometric.key"
private const val ADVANCED_UNLOCK_KEY_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES
private const val ADVANCED_UNLOCK_BLOCKS_MODES = KeyProperties.BLOCK_MODE_CBC
private const val ADVANCED_UNLOCK_ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7
@RequiresApi(api = Build.VERSION_CODES.M)
fun canAuthenticate(context: Context): Int {
return try {
BiometricManager.from(context).canAuthenticate(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& PreferencesUtil.isDeviceCredentialUnlockEnable(context)) {
BIOMETRIC_STRONG or DEVICE_CREDENTIAL
} else {
BIOMETRIC_STRONG
}
)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with strong biometric.", e)
try {
BiometricManager.from(context).canAuthenticate(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& PreferencesUtil.isDeviceCredentialUnlockEnable(context)) {
BIOMETRIC_WEAK or DEVICE_CREDENTIAL
} else {
BIOMETRIC_WEAK
}
)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with weak biometric.", e)
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
}
}
}
fun isDeviceSecure(context: Context): Boolean {
return ContextCompat.getSystemService(context, KeyguardManager::class.java)
?.isDeviceSecure ?: false
}
fun biometricUnlockSupported(context: Context): Boolean {
val biometricCanAuthenticate = try {
BiometricManager.from(context).canAuthenticate(BIOMETRIC_STRONG)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with strong biometric.", e)
try {
BiometricManager.from(context).canAuthenticate(BIOMETRIC_WEAK)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with weak biometric.", e)
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
}
}
return (biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_STATUS_UNKNOWN
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED
)
}
fun deviceCredentialUnlockSupported(context: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val biometricCanAuthenticate = BiometricManager.from(context).canAuthenticate(DEVICE_CREDENTIAL)
(biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_STATUS_UNKNOWN
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED
)
} else {
true
}
}
/**
* Remove entry key in keystore
*/
fun deleteEntryKeyInKeystoreForBiometric(fragmentActivity: FragmentActivity,
advancedCallback: AdvancedUnlockErrorCallback) {
AdvancedUnlockManager{ fragmentActivity }.apply {
advancedUnlockCallback = object : AdvancedUnlockCallback {
override fun onAuthenticationSucceeded() {}
override fun onAuthenticationFailed() {}
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {}
override fun handleEncryptedResult(encryptedValue: ByteArray, ivSpec: ByteArray) {}
override fun handleDecryptedResult(decryptedValue: ByteArray) {}
override fun onUnrecoverableKeyException(e: Exception) {
advancedCallback.onUnrecoverableKeyException(e)
}
override fun onInvalidKeyException(e: Exception) {
advancedCallback.onInvalidKeyException(e)
}
override fun onGenericException(e: Exception) {
advancedCallback.onGenericException(e)
}
}
deleteKeystoreKey()
}
}
fun deleteAllEntryKeysInKeystoreForBiometric(activity: FragmentActivity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
deleteEntryKeyInKeystoreForBiometric(
activity,
object : AdvancedUnlockErrorCallback {
fun showException(e: Exception) {
Toast.makeText(activity,
activity.getString(R.string.advanced_unlock_scanning_error, e.localizedMessage),
Toast.LENGTH_SHORT).show()
}
override fun onUnrecoverableKeyException(e: Exception) {
showException(e)
}
override fun onInvalidKeyException(e: Exception) {
showException(e)
}
override fun onGenericException(e: Exception) {
showException(e)
}
})
}
CipherDatabaseAction.getInstance(activity.applicationContext).deleteAll()
}
}
}

View File

@@ -0,0 +1,21 @@
package com.kunzisoft.keepass.biometric
import androidx.annotation.StringRes
import javax.crypto.Cipher
data class DeviceUnlockCryptoPrompt(
var type: DeviceUnlockCryptoPromptType,
var cipher: Cipher,
@StringRes var titleId: Int,
@StringRes var descriptionId: Int? = null,
var isDeviceCredentialOperation: Boolean,
var isBiometricOperation: Boolean
) {
fun isOldCredentialOperation(): Boolean {
return !isBiometricOperation && isDeviceCredentialOperation
}
}
enum class DeviceUnlockCryptoPromptType {
CREDENTIAL_ENCRYPTION, CREDENTIAL_DECRYPTION
}

View File

@@ -0,0 +1,363 @@
/*
* Copyright 2020 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePassDX.
*
* KeePassDX is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KeePassDX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.biometric
import android.app.Activity
import android.app.KeyguardManager
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.core.view.MenuProvider
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.view.DeviceUnlockView
import com.kunzisoft.keepass.view.hideByFading
import com.kunzisoft.keepass.view.showByFading
import com.kunzisoft.keepass.viewmodels.DeviceUnlockPromptMode
import com.kunzisoft.keepass.viewmodels.DeviceUnlockViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.concurrent.Executors
@RequiresApi(Build.VERSION_CODES.M)
class DeviceUnlockFragment: Fragment() {
private var mDeviceUnlockView: DeviceUnlockView? = null
private val mDeviceUnlockViewModel: DeviceUnlockViewModel by activityViewModels()
private var mBiometricPrompt: BiometricPrompt? = null
// Only to fix multiple fingerprint menu #332
private var mAllowDeviceUnlockMenu = false
private var mDeviceCredentialResultLauncher: ActivityResultLauncher<Intent>? = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
mDeviceUnlockViewModel.onAuthenticationSucceeded()
} else {
setAuthenticationFailed()
}
mDeviceUnlockViewModel.biometricPromptClosed()
}
private var biometricAuthenticationCallback = object: BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
mDeviceUnlockViewModel.onAuthenticationSucceeded(result)
mDeviceUnlockViewModel.biometricPromptClosed()
}
override fun onAuthenticationFailed() {
setAuthenticationFailed()
}
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
setAuthenticationError(errorCode, errString)
}
}
private val menuProvider: MenuProvider = object: MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
// biometric menu
if (mAllowDeviceUnlockMenu)
menuInflater.inflate(R.menu.device_unlock, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
when (menuItem.itemId) {
R.id.menu_keystore_remove_key ->
deleteEncryptedDatabaseKey()
}
return false
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
val rootView = inflater.inflate(R.layout.fragment_device_unlock, container, false)
mDeviceUnlockView = rootView.findViewById(R.id.device_unlock_view)
return rootView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Init device unlock prompt
mBiometricPrompt = BiometricPrompt(
this@DeviceUnlockFragment,
Executors.newSingleThreadExecutor(),
biometricAuthenticationCallback
)
activity?.addMenuProvider(menuProvider, viewLifecycleOwner)
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
mDeviceUnlockViewModel.uiState.collect { uiState ->
// Change mode
toggleDeviceCredentialMode(uiState.newDeviceUnlockMode)
// Prompt
manageDeviceCredentialPrompt(uiState.cryptoPromptState)
// Advanced menu
mAllowDeviceUnlockMenu = uiState.allowDeviceUnlockMenu
activity?.invalidateOptionsMenu()
}
}
}
}
fun cancelBiometricPrompt() {
lifecycleScope.launch(Dispatchers.Main) {
mBiometricPrompt?.cancelAuthentication()
}
}
private fun toggleDeviceCredentialMode(deviceUnlockMode: DeviceUnlockMode) {
lifecycleScope.launch(Dispatchers.Main) {
try {
when (deviceUnlockMode) {
DeviceUnlockMode.BIOMETRIC_UNAVAILABLE -> setNotAvailableMode()
DeviceUnlockMode.BIOMETRIC_SECURITY_UPDATE_REQUIRED -> setSecurityUpdateRequiredMode()
DeviceUnlockMode.DEVICE_CREDENTIAL_OR_BIOMETRIC_NOT_CONFIGURED -> setNotConfiguredMode()
DeviceUnlockMode.KEY_MANAGER_UNAVAILABLE -> setKeyManagerNotAvailableMode()
DeviceUnlockMode.WAIT_CREDENTIAL -> setWaitCredentialMode()
DeviceUnlockMode.STORE_CREDENTIAL -> setStoreCredentialMode()
DeviceUnlockMode.EXTRACT_CREDENTIAL -> setExtractCredentialMode()
}
} catch (e: Exception) {
mDeviceUnlockViewModel.setException(e)
}
}
}
private fun manageDeviceCredentialPrompt(
state: DeviceUnlockPromptMode
) {
mDeviceUnlockViewModel.cryptoPrompt?.let { prompt ->
when (state) {
DeviceUnlockPromptMode.SHOW -> {
openPrompt(prompt)
mDeviceUnlockViewModel.promptShown()
}
DeviceUnlockPromptMode.CLOSE -> {
cancelBiometricPrompt()
mDeviceUnlockViewModel.biometricPromptClosed()
}
else -> {}
}
}
}
private fun openPrompt(cryptoPrompt: DeviceUnlockCryptoPrompt) {
lifecycleScope.launch(Dispatchers.Main) {
try {
val promptTitle = getString(cryptoPrompt.titleId)
val promptDescription = cryptoPrompt.descriptionId?.let { descriptionId ->
getString(descriptionId)
} ?: ""
if (cryptoPrompt.isBiometricOperation) {
mBiometricPrompt?.authenticate(
BiometricPrompt.PromptInfo.Builder().apply {
setTitle(promptTitle)
if (promptDescription.isNotEmpty())
setDescription(promptDescription)
setConfirmationRequired(false)
if (isDeviceCredentialBiometricOperation(context)) {
setAllowedAuthenticators(DEVICE_CREDENTIAL)
} else {
setNegativeButtonText(getString(android.R.string.cancel))
}
}.build(),
BiometricPrompt.CryptoObject(cryptoPrompt.cipher)
)
} else if (cryptoPrompt.isDeviceCredentialOperation) {
context?.let { context ->
@Suppress("DEPRECATION")
mDeviceCredentialResultLauncher?.launch(
ContextCompat.getSystemService(
context,
KeyguardManager::class.java
)?.createConfirmDeviceCredentialIntent(
promptTitle,
promptDescription
)
)
}
}
} catch (e: Exception) {
Log.e(TAG, "Unable to open prompt", e)
mDeviceUnlockViewModel.setException(e)
}
}
}
private fun setNotAvailableMode() {
showViews(false)
mDeviceUnlockView?.setDeviceUnlockButtonViewClickListener(null)
}
private fun openBiometricSetting() {
mDeviceUnlockView?.setDeviceUnlockButtonViewClickListener {
try {
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
context?.startActivity(Intent(Settings.ACTION_BIOMETRIC_ENROLL))
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P -> {
@Suppress("DEPRECATION") context
?.startActivity(Intent(Settings.ACTION_FINGERPRINT_ENROLL))
}
else -> {
context?.startActivity(Intent(Settings.ACTION_SECURITY_SETTINGS))
}
}
} catch (e: Exception) {
// ACTION_SECURITY_SETTINGS does not contain fingerprint enrollment on some devices...
context?.startActivity(Intent(Settings.ACTION_SETTINGS))
}
}
}
private fun setSecurityUpdateRequiredMode() {
showViews(true)
setDeviceUnlockedTitleView(R.string.biometric_security_update_required)
openBiometricSetting()
}
private fun setNotConfiguredMode() {
showViews(true)
setDeviceUnlockedTitleView(R.string.configure_biometric)
openBiometricSetting()
}
private fun setKeyManagerNotAvailableMode() {
showViews(true)
setDeviceUnlockedTitleView(R.string.keystore_not_accessible)
openBiometricSetting()
}
private fun setWaitCredentialMode() {
showViews(true)
setDeviceUnlockedTitleView(R.string.unavailable)
context?.let { context ->
mDeviceUnlockView?.setDeviceUnlockButtonViewClickListener {
mDeviceUnlockViewModel.setException(SecurityException(
context.getString(R.string.credential_before_click_device_unlock_button)
))
}
}
}
private fun setStoreCredentialMode() {
showViews(true)
setDeviceUnlockedTitleView(R.string.unlock_and_link_biometric)
mDeviceUnlockView?.setDeviceUnlockButtonViewClickListener { _ ->
mDeviceUnlockViewModel.showPrompt()
}
}
private fun setExtractCredentialMode() {
showViews(true)
setDeviceUnlockedTitleView(R.string.unlock)
mDeviceUnlockView?.setDeviceUnlockButtonViewClickListener { _ ->
mDeviceUnlockViewModel.showPrompt()
}
}
fun deleteEncryptedDatabaseKey() {
mDeviceUnlockViewModel.deleteEncryptedDatabaseKey()
}
private fun showViews(show: Boolean) {
if (show) {
if (mDeviceUnlockView?.visibility != View.VISIBLE)
mDeviceUnlockView?.showByFading()
}
else {
if (mDeviceUnlockView?.visibility == View.VISIBLE)
mDeviceUnlockView?.hideByFading()
}
}
private fun setDeviceUnlockedTitleView(textId: Int) {
mDeviceUnlockView?.setTitle(textId)
}
private fun setAuthenticationError(errorCode: Int, errString: CharSequence) {
mDeviceUnlockViewModel.biometricPromptClosed()
when (errorCode) {
BiometricPrompt.ERROR_CANCELED,
BiometricPrompt.ERROR_NEGATIVE_BUTTON,
BiometricPrompt.ERROR_USER_CANCELED -> {
// No operation
Log.i(TAG, "$errString")
}
else -> {
Log.e(TAG, "Biometric authentication error. Code : $errorCode Error : $errString")
mDeviceUnlockViewModel.setException(SecurityException(errString.toString()))
}
}
}
private fun setAuthenticationFailed() {
Log.e(TAG, "Biometric authentication failed, biometric not recognized")
mDeviceUnlockViewModel.setException(
SecurityException(getString(R.string.device_unlock_not_recognized))
)
}
override fun onPause() {
super.onPause()
cancelBiometricPrompt()
mDeviceUnlockViewModel.clear()
}
override fun onDestroyView() {
mDeviceUnlockView = null
super.onDestroyView()
}
companion object {
private val TAG = DeviceUnlockFragment::class.java.name
}
}

View File

@@ -0,0 +1,430 @@
/*
* Copyright 2020 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePassDX.
*
* KeePassDX is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KeePassDX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.biometric
import android.app.KeyguardManager
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyPermanentlyInvalidatedException
import android.security.keystore.KeyProperties
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG
import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_WEAK
import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
import androidx.core.content.ContextCompat
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
import com.kunzisoft.keepass.settings.PreferencesUtil
import java.security.KeyStore
import java.security.UnrecoverableKeyException
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.spec.IvParameterSpec
@RequiresApi(api = Build.VERSION_CODES.M)
class DeviceUnlockManager(private var appContext: Context) {
private var keyStore: KeyStore? = null
private var keyGenerator: KeyGenerator? = null
private var cipher: Cipher? = null
private var biometricUnlockEnable = isBiometricUnlockEnable(appContext)
private var deviceCredentialUnlockEnable = isDeviceCredentialUnlockEnable(appContext)
init {
if (biometricUnlockEnable || deviceCredentialUnlockEnable) {
if (isDeviceSecure(appContext)) {
try {
this.keyStore = KeyStore.getInstance(DEVICE_UNLOCK_KEYSTORE)
this.keyGenerator = KeyGenerator.getInstance(
DEVICE_UNLOCK_KEY_ALGORITHM,
DEVICE_UNLOCK_KEYSTORE
)
this.cipher = Cipher.getInstance(
DEVICE_UNLOCK_KEY_ALGORITHM + "/"
+ DEVICE_UNLOCK_BLOCKS_MODES + "/"
+ DEVICE_UNLOCK_ENCRYPTION_PADDING
)
if (keyStore == null) {
throw SecurityException("Unable to initialize the keystore")
}
if (keyGenerator == null) {
throw SecurityException("Unable to initialize the key generator")
}
if (cipher == null) {
throw SecurityException("Unable to initialize the cipher")
}
} catch (e: Exception) {
Log.e(TAG, "Unable to initialize the device unlock manager", e)
throw e
}
} else {
throw SecurityException("Device not secure enough")
}
}
}
@Synchronized private fun getSecretKey(): SecretKey? {
try {
// Create new key if needed
keyStore?.let { keyStore ->
keyStore.load(null)
try {
if (!keyStore.containsAlias(DEVICE_UNLOCK_KEYSTORE_KEY)) {
// Set the alias of the entry in Android KeyStore where the key will appear
// and the constrains (purposes) in the constructor of the Builder
keyGenerator?.init(
KeyGenParameterSpec.Builder(
DEVICE_UNLOCK_KEYSTORE_KEY,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(DEVICE_UNLOCK_BLOCKS_MODES)
.setEncryptionPaddings(DEVICE_UNLOCK_ENCRYPTION_PADDING)
.apply {
// Require the user to authenticate with a fingerprint to authorize every use
// of the key, don't use it for device credential because it's the user authentication
if (biometricUnlockEnable) {
setUserAuthenticationRequired(true)
}
// To store in the security chip
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
&& appContext.packageManager.hasSystemFeature(
PackageManager.FEATURE_STRONGBOX_KEYSTORE)) {
setIsStrongBoxBacked(true)
}
}
.build())
keyGenerator?.generateKey()
}
} catch (e: Exception) {
Log.e(TAG, "Unable to create a key in keystore", e)
throw e
}
return keyStore.getKey(DEVICE_UNLOCK_KEYSTORE_KEY, null) as SecretKey?
}
} catch (e: Exception) {
Log.e(TAG, "Unable to retrieve the key in keystore", e)
throw e
}
return null
}
@Synchronized fun initEncryptData(
actionIfCypherInit: (cryptoPrompt: DeviceUnlockCryptoPrompt) -> Unit
) {
initEncryptData(true, actionIfCypherInit)
}
@Synchronized private fun initEncryptData(
firstLaunch: Boolean,
actionIfCypherInit: (cryptoPrompt: DeviceUnlockCryptoPrompt) -> Unit
) {
try {
getSecretKey()?.let { secretKey ->
cipher?.let { cipher ->
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
actionIfCypherInit.invoke(
DeviceUnlockCryptoPrompt(
type = DeviceUnlockCryptoPromptType.CREDENTIAL_ENCRYPTION,
cipher = cipher,
titleId = R.string.device_unlock_prompt_store_credential_title,
descriptionId = R.string.device_unlock_prompt_store_credential_message,
isDeviceCredentialOperation = isDeviceCredentialOperation(
deviceCredentialUnlockEnable
),
isBiometricOperation = isBiometricOperation(
biometricUnlockEnable, deviceCredentialUnlockEnable
)
)
)
}
}
} catch (unrecoverableKeyException: UnrecoverableKeyException) {
Log.e(TAG, "Unable to initialize encrypt data", unrecoverableKeyException)
throw unrecoverableKeyException
} catch (invalidKeyException: KeyPermanentlyInvalidatedException) {
Log.e(TAG, "Unable to initialize encrypt data", invalidKeyException)
if (firstLaunch) {
deleteAllEntryKeysInKeystoreForBiometric(appContext)
initEncryptData(false, actionIfCypherInit)
} else {
throw invalidKeyException
}
} catch (e: Exception) {
Log.e(TAG, "Unable to initialize encrypt data", e)
throw e
}
}
@Synchronized fun encryptData(
value: ByteArray,
cipher: Cipher?,
handleEncryptedResult: (encryptedValue: ByteArray, ivSpec: ByteArray) -> Unit
) {
try {
val encrypted = cipher?.doFinal(value) ?: byteArrayOf()
// passes updated iv spec on to callback so this can be stored for decryption
cipher?.parameters?.getParameterSpec(IvParameterSpec::class.java)?.let{ spec ->
handleEncryptedResult.invoke(encrypted, spec.iv)
}
} catch (e: Exception) {
Log.e(TAG, "Unable to encrypt data", e)
throw e
}
}
@Synchronized fun initDecryptData(
ivSpecValue: ByteArray,
actionIfCypherInit: (cryptoPrompt: DeviceUnlockCryptoPrompt) -> Unit
) {
initDecryptData(ivSpecValue, true, actionIfCypherInit)
}
@Synchronized private fun initDecryptData(
ivSpecValue: ByteArray,
firstLaunch: Boolean = true,
actionIfCypherInit: (cryptoPrompt: DeviceUnlockCryptoPrompt) -> Unit
) {
try {
// important to restore spec here that was used for decryption
val spec = IvParameterSpec(ivSpecValue)
getSecretKey()?.let { secretKey ->
cipher?.let { cipher ->
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec)
actionIfCypherInit.invoke(
DeviceUnlockCryptoPrompt(
type = DeviceUnlockCryptoPromptType.CREDENTIAL_DECRYPTION,
cipher = cipher,
titleId = R.string.device_unlock_prompt_extract_credential_title,
descriptionId = null,
isDeviceCredentialOperation = isDeviceCredentialOperation(
deviceCredentialUnlockEnable
),
isBiometricOperation = isBiometricOperation(
biometricUnlockEnable, deviceCredentialUnlockEnable
)
)
)
}
}
} catch (unrecoverableKeyException: UnrecoverableKeyException) {
Log.e(TAG, "Unable to initialize decrypt data", unrecoverableKeyException)
if (firstLaunch) {
deleteKeystoreKey()
initDecryptData(ivSpecValue, false, actionIfCypherInit)
} else {
throw unrecoverableKeyException
}
} catch (invalidKeyException: KeyPermanentlyInvalidatedException) {
Log.e(TAG, "Unable to initialize decrypt data", invalidKeyException)
if (firstLaunch) {
deleteAllEntryKeysInKeystoreForBiometric(appContext)
initDecryptData(ivSpecValue, false, actionIfCypherInit)
} else {
throw invalidKeyException
}
} catch (e: Exception) {
Log.e(TAG, "Unable to initialize decrypt data", e)
throw e
}
}
@Synchronized fun decryptData(
encryptedValue: ByteArray,
cipher: Cipher?,
handleDecryptedResult: (decryptedValue: ByteArray) -> Unit
) {
try {
// actual decryption here
cipher?.doFinal(encryptedValue)?.let { decrypted ->
handleDecryptedResult.invoke(decrypted)
}
} catch (e: Exception) {
Log.e(TAG, "Unable to decrypt data", e)
throw e
}
}
@Synchronized fun deleteKeystoreKey() {
try {
keyStore?.load(null)
keyStore?.deleteEntry(DEVICE_UNLOCK_KEYSTORE_KEY)
} catch (e: Exception) {
Log.e(TAG, "Unable to delete entry key in keystore", e)
throw e
}
}
companion object {
private val TAG = DeviceUnlockManager::class.java.name
private const val DEVICE_UNLOCK_KEYSTORE = "AndroidKeyStore"
private const val DEVICE_UNLOCK_KEYSTORE_KEY = "com.kunzisoft.keepass.biometric.key"
private const val DEVICE_UNLOCK_KEY_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES
private const val DEVICE_UNLOCK_BLOCKS_MODES = KeyProperties.BLOCK_MODE_CBC
private const val DEVICE_UNLOCK_ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7
@RequiresApi(api = Build.VERSION_CODES.M)
fun canAuthenticate(context: Context): Int {
return try {
BiometricManager.from(context).canAuthenticate(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& PreferencesUtil.isDeviceCredentialUnlockEnable(context)) {
BIOMETRIC_STRONG or DEVICE_CREDENTIAL
} else {
BIOMETRIC_STRONG
}
)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with strong biometric.", e)
try {
BiometricManager.from(context).canAuthenticate(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& PreferencesUtil.isDeviceCredentialUnlockEnable(context)) {
BIOMETRIC_WEAK or DEVICE_CREDENTIAL
} else {
BIOMETRIC_WEAK
}
)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with weak biometric.", e)
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
}
}
}
fun isDeviceSecure(context: Context): Boolean {
return ContextCompat.getSystemService(context, KeyguardManager::class.java)
?.isDeviceSecure ?: false
}
fun biometricUnlockSupported(context: Context): Boolean {
val biometricCanAuthenticate = try {
BiometricManager.from(context).canAuthenticate(BIOMETRIC_STRONG)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with strong biometric.", e)
try {
BiometricManager.from(context).canAuthenticate(BIOMETRIC_WEAK)
} catch (e: Exception) {
Log.e(TAG, "Unable to authenticate with weak biometric.", e)
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
}
}
return (biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_STATUS_UNKNOWN
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED
)
}
fun deviceCredentialUnlockSupported(context: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val biometricCanAuthenticate = BiometricManager.from(context).canAuthenticate(DEVICE_CREDENTIAL)
(biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_STATUS_UNKNOWN
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED
)
} else {
true
}
}
/**
* Remove entry key in keystore
*/
fun deleteEntryKeyInKeystoreForBiometric(
appContext: Context
) {
DeviceUnlockManager(appContext).apply {
deleteKeystoreKey()
}
}
fun deleteAllEntryKeysInKeystoreForBiometric(appContext: Context) {
try {
deleteEntryKeyInKeystoreForBiometric(appContext)
} catch (e: Exception) {
Toast.makeText(appContext,
deviceUnlockError(e, appContext),
Toast.LENGTH_SHORT).show()
} finally {
CipherDatabaseAction.getInstance(appContext).deleteAll()
}
}
}
}
fun deviceUnlockError(error: Throwable, context: Context): String {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& (error is UnrecoverableKeyException
|| error is KeyPermanentlyInvalidatedException)) {
context.getString(R.string.device_unlock_invalid_key)
} else
error.cause?.localizedMessage
?: error.localizedMessage
?: error.toString()
}
fun isBiometricUnlockEnable(appContext: Context) =
PreferencesUtil.isBiometricUnlockEnable(appContext)
fun isDeviceCredentialUnlockEnable(appContext: Context) =
PreferencesUtil.isDeviceCredentialUnlockEnable(appContext)
private fun isBiometricOperation(
biometricUnlockEnable: Boolean,
deviceCredentialUnlockEnable: Boolean
): Boolean {
return biometricUnlockEnable
|| isDeviceCredentialBiometricOperation(deviceCredentialUnlockEnable)
}
// Since Android 30, device credential is also a biometric operation
private fun isDeviceCredentialOperation(
deviceCredentialUnlockEnable: Boolean
): Boolean {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.R
&& deviceCredentialUnlockEnable
}
private fun isDeviceCredentialBiometricOperation(
deviceCredentialUnlockEnable: Boolean
): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& deviceCredentialUnlockEnable
}
fun isDeviceCredentialBiometricOperation(context: Context?): Boolean {
if (context == null) {
return false
}
return isDeviceCredentialBiometricOperation(
isDeviceCredentialUnlockEnable(context)
)
}

View File

@@ -0,0 +1,11 @@
package com.kunzisoft.keepass.biometric
enum class DeviceUnlockMode {
BIOMETRIC_UNAVAILABLE,
BIOMETRIC_SECURITY_UPDATE_REQUIRED,
DEVICE_CREDENTIAL_OR_BIOMETRIC_NOT_CONFIGURED,
KEY_MANAGER_UNAVAILABLE,
WAIT_CREDENTIAL,
STORE_CREDENTIAL,
EXTRACT_CREDENTIAL
}

View File

@@ -254,6 +254,7 @@ class DatabaseTaskProvider(
}
private fun initServiceConnection() {
stopDialog()
if (serviceConnection == null) {
serviceConnection = object : ServiceConnection {
override fun onBindingDied(name: ComponentName?) {

View File

@@ -59,9 +59,9 @@ object SearchHelper {
&& !searchInfo.containsOnlyNullValues()) {
// If search provide results
database.createVirtualGroupFromSearchInfo(
searchInfo.toString(),
searchInfo.isASearchByDomain(),
MAX_SEARCH_ENTRY
searchInfoString = searchInfo.toString(),
searchInfoByDomain = searchInfo.isASearchByDomain(),
max = MAX_SEARCH_ENTRY
)?.let { searchGroup ->
if (searchGroup.numberOfChildEntries > 0) {
searchWithoutUI = true

View File

@@ -89,8 +89,8 @@ class PasswordActivityEducation(activity: Activity)
onOuterViewClick: ((TapTargetView?) -> Unit)? = null): Boolean {
return checkAndPerformedEducation(isEducationBiometricPerformed(activity),
TapTarget.forView(educationView,
activity.getString(R.string.education_advanced_unlock_title),
activity.getString(R.string.education_advanced_unlock_summary))
activity.getString(R.string.education_device_unlock_title),
activity.getString(R.string.education_device_unlock_summary))
.outerCircleColorInt(getCircleColor())
.outerCircleAlpha(getCircleAlpha())
.icon(ContextCompat.getDrawable(activity, R.drawable.ic_fingerprint_24dp))

View File

@@ -15,13 +15,13 @@ import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.timeout.TimeoutHelper
class AdvancedUnlockNotificationService : NotificationService() {
class DeviceUnlockNotificationService : NotificationService() {
private lateinit var mTempCipherDao: ArrayList<CipherDatabaseEntity>
private var mActionTaskBinder = AdvancedUnlockBinder()
private var mActionTaskBinder = DeviceUnlockBinder()
inner class AdvancedUnlockBinder: Binder() {
inner class DeviceUnlockBinder: Binder() {
fun getCipherDatabase(databaseUri: Uri): CipherDatabaseEntity? {
return mTempCipherDao.firstOrNull { it.databaseUri == databaseUri.toString()}
}
@@ -48,11 +48,11 @@ class AdvancedUnlockNotificationService : NotificationService() {
override val notificationId: Int = 593
override fun retrieveChannelId(): String {
return CHANNEL_ADVANCED_UNLOCK_ID
return CHANNEL_DEVICE_UNLOCK_ID
}
override fun retrieveChannelName(): String {
return getString(R.string.advanced_unlock)
return getString(R.string.device_unlock)
}
override fun onCreate() {
@@ -60,7 +60,7 @@ class AdvancedUnlockNotificationService : NotificationService() {
mTempCipherDao = ArrayList()
}
// It's simpler to use pendingIntent to perform REMOVE_ADVANCED_UNLOCK_KEY_ACTION
// It's simpler to use pendingIntent to perform REMOVE_DEVICE_UNLOCK_KEY_ACTION
// because can be directly broadcast to another module or app
@SuppressLint("LaunchActivityFromNotification")
override fun onBind(intent: Intent): IBinder {
@@ -68,7 +68,7 @@ class AdvancedUnlockNotificationService : NotificationService() {
val pendingDeleteIntent = PendingIntent.getBroadcast(this,
4577,
Intent(REMOVE_ADVANCED_UNLOCK_KEY_ACTION),
Intent(REMOVE_DEVICE_UNLOCK_KEY_ACTION),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else {
@@ -81,28 +81,28 @@ class AdvancedUnlockNotificationService : NotificationService() {
} else {
R.drawable.notification_ic_device_unlock_24dp
})
setContentTitle(getString(R.string.advanced_unlock))
setContentText(getString(R.string.advanced_unlock_tap_delete))
setContentTitle(getString(R.string.device_unlock))
setContentText(getString(R.string.device_unlock_tap_delete))
setContentIntent(pendingDeleteIntent)
// Unfortunately swipe is disabled in lollipop+
setDeleteIntent(pendingDeleteIntent)
}
val notificationTimeoutMilliSecs = PreferencesUtil.getAdvancedUnlockTimeout(this)
val notificationTimeoutMilliSecs = PreferencesUtil.getDeviceUnlockTimeout(this)
// Not necessarily a foreground service
if (mTimerJob == null && notificationTimeoutMilliSecs != TimeoutHelper.NEVER) {
defineTimerJob(
notificationBuilder,
NotificationServiceType.ADVANCED_UNLOCK,
NotificationServiceType.DEVICE_UNLOCK,
notificationTimeoutMilliSecs
) {
sendBroadcast(Intent(REMOVE_ADVANCED_UNLOCK_KEY_ACTION))
sendBroadcast(Intent(REMOVE_DEVICE_UNLOCK_KEY_ACTION))
}
} else {
startForegroundCompat(
notificationId,
notificationBuilder,
NotificationServiceType.ADVANCED_UNLOCK
NotificationServiceType.DEVICE_UNLOCK
)
}
@@ -119,11 +119,11 @@ class AdvancedUnlockNotificationService : NotificationService() {
super.onDestroy()
}
class AdvancedUnlockReceiver(var removeKeyAction: () -> Unit): BroadcastReceiver() {
class DeviceUnlockReceiver(var removeKeyAction: () -> Unit): BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
intent.action?.let {
when (it) {
REMOVE_ADVANCED_UNLOCK_KEY_ACTION -> {
REMOVE_DEVICE_UNLOCK_KEY_ACTION -> {
removeKeyAction.invoke()
}
}
@@ -132,13 +132,13 @@ class AdvancedUnlockNotificationService : NotificationService() {
}
companion object {
private const val CHANNEL_ADVANCED_UNLOCK_ID = "com.kunzisoft.keepass.notification.channel.unlock"
const val REMOVE_ADVANCED_UNLOCK_KEY_ACTION = "com.kunzisoft.keepass.REMOVE_ADVANCED_UNLOCK_KEY"
private const val CHANNEL_DEVICE_UNLOCK_ID = "com.kunzisoft.keepass.notification.channel.unlock"
const val REMOVE_DEVICE_UNLOCK_KEY_ACTION = "com.kunzisoft.keepass.REMOVE_DEVICE_UNLOCK_KEY"
// Only one service connection
fun bindService(context: Context, serviceConnection: ServiceConnection, flags: Int) {
context.bindService(Intent(context,
AdvancedUnlockNotificationService::class.java),
DeviceUnlockNotificationService::class.java),
serviceConnection,
flags)
}

View File

@@ -12,6 +12,7 @@ import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
import android.os.Build
import android.os.IBinder
import android.util.Log
import android.util.TypedValue
import android.widget.Toast
import androidx.core.app.NotificationCompat
@@ -105,7 +106,7 @@ abstract class NotificationService : Service() {
NotificationServiceType.ATTACHMENT -> FOREGROUND_SERVICE_TYPE_DATA_SYNC
NotificationServiceType.CLIPBOARD -> foregroundServiceTimer
NotificationServiceType.KEYBOARD -> foregroundServiceTimer
NotificationServiceType.ADVANCED_UNLOCK -> foregroundServiceTimer
NotificationServiceType.DEVICE_UNLOCK -> foregroundServiceTimer
}
startForeground(notificationId, builder.build(), foregroundType)
} else {
@@ -156,11 +157,21 @@ abstract class NotificationService : Service() {
mReset = true
}
override fun onDestroy() {
override fun onTimeout(startId: Int, fgsType: Int) {
super.onTimeout(startId, fgsType)
Log.e(javaClass::class.simpleName, "The service took too long to execute")
cancelNotification()
stopSelf()
}
protected fun cancelNotification() {
mTimerJob?.cancel()
mTimerJob = null
notificationManager?.cancel(notificationId)
}
override fun onDestroy() {
cancelNotification()
super.onDestroy()
}

View File

@@ -5,5 +5,5 @@ enum class NotificationServiceType {
ATTACHMENT,
CLIPBOARD,
KEYBOARD,
ADVANCED_UNLOCK
DEVICE_UNLOCK
}

View File

@@ -23,15 +23,15 @@ import android.os.Bundle
import androidx.fragment.app.Fragment
class AdvancedUnlockSettingsActivity : SettingsActivity() {
class DeviceUnlockSettingsActivity : SettingsActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mTimeoutEnable = false
setTitle(NestedSettingsFragment.Screen.ADVANCED_UNLOCK)
setTitle(NestedSettingsFragment.Screen.DEVICE_UNLOCK)
}
override fun retrieveMainFragment(): Fragment {
return NestedSettingsFragment.newInstance(NestedSettingsFragment.Screen.ADVANCED_UNLOCK)
return NestedSettingsFragment.newInstance(NestedSettingsFragment.Screen.DEVICE_UNLOCK)
}
}

View File

@@ -84,9 +84,9 @@ class MainPreferenceFragment : PreferenceFragmentCompat() {
}
}
findPreference<Preference>(getString(R.string.settings_advanced_unlock_key))?.apply {
findPreference<Preference>(getString(R.string.settings_device_unlock_key))?.apply {
onPreferenceClickListener = Preference.OnPreferenceClickListener {
mCallback?.onNestedPreferenceSelected(NestedSettingsFragment.Screen.ADVANCED_UNLOCK)
mCallback?.onNestedPreferenceSelected(NestedSettingsFragment.Screen.DEVICE_UNLOCK)
false
}
}

View File

@@ -41,7 +41,7 @@ import com.kunzisoft.keepass.activities.dialogs.ProFeatureDialogFragment
import com.kunzisoft.keepass.activities.dialogs.UnavailableFeatureDialogFragment
import com.kunzisoft.keepass.activities.stylish.Stylish
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.biometric.AdvancedUnlockManager
import com.kunzisoft.keepass.biometric.DeviceUnlockManager
import com.kunzisoft.keepass.education.Education
import com.kunzisoft.keepass.icons.IconPackChooser
import com.kunzisoft.keepass.services.ClipboardEntryNotificationService
@@ -66,8 +66,8 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
Screen.FORM_FILLING -> {
onCreateFormFillingPreference(rootKey)
}
Screen.ADVANCED_UNLOCK -> {
onCreateAdvancedUnlockPreferences(rootKey)
Screen.DEVICE_UNLOCK -> {
onCreateDeviceUnlockPreferences(rootKey)
}
Screen.APPEARANCE -> {
onCreateAppearancePreferences(rootKey)
@@ -240,18 +240,18 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
}
}
private fun onCreateAdvancedUnlockPreferences(rootKey: String?) {
setPreferencesFromResource(R.xml.preferences_advanced_unlock, rootKey)
private fun onCreateDeviceUnlockPreferences(rootKey: String?) {
setPreferencesFromResource(R.xml.preferences_device_unlock, rootKey)
activity?.let { activity ->
val biometricUnlockEnablePreference: TwoStatePreference? = findPreference(getString(R.string.biometric_unlock_enable_key))
val deviceCredentialUnlockEnablePreference: TwoStatePreference? = findPreference(getString(R.string.device_credential_unlock_enable_key))
val autoOpenPromptPreference: TwoStatePreference? = findPreference(getString(R.string.biometric_auto_open_prompt_key))
val tempAdvancedUnlockPreference: TwoStatePreference? = findPreference(getString(R.string.temp_advanced_unlock_enable_key))
val tempDeviceUnlockPreference: TwoStatePreference? = findPreference(getString(R.string.temp_device_unlock_enable_key))
val biometricUnlockSupported = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
AdvancedUnlockManager.biometricUnlockSupported(activity)
DeviceUnlockManager.biometricUnlockSupported(activity)
} else false
biometricUnlockEnablePreference?.apply {
// False if under Marshmallow
@@ -272,7 +272,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
warningMessage(activity, keystoreWarning = false, deleteKeys = true) {
biometricUnlockEnablePreference.isChecked = false
autoOpenPromptPreference?.isEnabled = deviceCredentialChecked
tempAdvancedUnlockPreference?.isEnabled = deviceCredentialChecked
tempDeviceUnlockPreference?.isEnabled = deviceCredentialChecked
}
} else {
if (deviceCredentialChecked) {
@@ -286,7 +286,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
warningMessage(activity, keystoreWarning = true, deleteKeys = false) {
biometricUnlockEnablePreference.isChecked = true
autoOpenPromptPreference?.isEnabled = true
tempAdvancedUnlockPreference?.isEnabled = true
tempDeviceUnlockPreference?.isEnabled = true
}
}
}
@@ -296,7 +296,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
}
val deviceCredentialUnlockSupported = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
AdvancedUnlockManager.deviceCredentialUnlockSupported(activity)
DeviceUnlockManager.deviceCredentialUnlockSupported(activity)
} else false
deviceCredentialUnlockEnablePreference?.apply {
// Biometric unlock already checked
@@ -319,7 +319,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
warningMessage(activity, keystoreWarning = false, deleteKeys = true) {
deviceCredentialUnlockEnablePreference.isChecked = false
autoOpenPromptPreference?.isEnabled = biometricChecked
tempAdvancedUnlockPreference?.isEnabled = biometricChecked
tempDeviceUnlockPreference?.isEnabled = biometricChecked
}
} else {
if (biometricChecked) {
@@ -333,7 +333,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
warningMessage(activity, keystoreWarning = true, deleteKeys = false) {
deviceCredentialUnlockEnablePreference.isChecked = true
autoOpenPromptPreference?.isEnabled = true
tempAdvancedUnlockPreference?.isEnabled = true
tempDeviceUnlockPreference?.isEnabled = true
}
}
}
@@ -344,13 +344,13 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
autoOpenPromptPreference?.isEnabled = biometricUnlockEnablePreference?.isChecked == true
|| deviceCredentialUnlockEnablePreference?.isChecked == true
tempAdvancedUnlockPreference?.isEnabled = biometricUnlockEnablePreference?.isChecked == true
tempDeviceUnlockPreference?.isEnabled = biometricUnlockEnablePreference?.isChecked == true
|| deviceCredentialUnlockEnablePreference?.isChecked == true
tempAdvancedUnlockPreference?.setOnPreferenceClickListener {
tempAdvancedUnlockPreference.isChecked = !tempAdvancedUnlockPreference.isChecked
tempDeviceUnlockPreference?.setOnPreferenceClickListener {
tempDeviceUnlockPreference.isChecked = !tempDeviceUnlockPreference.isChecked
warningMessage(activity, keystoreWarning = false, deleteKeys = true) {
tempAdvancedUnlockPreference.isChecked = !tempAdvancedUnlockPreference.isChecked
tempDeviceUnlockPreference.isChecked = !tempDeviceUnlockPreference.isChecked
}
true
}
@@ -366,8 +366,8 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
}
}
findPreference<Preference>(getString(R.string.advanced_unlock_explanation_key))?.setOnPreferenceClickListener {
context?.openUrl(R.string.advanced_unlock_explanation_url)
findPreference<Preference>(getString(R.string.device_unlock_explanation_key))?.setOnPreferenceClickListener {
context?.openUrl(R.string.device_unlock_explanation_url)
false
}
}
@@ -378,14 +378,14 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
validate: (()->Unit)? = null) {
var message = ""
if (keystoreWarning) {
message += resources.getString(R.string.advanced_unlock_prompt_store_credential_message)
message += "\n\n" + resources.getString(R.string.advanced_unlock_keystore_warning)
message += resources.getString(R.string.device_unlock_prompt_store_credential_message)
message += "\n\n" + resources.getString(R.string.device_unlock_keystore_warning)
}
if (keystoreWarning && deleteKeys) {
message += "\n\n"
}
if (deleteKeys) {
message += resources.getString(R.string.advanced_unlock_delete_all_key_warning)
message += resources.getString(R.string.device_unlock_delete_all_key_warning)
}
warningAlertDialog = AlertDialog.Builder(activity)
.setMessage(message)
@@ -395,7 +395,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
validate?.invoke()
warningAlertDialog?.setOnDismissListener(null)
if (deleteKeys && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
AdvancedUnlockManager.deleteAllEntryKeysInKeystoreForBiometric(activity)
DeviceUnlockManager.deleteAllEntryKeysInKeystoreForBiometric(activity)
}
}
.setNegativeButton(resources.getString(android.R.string.cancel)
@@ -509,7 +509,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
when (preference.key) {
getString(R.string.app_timeout_key),
getString(R.string.clipboard_timeout_key),
getString(R.string.temp_advanced_unlock_timeout_key) -> {
getString(R.string.temp_device_unlock_timeout_key) -> {
dialogFragment = DurationDialogFragmentCompat.newInstance(preference.key)
}
else -> otherDialogFragment = true

View File

@@ -30,7 +30,7 @@ import com.kunzisoft.keepass.activities.dialogs.UnderDevelopmentFeatureDialogFra
abstract class NestedSettingsFragment : PreferenceFragmentCompat() {
enum class Screen {
APPLICATION, FORM_FILLING, ADVANCED_UNLOCK, APPEARANCE, DATABASE, DATABASE_SECURITY, DATABASE_MASTER_KEY
APPLICATION, FORM_FILLING, DEVICE_UNLOCK, APPEARANCE, DATABASE, DATABASE_SECURITY, DATABASE_MASTER_KEY
}
fun getScreen(): Screen {
@@ -66,7 +66,7 @@ abstract class NestedSettingsFragment : PreferenceFragmentCompat() {
val fragment: NestedSettingsFragment = when (key) {
Screen.APPLICATION,
Screen.FORM_FILLING,
Screen.ADVANCED_UNLOCK,
Screen.DEVICE_UNLOCK,
Screen.APPEARANCE -> NestedAppSettingsFragment()
Screen.DATABASE,
Screen.DATABASE_SECURITY,
@@ -83,7 +83,7 @@ abstract class NestedSettingsFragment : PreferenceFragmentCompat() {
return when (key) {
Screen.APPLICATION -> resources.getString(R.string.menu_app_settings)
Screen.FORM_FILLING -> resources.getString(R.string.menu_form_filling_settings)
Screen.ADVANCED_UNLOCK -> resources.getString(R.string.menu_advanced_unlock_settings)
Screen.DEVICE_UNLOCK -> resources.getString(R.string.menu_device_unlock_settings)
Screen.APPEARANCE -> resources.getString(R.string.menu_appearance_settings)
Screen.DATABASE -> resources.getString(R.string.menu_database_settings)
Screen.DATABASE_SECURITY -> resources.getString(R.string.menu_security_settings)

View File

@@ -29,7 +29,7 @@ import androidx.preference.PreferenceManager
import com.kunzisoft.keepass.BuildConfig
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.stylish.Stylish
import com.kunzisoft.keepass.biometric.AdvancedUnlockManager
import com.kunzisoft.keepass.biometric.DeviceUnlockManager
import com.kunzisoft.keepass.database.element.SortNodeEnum
import com.kunzisoft.keepass.database.search.SearchParameters
import com.kunzisoft.keepass.education.Education
@@ -460,10 +460,10 @@ object PreferencesUtil {
?: TimeoutHelper.DEFAULT_TIMEOUT
}
fun getAdvancedUnlockTimeout(context: Context): Long {
fun getDeviceUnlockTimeout(context: Context): Long {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getString(context.getString(R.string.temp_advanced_unlock_timeout_key),
context.getString(R.string.temp_advanced_unlock_timeout_default))?.toLong()
return prefs.getString(context.getString(R.string.temp_device_unlock_timeout_key),
context.getString(R.string.temp_device_unlock_timeout_default))?.toLong()
?: TimeoutHelper.DEFAULT_TIMEOUT
}
@@ -503,7 +503,7 @@ object PreferencesUtil {
context.resources.getBoolean(R.bool.enable_screenshot_mode_key_default))
}
fun isAdvancedUnlockEnable(context: Context): Boolean {
fun isDeviceUnlockEnable(context: Context): Boolean {
return isBiometricUnlockEnable(context) || isDeviceCredentialUnlockEnable(context)
}
@@ -512,7 +512,7 @@ object PreferencesUtil {
return prefs.getBoolean(context.getString(R.string.biometric_unlock_enable_key),
context.resources.getBoolean(R.bool.biometric_unlock_enable_default))
&& (if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
AdvancedUnlockManager.biometricUnlockSupported(context)
DeviceUnlockManager.biometricUnlockSupported(context)
} else {
false
})
@@ -526,13 +526,13 @@ object PreferencesUtil {
&& !isBiometricUnlockEnable(context)
}
fun isTempAdvancedUnlockEnable(context: Context): Boolean {
fun isTempDeviceUnlockEnable(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.temp_advanced_unlock_enable_key),
context.resources.getBoolean(R.bool.temp_advanced_unlock_enable_default))
return prefs.getBoolean(context.getString(R.string.temp_device_unlock_enable_key),
context.resources.getBoolean(R.bool.temp_device_unlock_enable_default))
}
fun isAdvancedUnlockPromptAutoOpenEnable(context: Context): Boolean {
fun isDeviceUnlockPromptAutoOpenEnable(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.biometric_auto_open_prompt_key),
context.resources.getBoolean(R.bool.biometric_auto_open_prompt_default))
@@ -618,12 +618,6 @@ object PreferencesUtil {
context.resources.getBoolean(R.bool.allow_no_password_default))
}
fun enableReadOnlyDatabase(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.enable_read_only_key),
context.resources.getBoolean(R.bool.enable_read_only_default))
}
fun deletePasswordAfterConnexionAttempt(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.delete_entered_password_key),
@@ -804,7 +798,6 @@ object PreferencesUtil {
when (name) {
context.getString(R.string.allow_no_password_key) -> editor.putBoolean(name, value.toBoolean())
context.getString(R.string.delete_entered_password_key) -> editor.putBoolean(name, value.toBoolean())
context.getString(R.string.enable_read_only_key) -> editor.putBoolean(name, value.toBoolean())
context.getString(R.string.enable_auto_save_database_key) -> editor.putBoolean(name, value.toBoolean())
context.getString(R.string.enable_keep_screen_on_key) -> editor.putBoolean(name, value.toBoolean())
context.getString(R.string.auto_focus_search_key) -> editor.putBoolean(name, value.toBoolean())
@@ -821,8 +814,8 @@ object PreferencesUtil {
context.getString(R.string.biometric_unlock_enable_key) -> editor.putBoolean(name, value.toBoolean())
context.getString(R.string.device_credential_unlock_enable_key) -> editor.putBoolean(name, value.toBoolean())
context.getString(R.string.biometric_auto_open_prompt_key) -> editor.putBoolean(name, value.toBoolean())
context.getString(R.string.temp_advanced_unlock_enable_key) -> editor.putBoolean(name, value.toBoolean())
context.getString(R.string.temp_advanced_unlock_timeout_key) -> editor.putString(name, value.toLong().toString())
context.getString(R.string.temp_device_unlock_enable_key) -> editor.putBoolean(name, value.toBoolean())
context.getString(R.string.temp_device_unlock_timeout_key) -> editor.putString(name, value.toLong().toString())
context.getString(R.string.magic_keyboard_key) -> editor.putBoolean(name, value.toBoolean())
context.getString(R.string.clipboard_notifications_key) -> editor.putBoolean(name, value.toBoolean())

View File

@@ -70,8 +70,12 @@ open class SettingsActivity
// To apply navigation bar with background color
/* TODO Settings nav bar
setTransparentNavigationBar {
coordinatorLayout?.applyWindowInsets(WindowInsetPosition.TOP)
footer?.applyWindowInsets(WindowInsetPosition.BOTTOM)
coordinatorLayout?.applyWindowInsets(EnumSet.of(
WindowInsetPosition.TOP_MARGINS,
WindowInsetPosition.BOTTOM_MARGINS,
WindowInsetPosition.START_MARGINS,
WindowInsetPosition.END_MARGINS,
))
}*/
mExternalFileHelper = ExternalFileHelper(this)

View File

@@ -65,7 +65,6 @@ object TimeoutHelper {
(context.applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager?)?.let { alarmManager ->
val triggerTime = System.currentTimeMillis() + timeout
Log.d(TAG, "TimeoutHelper start")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
&& !alarmManager.canScheduleExactAlarms()) {
alarmManager.set(
@@ -80,13 +79,6 @@ object TimeoutHelper {
getLockPendingIntent(context)
)
}
} else {
alarmManager.set(
AlarmManager.RTC,
triggerTime,
getLockPendingIntent(context)
)
}
}
}
}

View File

@@ -31,6 +31,7 @@ import android.os.Build
import android.util.Log
import androidx.core.content.ContextCompat
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.app.AppLifecycleObserver
import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.magikeyboard.MagikeyboardService
import com.kunzisoft.keepass.services.ClipboardEntryNotificationService
@@ -76,7 +77,6 @@ class LockReceiver(private var lockAction: () -> Unit) : BroadcastReceiver() {
// Launch the effective action after a small time
val first: Long = System.currentTimeMillis() + context.getString(R.string.timeout_screen_off).toLong()
(context.getSystemService(ALARM_SERVICE) as AlarmManager?)?.let { alarmManager ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
&& !alarmManager.canScheduleExactAlarms()) {
alarmManager.set(
@@ -91,13 +91,6 @@ class LockReceiver(private var lockAction: () -> Unit) : BroadcastReceiver() {
lockPendingIntent
)
}
} else {
alarmManager.set(
AlarmManager.RTC_WAKEUP,
first,
lockPendingIntent
)
}
}
} else {
cancelLockPendingIntent(context)
@@ -105,6 +98,7 @@ class LockReceiver(private var lockAction: () -> Unit) : BroadcastReceiver() {
}
LOCK_ACTION -> {
lockAction.invoke()
AppLifecycleObserver.lockBackgroundEvent = false
if (PreferencesUtil.isKeyboardPreviousLockEnable(context)) {
backToPreviousKeyboardAction?.invoke()
} else {}

View File

@@ -67,7 +67,6 @@ object UriUtil {
readOnly: Boolean) {
try {
// try to persist read and write permissions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
contentResolver?.apply {
var readPermissionAllowed = false
var writePermissionAllowed = false
@@ -118,7 +117,6 @@ object UriUtil {
}
}
}
}
} catch (e: Exception) {
if (release)
Log.e(TAG, "Unable to release persistable URI permission", e)
@@ -140,7 +138,6 @@ object UriUtil {
}
fun Context.releaseAllUnnecessaryPermissionUris() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
applicationContext?.let { appContext ->
val fileDatabaseHistoryAction = FileDatabaseHistoryAction.getInstance(appContext)
fileDatabaseHistoryAction.getDatabaseFileList { databaseFileList ->
@@ -163,11 +160,9 @@ object UriUtil {
}
}
}
}
fun Intent.getUri(key: String): Uri? {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
val clipData = this.clipData
if (clipData != null) {
if (clipData.description.label == key) {
@@ -179,7 +174,6 @@ object UriUtil {
}
}
}
}
} catch (e: Exception) {
return this.getParcelableExtraCompat(key)
}

View File

@@ -25,13 +25,12 @@ import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.Button
import android.widget.LinearLayout
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
import com.kunzisoft.keepass.R
@RequiresApi(api = Build.VERSION_CODES.M)
class AdvancedUnlockInfoView @JvmOverloads constructor(context: Context,
class DeviceUnlockView @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0)
: LinearLayout(context, attrs, defStyle) {
@@ -40,12 +39,12 @@ class AdvancedUnlockInfoView @JvmOverloads constructor(context: Context,
init {
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater?
inflater?.inflate(R.layout.view_advanced_unlock, this)
inflater?.inflate(R.layout.view_device_unlock, this)
biometricButtonView = findViewById(R.id.biometric_button)
}
fun setIconViewClickListener(listener: OnClickListener?) {
fun setDeviceUnlockButtonViewClickListener(listener: OnClickListener?) {
biometricButtonView?.setOnClickListener(listener)
}
@@ -60,14 +59,4 @@ class AdvancedUnlockInfoView @JvmOverloads constructor(context: Context,
fun setTitle(@StringRes textId: Int) {
title = context.getString(textId)
}
fun setMessage(text: CharSequence) {
if (text.isNotEmpty())
Toast.makeText(context, text, Toast.LENGTH_LONG).show()
}
fun setMessage(@StringRes textId: Int) {
Toast.makeText(context, textId, Toast.LENGTH_LONG).show()
}
}

View File

@@ -53,9 +53,7 @@ class MainCredentialView @JvmOverloads constructor(context: Context,
private var checkboxHardwareView: CompoundButton
private var hardwareKeySelectionView: HardwareKeySelectionView
var onPasswordChecked: (CompoundButton.OnCheckedChangeListener)? = null
var onKeyFileChecked: (CompoundButton.OnCheckedChangeListener)? = null
var onHardwareKeyChecked: (CompoundButton.OnCheckedChangeListener)? = null
var onConditionToStoreCredentialChanged: ((CredentialStorage, verified: Boolean) -> Unit)? = null
var onValidateListener: (() -> Unit)? = null
private var mCredentialStorage: CredentialStorage = CredentialStorage.PASSWORD
@@ -103,24 +101,33 @@ class MainCredentialView @JvmOverloads constructor(context: Context,
handled
}
checkboxPasswordView.setOnCheckedChangeListener { view, checked ->
onPasswordChecked?.onCheckedChanged(view, checked)
checkboxPasswordView.setOnCheckedChangeListener { _, _ ->
onConditionToStoreCredentialChanged?.invoke(
mCredentialStorage,
conditionToStoreCredential()
)
}
checkboxKeyFileView.setOnCheckedChangeListener { view, checked ->
checkboxKeyFileView.setOnCheckedChangeListener { _, checked ->
if (checked) {
if (keyFileSelectionView.uri == null) {
checkboxKeyFileView.isChecked = false
}
}
onKeyFileChecked?.onCheckedChanged(view, checked)
onConditionToStoreCredentialChanged?.invoke(
mCredentialStorage,
conditionToStoreCredential()
)
}
checkboxHardwareView.setOnCheckedChangeListener { view, checked ->
checkboxHardwareView.setOnCheckedChangeListener { _, checked ->
if (checked) {
if (hardwareKeySelectionView.hardwareKey == null) {
checkboxHardwareView.isChecked = false
}
}
onHardwareKeyChecked?.onCheckedChanged(view, checked)
onConditionToStoreCredentialChanged?.invoke(
mCredentialStorage,
conditionToStoreCredential()
)
}
hardwareKeySelectionView.selectionListener = { _ ->

View File

@@ -20,7 +20,6 @@
package com.kunzisoft.keepass.view
import android.content.Context
import android.os.Build
import android.text.Spannable
import android.util.AttributeSet
import android.util.TypedValue
@@ -104,21 +103,17 @@ class PasswordTextEditFieldView @JvmOverloads constructor(context: Context,
id = passwordProgressViewId
layoutParams = (layoutParams as LayoutParams?)?.also {
it.addRule(LEFT_OF, actionImageButtonId)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.addRule(START_OF, actionImageButtonId)
}
}
}
mPasswordEntropyView.apply {
id = passwordEntropyViewId
layoutParams = (layoutParams as LayoutParams?)?.also {
it.addRule(ALIGN_RIGHT, passwordProgressViewId)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.addRule(ALIGN_END, passwordProgressViewId)
}
}
}
}
private fun getEntropyStrength(passwordText: String) {
mPasswordEntropyCalculator.getEntropyStrength(passwordText) { entropyStrength ->

View File

@@ -123,7 +123,6 @@ class TemplateEditView @JvmOverloads constructor(context: Context,
setMaxChars(templateAttribute.options.getNumberChars())
setMaxLines(templateAttribute.options.getNumberLines())
setActionClick(templateAttribute, field, this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (field.protectedValue.isProtected) {
textDirection = TEXT_DIRECTION_LTR
}
@@ -133,7 +132,6 @@ class TemplateEditView @JvmOverloads constructor(context: Context,
}
}
}
}
override fun buildListItemsView(templateAttribute: TemplateAttribute,
field: Field): TextSelectFieldView? {

View File

@@ -63,9 +63,7 @@ class TemplateView @JvmOverloads constructor(context: Context,
// Here the value is often empty
if (field.protectedValue.isProtected) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
textDirection = TEXT_DIRECTION_LTR
}
if (mFirstTimeAskAllowCopyProtectedFields) {
setCopyButtonState(TextFieldView.ButtonState.DEACTIVATE)
setCopyButtonClickListener { _, _ ->
@@ -179,9 +177,7 @@ class TemplateView @JvmOverloads constructor(context: Context,
otpElement.type.name,
ProtectedString(false, otpElement.token)))
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
textDirection = TEXT_DIRECTION_LTR
}
mLastOtpTokenView = this
mOtpRunnable = Runnable {
if (otpElement.shouldRefreshToken()) {

View File

@@ -51,9 +51,7 @@ open class TextEditFieldView @JvmOverloads constructor(context: Context,
imeOptions = EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING
importantForAutofill = IMPORTANT_FOR_AUTOFILL_NO
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO
}
maxLines = 1
}
private var actionImageButton = AppCompatImageButton(
@@ -70,11 +68,9 @@ open class TextEditFieldView @JvmOverloads constructor(context: Context,
resources.displayMetrics
).toInt()
it.addRule(ALIGN_PARENT_RIGHT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.addRule(ALIGN_PARENT_END)
}
}
visibility = View.GONE
visibility = GONE
contentDescription = context.getString(R.string.menu_edit)
}
@@ -91,11 +87,9 @@ open class TextEditFieldView @JvmOverloads constructor(context: Context,
id = labelViewId
layoutParams = (layoutParams as LayoutParams?)?.also {
it.addRule(LEFT_OF, actionImageButtonId)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.addRule(START_OF, actionImageButtonId)
}
}
}
valueView.apply {
id = valueViewId
}
@@ -192,7 +186,7 @@ open class TextEditFieldView @JvmOverloads constructor(context: Context,
actionImageButton.setImageDrawable(ContextCompat.getDrawable(context, it))
}
actionImageButton.setOnClickListener(onActionClickListener)
actionImageButton.visibility = if (onActionClickListener == null) View.GONE else View.VISIBLE
actionImageButton.visibility = if (onActionClickListener == null) GONE else VISIBLE
}
override var isFieldVisible: Boolean

View File

@@ -63,13 +63,12 @@ open class TextFieldView @JvmOverloads constructor(context: Context,
4f,
resources.displayMetrics
).toInt()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.marginStart = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
4f,
resources.displayMetrics
).toInt()
}
}
}
protected val valueView = AppCompatTextView(context).apply {
@@ -88,14 +87,12 @@ open class TextFieldView @JvmOverloads constructor(context: Context,
8f,
resources.displayMetrics
).toInt()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.marginStart = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
8f,
resources.displayMetrics
).toInt()
}
}
setTextIsSelectable(true)
}
private var showButton = AppCompatImageButton(
@@ -128,24 +125,22 @@ open class TextFieldView @JvmOverloads constructor(context: Context,
id = copyButtonId
layoutParams = (layoutParams as LayoutParams?)?.also {
it.addRule(ALIGN_PARENT_RIGHT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.addRule(ALIGN_PARENT_END)
}
}
}
showButton.apply {
id = showButtonId
layoutParams = (layoutParams as LayoutParams?)?.also {
if (copyButton.isVisible) {
it.addRule(LEFT_OF, copyButtonId)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.addRule(START_OF, copyButtonId)
}
} else {
it.addRule(ALIGN_PARENT_RIGHT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.addRule(ALIGN_PARENT_END)
}
}
}
}
@@ -153,18 +148,14 @@ open class TextFieldView @JvmOverloads constructor(context: Context,
id = labelViewId
layoutParams = (layoutParams as LayoutParams?)?.also {
it.addRule(LEFT_OF, showButtonId)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.addRule(START_OF, showButtonId)
}
}
}
valueView.apply {
id = valueViewId
layoutParams = (layoutParams as LayoutParams?)?.also {
it.addRule(LEFT_OF, showButtonId)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.addRule(START_OF, showButtonId)
}
it.addRule(BELOW, labelViewId)
}
}

View File

@@ -10,7 +10,12 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.*
import android.widget.AdapterView
import android.widget.BaseAdapter
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.Spinner
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.appcompat.widget.AppCompatImageButton
import androidx.core.content.ContextCompat
@@ -51,9 +56,7 @@ class TextSelectFieldView @JvmOverloads constructor(context: Context,
imeOptions = EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING
importantForAutofill = IMPORTANT_FOR_AUTOFILL_NO
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO
}
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_arrow_down_white_24dp)
?.apply {
mutate().colorFilter = BlendModeColorFilterCompat
@@ -65,14 +68,12 @@ class TextSelectFieldView @JvmOverloads constructor(context: Context,
drawable,
null
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
setCompoundDrawablesRelativeWithIntrinsicBounds(
null,
null,
drawable,
null
)
}
isFocusable = false
inputType = InputType.TYPE_NULL
maxLines = 1
@@ -94,10 +95,8 @@ class TextSelectFieldView @JvmOverloads constructor(context: Context,
resources.displayMetrics
).toInt()
it.addRule(ALIGN_PARENT_RIGHT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it.addRule(ALIGN_PARENT_END)
}
}
visibility = View.GONE
contentDescription = context.getString(R.string.menu_edit)
}
@@ -132,18 +131,14 @@ class TextSelectFieldView @JvmOverloads constructor(context: Context,
id = labelViewId
layoutParams = (layoutParams as LayoutParams?).also {
it?.addRule(LEFT_OF, actionImageButtonId)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it?.addRule(START_OF, actionImageButtonId)
}
}
}
valueSpinnerView.apply {
id = valueViewId
layoutParams = (layoutParams as LayoutParams?).also {
it?.addRule(LEFT_OF, actionImageButtonId)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
it?.addRule(START_OF, actionImageButtonId)
}
it?.addRule(BELOW, labelViewId)
}
}

View File

@@ -24,7 +24,6 @@ import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PorterDuff
@@ -58,7 +57,6 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.forEach
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.core.view.updatePaddingRelative
import com.google.android.material.appbar.CollapsingToolbarLayout
import com.google.android.material.snackbar.Snackbar
@@ -66,6 +64,7 @@ import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.helper.getLocalizedMessage
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ActionRunnable
import java.util.EnumSet
/**
@@ -234,11 +233,7 @@ fun View.updateLockPaddingStart() {
R.dimen.hidden_lock_button_size
}
).let { lockPadding ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
updatePaddingRelative(lockPadding)
} else {
updatePadding(lockPadding)
}
}
}
@@ -308,10 +303,9 @@ fun CollapsingToolbarLayout.changeTitleColor(color: Int) {
invalidate()
}
@Suppress("DEPRECATION")
fun Activity.setTransparentNavigationBar(applyToStatusBar: Boolean = false, applyWindowInsets: () -> Unit) {
// Only in portrait
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1
&& resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
WindowCompat.setDecorFitsSystemWindows(window, false)
window.navigationBarColor = ContextCompat.getColor(this, R.color.surface_selector)
if (applyToStatusBar) {
@@ -327,7 +321,7 @@ fun Activity.setTransparentNavigationBar(applyToStatusBar: Boolean = false, appl
/**
* Apply a margin to a view to fix the window inset
*/
fun View.applyWindowInsets(position: WindowInsetPosition = WindowInsetPosition.BOTTOM) {
fun View.applyWindowInsets(positions: EnumSet<WindowInsetPosition>) {
ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets ->
var consumed = false
@@ -343,52 +337,78 @@ fun View.applyWindowInsets(position: WindowInsetPosition = WindowInsetPosition.B
}
}
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
when (position) {
WindowInsetPosition.TOP -> {
if (view.layoutParams is ViewGroup.MarginLayoutParams) {
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()
or WindowInsetsCompat.Type.displayCutout()
or WindowInsetsCompat.Type.ime())
val isRtl = layoutDirection == View.LAYOUT_DIRECTION_RTL
val wantTopMargins = positions.contains(WindowInsetPosition.TOP_MARGINS)
val wantBottomMargins = positions.contains(WindowInsetPosition.BOTTOM_MARGINS)
val wantStartMargins = positions.contains(WindowInsetPosition.START_MARGINS)
val wantEndMargins = positions.contains(WindowInsetPosition.END_MARGINS)
if (view.layoutParams is ViewGroup.MarginLayoutParams
&& (wantTopMargins || wantBottomMargins || wantStartMargins || wantEndMargins)) {
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
if (wantTopMargins) {
topMargin = insets.top
}
}
}
WindowInsetPosition.LEGIT_TOP -> {
if (view.layoutParams is ViewGroup.MarginLayoutParams) {
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = 0
}
}
}
WindowInsetPosition.BOTTOM -> {
if (view.layoutParams is ViewGroup.MarginLayoutParams) {
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
if (wantBottomMargins) {
bottomMargin = insets.bottom
}
if (wantStartMargins) {
if (isRtl) {
rightMargin = insets.right
} else {
leftMargin = insets.left
}
}
WindowInsetPosition.BOTTOM_IME -> {
val imeHeight = windowInsets.getInsets(WindowInsetsCompat.Type.ime()).bottom
if (view.layoutParams is ViewGroup.MarginLayoutParams) {
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = if (imeHeight > 1) 0 else insets.bottom
}
}
}
WindowInsetPosition.TOP_BOTTOM_IME -> {
val imeHeight = windowInsets.getInsets(WindowInsetsCompat.Type.ime()).bottom
if (view.layoutParams is ViewGroup.MarginLayoutParams) {
view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top
bottomMargin = if (imeHeight > 1) imeHeight else 0
if (wantEndMargins) {
if (isRtl) {
leftMargin = insets.left
} else {
rightMargin = insets.right
}
}
}
}
val wantTopPadding = positions.contains(WindowInsetPosition.TOP_PADDING)
val wantBottomPadding = positions.contains(WindowInsetPosition.BOTTOM_PADDING)
val wantStartPadding = positions.contains(WindowInsetPosition.START_PADDING)
val wantEndPadding = positions.contains(WindowInsetPosition.END_PADDING)
if (wantTopPadding || wantBottomPadding || wantStartPadding || wantEndPadding) {
val topPadding = if (wantTopPadding) insets.top else 0
val bottomPadding = if (wantBottomPadding) insets.bottom else 0
var leftPadding = 0
var rightPadding = 0
if (wantStartPadding) {
if (isRtl) {
rightPadding = insets.right
} else {
leftPadding = insets.left
}
}
if (wantEndPadding) {
if (isRtl) {
leftPadding = insets.left
} else {
rightPadding = insets.right
}
}
setPadding(leftPadding, topPadding, rightPadding, bottomPadding)
}
// If any of the children consumed the insets, return an appropriate value
if (consumed) WindowInsetsCompat.CONSUMED else windowInsets
}
}
enum class WindowInsetPosition {
TOP, BOTTOM, LEGIT_TOP, BOTTOM_IME, TOP_BOTTOM_IME
TOP_MARGINS, BOTTOM_MARGINS, START_MARGINS, END_MARGINS,
TOP_PADDING, BOTTOM_PADDING, START_PADDING, END_PADDING,
}

View File

@@ -1,32 +0,0 @@
package com.kunzisoft.keepass.viewmodels
import android.net.Uri
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
class AdvancedUnlockViewModel : ViewModel() {
var allowAutoOpenBiometricPrompt : Boolean = true
var deviceCredentialAuthSucceeded: Boolean? = null
val onInitAdvancedUnlockModeRequested : LiveData<Void?> get() = _onInitAdvancedUnlockModeRequested
private val _onInitAdvancedUnlockModeRequested = SingleLiveEvent<Void?>()
val onUnlockAvailabilityCheckRequested : LiveData<Void?> get() = _onUnlockAvailabilityCheckRequested
private val _onUnlockAvailabilityCheckRequested = SingleLiveEvent<Void?>()
val onDatabaseFileLoaded : LiveData<Uri?> get() = _onDatabaseFileLoaded
private val _onDatabaseFileLoaded = SingleLiveEvent<Uri?>()
fun initAdvancedUnlockMode() {
_onInitAdvancedUnlockModeRequested.call()
}
fun checkUnlockAvailability() {
_onUnlockAvailabilityCheckRequested.call()
}
fun databaseFileLoaded(databaseUri: Uri?) {
_onDatabaseFileLoaded.value = databaseUri
}
}

View File

@@ -0,0 +1,483 @@
package com.kunzisoft.keepass.viewmodels
import android.app.Application
import android.net.Uri
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.kunzisoft.keepass.app.AppLifecycleObserver
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
import com.kunzisoft.keepass.biometric.DeviceUnlockCryptoPrompt
import com.kunzisoft.keepass.biometric.DeviceUnlockCryptoPromptType
import com.kunzisoft.keepass.biometric.DeviceUnlockManager
import com.kunzisoft.keepass.biometric.DeviceUnlockMode
import com.kunzisoft.keepass.database.exception.UnknownDatabaseLocationException
import com.kunzisoft.keepass.model.CipherDecryptDatabase
import com.kunzisoft.keepass.model.CipherEncryptDatabase
import com.kunzisoft.keepass.model.CredentialStorage
import com.kunzisoft.keepass.settings.PreferencesUtil
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.crypto.Cipher
@RequiresApi(Build.VERSION_CODES.M)
class DeviceUnlockViewModel(application: Application): AndroidViewModel(application) {
private var cipherDatabase: CipherEncryptDatabase? = null
private var isConditionToStoreCredentialVerified: Boolean = false
private var deviceUnlockManager: DeviceUnlockManager? = null
private var databaseUri: Uri? = null
private var mCipherJob: Job? = null
private var deviceUnlockMode = DeviceUnlockMode.BIOMETRIC_UNAVAILABLE
var cryptoPrompt: DeviceUnlockCryptoPrompt? = null
private set
private var isAutoOpenBiometricPromptAllowed = true
private var cryptoPromptShowPending: Boolean = false
// TODO Retrieve credential storage from app database
var credentialDatabaseStorage: CredentialStorage = CredentialStorage.DEFAULT
val cipherDatabaseAction = CipherDatabaseAction.getInstance(getApplication())
private var cipherDatabaseListener = object: CipherDatabaseAction.CipherDatabaseListener {
override fun onCipherDatabaseRetrieved(
databaseUri: Uri,
cipherDatabase: CipherEncryptDatabase?
) {
if (databaseUri == this@DeviceUnlockViewModel.databaseUri) {
cipherDatabase?.let {
this@DeviceUnlockViewModel.cipherDatabase = it
checkUnlockAvailability()
} ?: deleteEncryptedDatabaseKey()
}
}
override fun onCipherDatabaseAddedOrUpdated(cipherDatabase: CipherEncryptDatabase) {
if (cipherDatabase.databaseUri == this@DeviceUnlockViewModel.databaseUri) {
this@DeviceUnlockViewModel.cipherDatabase = cipherDatabase
checkUnlockAvailability()
}
}
override fun onCipherDatabaseDeleted(databaseUri: Uri) {
if (databaseUri == this@DeviceUnlockViewModel.databaseUri) {
this@DeviceUnlockViewModel.cipherDatabase = null
checkUnlockAvailability()
}
}
override fun onAllCipherDatabasesDeleted() {
this@DeviceUnlockViewModel.cipherDatabase = null
checkUnlockAvailability()
}
override fun onCipherDatabaseCleared() {
this@DeviceUnlockViewModel.cipherDatabase = null
closeBiometricPrompt()
checkUnlockAvailability()
}
}
private val _uiState = MutableStateFlow(DeviceUnlockState())
val uiState: StateFlow<DeviceUnlockState> = _uiState
init {
AppLifecycleObserver.appJustLaunched
.onEach {
isAutoOpenBiometricPromptAllowed = true
checkUnlockAvailability()
}
.launchIn(viewModelScope)
cipherDatabaseAction.registerDatabaseListener(cipherDatabaseListener)
}
private fun cancelAndLaunchCipherJob(
coroutineExceptionHandler: CoroutineExceptionHandler = CoroutineExceptionHandler { _, e ->
setException(e)
},
block: suspend () -> Unit
) {
mCipherJob?.cancel()
mCipherJob = viewModelScope.launch(coroutineExceptionHandler) {
block()
}
}
fun checkConditionToStoreCredential(condition: Boolean) {
isConditionToStoreCredentialVerified = condition
checkUnlockAvailability()
}
/**
* Check unlock availability and change the current mode depending of device's state
*/
fun checkUnlockAvailability() {
if (PreferencesUtil.isBiometricUnlockEnable(getApplication())) {
// biometric not supported (by API level or hardware) so keep option hidden
// or manually disable
val biometricCanAuthenticate = DeviceUnlockManager.canAuthenticate(getApplication())
if (!PreferencesUtil.isDeviceUnlockEnable(getApplication())
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE) {
changeMode(DeviceUnlockMode.BIOMETRIC_UNAVAILABLE)
} else if (biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED) {
changeMode(DeviceUnlockMode.BIOMETRIC_SECURITY_UPDATE_REQUIRED)
} else {
// biometric is available but not configured, show icon but in disabled state with some information
if (biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
changeMode(DeviceUnlockMode.DEVICE_CREDENTIAL_OR_BIOMETRIC_NOT_CONFIGURED)
} else {
changeMode()
}
}
} else if (PreferencesUtil.isDeviceCredentialUnlockEnable(getApplication())) {
if (DeviceUnlockManager.isDeviceSecure(getApplication())) {
changeMode()
} else {
changeMode(DeviceUnlockMode.DEVICE_CREDENTIAL_OR_BIOMETRIC_NOT_CONFIGURED)
}
}
}
private fun changeMode() {
try {
if (isConditionToStoreCredentialVerified) {
// listen for encryption
changeMode(DeviceUnlockMode.STORE_CREDENTIAL)
} else if (cipherDatabase != null) {
// biometric available but no stored password found yet for this DB
// listen for decryption
changeMode(DeviceUnlockMode.EXTRACT_CREDENTIAL)
} else {
// wait for typing
changeMode(DeviceUnlockMode.WAIT_CREDENTIAL)
}
} catch (e: Exception) {
changeMode(DeviceUnlockMode.KEY_MANAGER_UNAVAILABLE)
setException(e)
}
}
private fun changeMode(deviceUnlockMode: DeviceUnlockMode) {
this.deviceUnlockMode = deviceUnlockMode
when (deviceUnlockMode) {
DeviceUnlockMode.STORE_CREDENTIAL -> initEncryptData()
DeviceUnlockMode.EXTRACT_CREDENTIAL -> initDecryptData()
else -> {}
}
_uiState.update { currentState ->
currentState.copy(
newDeviceUnlockMode = deviceUnlockMode,
allowDeviceUnlockMenu = cipherDatabase != null
&& deviceUnlockMode != DeviceUnlockMode.BIOMETRIC_UNAVAILABLE
&& deviceUnlockMode != DeviceUnlockMode.KEY_MANAGER_UNAVAILABLE
)
}
}
private fun connectDatabase(databaseUri: Uri) {
this.databaseUri = databaseUri
cipherDatabaseAction.getCipherDatabase(databaseUri)
}
private fun showPendingIfNecessary() {
// Reassign prompt state to open again if necessary
if (cryptoPrompt?.isOldCredentialOperation() != true
&& uiState.value.cryptoPromptState == DeviceUnlockPromptMode.IDLE_SHOW) {
cryptoPromptShowPending = true
}
}
private fun disconnectDatabase() {
this.databaseUri = null
this.cipherDatabase = null
clearPrompt()
changeMode(DeviceUnlockMode.BIOMETRIC_UNAVAILABLE)
}
fun connect(databaseUri: Uri?) {
Log.d(TAG, "Connect to device unlock")
// To get device credential unlock result, only if same database uri
if (databaseUri != null
&& PreferencesUtil.isDeviceUnlockEnable(getApplication())) {
if (databaseUri != this.databaseUri) {
connectDatabase(databaseUri)
}
} else {
disconnectDatabase()
}
}
fun disconnect() {
Log.d(TAG, "Disconnect from device unlock")
showPendingIfNecessary()
disconnectDatabase()
}
fun onAuthenticationSucceeded() {
cryptoPrompt?.let { prompt ->
when (prompt.type) {
DeviceUnlockCryptoPromptType.CREDENTIAL_ENCRYPTION ->
retrieveCredentialForEncryption( prompt.cipher)
DeviceUnlockCryptoPromptType.CREDENTIAL_DECRYPTION ->
decryptCredential( prompt.cipher)
}
}
}
fun onAuthenticationSucceeded(
result: BiometricPrompt.AuthenticationResult
) {
cryptoPrompt?.type?.let { type ->
when (type) {
DeviceUnlockCryptoPromptType.CREDENTIAL_ENCRYPTION ->
retrieveCredentialForEncryption(result.cryptoObject?.cipher)
DeviceUnlockCryptoPromptType.CREDENTIAL_DECRYPTION ->
decryptCredential(result.cryptoObject?.cipher)
}
}
}
private fun retrieveCredentialForEncryption(cipher: Cipher?) {
_uiState.update { currentState ->
currentState.copy(
credentialRequiredCipher = cipher
)
}
}
fun encryptCredential(
credential: ByteArray,
cipher: Cipher?
) {
cancelAndLaunchCipherJob {
deviceUnlockManager?.encryptData(
value = credential,
cipher = cipher,
handleEncryptedResult = { encryptedValue, ivSpec ->
databaseUri?.let { databaseUri ->
onCredentialEncrypted(
CipherEncryptDatabase().apply {
this.databaseUri = databaseUri
this.credentialStorage = credentialDatabaseStorage
this.encryptedValue = encryptedValue
this.specParameters = ivSpec
}
)
} ?: throw UnknownDatabaseLocationException()
}
)
}
// Reinit credential storage request
_uiState.update { currentState ->
currentState.copy(
credentialRequiredCipher = null
)
}
}
fun decryptCredential(cipher: Cipher?) {
// retrieve the encrypted value from preferences
cancelAndLaunchCipherJob {
databaseUri?.let { databaseUri ->
cipherDatabase?.encryptedValue?.let { encryptedCredential ->
deviceUnlockManager?.decryptData(
encryptedValue = encryptedCredential,
cipher = cipher,
handleDecryptedResult = { decryptedValue ->
// Load database directly with password retrieve
onCredentialDecrypted(
CipherDecryptDatabase().apply {
this.databaseUri = databaseUri
this.credentialStorage = credentialDatabaseStorage
this.decryptedValue = decryptedValue
}
)
cipherDatabaseAction.resetCipherParameters(databaseUri)
}
)
} ?: deleteEncryptedDatabaseKey()
} ?: run {
throw UnknownDatabaseLocationException()
}
}
}
fun onCredentialEncrypted(cipherEncryptDatabase: CipherEncryptDatabase) {
_uiState.update { currentState ->
currentState.copy(
cipherEncryptDatabase = cipherEncryptDatabase
)
}
}
fun consumeCredentialEncrypted() {
_uiState.update { currentState ->
currentState.copy(
cipherEncryptDatabase = null
)
}
}
fun onCredentialDecrypted(cipherDecryptDatabase: CipherDecryptDatabase) {
_uiState.update { currentState ->
currentState.copy(
cipherDecryptDatabase = cipherDecryptDatabase
)
}
}
fun consumeCredentialDecrypted() {
_uiState.update { currentState ->
currentState.copy(
cipherDecryptDatabase = null
)
}
}
fun onPromptRequested(
cryptoPrompt: DeviceUnlockCryptoPrompt,
autoOpen: Boolean = false
) {
this@DeviceUnlockViewModel.cryptoPrompt = cryptoPrompt
if (cryptoPromptShowPending
|| (autoOpen && PreferencesUtil.isDeviceUnlockPromptAutoOpenEnable(getApplication())))
showPrompt()
}
fun showPrompt() {
AppLifecycleObserver.lockBackgroundEvent = true
isAutoOpenBiometricPromptAllowed = false
cryptoPromptShowPending = false
if (cryptoPrompt == null) {
checkUnlockAvailability()
}
_uiState.update { currentState ->
currentState.copy(
cryptoPromptState = DeviceUnlockPromptMode.SHOW
)
}
}
fun promptShown() {
_uiState.update { currentState ->
currentState.copy(
cryptoPromptState = DeviceUnlockPromptMode.IDLE_SHOW
)
}
}
fun setException(value: Throwable?) {
_uiState.update { currentState ->
currentState.copy(
exception = value
)
}
}
fun exceptionShown() {
_uiState.update { currentState ->
currentState.copy(
exception = null
)
}
}
private fun initEncryptData() {
cancelAndLaunchCipherJob {
deviceUnlockManager = DeviceUnlockManager(getApplication())
deviceUnlockManager?.initEncryptData { cryptoPrompt ->
onPromptRequested(cryptoPrompt)
} ?: throw Exception("Device unlock manager not initialized")
}
}
private fun initDecryptData() {
cancelAndLaunchCipherJob {
cipherDatabase?.let { cipherDb ->
deviceUnlockManager = DeviceUnlockManager(getApplication())
deviceUnlockManager?.initDecryptData(cipherDb.specParameters) { cryptoPrompt ->
onPromptRequested(
cryptoPrompt,
autoOpen = isAutoOpenBiometricPromptAllowed
)
} ?: throw Exception("Device unlock manager not initialized")
} ?: throw Exception("Cipher database not initialized")
}
}
fun deleteEncryptedDatabaseKey() {
closeBiometricPrompt()
databaseUri?.let { databaseUri ->
cipherDatabaseAction.deleteByDatabaseUri(databaseUri)
} ?: run {
checkUnlockAvailability()
}
_uiState.update { currentState ->
currentState.copy(
allowDeviceUnlockMenu = false
)
}
}
fun closeBiometricPrompt() {
_uiState.update { currentState ->
currentState.copy(
cryptoPromptState = DeviceUnlockPromptMode.CLOSE
)
}
}
fun biometricPromptClosed() {
_uiState.update { currentState ->
currentState.copy(
cryptoPromptState = DeviceUnlockPromptMode.IDLE_CLOSE
)
}
}
private fun clearPrompt() {
cryptoPrompt = null
deviceUnlockManager = null
}
fun clear() {
if (cryptoPrompt?.isOldCredentialOperation() != true) {
clearPrompt()
}
}
override fun onCleared() {
super.onCleared()
cipherDatabaseAction.unregisterDatabaseListener(cipherDatabaseListener)
clearPrompt()
}
companion object {
private val TAG = DeviceUnlockViewModel::class.java.simpleName
}
}
enum class DeviceUnlockPromptMode {
IDLE_CLOSE, IDLE_SHOW, SHOW, CLOSE
}
data class DeviceUnlockState(
val newDeviceUnlockMode: DeviceUnlockMode = DeviceUnlockMode.BIOMETRIC_UNAVAILABLE,
val allowDeviceUnlockMenu: Boolean = false,
val credentialRequiredCipher: Cipher? = null,
val cipherEncryptDatabase: CipherEncryptDatabase? = null,
val cipherDecryptDatabase: CipherDecryptDatabase? = null,
val cryptoPromptState: DeviceUnlockPromptMode = DeviceUnlockPromptMode.IDLE_CLOSE,
val autoOpenPrompt: Boolean = false,
val exception: Throwable? = null
)

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<com.kunzisoft.keepass.view.AdvancedUnlockInfoView
<com.kunzisoft.keepass.view.DeviceUnlockView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/advanced_unlock_view"
android:id="@+id/device_unlock_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"

View File

@@ -19,10 +19,11 @@
-->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:filterTouchesWhenObscured="true"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<include

View File

@@ -20,6 +20,7 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_entry_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:filterTouchesWhenObscured="true">

View File

@@ -21,6 +21,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:filterTouchesWhenObscured="true"

View File

@@ -19,11 +19,12 @@
-->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:id="@+id/icon_picker_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:filterTouchesWhenObscured="true"
xmlns:app="http://schemas.android.com/apk/res-auto">
android:filterTouchesWhenObscured="true">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/icon_picker_coordinator"

View File

@@ -19,11 +19,12 @@
-->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:id="@+id/key_generator_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:filterTouchesWhenObscured="true"
xmlns:app="http://schemas.android.com/apk/res-auto">
android:filterTouchesWhenObscured="true">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/key_generator_coordinator"

View File

@@ -21,6 +21,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:filterTouchesWhenObscured="true"
@@ -180,7 +181,7 @@
android:layout_height="wrap_content"
android:background="?attr/colorSurface">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_advanced_unlock_container_view"
android:id="@+id/fragment_device_unlock_container_view"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
@@ -196,7 +197,7 @@
style="@style/KeepassDXStyle.Button.Primary"
app:icon="@drawable/ic_lock_open_white_24dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/fragment_advanced_unlock_container_view"
app:layout_constraintStart_toEndOf="@+id/fragment_device_unlock_container_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -19,6 +19,7 @@
-->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:filterTouchesWhenObscured="true"

View File

@@ -122,8 +122,7 @@
android:inputType="textPassword"
android:importantForAccessibility="no"
android:importantForAutofill="no"
android:hint="@string/otp_secret"
tools:targetApi="jelly_bean" />
android:hint="@string/otp_secret" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
@@ -178,8 +177,7 @@
tools:text="30"
android:maxLength="3"
android:digits="0123456789"
android:imeOptions="actionNext"
tools:targetApi="jelly_bean" />
android:imeOptions="actionNext" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/setup_otp_counter_label"
@@ -198,8 +196,7 @@
android:importantForAutofill="no"
android:hint="@string/otp_counter"
tools:text="1"
android:imeOptions="actionNext"
tools:targetApi="jelly_bean" />
android:imeOptions="actionNext" />
</com.google.android.material.textfield.TextInputLayout>
<androidx.constraintlayout.widget.Guideline
@@ -228,8 +225,7 @@
tools:text="6"
android:maxLength="2"
android:digits="0123456789"
android:imeOptions="actionNext"
tools:targetApi="jelly_bean" />
android:imeOptions="actionNext" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -65,7 +65,6 @@
android:layout_height="wrap_content"
android:src="@drawable/ic_arrow_right_white_24dp"
app:tint="?attr/colorOnSurface"
android:importantForAccessibility="no"
tools:targetApi="jelly_bean" />
android:importantForAccessibility="no" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@@ -17,10 +17,12 @@
You should have received a copy of the GNU General Public License
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:layout_alignParentBottom="true"
android:paddingTop="4dp"
android:paddingBottom="8dp"

View File

@@ -18,28 +18,28 @@
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
--><resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string name="homepage">الصفحة الرئيسة</string>
<string name="accept">قبول</string>
<string name="add_group">إضافة مجموعة</string>
<string name="encryption">التشفير</string>
<string name="encryption_algorithm">خوارزمية التشفير</string>
<string name="accept">اقبل</string>
<string name="add_group">أضف مجموعة</string>
<string name="encryption">التعمية</string>
<string name="encryption_algorithm">خوارزمية التعمية</string>
<string name="application">التطبيق</string>
<string name="brackets">الأقواس</string>
<string name="extended_ASCII">ASCII ممتد</string>
<string name="allow">سماح</string>
<string name="allow">اسمح</string>
<string name="clipboard_cleared">مُسِحت الحافظة</string>
<string name="clipboard_error_title">خطأ في الحافظة</string>
<string name="clipboard_error_clear">تعذَّر مسح الحافظة</string>
<string name="database">قاعدة البيانات</string>
<string name="decrypting_db">يفك تشفير محتوى قاعدة البيانات…</string>
<string name="decrypting_db">يفك تعمية محتوى قاعدة البيانات…</string>
<string name="digits">أرقام</string>
<string name="entry_cancel">إلغاء</string>
<string name="entry_cancel">ألغِ</string>
<string name="entry_notes">ملاحظات</string>
<string name="entry_confpassword">تأكيد كلمة السر</string>
<string name="entry_confpassword">أكّد كلمة السر</string>
<string name="entry_created">أُنشئ</string>
<string name="entry_modified">معدل</string>
<string name="entry_modified">مُعدل</string>
<string name="entry_not_found">تعذر العثور على بيانات المُدخلة.</string>
<string name="entry_password">كلمة السر</string>
<string name="save">حفظ</string>
<string name="save">احفظ</string>
<string name="entry_title">العنوان</string>
<string name="entry_url">رابط</string>
<string name="entry_user_name">اسم المستخدم</string>
@@ -49,8 +49,8 @@
<string name="error_pass_match">كلمتا السر غير متطابقتين.</string>
<string name="field_name">اسم الحقل</string>
<string name="field_value">قيمة الحقل</string>
<string name="generate_password">توليد كلمة سر</string>
<string name="hint_conf_pass">تأكيد كلمة السر</string>
<string name="generate_password">ولّد كلمة سر</string>
<string name="hint_conf_pass">أكّد كلمة السر</string>
<string name="hint_group_name">اسم المجموعة</string>
<string name="hint_length">الطول</string>
<string name="hint_pass">كلمة السر</string>
@@ -61,15 +61,15 @@
<string name="list_size_summary">حجم النص في قائمة العناصر</string>
<string name="loading_database">يحمل قاعدة البيانات…</string>
<string name="lowercase">حروف صغيرة</string>
<string name="hide_password_summary">إخفاء كلمات السر بشكل افتراضي</string>
<string name="hide_password_summary">أخفِ كلمات السر (***) افتراضيًا</string>
<string name="about">عن التطبيق</string>
<string name="menu_change_key_settings">تغيير المفتاح الرئيسي</string>
<string name="settings">الإعدادات</string>
<string name="menu_app_settings">إعدادات التطبيق</string>
<string name="menu_database_settings">إعدادات قاعدة البيانات</string>
<string name="menu_delete">حذف</string>
<string name="menu_delete">احذف</string>
<string name="menu_donate">التبرع</string>
<string name="menu_edit">تعديل</string>
<string name="menu_edit">عدّل</string>
<string name="menu_lock">اقفل قاعدة البيانات</string>
<string name="menu_open">فتح</string>
<string name="menu_search">البحث</string>
@@ -77,10 +77,10 @@
<string name="never">أبداً</string>
<string name="no_results">لا توجد نتائج للبحث</string>
<string name="no_url_handler">ثبت متصفح لزيارة هذا الرابط.</string>
<string name="progress_create">إنشاء قاعدة بيانات جديدة …</string>
<string name="progress_create">يُنشئ قاعدة بيانات جديدة …</string>
<string name="protection">الحماية</string>
<string name="read_only">محمي من التعديل</string>
<string name="content_description_remove_from_list">إزالة</string>
<string name="content_description_remove_from_list">أزل</string>
<string name="root">الجذر</string>
<string name="memory_usage">استخدام الذاكرة</string>
<string name="parallelism">التَّوازِي</string>
@@ -101,26 +101,25 @@
<string name="warning_no_encryption_key">أمتأكد أنك لا تريد استخدام أي مفتاح لتشفير ؟</string>
<string name="version_label">الإصدار %1$s</string>
<string name="education_new_node_title">أضف عناصر إلى قاعدة البيانات</string>
<string name="education_entry_new_field_title">إضافة حقول مخصصة</string>
<string name="education_field_copy_title">نسخ حقل</string>
<string name="education_lock_title">تأمين قاعدة البيانات</string>
<string name="education_entry_new_field_title">أضف حقول مخصّصة</string>
<string name="education_field_copy_title">انسخ حقل</string>
<string name="education_lock_title">اقفل قاعدة البيانات</string>
<string name="feedback">أرسل انطباعاتك</string>
<string name="about_description">\"KeePassDX\" هو تطبيق أندرويد لمدير كلمات المرور كي باس \"KeePass\"</string>
<string name="about_description">تطبيق أندرويد لمدير كلمات السر KeePass.</string>
<string name="add_entry">أضف مدخل</string>
<string name="edit_entry">تحرير مدخل</string>
<string name="edit_entry">عدّل مدخل</string>
<string name="key_derivation_function">وظيفة اشتقاق المفتاح</string>
<string name="app_timeout">المهلة</string>
<string name="app_timeout_summary">مدة الخمول قبل قفل قاعدة البيانات</string>
<string name="file_manager_install_description">مدير الملفات الذي يمكنه القيام بالإجراءين ACTION_CREATE_DOCUMENT و ACTION_OPEN_DOCUMENT ضروري لانشاء, وفتح وحفض قواعد البيانات.</string>
<string name="file_manager_install_description">مدير الملفات الذي يمكنه القيام بالإجراءين ACTION_CREATE_DOCUMENT و ACTION_OPEN_DOCUMENT ضروري لانشاء، وفتح وحفظ قواعد البيانات.</string>
<string name="clipboard_error">بعض الأجهزة لا تسمح للتطبيقات باستعمال الحافظة.</string>
<string name="clipboard_timeout">مهلة الحافظة</string>
<string name="clipboard_timeout_summary">مدة التخزين في الحافظة (إذا كان جهازك يدعمها)</string>
<string name="select_to_copy">اختر لنسخ %1$s إلى الحافظة</string>
<string name="retrieving_db_key">يجلب مفتاح قاعدة البيانات…</string>
<string name="default_checkbox">استخدامها كقاعدة بيانات افتراضية</string>
<string name="html_about_licence">KeePassDX © %1$d كونزيسوفت &lt;strong&gt;مفتوح المصدر&lt;/strong&gt; و &lt;strong&gt;بدون اعلانات&lt;/strong&gt;.
\n يوزع كما هو، بدون ضمان, تحت ترخيص &lt;strong&gt;GPLv3&lt;/strong&gt;.</string>
<string name="entry_accessed">نُفذ إليه</string>
<string name="html_about_licence">KeePassDX © %1$d كونزيسوفت &lt;strong&gt;مفتوح المصدر&lt;/strong&gt; و &lt;strong&gt;بدون إعلانات&lt;/strong&gt;. \n يوزع كما هو، دون ضمان، تحت ترخيص &lt;strong&gt;GPLv3&lt;/strong&gt;.</string>
<string name="entry_accessed">وُصِل إليه</string>
<string name="entry_expires">تنتهي صلاحيته في</string>
<string name="entry_keyfile">ملف المفتاح</string>
<string name="error_arc4">تشفير دفق Arcfour غير مدعوم.</string>
@@ -129,34 +128,34 @@
<string name="error_nokeyfile">اختر ملف مفتاح.</string>
<string name="error_out_of_memory">لا ذاكرة لتحميل قاعدة البيانات كاملة.</string>
<string name="error_load_database">تعذر تحميل قاعدة البيانات.</string>
<string name="error_load_database_KDF_memory">لا يمكن تحميل المفتاح، حاول تقليل \"الذاكرة المستخدمة\" من قبل KDF.</string>
<string name="error_load_database_KDF_memory">تعذر تحميل المفتاح. حاول تقليل \"الذاكرة المستخدمة\" من قِبل KDF.</string>
<string name="error_pass_gen_type">يجب تحديد نوع واحد على الأقل لتوليد كلمة السر.</string>
<string name="error_rounds_too_large">\"جولات التحويل\" كثيرة جداً. الإعداد إلى 2147483648.</string>
<string name="error_string_key">يجب أن يكون لكل سلسلة اسم حقل.</string>
<string name="error_wrong_length">أدخل عددًا صحيحًا موجبًا في حقل «الطول».</string>
<string name="error_autofill_enable_service">تعذر تمكين خدمة الملء التلقائي.</string>
<string name="file_not_found_content">تعذر إيجاد الملف. جرِّب فتحه من متصفح ملفات.</string>
<string name="file_browser">مدير الملفات.</string>
<string name="file_browser">مدير الملفات</string>
<string name="invalid_credentials">تعذر قراءة الإعتمادات.</string>
<string name="invalid_db_sig">تعذر تمييز نسق قاعدة البيانات.</string>
<string name="keyfile_is_empty">ملف المفتاح فارغ.</string>
<string name="list_entries_show_username_title">أظهر أسماء المستخدمين</string>
<string name="list_entries_show_username_summary">اعرض اسماء المستخدمين في قوائم المدخلات</string>
<string name="hint_generated_password">كلمة السر الموَلدة.</string>
<string name="hint_keyfile">الملف المفتاحي.</string>
<string name="hide_password_title">اخفاء كلمات السر</string>
<string name="list_entries_show_username_summary">يعرض اسماء المستخدمين في قوائم المدخلات</string>
<string name="hint_generated_password">كلمة السر مولّدة</string>
<string name="hint_keyfile">ملف المفتاح</string>
<string name="hide_password_title">أخفِ كلمات السر</string>
<string name="copy_field">نُسخة من %1$s</string>
<string name="menu_copy">نسخ</string>
<string name="menu_move">نقل</string>
<string name="menu_paste">لصق</string>
<string name="menu_cancel">الغاء</string>
<string name="menu_hide_password">اخفاء كلمة السر</string>
<string name="menu_showpass">اظهار كلمة السر</string>
<string name="menu_cancel">ألغِ</string>
<string name="menu_hide_password">أخفِ كلمة السر</string>
<string name="menu_showpass">أظهر كلمة السر</string>
<string name="menu_url">الانتقال الى الرابط</string>
<string name="menu_file_selection_read_only">محمي من التعديل</string>
<string name="menu_open_file_read_and_write">قابل للتعديل</string>
<string name="select_database_file">فتح مخزن موجود</string>
<string name="create_keepass_file">انشاء مخزن جديد</string>
<string name="select_database_file">افتح مخزن موجود</string>
<string name="create_keepass_file">أنشئ مخزن جديد</string>
<string name="progress_title">قيد العمل…</string>
<string name="read_only_warning">KeePassDX يحتاج صلاحية الكتابة من اجل تعديل قاعدة البيانات.</string>
<string name="encryption_explanation">خوارزمية تشفير جميع البيانات</string>
@@ -166,7 +165,7 @@
<string name="unavailable">غير متوفر</string>
<string name="menu_appearance_settings">المظهر</string>
<string name="general">عام</string>
<string name="autofill">ملأ تلقائي</string>
<string name="autofill">الملء التلقائي</string>
<string name="autofill_sign_in_prompt">سجل باستخدام KeePassDX</string>
<string name="set_autofill_service_title">تعيين خدمة الملأ التلقائي الافتراضية</string>
<string name="password_size_title">حجم كلمة السر المولدة</string>
@@ -178,14 +177,14 @@
<string name="clipboard_warning">اذا فشل الحذف التلقائي من الحافظة ,احذف تأريخه يدويا.</string>
<string name="lock_database_screen_off_title">قفل الشاشة</string>
<string name="lock_database_screen_off_summary">اقفل قاعدة البيانات بعد بضع ثوانٍ بمجرد إيقاف تشغيل الشاشة</string>
<string name="biometric_delete_all_key_title">حذف مفاتيح التشفير</string>
<string name="biometric_delete_all_key_title">احذف مفاتيح التعمية</string>
<string name="unavailable_feature_text">لا يمكن بدأ هذه الميزة .</string>
<string name="unavailable_feature_version">هذا الجهاز يعمل بأندرويد %1$s لكن يحتاج نسخة %2$s على الأقل.</string>
<string name="file_name">اسم الملف</string>
<string name="path">مسار</string>
<string name="database_history">تأريخ</string>
<string name="clipboard_notifications_summary">أظهر اشعارات الحافظة لنسخ الحقول عند عرض مدخل</string>
<string name="advanced_unlock">فتح الجهاز</string>
<string name="device_unlock">فتح الجهاز</string>
<string name="biometric_unlock_enable_title">فحص البصمة</string>
<string name="biometric_unlock_enable_summary">يتيح لك مسح بياناتك الحيوية لفتح قاعدة البيانات</string>
<string name="monospace_font_fields_enable_summary">غير خط الحقول لتوضيح المحارف</string>
@@ -213,15 +212,13 @@
<string name="keyboard_keys_category">مفاتيح</string>
<string name="keyboard_key_vibrate_title">إهتزاز عند اللمس</string>
<string name="keyboard_key_sound_title">صوت عند اللمس</string>
<string name="allow_no_password_title">إسمح بدون المفتاح الرئيسي</string>
<string name="enable_read_only_title">محمي من التعديل</string>
<string name="enable_read_only_summary">افتح قاعدة البيانات في وضع القراءة افتراضيا</string>
<string name="allow_no_password_title">اسمح بدون المفتاح الرئيسي</string>
<string name="enable_education_screens_title">تلميحات تعليمية</string>
<string name="reset_education_screens_summary">أعد عرض كل المعلومات التعليمية</string>
<string name="reset_education_screens_text">إعادة تعيين الشاشات التلميحات</string>
<string name="education_create_database_title">أنشئ قاعدة بيانات</string>
<string name="education_create_database_summary">أنشئ ملف إدارة كلمات السر.</string>
<string name="education_select_database_title">إفتح قاعدة بيانات</string>
<string name="education_select_database_title">افتح قاعدة بيانات موجودة بالفعل</string>
<string name="sort_recycle_bin_bottom">سلة المحذوفات في الأسفل</string>
<string name="sort_db">ترتيب طبيعي</string>
<string name="sort_last_access_time">الوصول</string>
@@ -234,10 +231,10 @@
<string name="keyboard_notification_entry_content_title">%1$s متوفر على Magikeyboard</string>
<string name="keyboard_notification_entry_content_text">%1$s</string>
<string name="reset_education_screens_title">إعادة تعيين التلميحات التعليمية</string>
<string name="education_search_title">البحث من خلال الإدخالات</string>
<string name="education_search_title">ابحث من خلال المدخلات</string>
<string name="content_description_open_file">افتح الملف</string>
<string name="content_description_add_entry">إضافة مدخلة</string>
<string name="content_description_add_group">إضافة مجموعة</string>
<string name="content_description_add_entry">أضف مدخل</string>
<string name="content_description_add_group">أضف مجموعة</string>
<string name="content_description_file_information">معلومات الملف</string>
<string name="entry_password_generator">مولد كلمة السر</string>
<string name="content_description_background">الخلفية</string>
@@ -250,22 +247,22 @@
<string name="do_not_kill_app">لا تقتل التطبيق…</string>
<string name="content_description_node_children">العقد الفرعية</string>
<string name="content_description_add_node">أضف عقدة</string>
<string name="content_description_entry_icon">ايقونة المدخل</string>
<string name="content_description_entry_icon">أيقونة المدخل</string>
<string name="content_description_password_length">طول كلمة السر</string>
<string name="entry_add_field">أضف حقل</string>
<string name="content_description_remove_field">أزل حقل</string>
<string name="error_move_entry_here">يتعذر نقل مدخل إلى هنا.</string>
<string name="error_copy_entry_here">يتعذر نسخ مدخال إلى هنا.</string>
<string name="list_groups_show_number_entries_title">عرض عدد المدخلات</string>
<string name="list_groups_show_number_entries_summary">عرض عدد المدخلات في المجموعة</string>
<string name="content_description_update_from_list">تحديث</string>
<string name="error_move_entry_here">لا يمكنك نقل مدخل هنا.</string>
<string name="error_copy_entry_here">لا يمكنك نسخ مدخل هنا.</string>
<string name="list_groups_show_number_entries_title">أظهر عدد المدخلات</string>
<string name="list_groups_show_number_entries_summary">يعرض عدد المدخلات في المجموعة</string>
<string name="content_description_update_from_list">حدِّث</string>
<string name="content_description_keyboard_close_fields">أغلق الحقول</string>
<string name="error_create_database_file">لا يمكن انشاء قاعدة بيانات بكلمة السر وملف المفتاح الحاليين.</string>
<string name="menu_advanced_unlock_settings">فك قفل الجهاز</string>
<string name="error_create_database_file">تعذر إنشاء قاعدة بيانات بكلمة السر وملف المفتاح الحاليين.</string>
<string name="menu_device_unlock_settings">فك قفل الجهاز</string>
<string name="entry_attachments">مرفقات</string>
<string name="entry_history">السجل</string>
<string name="entry_add_attachment">أضف مرفقا</string>
<string name="discard">إلغاء</string>
<string name="entry_history">التاريخ</string>
<string name="entry_add_attachment">أضف مرفقًا</string>
<string name="discard">تجاهل</string>
<string name="discard_changes">تجاهل التغييرات؟</string>
<string name="validate">تأكيد</string>
<string name="security">الأمان</string>
@@ -273,27 +270,27 @@
<string name="error_otp_period">يجب ان تكون المدة بين %1$d و%2$d ثانية.</string>
<string name="error_otp_secret_key">المفتاح السري يجب ان يكون بصيغة Base32.</string>
<string name="error_save_database">تعذر حفظ قاعدة البيانات.</string>
<string name="error_create_database">لا يمكن إنشاء ملف قاعدة البيانات.</string>
<string name="error_copy_group_here">لا يمكن نسخ مجموعة هنا.</string>
<string name="error_create_database">تعذر إنشاء ملف قاعدة البيانات.</string>
<string name="error_copy_group_here">لا يمكنك نسخ مجموعة هنا.</string>
<string name="error_label_exists">هذه التسمية موجودة بالفعل.</string>
<string name="otp_period">المدة (ثواني)</string>
<string name="otp_algorithm">الخوارزمية</string>
<string name="otp_digits">أرقام</string>
<string name="otp_counter">العداد</string>
<string name="entry_setup_otp">عيّن كلمة مرور لمرة واحدة</string>
<string name="entry_setup_otp">عيّن كلمة سر لمرة واحدة</string>
<string name="entry_UUID">UUID</string>
<string name="html_about_contribution">من أجل &lt;strong&gt;حماية خصوصيتا&lt;/strong&gt;٫&lt;strong&gt; إصلاح العلل&lt;/strong&gt;٫ &lt;strong&gt;إضافة مميزات&lt;/strong&gt; &lt;strong&gt;وجعلنا نشطاء دائما&lt;/strong&gt;٫ نحن نعتمد على &lt;strong&gt;مساهمتك&lt;/strong&gt;.</string>
<string name="content_description_keyfile_checkbox">خانة تأشير الملف المفتاحي</string>
<string name="html_about_contribution">لكي &lt;strong&gt;نحافظ على حريتنا&lt;/strong&gt;، و&lt;strong&gt;نصلح الأخطاء&lt;/strong&gt;، و&lt;strong&gt;نضيف ميزات&lt;/strong&gt;، و&lt;strong&gt;نبقى دائمًا نشطين&lt;/strong&gt;، فإننا نعتمد على &lt;strong&gt;مساهمتكم&lt;/strong&gt;.</string>
<string name="content_description_keyfile_checkbox">خانة تأشير ملف المفتاح</string>
<string name="content_description_password_checkbox">خانة تأشير كلمة السر</string>
<string name="content_description_add_item">أضف عنصر</string>
<string name="warning_permanently_delete_nodes">حذف العقد المحددة نهائيا؟</string>
<string name="filter">مرشح</string>
<string name="command_execution">ينفذ الأمر…</string>
<string name="hide_broken_locations_title">اِخفي روابط قواعد البيانات المعطلة</string>
<string name="hide_broken_locations_title">أخفِ روابط قواعد البيانات المعطوبة</string>
<string name="show_recent_files_summary">أظهر موقع قواعد البيانات الأخيرة</string>
<string name="show_recent_files_title">أظهر الملفات الأخيرة</string>
<string name="remember_keyfile_locations_summary">تعقب موقع الملفات المفتاحية لقاعدة البيانات</string>
<string name="remember_keyfile_locations_title">تذكر موقع الملف المفتاحي</string>
<string name="remember_keyfile_locations_title">تذكر موقع ملف المفتاح</string>
<string name="remember_database_locations_summary">تعقب موقع قاعدة البيانات</string>
<string name="remember_database_locations_title">تذكر موقع تخزين قاعدة البيانات</string>
<string name="contains_duplicate_uuid_procedure">للمتابعة هل تريد حل المشكلة بتوليد UUID للعناصر المكررة ؟</string>
@@ -308,48 +305,48 @@
<string name="creating_database">ينشئ قاعدة البيانات…</string>
<string name="error_string_type">لا يطابق هذا النص العنصر المطلوب.</string>
<string name="error_otp_counter">على العداد أن يكون ما بين %1$d و %2$d.</string>
<string name="entry_otp">كلمة مرور لمرة واحدة</string>
<string name="otp_type">نوع كلمة المرور لمرة واحدة</string>
<string name="entry_otp">كلمة سر لمرة واحدة</string>
<string name="otp_type">نوع كلمة السر لمرة واحدة (OTP)</string>
<string name="error_disallow_no_credentials">عين اعتماد واحد على الأقل.</string>
<string name="contribution">ساهم</string>
<string name="contact">الإتصال بنا</string>
<string name="contact">التواصل</string>
<string name="biometric">البصمة</string>
<string name="warning_empty_keyfile_explanation">يجب ألا تغير محتوى ملف المفتاح، في أحسن الحالات يجب أن يحتوي بيانات مولدة عشوائيا.</string>
<string name="warning_empty_keyfile">من غير المستحسن اضافة ملف مفتاح فارغ.</string>
<string name="warning_sure_remove_data">أزل هذه البيانات عل أي حال؟</string>
<string name="warning_sure_add_file">أأضف الملف على أي حال؟</string>
<string name="warning_replace_file">رفعُ هذا الملف سيستبدل الموجود مسبقا.</string>
<string name="warning_replace_file">رفع هذا الملف سيستبدل الموجود مسبقًا.</string>
<string name="warning_database_link_revoked">أبطلَ مدير الملفات الوصول للملف</string>
<string name="warning_database_read_only">أعط صلاحية الكتابة من أجل حفظ قاعدة البيانات</string>
<string name="warning_password_encoding">تجنب استخدام المحارف غير الموجودة في ترميز قاعدة البيانات (تحوَّل المحارف غير الموجودة لنفس الحرف).</string>
<string name="hide_broken_locations_summary">إخف الروابط المعطلة في قائمة قواعد البيانات الحديثة</string>
<string name="hide_broken_locations_summary">أخفِ الروابط المعطوبة في قائمة قواعد البيانات الحديثة</string>
<string name="auto_focus_search_summary">افتح البحث عند فتح قاعدة البيانات</string>
<string name="content_description_credentials_information">معلومات بيانات الاعتماد</string>
<string name="max_history_items_title">العدد الأقصى</string>
<string name="recycle_bin_group_title">مجموعة سلة المحذوفات</string>
<string name="recycle_bin_summary">أُنقل المجموعات والمدخلات لسلة المحذوفات قبل حذفها</string>
<string name="database_data_remove_unlinked_attachments_summary">أزِل المرفقات غير المرتبطة بإدخال في قاعدة البيانات</string>
<string name="database_data_remove_unlinked_attachments_summary">أزل المرفقات غير المرتبطة بمدخل في قاعدة البيانات</string>
<string name="database_data_remove_unlinked_attachments_title">أزل البيانات غير المرتبطة</string>
<string name="database_data_compression_summary">ضغط البيانات يقلص من حجم قاعدة البيانات</string>
<string name="database_data_compression_title">ضغط البيانات</string>
<string name="data">البيانات</string>
<string name="unavailable_feature_hardware">تعذر العثور على ماسح البصمة.</string>
<string name="biometric_delete_all_key_summary">احذف كل مفاتيح التشفير المرتبطة بفتح الجهاز</string>
<string name="advanced_unlock_explanation_summary">استخدم إلغاء القفل الجهاز لفتح قاعدة البيانات بسهولة</string>
<string name="biometric_delete_all_key_summary">احذف كل مفاتيح التعمية المرتبطة بفتح الجهاز</string>
<string name="device_unlock_explanation_summary">استخدم إلغاء القفل الجهاز لفتح قاعدة البيانات بسهولة</string>
<string name="lock_database_show_button_summary">يعرض زر القَفل في الواجهة</string>
<string name="lock_database_show_button_title">اعرض زر القَفل</string>
<string name="lock_database_show_button_title">أظهر زر القفل</string>
<string name="lock_database_back_root_summary">قفل قاعدة البيانات عند النقر على زر الرجوع في الشاشة الرئيسية</string>
<string name="lock_database_back_root_title">اضغط على \"رجوع\" للإقفال</string>
<string name="clipboard_explanation_summary">انسخ حقول الإدخال باستخدام الحافظة</string>
<string name="clipboard_explanation_summary">انسخ حقول المدخل باستخدام الحافظة</string>
<string name="database_opened">قاعدة البيانات مفتوحة</string>
<string name="autofill_preference_title">إعدادات الملء التلقائي</string>
<string name="education_entry_edit_title">حرر المدخلة</string>
<string name="education_advanced_unlock_summary">لفتح قاعدة البيانات بسرعة اربط كلمة المرور بالبصمة.</string>
<string name="education_search_summary">لإيجاد كلمة المرور، أدخل العنوان أو اسم المستخدم أو محتوى أحد الحقول.</string>
<string name="education_entry_edit_title">عدّل المدخل</string>
<string name="education_device_unlock_summary">اربط كلمة سر ببياناتك البيومترية الممسوحة ضوئيًا أو بيانات اعتماد جهازك لفتح قفل قاعدة بياناتك بسرعة.</string>
<string name="education_search_summary">لإيجاد كلمة السر، أدخل العنوان أو اسم المستخدم أو محتوى أحد الحقول.</string>
<string name="education_new_node_summary">المدخلات لإدارة معرفاتك الرقمية.
\n
\nالمجموعات (المجلدات) لتنظيم المدخلات في قاعدة البيانات.</string>
<string name="education_select_database_summary">لمتابعة استخدام قاعدة البيانات السابقة، افتحها من مدير الملفات.</string>
<string name="education_select_database_summary">افتح ملف قاعدة البيانات السابق من متصفح ملفاتك لمتابعة استخدامه.</string>
<string name="enable_auto_save_database_summary">حفظ قاعدة البيانات بعد كل إجراء (في وضع \"التعديل\")</string>
<string name="enable_auto_save_database_title">الحفظ التلقائي لقاعدة البيانات</string>
<string name="delete_entered_password_title">احذف كلمة السر</string>
@@ -357,15 +354,12 @@
<string name="autofill_web_domain_blocklist_title">قائمة النطاقات المحظورة</string>
<string name="autofill_application_id_blocklist_summary">منع الملء التلقائي للتطبيقات الموجودة في القائمة</string>
<string name="autofill_application_id_blocklist_title">قائمة التطبيقات المحظورة</string>
<string name="content_description_repeat_toggle_password_visibility">بدِّل ظهور كلمة السر</string>
<string name="hide_expired_entries_summary">لن تعرض المدخلات منتهية الصلاحية</string>
<string name="education_read_only_summary">تغيير وضع الافتتاح للجلسة.
\n
\nيمنع \"محمي ضد الكتابة\" التغييرات غير المقصودة في قاعدة البيانات.
\n\"قابل للتعديل\" يتيح لك إضافة أو حذف أو تعديل جميع العناصر كما تريد.</string>
<string name="education_read_only_title">احمي قاعدة البيانات من التعديل</string>
<string name="education_unlock_title">افتح قاعدة البيانات</string>
<string name="education_add_attachment_summary">أضف مرفقا للمدخلة لحفظ بيانات اضافية.</string>
<string name="content_description_repeat_toggle_password_visibility">أعد تبديل ظهور كلمة السر</string>
<string name="hide_expired_entries_summary">لا يتم عرض المدخلات منتهية الصلاحية</string>
<string name="education_read_only_summary">غيّر وضع الافتتاح للجلسة. \n \nيمنع \"محمي ضد الكتابة\" التغييرات غير المقصودة في قاعدة البيانات. \n\"قابل للتعديل\" يتيح لك إضافة أو حذف أو تعديل جميع العناصر كما تريد.</string>
<string name="education_read_only_title">احمِ قاعدة بياناتك من التعديل</string>
<string name="education_unlock_title">افتح قاعدة بياناتك</string>
<string name="education_add_attachment_summary">ارفع مرفقًا إلى مدخلك لحفظ البيانات الخارجية الهامة.</string>
<string name="education_add_attachment_title">أضف مرفقا</string>
<string name="autofill_block">احظر الملء التلقائي</string>
<string name="keyboard_previous_database_credentials_title">شاشة بيانات اعتماد قاعدة البيانات</string>
@@ -402,7 +396,7 @@
<string name="education_generate_password_title">أنشئ كلمة سر قوية</string>
<string name="save_mode">وضع الحفظ</string>
<string name="search_mode">وضع البحث</string>
<string name="version">النسخة</string>
<string name="version">النُسخة</string>
<string name="template_group_name">النماذج</string>
<string name="holder">الحامل</string>
<string name="number">الرقم</string>
@@ -410,7 +404,7 @@
<string name="personal_identification_number">PIN</string>
<string name="id_card">بطاقة الهوية</string>
<string name="type">النوع</string>
<string name="cryptocurrency">محفظة عملات مشفرة</string>
<string name="cryptocurrency">محفظة عملات التعموية</string>
<string name="public_key">المفتاح العمومي</string>
<string name="private_key">المفتاح الخاص</string>
<string name="account">الحساب</string>
@@ -418,13 +412,13 @@
<string name="bank_name">اسم المصرف</string>
<string name="secure_note">ملاحظة آمنة</string>
<string name="error_word_reserved">هذه الكلمة محجوزة ولا يمكن استخدامها.</string>
<string name="error_field_name_already_exists">اسم الحقل موجود سلفًا.</string>
<string name="error_file_to_big">الملف الذي ترفعه كبير.</string>
<string name="error_field_name_already_exists">اسم الحقل موجود بالفعل.</string>
<string name="error_file_to_big">الملف الذي تحاول رفعه كبير جدًا.</string>
<string name="error_upload_file">حدث خطأ أثناء رفع الملف.</string>
<string name="error_duplicate_file">بيانات الملف موجودة سلفًا.</string>
<string name="error_duplicate_file">بيانات الملف موجودة بالفعل.</string>
<string name="error_remove_file">حدث خطأ أثناء إزالة بيانات الملف.</string>
<string name="error_start_database_action">حدث خطأ أثناء تنفيذ إجراء على قاعدة البيانات.</string>
<string name="content_description_otp_information">معلومات كلمة المرور لمرة واحدة</string>
<string name="content_description_otp_information">معلومات كلمة السر لمرة واحدة</string>
<string name="membership">العضوية</string>
<string name="name">الاسم</string>
<string name="email">البريد الإلكتروني</string>
@@ -452,8 +446,8 @@
<string name="properties">الخصائص</string>
<string name="token">الرمز</string>
<string name="seed">البذرة</string>
<string name="error_database_uri_null">يتعذر استرداد مسار قاعدة البيانات.</string>
<string name="error_rebuild_list">يتعذر إعادة بناء القائمة بشكل صحيح.</string>
<string name="error_database_uri_null">لا يمكن استرداد URI قاعدة البيانات.</string>
<string name="error_rebuild_list">تعذر إعادة بناء القائمة بشكل صحيح.</string>
<string name="menu_keystore_remove_key">احذف رمز فك القفل الجهاز</string>
<string name="menu_form_filling_settings">ملء النموذج</string>
<string name="menu_reload_database">أعد تحميل البيانات</string>
@@ -467,14 +461,14 @@
<string name="error_export_app_properties">خطأ أثناء تصدير إعدادات التطبيق.</string>
<string name="warning_database_info_changed">غُيِّرت معلومات قاعدة البيانات من خارج هذا التطبيق.</string>
<string name="warning_database_info_changed_options">ادمج البيانات أو استبدل التعديلات الخارجية بحفظ قاعدة البيانات أو أعد تحميلها لجلب آخر التغييرات.</string>
<string name="credential_before_click_advanced_unlock_button">اكتب كلمة السر، وأنقر هذا الزر.</string>
<string name="credential_before_click_device_unlock_button">اكتب كلمة السر، وأنقر هذا الزر.</string>
<string name="device_credential">بيانات الاعتماد للجهاز</string>
<string name="advanced_unlock_tap_delete">انقر لحذف مفاتيح فتح الجهاز</string>
<string name="device_unlock_tap_delete">انقر لحذف مفاتيح فتح الجهاز</string>
<string name="keyboard_auto_go_action_title">إجراء اللمس التلقائي</string>
<string name="keyboard_previous_fill_in_title">العودة إلى الوراء</string>
<string name="keyboard_previous_lock_title">اقفل قاعدة البيانات</string>
<string name="education_advanced_unlock_title">فتح قاعدة بيانات الجهاز</string>
<string name="hint_icon_name">اسم الأيقونة.</string>
<string name="education_device_unlock_title">فتح قاعدة بيانات الجهاز</string>
<string name="hint_icon_name">اسم الأيقونة</string>
<string name="autofill_manual_selection_title">اختيار يدوي</string>
<string name="description_app_properties">خصائص KeePassDX لإدارة إعدادات التطبيقات</string>
<string name="warning_empty_recycle_bin">هل تريد حذف جميع العقد نهائيًا من سلة المهملات؟</string>
@@ -482,7 +476,7 @@
<string name="autofill_ask_to_save_data_title">اسأل لحفظ البيانات</string>
<string name="content_description_database_color">لون قاعدة البيانات</string>
<string name="menu_merge_from">ادمج من…</string>
<string name="show_uuid_summary">يعرض \"المعرف العام\" المرتبط بمُدخل او بمجموعة</string>
<string name="show_uuid_summary">يعرض UUID المرتبط بمدخل أو بمجموعة</string>
<string name="expired">انتهت</string>
<string name="tags">الوسوم</string>
<string name="menu_merge_database">ادمج البيانات</string>
@@ -491,10 +485,10 @@
<string name="warning_file_too_big">يفترض بقاعدة البيانات أن تحوي ملفات صغيرة الحجم ( كمفاتيح PGP).
\n
\nبرفع هذا الملف قد يزداد حجم قاعدة البيانات ويضعف أداءها.</string>
<string name="error_move_group_here">يتعذر نقل المجموعة إلى هنا.</string>
<string name="error_move_group_here">لا يمكنك نقل مجموعة هنا.</string>
<string name="menu_save_copy_to">احفظ نسخة إلى…</string>
<string name="searchable">يمكن البحث عنه</string>
<string name="custom_data">بيانات مخصصة</string>
<string name="custom_data">بيانات مخصّصة</string>
<string name="case_sensitive">حساسة لحالة الأحرف</string>
<string name="regex">تعابير نمطية</string>
<string name="enable_keep_screen_on_title">أبقِ الشاشة شغّالة</string>
@@ -510,42 +504,42 @@
<string name="autofill_close_database_summary">أغلق قاعدة البيانات بعد الملء التلقائي</string>
<string name="autofill_ask_to_save_data_summary">اسأل عن حفظ البيانات عند ملئك لنموذج</string>
<string name="templates_group_uuid_title">مجموعة القوالب</string>
<string name="advanced_unlock_timeout">انتهت مهلة فتح الجهاز</string>
<string name="temp_advanced_unlock_timeout_summary">مهلة استخدام فتح الجهاز قبل حذف محتواها</string>
<string name="advanced_unlock_delete_all_key_warning">أتريد حذف كل مفاتيح التشفير المرتبطة بفتح الجهاز؟</string>
<string name="device_unlock_timeout">انتهت مهلة فتح الجهاز</string>
<string name="temp_device_unlock_timeout_summary">مهلة استخدام فتح الجهاز قبل حذف محتواها</string>
<string name="device_unlock_delete_all_key_warning">أتريد حذف كل مفاتيح التعمية المرتبطة بفتح الجهاز؟</string>
<string name="templates">القوالب</string>
<string name="templates_group_enable_title">استخدام القوالب</string>
<string name="notification">الإشعارات</string>
<string name="temp_advanced_unlock_enable_summary">لا تقم بتخزين أي محتوى مشفر لاستخدام إلغاء قفل الجهاز</string>
<string name="temp_advanced_unlock_timeout_title">انتهاء صلاحية فتح الحهاز</string>
<string name="hide_expired_entries_title">إخفاء الإدخالات منتهية الصلاحية</string>
<string name="content_description_hardware_key_checkbox">خانة إختيار مفتاح الجهاز</string>
<string name="content_description_passphrase_word_count">عدد عبارات المرور</string>
<string name="temp_device_unlock_enable_summary">لا تقم بتخزين أي محتوى مشفر لاستخدام إلغاء قفل الجهاز</string>
<string name="temp_device_unlock_timeout_title">انتهاء صلاحية فتح الحهاز</string>
<string name="hide_expired_entries_title">أخفِ المدخلات منتهية الصلاحية</string>
<string name="content_description_hardware_key_checkbox">خانة إختيار مفتاح العتاد</string>
<string name="content_description_passphrase_word_count">عدد عبارات السر</string>
<string name="content_description_entry_background_color">لون خلفية المدخل</string>
<string name="passphrase">عبارة المرور</string>
<string name="colorize_password_title">تلوين كلمات المرور</string>
<string name="passphrase">عبارة السر</string>
<string name="colorize_password_title">لوّن كلمات السر</string>
<string name="permission">الإذن</string>
<string name="advanced_unlock_prompt_not_initialized">تعذر تهيئة موجه إلغاء قفل الجهاز.</string>
<string name="device_unlock_prompt_not_initialized">تعذر تهيئة موجه إلغاء قفل الجهاز.</string>
<string name="biometric_security_update_required">مطلوب تحديث أمان المقاييس الحيوية.</string>
<string name="advanced_unlock_not_recognized">تعذر التعرف على طباعة فتح الجهاز</string>
<string name="temp_advanced_unlock_enable_title">فتح جهاز مؤقت</string>
<string name="device_unlock_not_recognized">تعذر التعرف على طباعة فتح الجهاز</string>
<string name="temp_device_unlock_enable_title">فتح جهاز مؤقت</string>
<string name="autofill_inline_suggestions_title">اقتراحات مضمنة</string>
<string name="education_setup_OTP_summary">قم بإعداد إدارة كلمات المرور لمرة واحدة (HOTP / TOTP) لإنشاء رمز مميز مطلوب للمصادقة الثنائية (2FA).</string>
<string name="education_setup_OTP_summary">أعِدّ إدارة كلمات السر لمرة واحدة (HOTP / TOTP) لإنشاء رمز مميز مطلوب لاستيثاق الثنائي (2FA).</string>
<string name="education_field_copy_summary">يمكن لصق الحقول المنسوخة في أي مكان.
\n
\nاستخدم طريقة ملء النموذج التي تفضلها.</string>
<string name="html_text_dev_feature_work_hard">نحن نعمل بجد لإصدار هذه الميزة بسرعة.</string>
<string name="autofill_inline_suggestions_summary">حاول عرض اقتراحات الملء التلقائي مباشرة من لوحة مفاتيح متوافقة</string>
<string name="delete_entered_password_summary">يحذف كلمة المرور التي تم إدخالها بعد محاولة الاتصال بقاعدة البيانات</string>
<string name="delete_entered_password_summary">يحذف كلمة السر التي أُدخلت بعد محاولة الاتصال بقاعدة البيانات</string>
<string name="education_lock_summary">اقفل قاعدة بياناتك بسرعة، يمكنك إعداد التطبيق لقفلها بعد فترة، وعند إيقاف تشغيل الشاشة.</string>
<string name="education_sort_title">فرز العنصر</string>
<string name="contribute">ساهِم</string>
<string name="upload_attachment">رفع %1$s</string>
<string name="download_canceled">ألغيت!</string>
<string name="unit_kibibyte">كيلو بايت</string>
<string name="unit_mebibyte">ميغا بايت</string>
<string name="unit_gibibyte">جيجابت</string>
<string name="entropy">إنتروبيا: %1$s بت</string>
<string name="upload_attachment">ارفع %1$s</string>
<string name="download_canceled">أُلغِيَ!</string>
<string name="unit_kibibyte">ك.بايت</string>
<string name="unit_mebibyte">م.بايت</string>
<string name="unit_gibibyte">ج.بايت</string>
<string name="entropy">الانتروبيا: %1$s بت</string>
<string name="entropy_high">الانتروبيا: مرتفع</string>
<string name="entropy_calculate">الانتروبيا: احسب…</string>
<string name="exclude_ambiguous_chars">استبعاد الأحرف الغامضة</string>
@@ -557,7 +551,7 @@
<string name="title_case">حالة العنوان</string>
<string name="character_count">عدد الأحرف: %1$d</string>
<string name="style_choose_summary">السمة المستخدمة في التطبيق</string>
<string name="show_entry_colors_summary">يعرض ألوان المقدمة والخلفية لإدخال</string>
<string name="show_entry_colors_summary">يعرض ألوان المقدمة والخلفية للمدخل</string>
<string name="icon_pack_choose_summary">حزمة الأيقونات المستخدمة في التطبيق</string>
<string name="show_entry_colors_title">ألوان الدخول</string>
<string name="device_credential_unlock_enable_title">فتح بيانات اعتماد الجهاز</string>
@@ -569,21 +563,21 @@
<string name="download_finalization">جارِ الانتهاء…</string>
<string name="download_complete">مكتمل!</string>
<string name="unit_byte">B</string>
<string name="icon_section_custom">مُخصص</string>
<string name="icon_section_custom">مخصّص</string>
<string name="content_description_entry_foreground_color">لون مقدمة الدخول</string>
<string name="keyboard_previous_fill_in_summary">العودة تلقائيًا إلى لوحة المفاتيح السابقة بعد تنفيذ \"إجراء المفتاح التلقائي\"</string>
<string name="download_attachment">تثبيت %1$s</string>
<string name="download_attachment">ثبِّت %1$s</string>
<string name="html_about_privacy">&lt;strong&gt; لا يتم استرداد أي بيانات مستخدم&lt;/strong&gt;، هذا التطبيق لا يتصل بأي خادم، ويعمل محليًا فقط ويحترم خصوصية المستخدمين تمامًا.</string>
<string name="error_cancel_by_user">ألغى المستخدم.</string>
<string name="show_otp_token_title">إظهار رمز \"الاقتران لمرة واحدة\" OTP</string>
<string name="show_otp_token_summary">إظهار رموز\"الاقتران لمرة واحدة\" في قائمة المدخلات</string>
<string name="error_cancel_by_user">أُلغِيَ بواسطة المستخدم.</string>
<string name="show_otp_token_title">أظهر رمز OTP</string>
<string name="show_otp_token_summary">يعرض رموز OTP في قائمة المدخلات</string>
<string name="warning_database_already_opened">قاعدة البيانات مفتوحة بالفعل، أغلقها أولاً لفتح قاعدة البيانات الجديدة</string>
<string name="warning_database_info_reloaded">ستؤدي إعادة تحميل قاعدة البيانات إلى حذف البيانات المعدلة محليًا.</string>
<string name="templates_group_enable_summary">استخدم القوالب الديناميكية لملء حقول الإدخال</string>
<string name="templates_group_enable_summary">استخدم القوالب الديناميكية لملء حقول المدخل</string>
<string name="keyboard_auto_go_action_summary">إجراء مفتاح \"Go\" بعد الضغط على مفتاح \"Field\"</string>
<string name="allow_no_password_summary">يسمح بالنقر فوق الزر \"فتح\" إذا لم يتم تحديد بيانات اعتماد</string>
<string name="education_generate_password_summary">أنشئ كلمة مرور قوية لربطها بإدخالك، وحددها بسهولة وفقًا لمعايير النموذج ولا تنس كلمة المرور الآمنة.</string>
<string name="education_setup_OTP_title">قم بإعداد OTP</string>
<string name="education_generate_password_summary">أنشئ كلمة سر قوية لربطها بإدخالك، وحددها بسهولة وفقًا لمعايير النموذج ولا تنسَ كلمة السر الآمنة.</string>
<string name="education_setup_OTP_title">أعِدّ OTP</string>
<string name="style_brightness_title">سطوع السمة</string>
<string name="word_separator">الفاصل</string>
<string name="screenshot_mode_banner_text">وضع لقطة الشاشة</string>
@@ -597,59 +591,58 @@
<string name="kdf_explanation">لإنشاء مفتاح خوارزمية التشفير، يتحول المفتاح الرئيسي باستخدام وظيفة اشتقاق مفتاح مملح عشوائيًا.</string>
<string name="html_text_dev_feature_buy_pro">بشراء الإصدار &lt;strong&gt; pro &lt;/strong&gt;،</string>
<string name="auto_type">كتابة تلقائيًا</string>
<string name="hardware_key">مفتاح الجهاز</string>
<string name="advanced_unlock_prompt_store_credential_title">رابط لفتح الجهاز</string>
<string name="hardware_key">مفتاح العتاد</string>
<string name="device_unlock_prompt_store_credential_title">رابط لفتح الجهاز</string>
<string name="backspace">فراغ للخلف</string>
<string name="enter">دخول</string>
<string name="education_sort_summary">اختر كيفية فرز الإدخالات والمجموعات.</string>
<string name="education_sort_summary">اختر كيفية فرز المدخلات والمجموعات.</string>
<string name="html_text_feature_generosity">هذا &lt;strong&gt; النمط المرئي&lt;/strong&gt; متاح بفضل كرمك.</string>
<string name="info">المعلومات</string>
<string name="waiting_challenge_response">في انتظار استجابة التحدي…</string>
<string name="bank_identifier_code">SWIFT / BIC</string>
<string name="international_bank_account_number">IBAN</string>
<string name="error_no_hardware_key">حدد مفتاح الجهاز.</string>
<string name="colorize_password_summary">تلوين أحرف كلمة المرور حسب النوع</string>
<string name="enable_keep_screen_on_summary">استمر في تشغيل الشاشة عند مشاهدة إدخال أو تعديله</string>
<string name="error_no_hardware_key">حدّد مفتاح العتاد.</string>
<string name="colorize_password_summary">لوّن أحرف كلمة السر حسب النوع</string>
<string name="enable_keep_screen_on_summary">استمر في تشغيل الشاشة عند مشاهدة مدخل أو تعديله</string>
<string name="enable_screenshot_mode_title">وضع لقطة الشاشة</string>
<string name="navigation_drawer_open">درج التنقل مفتوح</string>
<string name="waiting_challenge_request">في انتظار طلب التحدي…</string>
<string name="navigation_drawer_close">درج التنقل مقفول</string>
<string name="error_XML_malformed">XML تالف.</string>
<string name="error_otp_type">لم يتم التعرف على نوع OTP الحالي من خلال هذا النموذج، وقد لا يؤدي التحقق من صحته إلى إنشاء الرمز المميز بشكل صحيح.</string>
<string name="error_challenge_already_requested">التحدي مطلوب بالفعل.</string>
<string name="error_challenge_already_requested">التحدي طُلَب بالفعل.</string>
<string name="error_response_already_provided">تقدم الرد بالفعل.</string>
<string name="error_no_response_from_challenge">غير قادر على الحصول على رد من التحدي.</string>
<string name="error_driver_required">مطلوب تعريف لـ%1$s.</string>
<string name="error_unable_merge_database_kdb">غير قادر على الدمج مع ملف قاعدة بيانات kdb.</string>
<string name="error_location_unknown">موقع قاعدة البيانات غير معروف، لا يمكن تنفيذ إجراء قاعدة البيانات.</string>
<string name="menu_advanced_unlock_settings_summary">القياس الحيوي، بيانات اعتماد الجهاز</string>
<string name="menu_device_unlock_settings_summary">القياس الحيوي، بيانات اعتماد الجهاز</string>
<string name="menu_database_settings_summary">البيانات الوصفية، سلة المحذوفات، القوالب، التاريخ</string>
<string name="menu_security_settings_summary">التشفير، وظيفة اشتقاق المفتاح</string>
<string name="error_hardware_key_unsupported">مفتاح الجهاز غير مدعوم.</string>
<string name="error_hardware_key_unsupported">مفتاح العتاد غير مدعوم.</string>
<string name="master_key_settings_summary">التغيير والتجديد</string>
<string name="error_empty_key">لا يمكن أن يكون المفتاح فارغًا.</string>
<string name="corrupted_file">ملف تالف.</string>
<string name="warning_keyfile_integrity">لا يتم ضمان تجزئة الملف لأن Android يمكنه تغيير بياناته بسرعة. قم بتغيير امتداد الملف إلى bin. من أجل التكامل الصحيح.</string>
<string name="invalid_db_same_uuid">%1$s بنفس UUID %2$s موجود بالفعل.</string>
<string name="remember_hardware_key_title">تذكر مفاتيح الأجهزة</string>
<string name="remember_hardware_key_title">تذكر مفاتيح العتاد</string>
<string name="warning_exact_alarm">لم تسمح للتطبيق باستخدام منبه دقيق. نتيجة لذلك، لن يتم تنفيذ الميزات التي تتطلب مؤقتًا في وقت محدد.</string>
<string name="remember_hardware_key_summary">يتتبع مفاتيح الأجهزة المستخدمة</string>
<string name="remember_hardware_key_summary">يتتبع مفاتيح العتاد المستخدمة</string>
<string name="warning_database_notification_permission">يسمح لك إذن الإشعار بعرض حالة قاعدة البيانات وقفلها باستخدام زر يسهل الوصول إليه.
\n
\nإذا لم تنشط هذا الإذن، فلن تكون قاعدة البيانات المفتوحة في الخلفية مرئية إذا كان هناك تطبيق آخر في المقدمة.</string>
<string name="warning_copy_permission">مطلوب إذن الإشعار لاستخدام ميزة إشعار الحافظة.</string>
<string name="merge_success">اكتمل الدمج بنجاح</string>
<string name="advanced_unlock_prompt_store_credential_message">ما زلت بحاجة إلى تذكر بيانات الاعتماد الرئيسية في مخزنك إذا كنت تستخدم التعرف على فتح الجهاز.</string>
<string name="advanced_unlock_prompt_extract_credential_title">التعرف على فتح الجهاز</string>
<string name="device_unlock_prompt_store_credential_message">ما زلت بحاجة إلى تذكر بيانات الاعتماد الرئيسية في مخزنك إذا كنت تستخدم التعرّف على فتح الجهاز.</string>
<string name="device_unlock_prompt_extract_credential_title">التعرف على فتح الجهاز</string>
<string name="later">لاحقًا</string>
<string name="configure">تضبيط</string>
<string name="advanced_unlock_prompt_extract_credential_message">استخراج بيانات اعتماد قاعدة البيانات مع بيانات فتح الجهاز</string>
<string name="device_unlock_prompt_extract_credential_message">استخراج بيانات اعتماد قاعدة البيانات مع بيانات فتح الجهاز</string>
<string name="ask">إسأل</string>
<string name="configure_biometric">لم تسجل بيانات اعتماد المقاييس الحيوية أو الجهاز.</string>
<string name="show_uuid_title">إظهار \"المعرف العام المميز\" UUID</string>
<string name="show_uuid_title">أظهر \"المعرّف العام المميز\" UUID</string>
<string name="unlock_and_link_biometric">رابط فتح الجهاز</string>
<string name="advanced_unlock_invalid_key">لا يمكن قراءة مفتاح فتح الجهاز. يرجى حذفه وتكرار إجراء التعرف على الفتح.</string>
<string name="advanced_unlock_scanning_error">خطأ في فتح الجهاز: %1$s</string>
<string name="device_unlock_invalid_key">لا يمكن قراءة مفتاح فتح الجهاز. يرجى حذفه وتكرار إجراء التعرف على الفتح.</string>
<string name="menu_appearance_settings_summary">المظاهر والألوان والسمات</string>
<string name="autofill_explanation_summary">تمكين الملء التلقائي لملء النماذج بسرعة في التطبيقات الأخرى</string>
<string name="device_credential_unlock_enable_summary">يتيح لك استخدام بيانات اعتماد جهازك لفتح قاعدة البيانات</string>
@@ -657,37 +650,33 @@
<string name="unlock">فتح</string>
<string name="menu_app_settings_summary">البحث، القفل، التاريخ، الخصائص</string>
<string name="menu_form_filling_settings_summary">لوحة المفاتيح، الملء التلقائي، الحافظة</string>
<string name="advanced_unlock_keystore_warning">ستقوم هذه الميزة بتخزين بيانات الاعتماد المشفرة في KeyStore الآمن بجهازك.
<string name="device_unlock_keystore_warning">ستقوم هذه الميزة بتخزين بيانات الاعتماد المشفرة في KeyStore الآمن بجهازك.
\n
\nاعتمادًا على تطبيق API الأصلي لنظام التشغيل، قد لا يعمل بكامل طاقته.
\n
\nتحقق من توافق وأمن KeyStore مع الشركة المصنعة لجهازك ومنشئ ROM الذي تستخدمه.</string>
<string name="keyboard_selection_entry_summary">عند عرض إدخال في KeePassDX، عبئ Magikeyboard بهذا الإدخال</string>
<string name="keyboard_selection_entry_summary">عند عرض مدخل في KeePassDX، عبئ Magikeyboard بهذا المدخل</string>
<string name="enable_screenshot_mode_summary">اسمح لتطبيقات الطرف الثالث بتسجيل أو التقاط لقطات شاشة للتطبيق</string>
<string name="keyboard_save_search_info_summary">حاول حفظ المعلومات المشتركة عند إجراء اختيار إدخال يدوي لاستخدامات مستقبلية أسهل</string>
<string name="education_entry_edit_summary">تحرير الإدخال الخاص بك مع الحقول المخصصة. يمكن الرجوع إلى بيانات التجمع بين حقول الإدخال المختلفة.</string>
<string name="education_validate_entry_title">تحقق من صحة الإدخال</string>
<string name="education_validate_entry_summary">تذكر التحقق من صحة الإدخال الخاص بك وحفظ قاعدة البيانات الخاصة بك.
\n
\nإذا تم تنشيط القفل التلقائي ونسيت أنك تجري تعديلاً، فإنك تخاطر بفقدان بياناتك.</string>
<string name="education_entry_new_field_summary">قم بتسجيل حقل إضافي، أضف قيمة وقم بحمايته بشكل اختياري.</string>
<string name="education_unlock_summary">أدخل كلمة المرور و/أو ملف المفتاح لفتح قاعدة بياناتك.
\n
\nقم بعمل نسخة احتياطية من ملف قاعدة البيانات في مكان آمن بعد كل تغيير.</string>
<string name="keyboard_save_search_info_summary">حاول حفظ المعلومات المشتركة عند إجراء اختيار مدخل يدوي لاستخدامات مستقبلية أسهل</string>
<string name="education_entry_edit_summary">عدّل إدخالك مع الحقول المخصّصة. يمكن الرجوع إلى بيانات التجمع بين حقول مدخل المختلفة.</string>
<string name="education_validate_entry_title">تحقق من صحة المدخل</string>
<string name="education_validate_entry_summary">تذكر التحقق من صحة إدخالك وحفظ قاعدة بياناتك. \n \nإذا القفل التلقائي مُنشّط ونسيت أنك تجري تعديلاً، فإنك تخاطر بفقدان بياناتك.</string>
<string name="education_entry_new_field_summary">سجِّل حقلاً إضافيًا، أضف قيمة، واحمها اختياريًا.</string>
<string name="education_unlock_summary">أدخل كلمة السر و/أو ملف المفتاح لفتح قاعدة بياناتك. \n \nاحتفظ بنسخة احتياطية من ملف قاعدة البيانات في مكان آمن بعد كل تغيير.</string>
<string name="html_text_dev_feature_thanks">شكرا جزيلا لمساهمتك.</string>
<string name="at_least_one_char">على الأقل حرف واحد من كل منهما</string>
<string name="html_text_dev_feature_upgrade">تذكر أن تحافظ على تحديث تطبيقك عن طريق تثبيت إصدارات جديدة.</string>
<string name="download">تثبيت</string>
<string name="html_text_ad_free">على عكس العديد من تطبيقات إدارة كلمات المرور ، فإن هذا التطبيق &lt;strong&gt;بدون إعلانات&lt;/strong&gt;، و &lt;strong&gt;برنامج حر متروك الحقوق&lt;/strong&gt; ولا يجمع البيانات الشخصية على خوادمه، بغض النظر عن الإصدار الذي تستخدمه.</string>
<string name="html_text_ad_free">على عكس العديد من تطبيقات إدارة كلمات السر، هذا التطبيق &lt;strong&gt;خالٍ من الإعلانات&lt;/strong&gt;، و&lt;strong&gt;برنامج حر متروك الحقوق&lt;/strong&gt; ولا يجمع بيانات شخصية على خوادمه، بغض النظر عن الإصدار الذي تستخدمه.</string>
<string name="download_initialization">جارِ التهيئة…</string>
<string name="download_progression">قيد التقدم: %1$d%%</string>
<string name="html_text_buy_pro">بشراء الإصدار الاحترافي، ستتمتع بإمكانية الوصول إلى هذا &lt;strong&gt; النمط المرئي&lt;/strong&gt; وستساعد بشكل خاص في &lt;strong&gt; تنفيذ مشروعات المجتمع. &lt;/strong&gt;</string>
<string name="html_text_donation">من خلال &lt;strong&gt;المساهمة&lt;/strong&gt; في المشروع <i>(مالياً أو برمجياً أو ترجمة)</i>، ستساعده على الاستمرار في الحياة والازدهار، وستكون مؤهلاً أيضاً لإجراء فتح &lt;strong&gt;السمة&lt;/strong&gt;.</string>
<string name="html_text_donation">من خلال &lt;strong&gt;المساهمة&lt;/strong&gt; في المشروع &lt;i&gt;(مالياً أو برمجياً أو ترجمة)&lt;/i&gt;، ستساعده على الاستمرار في الحياة والازدهار، وستكون مؤهلاً أيضاً لإجراء فتح &lt;strong&gt;السمة&lt;/strong&gt;.</string>
<string name="html_text_dev_feature_encourage">أنت تشجع المطورين على إنشاء &lt;strong&gt; ميزات جديدة&lt;/strong&gt; و &lt;strong&gt; إصلاح الخلل&lt;/strong&gt; وفقًا لملاحظاتك.</string>
<string name="style_name_forest">غابة</string>
<string name="style_name_simple">بسيط</string>
<string name="style_name_moon">قمر</string>
<string name="style_name_divine">إلهي</string>
<string name="style_name_divine">فائق</string>
<string name="style_name_classic">كلاسيكي</string>
<string name="style_name_dark">داكن</string>
<string name="style_name_reply">رد</string>
@@ -697,10 +686,11 @@
<string name="style_name_follow_system">اتبع النظام</string>
<string name="style_name_light">فاتح</string>
<string name="hide_templates_summary">لا يتم عرض القوالب</string>
<string name="generate_keyfile">ولّد ملف المفتاح</string>
<string name="generate_keyfile">ولّد ملف مفتاح</string>
<string name="nodes">العُقد</string>
<string name="recursive_number_entries_title">عدد متكرر من الإدخالات</string>
<string name="recursive_number_entries_summary">يحسب بشكل متكرر عدد الإدخالات في المجموعة</string>
<string name="recursive_number_entries_title">عدد متكرر من المدخلات</string>
<string name="recursive_number_entries_summary">يحسب بشكل متكرر عدد المدخلات في المجموعة</string>
<string name="warning_large_keyfile">لا يُنصح بإضافة ملف مفتاحي كبير، فقد يؤدي هذا إلى منع فتح قاعدة البيانات.</string>
<string name="hide_templates_title">أخفِ القوالب</string>
<string name="error_otp_secret_length">يجب أن يتكوّن المفتاح السري من %1$d أحرف على الأقل.</string>
</resources>

View File

@@ -129,8 +129,8 @@
<string name="copy_field">%1$s nüsxələndi</string>
<string name="menu_form_filling_settings">Forum doldurma</string>
<string name="menu_form_filling_settings_summary">Klaviatura, avtomatik douldurma, mübadilə buferi</string>
<string name="menu_advanced_unlock_settings">Cihaz kilidini aç</string>
<string name="menu_advanced_unlock_settings_summary">Biometrik, cihaz şəxsiyyətini təyin edən məlumatlar</string>
<string name="menu_device_unlock_settings">Cihaz kilidini aç</string>
<string name="menu_device_unlock_settings_summary">Biometrik, cihaz şəxsiyyətini təyin edən məlumatlar</string>
<string name="menu_security_settings_summary">Şifrələmə, açar yaratma funskiyası</string>
<string name="menu_master_key_settings">Ana açar parametrləri</string>
<string name="settings">Parametrlər</string>
@@ -197,9 +197,8 @@
<string name="ask">Soruş</string>
<string name="configure">Kofiqurasiya et</string>
<string name="keystore_not_accessible">Açar ehtiyyatı düzgün formada başladılmadı.</string>
<string name="advanced_unlock_prompt_store_credential_title">Cihaz kilidini açma linki</string>
<string name="device_unlock_prompt_store_credential_title">Cihaz kilidini açma linki</string>
<string name="database_history">Tarixçə</string>
<string name="advanced_unlock_scanning_error">Cihaz kilidini açma xətası: %1$s</string>
<string name="warning_database_info_reloaded">Məlumat bazasını yenidən yükləmək lokal olaraq modifikasiya olunmuş faylları siləcəkdir.</string>
<string name="warning_database_revoked">Fayla giriş fayl meneceri tərəfindən ləğv edildi, məlumat bazasını bağlayın və onu olduğu yerdən yenidən açın.</string>
<string name="warning_exact_alarm">Siz tətəbiqin zəngli saatdan istifadə etməsinə icazə verməmisiniz. Nəticədə, taymer tələb edən funksiyalar dəqiq bir zamanda işləməyəckdir.</string>
@@ -210,11 +209,11 @@
<string name="configure_biometric">Biometrik və ya cihaz şəxsiyyəti ilə doğrulama məlumatları tapılmadı.</string>
<string name="biometric_security_update_required">Biometrik təhlükəsizlik yenilənməsi lazımdır.</string>
<string name="unlock_and_link_biometric">Cihaz kilid açma linki</string>
<string name="advanced_unlock_prompt_extract_credential_title">Cihaz kilidini tanıma</string>
<string name="device_unlock_prompt_extract_credential_title">Cihaz kilidini tanıma</string>
<string name="encrypted_value_stored">Şifrələnmiş şifrə ehtiyyata alındı</string>
<string name="advanced_unlock_not_recognized">Cihaz kilidini açmaq üçün barmaq izi tanınmadı</string>
<string name="device_unlock_not_recognized">Cihaz kilidini açmaq üçün barmaq izi tanınmadı</string>
<string name="unavailable">Mövcud deyil</string>
<string name="credential_before_click_advanced_unlock_button">Şifrəni yazın və sonra bu düyməyə basın.</string>
<string name="credential_before_click_device_unlock_button">Şifrəni yazın və sonra bu düyməyə basın.</string>
<string name="properties">Xüsusiyyətlər</string>
<string name="menu_appearance_settings">Görünüş</string>
<string name="menu_appearance_settings_summary">Tema, rəng və atributlar</string>
@@ -226,11 +225,11 @@
<string name="autofill_sign_in_prompt">KeePassDX ile giriş edin</string>
<string name="education_entry_new_field_title">Xüsusi bölmələr əlavə edin</string>
<string name="education_add_attachment_title">Qoşma əlavə edin</string>
<string name="advanced_unlock_explanation_summary">Məlumat bazasını daha asan açmaq üçün cihazın kilid açma funksiyasından istifadə edin</string>
<string name="device_unlock_explanation_summary">Məlumat bazasını daha asan açmaq üçün cihazın kilid açma funksiyasından istifadə edin</string>
<string name="device_credential_unlock_enable_summary">Məlumat bazasını açmaq üçün cihaz şəxsiyyət məlumatlarından istifadə etməyə imkan verir</string>
<string name="education_add_attachment_summary">Önəmli xarici məlumatları yadda saxlamaq üçün şifrənizə (qeyd) qoşma əlavə edin.</string>
<string name="temp_advanced_unlock_enable_title">Müvəqqəti kilid açma</string>
<string name="temp_advanced_unlock_timeout_title">Cihazın kilid açma müddəti bitdi</string>
<string name="temp_device_unlock_enable_title">Müvəqqəti kilid açma</string>
<string name="temp_device_unlock_timeout_title">Cihazın kilid açma müddəti bitdi</string>
<string name="unavailable_feature_version">Bu cihazda Andoird %1$s versiyası var, lakin %2$svə ya daha sonrakı versiya lazımdır.</string>
<string name="path">Yol</string>
<string name="unavailable_feature_hardware">Lazımi aparat-təchizat tapılmadı.</string>
@@ -256,7 +255,7 @@
<string name="device_credential_unlock_enable_title">Cihaz şəxsiyyət məlumatları ilə kilid açma</string>
<string name="biometric_auto_open_prompt_title">Avtomatik açma istəyi</string>
<string name="biometric_auto_open_prompt_summary">Məlumat bazası ondan istifadə ediləcək şəkildə quraşdırılıbsa, cihaz kilidini avtomatik olaraq tələb et</string>
<string name="temp_advanced_unlock_enable_summary">Cihaz kilidini açmaq üçün hər hansısa şifrələnmiş məzmunu saxlamayın</string>
<string name="temp_device_unlock_enable_summary">Cihaz kilidini açmaq üçün hər hansısa şifrələnmiş məzmunu saxlamayın</string>
<string name="biometric_delete_all_key_title">Şifrələnmiş açarları silin</string>
<string name="unavailable_feature_text">Bu funksiya işləmədi.</string>
<string name="file_name">Fayl adı</string>
@@ -342,7 +341,7 @@
<string name="clipboard_notifications_summary">Şifrəni göstərərkən sahələri (bölmə) nüsxələmək üçün mübadilə buferi bildirişlərini göstər</string>
<string name="clipboard_warning">Əgər mübadilə buferinin avtomatik silinməsi uğursuz olarsa, onun tarixçəsini əllə silin.</string>
<string name="html_text_ad_free">Digər bir çox şifrə menecerlerindən fərqli olaraq, bu tətbiq &lt;strong&gt;reklamsız&lt;/strong&gt;,&lt;strong&gt;azad lisenziyaya sahibdir&lt;/strong&gt; və hansı versiyanı istifadə etdiyinizdən asılı olmayaraq, şəxsi məlumatlarınızı öz serverlərində toplamır.</string>
<string name="advanced_unlock_keystore_warning">Bu xüsusiyyət, şifrələnən şəxsiyyəti təsdiq edən məlumatları cihazın təhlükəsiz açar bazasında saxlayacaqdır.\n\nƏməliyyat sisteminin yerli APİ-nin tətbiqindən asılı olaraq, tam olaraq funksional olmaya bilər.\n\nCihazın istehsalçısı və istifadə etdiyiniz ROM-un tərtibatçısı ilə açar bazasının uyğunluğu və təhlükəsizliyini yoxlayın.</string>
<string name="device_unlock_keystore_warning">Bu xüsusiyyət, şifrələnən şəxsiyyəti təsdiq edən məlumatları cihazın təhlükəsiz açar bazasında saxlayacaqdır.\n\nƏməliyyat sisteminin yerli APİ-nin tətbiqindən asılı olaraq, tam olaraq funksional olmaya bilər.\n\nCihazın istehsalçısı və istifadə etdiyiniz ROM-un tərtibatçısı ilə açar bazasının uyğunluğu və təhlükəsizliyini yoxlayın.</string>
<string name="autofill_inline_suggestions_title">Cümlə daxili təkliflər</string>
<string name="autofill_inline_suggestions_summary">Birbaşa uyğun olan klaviaturadan avtomatik doldurma təkliflərini göstərməyə çalış</string>
<string name="autofill_manual_selection_title">Əllə seçim</string>
@@ -350,7 +349,6 @@
<string name="autofill_save_search_info_title">Axtarış məlumatlarını yadda saxla</string>
<string name="autofill_inline_suggestions_keyboard">Avtomatik doldurma təklifləri əlavə edildi.</string>
<string name="allow_no_password_title">Ana açar olmamasına icazə ver</string>
<string name="enable_read_only_summary">Məlumat bazasını standart olaraq yazma-qorumalı (dəyişməz) aç</string>
<string name="enable_auto_save_database_title">Məlumat bazasını avtomatik olaraq yadda saxla</string>
<string name="reset_education_screens_summary">Bütün təlim məlumatlarını yenidən göstər</string>
<string name="reset_education_screens_text">Təlim ipuclarını sıfırlamaq</string>
@@ -514,10 +512,10 @@
<string name="warning_database_link_revoked">Fayla giriş icazəsi fayl meneceri tərəfindən rədd edildi</string>
<string name="warning_database_already_opened">Məlumat bazası artıq açıqdır, yenisi açmaq üçün öncə onu bağlayın</string>
<string name="warning_empty_password">Şifrə qoruması olmadan davam edilsinmi?</string>
<string name="advanced_unlock_prompt_store_credential_message">Cihazın kilid açma funksiyasından istifadə etsəniz belə, kassanın əsas şəxsiyyət təyin etmə məlumatlarını yenə də xatırlamaq lazımdır.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Cihazın kilid açma funksiyası ilə məlumat bazasının şəxsiyyətini tədiq edən məlumatlarını əldə edin</string>
<string name="advanced_unlock_invalid_key">Cihazın kilid açma açarı oxunmadı. Zəhmət olmazsa, onu silin və kilid açma prossesini təkrarlayın.</string>
<string name="advanced_unlock_prompt_not_initialized">Cihaz kilid açma istəyini başlatmaq mümkün deyil.</string>
<string name="device_unlock_prompt_store_credential_message">Cihazın kilid açma funksiyasından istifadə etsəniz belə, kassanın əsas şəxsiyyət təyin etmə məlumatlarını yenə də xatırlamaq lazımdır.</string>
<string name="device_unlock_prompt_extract_credential_message">Cihazın kilid açma funksiyası ilə məlumat bazasının şəxsiyyətini tədiq edən məlumatlarını əldə edin</string>
<string name="device_unlock_invalid_key">Cihazın kilid açma açarı oxunmadı. Zəhmət olmazsa, onu silin və kilid açma prossesini təkrarlayın.</string>
<string name="device_unlock_prompt_not_initialized">Cihaz kilid açma istəyini başlatmaq mümkün deyil.</string>
<string name="autofill_explanation_summary">Digər tətbiqlərdə formları (anket) daha sürətli doldurmaq üçün avtomatik doldurma funksiyasını aktiv edin</string>
<string name="autofill_select_entry">Şifrə seç .…</string>
<string name="set_autofill_service_title">Standart avtomatik doldurma xidmətini təyin edin</string>
@@ -536,12 +534,12 @@
<string name="lock_database_show_button_summary">İstifadəçi interfeysində kilid düyməsini göstərin</string>
<string name="content">Məzmun</string>
<string name="unlock">Kilidi aç</string>
<string name="advanced_unlock">Cihaz kilidini aç</string>
<string name="advanced_unlock_tap_delete">Cihaz kilid açma açarlarını silmək üçün toxunun</string>
<string name="temp_advanced_unlock_timeout_summary">Məzmununu silmədən öncə cihazın kilidini açma istifadə müddəti</string>
<string name="advanced_unlock_timeout">Cihaz kilidi açma taymout müddəti</string>
<string name="device_unlock">Cihaz kilidini aç</string>
<string name="device_unlock_tap_delete">Cihaz kilid açma açarlarını silmək üçün toxunun</string>
<string name="temp_device_unlock_timeout_summary">Məzmununu silmədən öncə cihazın kilidini açma istifadə müddəti</string>
<string name="device_unlock_timeout">Cihaz kilidi açma taymout müddəti</string>
<string name="biometric_delete_all_key_summary">Cihaz kilid açma tanıması ilə bağlı bütün şifrəli açarları silin</string>
<string name="advanced_unlock_delete_all_key_warning">Cihaz kilid açma tanıması ilə bağlı bütün şifrəli açarlar silinsinmi?</string>
<string name="device_unlock_delete_all_key_warning">Cihaz kilid açma tanıması ilə bağlı bütün şifrəli açarlar silinsinmi?</string>
<string name="database_data_remove_unlinked_attachments_summary">Məlumat bazasında olan, lakin şifrəyə bağlı olmayan qoşmaları silin</string>
<string name="max_history_items_summary">Hər şifrə başına düşən keçmiş məlumatların (fayl) sayını limitləyin</string>
<string name="monospace_font_fields_enable_title">Sahə (bölmə) yazı tipi</string>
@@ -573,7 +571,6 @@
<string name="allow_no_password_summary">Əgər şəxsiyyəti təsdiq edən məlumatlar seçilməyibsə, \"Aç\" düyməsinin sıxılmasına icazə ver</string>
<string name="delete_entered_password_title">Şifrəni sil</string>
<string name="delete_entered_password_summary">Məlumat bazasına bağlantı cəhdindən sonra daxil edilmiş şifrəni sil</string>
<string name="enable_read_only_title">Yazma qorumalı</string>
<string name="enable_auto_save_database_summary">Hər önəmli prossesdən sonra məlumat bazasını yadda saxla (\"Modifikasiya edilə bilən\" modda keçərlidir)</string>
<string name="enable_keep_screen_on_title">Ekranııq saxla</string>
<string name="enable_keep_screen_on_summary">Şifrəyə baxarkən və ya redaktə edərkən ekranııq saxla</string>
@@ -599,8 +596,8 @@
<string name="education_select_database_summary">İstifadəyə davam etmək üçün fayl brauzerinizdən əvvəlki məlumat bazası faylınıın.</string>
<string name="education_new_node_summary">Şifrələr rəqəmsal şəxsiyyəti təsdiq edən məlumatları idarə etməyinizə kömək edir.\n\nQruplar (~qovluqlar) məlumat bazasındakı şifrələri düzəltdir.</string>
<string name="education_search_title">Şifrələrdə axtarış edin</string>
<string name="education_advanced_unlock_title">Cihaz maəlumat bazası kilidini açma</string>
<string name="education_advanced_unlock_summary">Məlumat bazanızı daha sürətli açmaq üçün şifrənizi skan edilmiş biometriya və ya cihaz şəxsiyyəti təsdiq edən məlumatlarla əlaqələndirin.</string>
<string name="education_device_unlock_title">Cihaz maəlumat bazası kilidini açma</string>
<string name="education_device_unlock_summary">Məlumat bazanızı daha sürətli açmaq üçün şifrənizi skan edilmiş biometriya və ya cihaz şəxsiyyəti təsdiq edən məlumatlarla əlaqələndirin.</string>
<string name="education_entry_edit_summary">Şifrəyə özəl sahələrlə (bölmə) düzəliş edin. Ümumi məlumatlara müxtəlif şifrə sahələri arasında istinad edilə bilər.</string>
<string name="education_sort_title">Məlumatları (fayl) sıralayın</string>
<string name="education_sort_summary">Şifrə və qrupların necə sıralandığını seçin.</string>

View File

@@ -40,7 +40,7 @@
<string name="menu_master_key_settings">Postavke glavnog ključa</string>
<string name="menu_security_settings">Bezbednosne postavke</string>
<string name="menu_database_settings">Postavke baze podataka</string>
<string name="menu_advanced_unlock_settings">Napredno otključavanje</string>
<string name="menu_device_unlock_settings">Napredno otključavanje</string>
<string name="menu_form_filling_settings">Popunjavanje obrasca</string>
<string name="menu_app_settings">Postavke aplikacije</string>
<string name="settings">Postavke</string>
@@ -196,8 +196,8 @@
<string name="biometric_auto_open_prompt_title">Automatski otvori biometrijski upit</string>
<string name="biometric_unlock_enable_summary">Omogućava Vam da skenirate svoju biometriju da biste otvorili bazu podataka</string>
<string name="biometric_unlock_enable_title">Biometrijsko otključavanje</string>
<string name="advanced_unlock_explanation_summary">Koristite napredno otključavanje kako bi ste lakše otvorili bazu podataka</string>
<string name="advanced_unlock">Napredno otključavanje</string>
<string name="device_unlock_explanation_summary">Koristite napredno otključavanje kako bi ste lakše otvorili bazu podataka</string>
<string name="device_unlock">Napredno otključavanje</string>
<string name="education_unlock_summary">Unesite lozinku i/ili datoteku ključa da bi ste otključali bazu podataka.
\n
\nNapravite rezervnu kopiju datoteke baze podataka na bezbednom mestu nakon svake promene.</string>
@@ -394,7 +394,7 @@
<string name="error_driver_required">Potreban je drajver za %1$s.</string>
<string name="menu_app_settings_summary">Pretraga, zaključavanje, istorija, svojstva</string>
<string name="menu_form_filling_settings_summary">Tastatura, automatsko popunjavanje, klipbord</string>
<string name="menu_advanced_unlock_settings_summary">Biometrija, akreditiv uređaja</string>
<string name="menu_device_unlock_settings_summary">Biometrija, akreditiv uređaja</string>
<string name="menu_database_settings_summary">Metapodaci, korpa za otpatke, šabloni, istorija</string>
<string name="menu_security_settings_summary">Šifrovanje, funkcija izvođenja ključa</string>
<string name="master_key_settings_summary">Promena, obnova</string>

View File

@@ -0,0 +1,667 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="contact">Кантакт</string>
<string name="info">Iнфа</string>
<string name="contribution">Унёсак</string>
<string name="feedback">Зваротная сувязь</string>
<string name="homepage">Хатняя старонка</string>
<string name="about_description">Android рэалізацыя мэнэджара пароляў KeePass.</string>
<string name="accept">Прыняць</string>
<string name="add_entry">Дадаць запіс</string>
<string name="edit_entry">Рэдагаваць запіс</string>
<string name="add_group">Дадаць групу</string>
<string name="master_key">Галоўны ключ</string>
<string name="security">Бяспека</string>
<string name="encryption">Шыфраванне</string>
<string name="encryption_algorithm">Алгарытм шыфравання</string>
<string name="key_derivation_function">Функцыя вывядзення ключа</string>
<string name="app_timeout">Тайм-аўт</string>
<string name="app_timeout_summary">Час бяздзейнасці перад блакаваннем базы дадзеных</string>
<string name="application">Праграма</string>
<string name="extended_ASCII">Пашыраны ASCII</string>
<string name="file_manager_install_description">Каб ствараць, адкрываць і захоўваць файлы базы дадзеных, патрабуецца файлавы мэнэджар, які прымае дзеянні ACTION_CREATE_DOCUMENT і ACTION_OPEN_DOCUMENT.</string>
<string name="allow">Дазволіць</string>
<string name="clipboard_cleared">Буфер абмену ачышчаны</string>
<string name="clipboard_error_title">Памылка буфера абмену</string>
<string name="clipboard_error">Некаторыя прылады не дазваляюць праграмам выкарыстоўваць буфер абмену.</string>
<string name="clipboard_error_clear">Не ўдалося ачысціць буфер абмену</string>
<string name="clipboard_timeout">Тайм-аўт буфера абмену</string>
<string name="clipboard_timeout_summary">Працягласць захоўвання ў буферы абмену (калі падтрымліваецца прыладай)</string>
<string name="content_description_open_file">Адкрыць файл</string>
<string name="content_description_add_node">Дадаць вузел</string>
<string name="content_description_add_entry">Дадаць запіс</string>
<string name="content_description_add_group">Дадаць групу</string>
<string name="content_description_add_item">Дадаць элемент</string>
<string name="content_description_file_information">Інфармацыя пра файл</string>
<string name="content_description_credentials_information">Інфармацыя пра ўліковыя дадзеныя</string>
<string name="content_description_otp_information">Інфармацыя пра аднаразовы пароль</string>
<string name="brackets">Дужкі</string>
<string name="content_description_background">Фон</string>
<string name="content_description_node_children">Даччыныя вузлы</string>
<string name="content_description_password_checkbox">Сцяжок пароля</string>
<string name="content_description_keyfile_checkbox">Сцяжок файла ключа</string>
<string name="content_description_hardware_key_checkbox">Сцяжок апаратнага ключа</string>
<string name="content_description_repeat_toggle_password_visibility">Паўтарыць пераключэнне бачнасці пароля</string>
<string name="content_description_entry_icon">Значок запісу</string>
<string name="content_description_database_color">Колер базы дадзеных</string>
<string name="content_description_entry_foreground_color">Колер пярэдняга плану запісу</string>
<string name="content_description_entry_background_color">Колер фону запісу</string>
<string name="content_description_nav_header">Загаловак навігацыі</string>
<string name="navigation_drawer_open">Навігацыйны скрыню адкрыты</string>
<string name="navigation_drawer_close">Навігацыйны скрыню зачынены</string>
<string name="validate">Праверыць</string>
<string name="discard_changes">Адхіліць змены?</string>
<string name="discard">Адхіліць</string>
<string name="entry_password_generator">Генератар пароляў</string>
<string name="content_description_password_length">Даўжыня пароля</string>
<string name="content_description_passphrase_word_count">Колькасць слоў парольнай фразы</string>
<string name="entry_add_field">Дадаць поле</string>
<string name="entry_add_attachment">Дадаць укладанне</string>
<string name="content_description_remove_field">Выдаліць поле</string>
<string name="content_description_update_from_list">Абнавіць</string>
<string name="content_description_remove_from_list">Сцерці</string>
<string name="content_description_keyboard_close_fields">Закрыць палі</string>
<string name="select_to_copy">Выберыце, каб скапіяваць %1$s у буфер абмену</string>
<string name="retrieving_db_key">Атрыманне ключа базы дадзеных…</string>
<string name="waiting_challenge_request">Чаканне запыту выкліку…</string>
<string name="waiting_challenge_response">Чаканне адказу на выклік…</string>
<string name="database">База дадзеных</string>
<string name="template_group_name">Шаблоны</string>
<string name="decrypting_db">Расшыфроўка змесціва базы дадзеных…</string>
<string name="default_checkbox">Выкарыстоўваць як базу дадзеных па змаўчанні</string>
<string name="digits">Лічбы</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft з\'яўляецца &lt;strong&gt;праграмай з адкрытым зыходным кодам&lt;/strong&gt; і &lt;strong&gt;без рэкламы&lt;/strong&gt;. \nПрадастаўляецца «як ёсць», па ліцэнзіі &lt;strong&gt;GPLv3&lt;/strong&gt;, без якіх-небудзь гарантый.</string>
<string name="html_about_privacy">&lt;strong&gt;Карыстальніцкія дадзеныя не атрымліваюцца&lt;/strong&gt;, гэтая праграма не падключаецца да сервераў, працуе толькі лакальна і цалкам паважае прыватнасць карыстальнікаў.</string>
<string name="html_about_contribution">Каб &lt;strong&gt;захаваць нашу свабоду&lt;/strong&gt;, &lt;strong&gt;выпраўляць памылкі&lt;/strong&gt;, &lt;strong&gt;дадаваць функцыі&lt;/strong&gt; і &lt;strong&gt;заўсёды быць актыўнымі&lt;/strong&gt;, мы разлічваем на ваш &lt;strong&gt;уклад&lt;/strong&gt;.</string>
<string name="entry_accessed">Доступ</string>
<string name="entry_cancel">Адмена</string>
<string name="entry_notes">Заўвагі</string>
<string name="entry_confpassword">Пацвердзіць пароль</string>
<string name="entry_created">Створаны</string>
<string name="entry_expires">Тэрмін дзеяння</string>
<string name="expired">Скончыўся</string>
<string name="entry_UUID">UUID</string>
<string name="entry_history">Гісторыя</string>
<string name="entry_attachments">Укладанні</string>
<string name="entry_keyfile">Файл ключа</string>
<string name="hardware_key">Апаратны ключ</string>
<string name="entry_modified">Зменены</string>
<string name="searchable">Магчымасць пошуку</string>
<string name="inherited">Успадкаваць</string>
<string name="auto_type">Аўта-ўвод</string>
<string name="auto_type_sequence">Паслядоўнасць аўта-ўводу</string>
<string name="entry_not_found">Не ўдалося знайсці дадзеныя запісу.</string>
<string name="entry_password">Пароль</string>
<string name="tags">Тэгі</string>
<string name="custom_data">Карыстальніцкія дадзеныя</string>
<string name="save">Захаваць</string>
<string name="entry_title">Назва</string>
<string name="entry_setup_otp">Наладзіць аднаразовы пароль</string>
<string name="otp_type">Тып OTP</string>
<string name="otp_secret">Сакрэт</string>
<string name="otp_period">Перыяд (секунды)</string>
<string name="otp_counter">Лічыльнік</string>
<string name="otp_digits">Лічбы</string>
<string name="search_filters">Фільтры пошуку</string>
<string name="otp_algorithm">Алгарытм</string>
<string name="current_group">Цяперашняя група</string>
<string name="case_sensitive">З улікам рэгістра</string>
<string name="regex">Рэгулярны выраз</string>
<string name="debit_credit_card">Дэбетавая / Крэдытная карта</string>
<string name="holder">Уладальнік</string>
<string name="number">Нумар</string>
<string name="card_verification_value">CVV</string>
<string name="personal_identification_number">PIN</string>
<string name="id_card">Пасведчанне асобы</string>
<string name="name">Назва</string>
<string name="place_of_issue">Месца выдачы</string>
<string name="date_of_issue">Дата выдачы</string>
<string name="email">Электронная пошта</string>
<string name="email_address">Адрас электроннай пошты</string>
<string name="wireless">Wi-Fi</string>
<string name="ssid">SSID</string>
<string name="type">Тып</string>
<string name="cryptocurrency">Крыптавалютны кашалёк</string>
<string name="token">Токен</string>
<string name="public_key">Адкрыты ключ</string>
<string name="private_key">Закрыты ключ</string>
<string name="seed">Насенне</string>
<string name="account">Рахунак</string>
<string name="bank">Банк</string>
<string name="bank_name">Назва банка</string>
<string name="bank_identifier_code">SWIFT / BIC</string>
<string name="international_bank_account_number">IBAN</string>
<string name="secure_note">Бяспечная нататка</string>
<string name="membership">Членства</string>
<string name="standard">Стандартны</string>
<string name="template">Шаблон</string>
<string name="version">Версія</string>
<string name="entry_otp">OTP</string>
<string name="entry_url">URL</string>
<string name="entry_user_name">Імя карыстальніка</string>
<string name="error_arc4">Патокавы шыфр Arcfour не падтрымліваецца.</string>
<string name="error_can_not_handle_uri">Не ўдалося апрацаваць гэты URI ў KeePassDX.</string>
<string name="error_file_not_create">Не ўдалося стварыць файл.</string>
<string name="error_invalid_db">Не ўдалося прачытаць базу дадзеных.</string>
<string name="error_invalid_path">Пераканайцеся, што шлях правільны.</string>
<string name="error_invalid_OTP">Няправільны сакрэт OTP.</string>
<string name="error_no_name">Увядзіце імя.</string>
<string name="error_word_reserved">Гэтае слова зарэзервавана і не можа быць выкарыстана.</string>
<string name="error_nokeyfile">Выберыце файл ключа.</string>
<string name="error_no_hardware_key">Выберыце апаратны ключ.</string>
<string name="error_out_of_memory">Не хапае памяці для загрузкі ўсёй базы дадзеных.</string>
<string name="error_XML_malformed">XML мае няправільны фармат.</string>
<string name="error_load_database">Не ўдалося загрузіць базу дадзеных.</string>
<string name="error_load_database_KDF_memory">Не ўдалося загрузіць ключ. Паспрабуйце знізіць Выкарыстанне памяці KDF.</string>
<string name="error_pass_gen_type">Павінен быць абраны хаця б адзін тып генерацыі пароляў.</string>
<string name="error_disallow_no_credentials">Павінен быць усталяваны хаця б адзін набор уліковых дадзеных.</string>
<string name="error_pass_match">Паролі не супадаюць.</string>
<string name="error_rounds_too_large">Колькасць цыклаў пераўтварэння занадта высокая. Устаноўка 2147483648.</string>
<string name="error_string_key">Кожны радок павінен мець назву поля.</string>
<string name="error_label_exists">Гэтая метка ўжо існуе.</string>
<string name="error_wrong_length">Увядзіце станоўчае цэлае лік у полі Даўжыня.</string>
<string name="error_autofill_enable_service">Не ўдалося ўключыць службу аўтазапаўнення.</string>
<string name="error_move_group_here">Вы не можаце перамясціць групу сюды.</string>
<string name="error_move_entry_here">Вы не можаце перамясціць запіс сюды.</string>
<string name="error_copy_entry_here">Вы не можаце скапіяваць запіс сюды.</string>
<string name="error_copy_group_here">Вы не можаце скапіяваць групу сюды.</string>
<string name="error_create_database">Немагчыма стварыць файл базы дадзеных.</string>
<string name="error_create_database_file">Немагчыма стварыць базу дадзеных з гэтым паролем і файлам ключа.</string>
<string name="error_save_database">Не ўдалося захаваць базу дадзеных.</string>
<string name="error_otp_secret_key">Сакрэтны ключ павінен быць у фармаце Base32.</string>
<string name="error_otp_secret_length">Даўжыня сакрэтнага ключа павінна быць не менш за %1$d сімвалаў.</string>
<string name="error_otp_counter">Лічыльнік павінен быць паміж %1$d і %2$d.</string>
<string name="error_otp_period">Перыяд павінен быць ад %1$d да %2$d секунд.</string>
<string name="error_otp_digits">Токен павінен утрымоўваць ад %1$d да %2$d лічбаў.</string>
<string name="error_otp_type">Існуючы тып OTP не распазнаецца гэтай формай, яго праверка можа больш не генераваць токен правільна.</string>
<string name="error_string_type">Гэты тэкст не супадае з запытаным элементам.</string>
<string name="error_registration_read_only">Захаванне новага элемента недапушчальна ў базе дадзеных, адкрытай толькі для чытання.</string>
<string name="error_field_name_already_exists">Назва поля ўжо існуе.</string>
<string name="error_database_uri_null">Немагчыма атрымаць URI базы дадзеных.</string>
<string name="error_rebuild_list">Не ўдалося правільна аднавіць спіс.</string>
<string name="error_file_to_big">Файл, які вы спрабуеце загрузіць, занадта вялікі.</string>
<string name="error_upload_file">Адбылася памылка пры загрузцы дадзеных файла.</string>
<string name="error_duplicate_file">Дадзеныя файла ўжо існуюць.</string>
<string name="error_remove_file">Адбылася памылка пры выдаленні дадзеных файла.</string>
<string name="error_start_database_action">Адбылася памылка пры выкананні дзеянняў з базай дадзеных.</string>
<string name="error_challenge_already_requested">Выклік ужо запытаны.</string>
<string name="error_response_already_provided">Адказнае дзеянне ўжо выканана.</string>
<string name="error_no_response_from_challenge">Немагчыма атрымаць адказ на выклік.</string>
<string name="error_cancel_by_user">Скасавана карыстальнікам.</string>
<string name="error_driver_required">Патрабуецца драйвер для %1$s.</string>
<string name="error_unable_merge_database_kdb">Немагчыма аб\'яднаць з файламі базы дадзеных kdb.</string>
<string name="error_location_unknown">Месцазнаходжанне базы дадзеных невядома, дзеянне з базай дадзеных не можа быць выканана.</string>
<string name="error_hardware_key_unsupported">Апаратны ключ не падтрымліваецца.</string>
<string name="error_empty_key">Ключ не можа быць пустым.</string>
<string name="field_name">Назва поля</string>
<string name="field_value">Значэнне поля</string>
<string name="file_not_found_content">Не ўдалося знайсці файл. Паспрабуйце зноў адкрыць яго з файлавага мэнэджара.</string>
<string name="corrupted_file">Пашкоджаны файл.</string>
<string name="file_browser">Файлавы мэнэджар</string>
<string name="generate_password">Стварыць пароль</string>
<string name="generate_keyfile">Стварыць файл ключа</string>
<string name="hint_conf_pass">Пацвердзіць пароль</string>
<string name="hint_generated_password">Згенераваны пароль</string>
<string name="hint_group_name">Назва групы</string>
<string name="hint_icon_name">Назва значка</string>
<string name="hint_keyfile">Файл ключа</string>
<string name="hint_length">Даўжыня</string>
<string name="hint_pass">Пароль</string>
<string name="password">Пароль</string>
<string name="passphrase">Парольная фраза</string>
<string name="invalid_credentials">Не ўдалося прачытаць уліковыя дадзеныя.</string>
<string name="invalid_algorithm">Няправільны алгарытм.</string>
<string name="invalid_db_same_uuid">%1$s з такім жа UUID %2$s ужо існуе.</string>
<string name="invalid_db_sig">Не ўдалося распазнаць фармат базы дадзеных.</string>
<string name="keyfile_is_empty">Файл ключа пусты.</string>
<string name="length">Даўжыня</string>
<string name="nodes">Вузлы</string>
<string name="hide_password_title">Схаваць паролі</string>
<string name="hide_password_summary">Маскіраваць паролі (***) па змаўчанні</string>
<string name="colorize_password_title">Размаляваць паролі</string>
<string name="colorize_password_summary">Размаляваць сімвалы пароля па тыпу</string>
<string name="list_entries_show_username_title">Паказаць імёны карыстальнікаў</string>
<string name="list_entries_show_username_summary">Адлюстроўвае імёны карыстальнікаў у спісах запісаў</string>
<string name="list_groups_show_number_entries_title">Паказаць колькасць запісаў</string>
<string name="list_groups_show_number_entries_summary">Адлюстроўвае колькасць запісаў у групе</string>
<string name="recursive_number_entries_title">Рэкурсіўная колькасць запісаў</string>
<string name="recursive_number_entries_summary">Рэкурсіўна падлічвае колькасць запісаў у групе</string>
<string name="show_otp_token_title">Паказаць токен OTP</string>
<string name="show_otp_token_summary">Адлюстроўвае токены OTP у спісе запісаў</string>
<string name="show_uuid_title">Паказаць UUID</string>
<string name="show_uuid_summary">Адлюстроўвае UUID, прывязаны да запісу або групы</string>
<string name="list_size_title">Памер элементаў спісу</string>
<string name="list_size_summary">Памер тэксту ў спісе элементаў</string>
<string name="creating_database">Стварэнне базы дадзеных…</string>
<string name="loading_database">Загрузка базы дадзеных…</string>
<string name="lowercase">Ніжні рэгістр</string>
<string name="about">Аб праграме</string>
<string name="menu_change_key_settings">Змяніць галоўны ключ</string>
<string name="copy_field">Копія %1$s</string>
<string name="settings">Налады</string>
<string name="menu_app_settings">Налады праграмы</string>
<string name="menu_app_settings_summary">Пошук, блакаванне, гісторыя, уласцівасці</string>
<string name="menu_form_filling_settings">Запаўненне формы</string>
<string name="menu_form_filling_settings_summary">Клавіятура, аўтазапаўненне, буфер абмену</string>
<string name="menu_device_unlock_settings">Разблакіроўка прылады</string>
<string name="menu_device_unlock_settings_summary">Біяметрыя, уліковыя дадзеныя прылады</string>
<string name="menu_database_settings">Налады базы дадзеных</string>
<string name="menu_database_settings_summary">Метададзеныя, смеццевая скрыня, шаблоны, гісторыя</string>
<string name="menu_security_settings">Налады бяспекі</string>
<string name="menu_security_settings_summary">Шыфраванне, функцыя вывядзення ключа</string>
<string name="menu_master_key_settings">Налады галоўнага ключа</string>
<string name="master_key_settings_summary">Змена, аднаўленне</string>
<string name="menu_donate">Ахвяраваць</string>
<string name="menu_edit">Рэдагаваць</string>
<string name="menu_copy">Капіяваць</string>
<string name="menu_move">Перамясціць</string>
<string name="menu_paste">Уставіць</string>
<string name="menu_delete">Выдаліць</string>
<string name="menu_cancel">Адмена</string>
<string name="menu_hide_password">Схаваць пароль</string>
<string name="menu_lock">Заблакаваць базу дадзеных</string>
<string name="menu_save_database">Захаваць дадзеныя</string>
<string name="menu_merge_database">Аб\'яднаць дадзеныя</string>
<string name="menu_reload_database">Перазагрузіць дадзеныя</string>
<string name="menu_merge_from">Аб\'яднаць з…</string>
<string name="menu_save_copy_to">Захаваць копію ў…</string>
<string name="menu_open">Адкрыць</string>
<string name="menu_search">Пошук</string>
<string name="menu_showpass">Паказаць пароль</string>
<string name="menu_keystore_remove_key">Выдаліць ключ разблакіроўкі прылады</string>
<string name="menu_url">Перайсці па URL</string>
<string name="menu_file_selection_read_only">Абаронены ад запісу</string>
<string name="menu_open_file_read_and_write">З магчымасцю змены</string>
<string name="menu_empty_recycle_bin">Ачысціць смеццевую скрыню</string>
<string name="menu_restore_entry_history">Аднавіць гісторыю</string>
<string name="menu_delete_entry_history">Выдаліць гісторыю</string>
<string name="menu_external_icon">Знешні значок</string>
<string name="minus">Мінус</string>
<string name="never">Ніколі</string>
<string name="no_results">Няма вынікаў пошуку</string>
<string name="no_url_handler">Усталюйце вэб-браўзер, каб адкрыць гэты URL.</string>
<string name="select_database_file">Адкрыць існуючае сховішча</string>
<string name="create_keepass_file">Стварыць новае сховішча</string>
<string name="auto_focus_search_title">Хуткі пошук</string>
<string name="auto_focus_search_summary">Запытаць пошук пры адкрыцці базы дадзеных</string>
<string name="subdomain_search_title">Пошук па паддаменах</string>
<string name="subdomain_search_summary">Пошук вэб-даменаў з абмежаваннямі паддаменаў</string>
<string name="progress_create">Стварэнне новай базы дадзеных…</string>
<string name="progress_title">Працую…</string>
<string name="protection">Абарона</string>
<string name="read_only">Абаронены ад запісу</string>
<string name="read_only_warning">У залежнасці ад вашага файлавага мэнэджара, KeePassDX можа не мець дазволу на запіс у сховішча.</string>
<string name="contains_duplicate_uuid">База дадзеных змяшчае дублікаты UUID.</string>
<string name="contains_duplicate_uuid_procedure">Вырашыць праблему шляхам генерацыі новых UUID для дублікатаў, каб працягнуць?</string>
<string name="search_mode">Рэжым пошуку</string>
<string name="save_mode">Рэжым захавання</string>
<string name="selection_mode">Рэжым выбару</string>
<string name="registration_mode">Рэжым рэгістрацыі</string>
<string name="remember_database_locations_title">Запамінаць размяшчэнне баз дадзеных</string>
<string name="remember_database_locations_summary">Адсочвае, дзе захоўваюцца базы дадзеных</string>
<string name="remember_keyfile_locations_title">Запамінаць размяшчэнне файлаў ключоў</string>
<string name="remember_keyfile_locations_summary">Адсочвае, дзе захоўваюцца файлы ключоў</string>
<string name="remember_hardware_key_title">Запамінаць апаратныя ключы</string>
<string name="remember_hardware_key_summary">Адсочвае выкарыстаныя апаратныя ключы</string>
<string name="show_recent_files_title">Паказваць апошнія файлы</string>
<string name="show_recent_files_summary">Паказваць размяшчэнне нядаўніх баз дадзеных</string>
<string name="hide_broken_locations_title">Схаваць зламаныя спасылкі на базы дадзеных</string>
<string name="hide_broken_locations_summary">Схаваць зламаныя спасылкі ў спісе нядаўніх баз дадзеных</string>
<string name="import_app_properties_title">Імпартаваць налады праграмы</string>
<string name="import_app_properties_summary">Выберыце файл для імпарту налад праграмы</string>
<string name="export_app_properties_title">Экспартаваць налады праграмы</string>
<string name="export_app_properties_summary">Стварыць файл для экспарту налад праграмы</string>
<string name="description_app_properties">Уласцівасці KeePassDX для кіравання наладамі праграмы</string>
<string name="success_import_app_properties">Налады праграмы імпартаваны</string>
<string name="error_import_app_properties">Памылка падчас імпарту налад праграмы.</string>
<string name="success_export_app_properties">Налады праграмы экспартаваны</string>
<string name="error_export_app_properties">Памылка падчас экспарту налад праграмы.</string>
<string name="root">Корань</string>
<string name="encryption_explanation">Алгарытм шыфравання базы дадзеных, які выкарыстоўваецца для ўсіх дадзеных</string>
<string name="kdf_explanation">Каб стварыць ключ для алгарытму шыфравання, галоўны ключ пераўтворыцца з дапамогай выпадкова саленай функцыі вывядзення ключа.</string>
<string name="rounds">Цыклы пераўтварэння</string>
<string name="rounds_explanation">Дадатковыя цыклы шыфравання забяспечваюць больш высокую абарону ад нападаў грубай сілы, але могуць моцна запаволіць загрузку і захаванне.</string>
<string name="memory_usage">Выкарыстанне памяці</string>
<string name="memory_usage_explanation">Аб\'ём памяці, які будзе выкарыстоўвацца функцыяй вывядзення ключа.</string>
<string name="parallelism">Паралелізм</string>
<string name="parallelism_explanation">Ступень паралелізму (г.зн. колькасць патокаў), выкарыстоўваных функцыяй вывядзення ключа.</string>
<string name="saving_database">Захаванне базы дадзеных…</string>
<string name="command_execution">Выкананне каманды…</string>
<string name="do_not_kill_app">Не зачыняйце праграму…</string>
<string name="space">Прабел</string>
<string name="filter">Фільтр</string>
<string name="sort_menu">Сартаваць</string>
<string name="sort_ascending">Спачатку ніжэйшыя ↓</string>
<string name="sort_groups_before">Групы спачатку</string>
<string name="sort_recycle_bin_bottom">Смеццевая скрыня ўнізе</string>
<string name="sort_db">Натуральны парадак</string>
<string name="sort_title">Назва</string>
<string name="sort_username">Імя карыстальніка</string>
<string name="sort_creation_time">Стварэнне</string>
<string name="sort_last_modify_time">Змена</string>
<string name="sort_last_access_time">Доступ</string>
<string name="special">Спецыяльныя</string>
<string name="search">Пошук</string>
<string name="underline">Падкрэсліванне</string>
<string name="unsupported_db_version">Непадтрымліваемая версія базы дадзеных.</string>
<string name="uppercase">ВЕРХНІ РЭГІСТР</string>
<string name="warning">Папярэджанне</string>
<string name="warning_password_encoding">Пазбягайце сімвалаў пароляў па-за межамі фармату кадоўкі тэксту ў файле базы дадзеных (нераспазнаныя сімвалы пераўтвараюцца ў адну і тую ж літару).</string>
<string name="warning_database_read_only">Дайце дазвол на запіс у файл, каб захаваць змены ў базе дадзеных</string>
<string name="warning_database_link_revoked">Доступ да файла скасаваны файлавым мэнэджарам</string>
<string name="warning_database_already_opened">База дадзеных ужо адкрыта, спачатку зачыніце яе, каб адкрыць новую</string>
<string name="warning_empty_password">Працягнуць без абароны блакаваннем паролем?</string>
<string name="warning_no_encryption_key">Працягнуць без ключа шыфравання?</string>
<string name="warning_permanently_delete_nodes">Беззваротна выдаліць выбраныя вузлы?</string>
<string name="warning_empty_recycle_bin">Беззваротна выдаліць усе вузлы са смеццевай скрыні?</string>
<string name="warning_file_too_big">База дадзеных KeePass павінна ўтрымліваць толькі невялікія службовыя файлы (напрыклад, файлы PGP-ключа).\n\nВаша база дадзеных можа стаць вельмі вялікай і знізіць прадукцыйнасць пасля гэтай загрузкі.</string>
<string name="warning_replace_file">Загрузка гэтага файла заменіць існуючы.</string>
<string name="warning_sure_add_file">Усё роўна дадаць файл?</string>
<string name="warning_remove_unlinked_attachment">Выдаленне незвязаных дадзеных можа паменшыць памер вашай базы дадзеных, але таксама можа выдаліць дадзеныя, якія выкарыстоўваюцца для плагінаў KeePass.</string>
<string name="warning_sure_remove_data">Усё роўна выдаліць гэтыя дадзеныя?</string>
<string name="warning_empty_keyfile">Не рэкамендуецца дадаваць пусты файл ключа.</string>
<string name="warning_large_keyfile">Не рэкамендуецца дадаваць вялікі файл ключа, гэта можа перашкодзіць адкрыццю базы дадзеных.</string>
<string name="warning_empty_keyfile_explanation">Змесціва файла ключа ніколі не павінна змяняцца, і ў лепшым выпадку, павінна ўтрымліваць выпадкова згенераваныя дадзеныя.</string>
<string name="warning_database_info_changed">Інфармацыя, якая змяшчаецца ў файле базы дадзеных, была зменена па-за межамі праграмы.</string>
<string name="warning_database_info_changed_options">Аб\'яднаць дадзеныя, захаваць базу дадзеных з перазапісам знешніх мадыфікацый або перазагрузіць яе з апошнімі зменамі.</string>
<string name="warning_database_info_changed_options_read_only">Перазагрузіць базу дадзеных з апошнімі зменамі.</string>
<string name="warning_database_info_reloaded">Перазагрузка базы дадзеных выдаліць лакальна змененыя дадзеныя.</string>
<string name="warning_database_revoked">Доступ да файла скасаваны файлавым мэнэджарам, зачыніце базу дадзеных і зноў адкрыйце яе з яе месцазнаходжання.</string>
<string name="warning_exact_alarm">Вы не дазволілі праграме выкарыстоўваць дакладны таймер. У выніку функцыі, якія патрабуюць таймера, не будуць выкананы з дакладным часам.</string>
<string name="warning_keyfile_integrity">Цэласнасць файла не гарантуецца, бо Android можа змяняць яго дадзеныя на хаду. Зменіце пашырэнне файла на .bin для правільнай цэласнасці.</string>
<string name="warning_database_notification_permission">Дазвол на апавяшчэнні дазваляе адлюстроўваць статус базы дадзеных і блакаваць яе з дапамогай лёгкадаступнай кнопкі.\n\nКалі вы не актывуеце гэты дазвол, база дадзеных, адкрытая ў фонавым рэжыме, не будзе бачная, калі на пярэднім плане знаходзіцца іншая праграма.</string>
<string name="warning_copy_permission">Дазвол на апавяшчэнні неабходны для выкарыстання функцыі апавяшчэння аб буферы абмену.</string>
<string name="later">Пазней</string>
<string name="ask">Спытаць</string>
<string name="merge_success">Аб\'яднанне паспяхова завершана</string>
<string name="permission">Дазвол</string>
<string name="version_label">Версія %1$s</string>
<string name="build_label">Зборка %1$s</string>
<string name="configure">Наладзіць</string>
<string name="configure_biometric">Біяметрычныя або ўліковыя дадзеныя прылады не зарэгістраваны.</string>
<string name="biometric_security_update_required">Патрабуецца абнаўленне біяметрычнай бяспекі.</string>
<string name="keystore_not_accessible">Сховішча ключоў неналежным чынам ініцыялізавана.</string>
<string name="unlock_and_link_biometric">Спасылка на разблакіроўку прылады</string>
<string name="device_unlock_prompt_store_credential_title">Спасылка на разблакіроўку прылады</string>
<string name="device_unlock_prompt_store_credential_message">Вам усё роўна трэба памятаць асноўныя ўліковыя дадзеныя сховішча, калі вы выкарыстоўваеце распазнаванне разблакіроўкі прылады.</string>
<string name="device_unlock_prompt_extract_credential_title">Распазнаванне разблакіроўкі прылады</string>
<string name="device_unlock_prompt_extract_credential_message">Выняць уліковыя дадзеныя базы дадзеных з дапамогай дадзеных разблакіроўкі прылады</string>
<string name="encrypted_value_stored">Зашыфраваны пароль захаваны</string>
<string name="device_unlock_invalid_key">Немагчыма прачытаць ключ разблакіроўкі прылады. Выдаліце яго і паўтарыце працэдуру распазнавання разблакіроўкі.</string>
<string name="device_unlock_not_recognized">Не ўдалося распазнаць адбітак разблакіроўкі прылады</string>
<string name="unavailable">Недаступна</string>
<string name="device_unlock_prompt_not_initialized">Немагчыма ініцыялізаваць запыт разблакіроўкі прылады.</string>
<string name="credential_before_click_device_unlock_button">Увядзіце пароль, а затым націсніце гэтую кнопку.</string>
<string name="database_history">Гісторыя</string>
<string name="properties">Уласцівасці</string>
<string name="menu_appearance_settings">Знешні выгляд</string>
<string name="menu_appearance_settings_summary">Тэмы, колеры, атрыбуты</string>
<string name="biometric">Біяметрычны</string>
<string name="device_credential">Уліковыя дадзеныя прылады</string>
<string name="general">Агульнае</string>
<string name="autofill">Аўтазапаўненне</string>
<string name="autofill_service_name">Аўтазапаўненне формы KeePassDX</string>
<string name="autofill_sign_in_prompt">Увайсці з дапамогай KeePassDX</string>
<string name="autofill_explanation_summary">Уключыце аўтазапаўненне, каб хутка запаўняць формы ў іншых праграмах</string>
<string name="autofill_select_entry">Выбраць запіс…</string>
<string name="set_autofill_service_title">Усталяваць службу аўтазапаўнення па змаўчанні</string>
<string name="autofill_preference_title">Налады аўтазапаўнення</string>
<string name="password_size_title">Памер згенераванага пароля</string>
<string name="password_size_summary">Усталёўвае памер згенераваных пароляў па змаўчанні</string>
<string name="list_password_generator_options_title">Сімвалы пароля</string>
<string name="list_password_generator_options_summary">Усталяваць дазволеныя сімвалы генератара пароляў</string>
<string name="database_opened">База дадзеных адкрыта</string>
<string name="clipboard">Буфер абмену</string>
<string name="clipboard_explanation_summary">Капіюйце палі запісу, выкарыстоўваючы буфер абмену вашай прылады</string>
<string name="clipboard_notifications_title">Апавяшчэнні буфера абмену</string>
<string name="clipboard_notifications_summary">Паказваць апавяшчэнні буфера абмену, каб капіяваць палі пры праглядзе запісу</string>
<string name="clipboard_warning">Калі аўтаматычнае выдаленне з буфера абмену не ўдаецца, выдаліце яго гісторыю ўручную.</string>
<string name="lock">Блакаванне</string>
<string name="lock_database_screen_off_title">Блакаванне экрана</string>
<string name="lock_database_screen_off_summary">Блакаваць базу дадзеных праз некалькі секунд пасля выключэння экрана</string>
<string name="lock_database_back_root_title">Націснуць «Назад», каб заблакаваць</string>
<string name="lock_database_back_root_summary">Блакаваць базу дадзеных, калі карыстальнік націскае кнопку «Назад» на галоўным экране</string>
<string name="lock_database_show_button_title">Паказаць кнопку блакавання</string>
<string name="lock_database_show_button_summary">Адлюстроўвае кнопку блакавання ў карыстальніцкім інтэрфейсе</string>
<string name="content">Змесціва</string>
<string name="unlock">Разблакіраваць</string>
<string name="device_unlock">Разблакіроўка прылады</string>
<string name="device_unlock_tap_delete">Націсніце, каб выдаліць ключы разблакіроўкі прылады</string>
<string name="device_unlock_explanation_summary">Выкарыстоўвайце разблакіроўку прылады, каб лягчэй адкрываць базу дадзеных</string>
<string name="biometric_unlock_enable_title">Біяметрычная разблакіроўка</string>
<string name="biometric_unlock_enable_summary">Дазваляе сканаваць біяметрыю для адкрыцця базы дадзеных</string>
<string name="device_credential_unlock_enable_title">Разблакіроўка з дапамогай уліковых дадзеных прылады</string>
<string name="device_credential_unlock_enable_summary">Дазваляе выкарыстоўваць уліковыя дадзеныя прылады для адкрыцця базы дадзеных</string>
<string name="biometric_auto_open_prompt_title">Запыт на аўтаматычнае адкрыццё</string>
<string name="biometric_auto_open_prompt_summary">Аўтаматычна запытваць разблакіроўку прылады, калі база дадзеных наладжана на яе выкарыстанне</string>
<string name="temp_device_unlock_enable_title">Часовая разблакіроўка прылады</string>
<string name="temp_device_unlock_enable_summary">Не захоўваць зашыфраванае змесціва для выкарыстання разблакіроўкі прылады</string>
<string name="temp_device_unlock_timeout_title">Тэрмін дзеяння разблакіроўкі прылады</string>
<string name="temp_device_unlock_timeout_summary">Працягласць выкарыстання разблакіроўкі прылады перад выдаленнем яе змесціва</string>
<string name="device_unlock_timeout">Тайм-аўт разблакіроўкі прылады</string>
<string name="biometric_delete_all_key_title">Выдаліць ключы шыфравання</string>
<string name="biometric_delete_all_key_summary">Выдаліць усе ключы шыфравання, звязаныя з распазнаваннем разблакіроўкі прылады</string>
<string name="device_unlock_delete_all_key_warning">Выдаліць усе ключы шыфравання, звязаныя з распазнаваннем разблакіроўкі прылады?</string>
<string name="device_unlock_keystore_warning">Гэтая функцыя будзе захоўваць зашыфраваныя дадзеныя ўліковых дадзеных у бяспечным Keystore вашай прылады.\n\nУ залежнасці ад рэалізацыі натыўнага API аперацыйнай сістэмы, яна можа быць не цалкам функцыянальнай.\n\nПраверце сумяшчальнасць і бяспеку Keystore з вытворцам вашай прылады і стваральнікам ПЗ, якое вы выкарыстоўваеце.</string>
<string name="unavailable_feature_text">Не ўдалося запусціць гэтую функцыю.</string>
<string name="unavailable_feature_version">Прылада працуе на Android %1$s, але патрабуецца %2$s або больш позняя версія.</string>
<string name="unavailable_feature_hardware">Не ўдалося знайсці адпаведнае апаратнае забеспячэнне.</string>
<string name="file_name">Імя файла</string>
<string name="path">Шлях</string>
<string name="assign_master_key">Прызначыць галоўны ключ</string>
<string name="data">Дадзеныя</string>
<string name="database_data_compression_title">Сцісканне дадзеных</string>
<string name="database_data_compression_summary">Сцісканне дадзеных памяншае памер базы дадзеных</string>
<string name="database_data_remove_unlinked_attachments_title">Выдаліць незвязаныя дадзеныя</string>
<string name="database_data_remove_unlinked_attachments_summary">Выдаляе ўкладанні, якія змяшчаюцца ў базе дадзеных, але не звязаны з запісам</string>
<string name="recycle_bin_title">Выкарыстанне смеццевай скрыні</string>
<string name="recycle_bin_summary">Перамяшчае групы і запісы ў групу Смеццевая скрыня перад выдаленнем</string>
<string name="recycle_bin_group_title">Група смеццевай скрыні</string>
<string name="templates_group_enable_title">Выкарыстанне шаблонаў</string>
<string name="templates_group_enable_summary">Выкарыстоўвайце дынамічныя шаблоны для запаўнення палёў запісу</string>
<string name="templates_group_uuid_title">Група шаблонаў</string>
<string name="max_history_items_title">Максімальная колькасць</string>
<string name="max_history_items_summary">Абмежаваць колькасць элементаў гісторыі на запіс</string>
<string name="max_history_size_title">Максімальны памер</string>
<string name="max_history_size_summary">Абмежаваць памер гісторыі на запіс</string>
<string name="settings_database_recommend_changing_master_key_title">Рэкамендаваць абнаўленне</string>
<string name="settings_database_recommend_changing_master_key_summary">Рэкамендаваць змену галоўнага ключа (дні)</string>
<string name="settings_database_force_changing_master_key_title">Прымусовае абнаўленне</string>
<string name="settings_database_force_changing_master_key_summary">Патрабаваць змены галоўнага ключа (дні)</string>
<string name="settings_database_force_changing_master_key_next_time_title">Прымусовае абнаўленне наступным разам</string>
<string name="settings_database_force_changing_master_key_next_time_summary">Патрабаваць змены галоўнага ключа ў наступны раз (адзін раз)</string>
<string name="monospace_font_fields_enable_title">Шрыфт поля</string>
<string name="monospace_font_fields_enable_summary">Змяніць шрыфт, які выкарыстоўваецца ў палях, для лепшай бачнасці сімвалаў</string>
<string name="allow_copy_password_title">Давер буфера абмену</string>
<string name="allow_copy_password_summary">Дазволіць капіяванне пароля запісу і абароненых палёў у буфер абмену</string>
<string name="allow_copy_password_warning">Папярэджанне: Буфер абмену выкарыстоўваецца ўсімі праграмамі. Калі капіююцца канфідэнцыйныя дадзеныя, іншае праграмнае забеспячэнне можа аднавіць іх.</string>
<string name="enable">Уключыць</string>
<string name="disable">Адключыць</string>
<string name="notification">Апавяшчэнне</string>
<string name="clear_clipboard_notification_title">Ачысціць пры закрыцці</string>
<string name="clear_clipboard_notification_summary">Блакаваць базу дадзеных пасля заканчэння тэрміну дзеяння буфера абмену або закрыцця апавяшчэння пасля пачатку выкарыстання</string>
<string name="database_name_title">Назва базы дадзеных</string>
<string name="database_description_title">Апісанне базы дадзеных</string>
<string name="database_default_username_title">Імя карыстальніка па змаўчанні</string>
<string name="database_custom_color_title">Карыстальніцкі колер базы дадзеных</string>
<string name="database_version_title">Версія базы дадзеных</string>
<string name="text_appearance">Тэкст</string>
<string name="application_appearance">Інтэрфейс</string>
<string name="other">Іншае</string>
<string name="compression">Сцісканне</string>
<string name="compression_none">Няма</string>
<string name="compression_gzip">Gzip</string>
<string name="recycle_bin">Смеццевая скрыня</string>
<string name="templates">Шаблоны</string>
<string name="keyboard">Клавіятура</string>
<string name="magic_keyboard_title">Магічная клавіятура</string>
<string name="magic_keyboard_explanation_summary">Актываваць карыстальніцкую клавіятуру, якая запаўняе вашыя паролі і ўсе палі ідэнтычнасці</string>
<string name="device_keyboard_setting_title">Налады клавіятуры прылады</string>
<string name="keyboard_name">Магічная клавіятура</string>
<string name="keyboard_label">Магічная клавіятура (KeePassDX)</string>
<string name="keyboard_setting_label">Налады магічнай клавіятуры</string>
<string name="keyboard_entry_category">Запіс</string>
<string name="keyboard_selection_entry_title">Выбар запісу</string>
<string name="keyboard_selection_entry_summary">Пры праглядзе запісу ў KeePassDX, запоўніце магічную клавіятуру гэтым запісам</string>
<string name="keyboard_notification_entry_title">Інфармацыя аб апавяшчэннях</string>
<string name="keyboard_notification_entry_summary">Паказваць апавяшчэнне, калі запіс даступны</string>
<string name="keyboard_save_search_info_title">Захаваць агульную інфармацыю</string>
<string name="keyboard_save_search_info_summary">Паспрабаваць захаваць агульную інфармацыю пры ручным выбары запісу для палягчэння будучага выкарыстання</string>
<string name="keyboard_notification_entry_clear_close_title">Ачысціць пры закрыцці</string>
<string name="keyboard_notification_entry_clear_close_summary">Зачыніць базу дадзеных пры закрыцці апавяшчэння</string>
<string name="keyboard_entry_timeout_title">Тайм-аўт</string>
<string name="keyboard_entry_timeout_summary">Тайм-аўт для ачысткі запісу клавіятуры</string>
<string name="keyboard_notification_entry_content_title_text">Запіс</string>
<string name="keyboard_notification_entry_content_title">%1$s даступны на магічнай клавіятуры</string>
<string name="keyboard_notification_entry_content_text">%1$s</string>
<string name="keyboard_appearance_category">Знешні выгляд</string>
<string name="keyboard_theme_title">Тэма клавіятуры</string>
<string name="keyboard_keys_category">Клавішы</string>
<string name="keyboard_auto_go_action_title">Аўтаматычнае дзеянне клавішы</string>
<string name="keyboard_auto_go_action_summary">Дзеянне клавішы Go пасля націску на клавішу Поле</string>
<string name="keyboard_key_vibrate_title">Вібрацыйныя націскі клавіш</string>
<string name="keyboard_key_sound_title">Гукавыя націскі клавіш</string>
<string name="keyboard_change">Змяніць клавіятуру</string>
<string name="keyboard_previous_database_credentials_title">Экран уліковых дадзеных базы дадзеных</string>
<string name="keyboard_previous_database_credentials_summary">Аўтаматычна пераключацца назад на папярэднюю клавіятуру на экране ўліковых дадзеных базы дадзеных</string>
<string name="keyboard_previous_search_title">Экран пошуку</string>
<string name="keyboard_previous_search_summary">Аўтаматычна пераключацца назад на папярэднюю клавіятуру на экране пошуку</string>
<string name="keyboard_previous_fill_in_title">Пераключыцца назад</string>
<string name="keyboard_previous_fill_in_summary">Аўтаматычна пераключацца назад на папярэднюю клавіятуру пасля выканання Аўтаматычнага дзеяння клавішы</string>
<string name="keyboard_previous_lock_title">Заблакаваць базу дадзеных</string>
<string name="keyboard_previous_lock_summary">Аўтаматычна пераключацца назад на папярэднюю клавіятуру пасля блакавання базы дадзеных</string>
<string name="custom_fields">Карыстальніцкія палі</string>
<string name="back_to_previous_keyboard">Вярнуцца да папярэдняй клавіятуры</string>
<string name="select_entry">Выбраць запіс</string>
<string name="backspace">Backspace</string>
<string name="enter">Enter</string>
<string name="autofill_close_database_title">Зачыніць базу дадзеных</string>
<string name="autofill_close_database_summary">Зачыніць базу дадзеных пасля выбару аўтазапаўнення</string>
<string name="autofill_inline_suggestions_title">Убудаваныя прапановы</string>
<string name="autofill_inline_suggestions_summary">Спрабаваць адлюстраваць прапановы аўтазапаўнення непасрэдна з сумяшчальнай клавіятуры</string>
<string name="autofill_manual_selection_title">Ручной выбар</string>
<string name="autofill_manual_selection_summary">Адлюстраваць опцыю, каб дазволіць карыстальніку выбраць запіс базы дадзеных</string>
<string name="autofill_save_search_info_title">Захаваць інфармацыю пошуку</string>
<string name="autofill_save_search_info_summary">Спрабаваць захаваць інфармацыю пошуку пры ручным выбары запісу для палягчэння будучага выкарыстання</string>
<string name="autofill_ask_to_save_data_title">Спытаць пра захаванне дадзеных</string>
<string name="autofill_ask_to_save_data_summary">Спытаць пра захаванне дадзеных пасля завяршэння запаўнення формы</string>
<string name="autofill_application_id_blocklist_title">Чорны спіс праграм</string>
<string name="autofill_application_id_blocklist_summary">Чорны спіс, які перашкаджае аўтазапаўненню праграм</string>
<string name="autofill_web_domain_blocklist_title">Чорны спіс вэб-даменаў</string>
<string name="autofill_web_domain_blocklist_summary">Чорны спіс, які перашкаджае аўтазапаўненню вэб-даменаў</string>
<string name="autofill_block">Заблакаваць аўтазапаўненне</string>
<string name="autofill_block_restart">Перазапусціце праграму, якая змяшчае форму, каб актываваць блакаванне.</string>
<string name="autofill_read_only_save">Захаванне дадзеных недапушчальна для базы дадзеных, адкрытай толькі для чытання.</string>
<string name="autofill_inline_suggestions_keyboard">Прапановы аўтазапаўнення дададзены.</string>
<string name="allow_no_password_title">Дазволіць без галоўнага ключа</string>
<string name="allow_no_password_summary">Дазваляе націснуць кнопку Адкрыць, калі не выбраны ўліковыя дадзеныя</string>
<string name="delete_entered_password_title">Выдаліць пароль</string>
<string name="delete_entered_password_summary">Выдаляе ўведзены пароль пасля спробы падключэння да базы дадзеных</string>
<string name="enable_auto_save_database_title">Аўтазахаванне базы дадзеных</string>
<string name="enable_auto_save_database_summary">Захоўваць базу дадзеных пасля кожнага важнага дзеяння (у рэжыме З магчымасцю змены)</string>
<string name="enable_keep_screen_on_title">Трымаць экран уключаным</string>
<string name="enable_keep_screen_on_summary">Трымаць экран уключаным пры праглядзе або рэдагаванні запісу</string>
<string name="enable_screenshot_mode_title">Рэжым скрыншота</string>
<string name="enable_screenshot_mode_summary">Дазволіць староннім праграмам запісваць або рабіць скрыншоты праграмы</string>
<string name="enable_education_screens_title">Навучальныя падказкі</string>
<string name="enable_education_screens_summary">Вылучыць элементы, каб даведацца, як працуе праграма</string>
<string name="reset_education_screens_title">Скінуць навучальныя падказкі</string>
<string name="reset_education_screens_summary">Паказаць усю навучальную інфармацыю зноўку</string>
<string name="reset_education_screens_text">Навучальныя падказкі скінуты</string>
<string name="education_create_database_title">Стварыце свой файл базы дадзеных</string>
<string name="education_create_database_summary">Стварыце свой першы файл кіравання паролямі.</string>
<string name="education_select_database_title">Адкрыць існуючую базу дадзеных</string>
<string name="education_select_database_summary">Адкрыйце свой папярэдні файл базы дадзеных з файлавага браўзера, каб працягнуць выкарыстоўваць яго.</string>
<string name="education_new_node_title">Дадаць элементы ў вашу базу дадзеных</string>
<string name="education_new_node_summary">Запісы дапамагаюць кіраваць лічбавымі ідэнтыфікацыйнымі дадзенымі.\n\nГрупы (~тэчкі) арганізуюць запісы ў вашай базе дадзеных.</string>
<string name="education_search_title">Пошук па запісах</string>
<string name="education_search_summary">Увядзіце назву, імя карыстальніка або змесціва іншых палёў, каб знайсці свае паролі.</string>
<string name="education_device_unlock_title">Разблакіроўка базы дадзеных прылады</string>
<string name="education_device_unlock_summary">Прывяжыце свой пароль да адсканаванай біяметрыі або ўліковых дадзеных прылады, каб хутка разблакаваць базу дадзеных.</string>
<string name="education_entry_edit_title">Рэдагаваць гэты запіс</string>
<string name="education_entry_edit_summary">Рэдагуйце свой запіс з дапамогай карыстальніцкіх палёў. Дадзеныя пула могуць спасылацца паміж рознымі палямі запісаў.</string>
<string name="education_generate_password_title">Стварыць надзейны пароль</string>
<string name="education_generate_password_summary">Стварыце надзейны пароль, каб звязаць яго са сваім запісам, лёгка вызначыце яго ў адпаведнасці з крытэрыямі формы і не забудзьцеся пра бяспечны пароль.</string>
<string name="education_validate_entry_title">Праверыць запіс</string>
<string name="education_validate_entry_summary">Не забудзьцеся праверыць свой запіс і захаваць базу дадзеных.\n\nКалі актывавана аўтаматычнае блакаванне і вы забыліся, што рабілі змены, вы рызыкуеце страціць свае дадзеныя.</string>
<string name="education_entry_new_field_title">Дадаць карыстальніцкія палі</string>
<string name="education_entry_new_field_summary">Зарэгіструйце дадатковае поле, дадайце значэнне і пры жаданні абароніце яго.</string>
<string name="education_add_attachment_title">Дадаць укладанне</string>
<string name="education_add_attachment_summary">Загрузіце ўкладанне ў свой запіс, каб захаваць важныя знешнія дадзеныя.</string>
<string name="education_setup_OTP_title">Наладзіць OTP</string>
<string name="education_setup_OTP_summary">Наладзьце кіраванне аднаразовым паролем (HOTP / TOTP) для стварэння токена, які запытваецца для двухфактарнай аўтэнтыфікацыі (2FA).</string>
<string name="education_unlock_title">Разблакаваць вашу базу дадзеных</string>
<string name="education_unlock_summary">Увядзіце пароль і/або файл ключа, каб разблакаваць базу дадзеных.\n\nСтварыце рэзервовую копію файла базы дадзеных у бяспечным месцы пасля кожнай змены.</string>
<string name="education_read_only_title">Абараніць вашу базу дадзеных ад запісу</string>
<string name="education_read_only_summary">Змяніць рэжым адкрыцця для сеансу.\n\n\"Абаронены ад запісу\"- прадухіляе ненаўмысныя змены ў базе дадзеных.\n\"Мадыкафаны\"- дазваляе вам дадаваць, выдаляць або змяняць усе элементы, як пажадаеце.</string>
<string name="education_field_copy_title">Скапіяваць поле</string>
<string name="education_field_copy_summary">Скапіяваныя палі можна ўставіць у любым месцы.\n\nВыкарыстоўвайце метад запаўнення формы, які вам больш падабаецца.</string>
<string name="education_lock_title">Заблакаваць базу дадзеных</string>
<string name="education_lock_summary">Хутка заблакаваць базу дадзеных, вы можаце наладзіць праграму, каб яна блакавалася праз некаторы час і калі экран выключаецца.</string>
<string name="education_sort_title">Сартаванне элементаў</string>
<string name="education_sort_summary">Выберыце, як сартаваць запісы і групы.</string>
<string name="education_donation_title">Удзельнічаць</string>
<string name="education_donation_summary">Дапамажыце павысіць стабільнасць, бяспеку і дадаць больш функцый.</string>
<string name="html_text_ad_free">У адрозненне ад многіх праграм для кіравання паролямі, гэтая &lt;strong&gt;без рэкламы&lt;/strong&gt;, &lt;strong&gt;копілефтнае свабоднае праграмнае забеспячэнне&lt;/strong&gt; і не збірае персанальныя дадзеныя на сваіх серверах, незалежна ад версіі, якой вы карыстаецеся.</string>
<string name="html_text_buy_pro">Купляючы pro-версію, вы атрымаеце доступ да гэтага &lt;strong&gt;візуальнага стылю&lt;/strong&gt; і асабліва дапаможаце &lt;strong&gt;рэалізацыі грамадскіх праектаў.&lt;/strong&gt;</string>
<string name="html_text_feature_generosity">Гэты &lt;strong&gt;візуальны стыль&lt;/strong&gt; даступны дзякуючы вашай шчодрасці.</string>
<string name="html_text_donation">&lt;strong&gt;Унёсшы ўклад&lt;/strong&gt; у праект &lt;i&gt;(матэрыяльна, кодам, перакладам)&lt;/i&gt;, вы дапаможаце яму працягваць жыць і развівацца, а таксама будзеце мець права на працэдуру разблакіроўкі &lt;strong&gt;тэмы&lt;/strong&gt;.</string>
<string name="html_text_dev_feature">Гэтая функцыя &lt;strong&gt;знаходзіцца ў стадыі распрацоўкі&lt;/strong&gt; і патрабуе вашага &lt;strong&gt;ўкладу&lt;/strong&gt;, каб неўзабаве стаць даступнай.</string>
<string name="html_text_dev_feature_buy_pro">Купляючы &lt;strong&gt;pro-версію&lt;/strong&gt;,</string>
<string name="html_text_dev_feature_contibute">&lt;strong&gt;Унёсшы ўклад&lt;/strong&gt;,</string>
<string name="html_text_dev_feature_encourage">вы заахвочваеце распрацоўшчыкаў ствараць &lt;strong&gt;новыя функцыі&lt;/strong&gt; і &lt;strong&gt;выпраўляць памылкі&lt;/strong&gt; ў адпаведнасці з вашымі заўвагамі.</string>
<string name="html_text_dev_feature_thanks">Вялікі дзякуй за ваш уклад.</string>
<string name="html_text_dev_feature_work_hard">Мы прыкладаем усе намаганні, каб хутка выпусціць гэтую функцыю.</string>
<string name="html_text_dev_feature_upgrade">Не забудзьцеся абнаўляць праграму, усталёўваючы новыя версіі.</string>
<string name="download">Спампаваць</string>
<string name="contribute">Унесці ўклад</string>
<string name="download_attachment">Спампаваць %1$s</string>
<string name="upload_attachment">Загрузіць %1$s</string>
<string name="download_initialization">Ініцыялізацыя…</string>
<string name="download_progression">Выконваецца: %1$d%%</string>
<string name="download_finalization">Завяршэнне…</string>
<string name="download_complete">Гатова!</string>
<string name="download_canceled">Скасавана!</string>
<string name="unit_byte">Б</string>
<string name="unit_kibibyte">КіБ</string>
<string name="unit_mebibyte">МіБ</string>
<string name="unit_gibibyte">ГіБ</string>
<string name="entropy">Энтрапія: %1$s біт</string>
<string name="entropy_high">Энтрапія: Высокая</string>
<string name="entropy_calculate">Энтрапія: Разлік…</string>
<string name="at_least_one_char">Хаця б адзін сімвал з кожнай</string>
<string name="exclude_ambiguous_chars">Выключыць неадназначныя сімвалы</string>
<string name="consider_chars_filter">Разглядаць сімвалы</string>
<string name="word_separator">Падзяляльнік слоў</string>
<string name="ignore_chars_filter">Ігнараваць сімвалы</string>
<string name="lower_case">ніжні рэгістр</string>
<string name="upper_case">ВЕРХНІ РЭГІСТР</string>
<string name="title_case">Рэгістр загалоўкаў</string>
<string name="character_count">Колькасць сімвалаў: %1$d</string>
<string name="screenshot_mode_banner_text">Рэжым скрыншота</string>
<string name="style_choose_title">Тэма праграмы</string>
<string name="style_choose_summary">Тэма, якая выкарыстоўваецца ў праграме</string>
<string name="style_name_forest">Лес</string>
<string name="style_name_divine">Боскі</string>
<string name="style_name_classic">Класічны</string>
<string name="style_name_simple">Просты</string>
<string name="style_name_moon">Месяц</string>
<string name="style_name_sun">Сонца</string>
<string name="style_name_reply">Адказ</string>
<string name="style_name_kunzite">Кунцыт</string>
<string name="style_name_follow_system">Па сістэме</string>
<string name="style_brightness_title">Яркасць тэмы</string>
<string name="style_brightness_summary">Выбраць светлыя або цёмныя тэмы</string>
<string name="style_name_light">Светлая</string>
<string name="style_name_dark">Цёмная</string>
<string name="icon_section_standard">Стандартны</string>
<string name="icon_section_custom">Карыстальніцкі</string>
<string name="icon_pack_choose_title">Пакет значкоў</string>
<string name="icon_pack_choose_summary">Пакет значкоў, які выкарыстоўваецца ў праграме</string>
<string name="show_entry_colors_title">Колеры запісаў</string>
<string name="show_entry_colors_summary">Адлюстроўвае колеры пярэдняга плану і фону для запісу</string>
<string name="hide_expired_entries_title">Схаваць запісы з мінулым тэрмінам дзеяння</string>
<string name="hide_expired_entries_summary">Запісы з мінулым тэрмінам дзеяння не паказваюцца</string>
<string name="hide_templates_title">Схаваць шаблоны</string>
<string name="hide_templates_summary">Шаблоны не паказваюцца</string>
</resources>

View File

@@ -22,7 +22,7 @@
<string name="clipboard_timeout_summary">Продължителност на съхранение в клипборда (ако се поддържа от вашето устройство)</string>
<string name="clipboard_error">Някои устройства не позволяват на приложенията да използват клипборда.</string>
<string name="entry_title">Заглавие</string>
<string name="about_description">Версия за Андроид на приложението за управление на пароли KeePass</string>
<string name="about_description">Разработка за Андроид на приложението за управление на пароли KeePass.</string>
<string name="save">Запазване</string>
<string name="entry_confpassword">Потвърждаване на парола</string>
<string name="key_derivation_function">Функция за извличане на ключ</string>
@@ -83,7 +83,7 @@
<string name="error_nokeyfile">Избиране на файл с ключ.</string>
<string name="entry_keyfile">Файл с ключ</string>
<string name="error_no_hardware_key">Изберете хардуерен ключ.</string>
<string name="advanced_unlock_prompt_store_credential_message">Въпреки че използвате разпознаване на отключването на устройството ще трябва да запомните главната парола на хранилището.</string>
<string name="device_unlock_prompt_store_credential_message">Въпреки че използвате разпознаване на отключването на устройството ще трябва да запомните главната парола на хранилището.</string>
<string name="create_keepass_file">Ново хранилище</string>
<string name="recycle_bin">Кошче</string>
<string name="default_checkbox">Използване като хранилище по подразбиране</string>
@@ -187,7 +187,7 @@
<string name="cryptocurrency">Портфейл за криптовалута</string>
<string name="token">Код за достъп</string>
<string name="menu_change_key_settings">Промяна на главната парола</string>
<string name="menu_advanced_unlock_settings">Отключване на устройството</string>
<string name="menu_device_unlock_settings">Отключване на устройството</string>
<string name="menu_security_settings">Настройки за сигурност</string>
<string name="menu_donate">Даряване</string>
<string name="menu_edit">Променяне</string>
@@ -236,7 +236,7 @@
<string name="download_initialization">Подготвяне…</string>
<string name="content_description_entry_background_color">Цвят на фона на запис</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft е приложение с &lt;strong&gt;отворен код&lt;/strong&gt; и &lt;strong&gt;без реклами&lt;/strong&gt;. \nРазпространява се под лиценза &lt;strong&gt;GPLv3&lt;/strong&gt; без каквато и да е гаранция.</string>
<string name="menu_advanced_unlock_settings_summary">Биометрия, удостоверяване</string>
<string name="menu_device_unlock_settings_summary">Биометрия, удостоверяване</string>
<string name="menu_security_settings_summary">Шифроване, функция за извличане на ключ</string>
<string name="menu_master_key_settings">Настройки на главната парола</string>
<string name="file_browser">Управление на файлове</string>
@@ -251,8 +251,8 @@
<string name="database_custom_color_title">Цвят на хранилището по избор</string>
<string name="keyboard_theme_title">Тема на клавиатурата</string>
<string name="keyboard_auto_go_action_title">Автоматично действие на клавиш</string>
<string name="education_advanced_unlock_title">Отключвайте хранилището заедно с устройството</string>
<string name="education_advanced_unlock_summary">Свържете паролата със сканиране на биометрични данни или удостоверяване на устройството, за да отключвате бързо хранилищата.</string>
<string name="education_device_unlock_title">Отключвайте хранилището заедно с устройството</string>
<string name="education_device_unlock_summary">Свържете паролата със сканиране на биометрични данни или удостоверяване на устройството, за да отключвате бързо хранилищата.</string>
<string name="education_entry_new_field_summary">Създайте допълнително поле, добавете стойност и при необходимост я защитете.</string>
<string name="education_unlock_title">Отключете хранилището</string>
<string name="education_sort_title">Сортиране на записи</string>
@@ -292,7 +292,7 @@
<string name="password_size_title">Дължина на създаваните пароли</string>
<string name="lock_database_back_root_title">Заключване при „Назад“</string>
<string name="content">Съдържание</string>
<string name="advanced_unlock">Отключване на устройството</string>
<string name="device_unlock">Отключване на устройството</string>
<string name="settings_database_recommend_changing_master_key_title">Препоръчителна смяна</string>
<string name="settings_database_recommend_changing_master_key_summary">Препоръчване на смяна на главната парола (в дни)</string>
<string name="settings_database_force_changing_master_key_title">Принудителна смяна</string>
@@ -352,7 +352,6 @@
<string name="keyboard_setting_label">Настройки на Magikeyboard</string>
<string name="keyboard_selection_entry_title">Избор на записи</string>
<string name="allow_no_password_title">Разрешаване без главна парола</string>
<string name="enable_read_only_title">Само за четене</string>
<string name="keyboard_notification_entry_content_text">%1$s</string>
<string name="keyboard_notification_entry_content_title">Записът %1$s е достъпен в Magikeyboard</string>
<string name="keyboard_notification_entry_content_title_text">Запис</string>
@@ -402,7 +401,6 @@
<string name="lock_database_show_button_title">Бутон за заключване</string>
<string name="autofill_explanation_summary">Включете услугата за попълване на формуляри в други приложения</string>
<string name="properties">Свойства</string>
<string name="enable_read_only_summary">По подразбиране отваря хранилището само за четене</string>
<string name="education_validate_entry_summary">Не забравяйте да потвърдите записа и да го запазите в хранилището.
\n
\nАко се задейства автоматичното заключване, а сте направили промени, рискувате загуба на данни.</string>
@@ -456,7 +454,7 @@
<string name="html_text_dev_feature_upgrade">Не забравяйте да обновявате приложението.</string>
<string name="html_text_dev_feature_encourage">вие поощрявате разработчиците да добавят &lt;strong&gt;нови възможности&lt;/strong&gt; и да &lt;strong&gt;отстраняват дефекти&lt;/strong&gt; според вашите отзиви.</string>
<string name="html_text_buy_pro">Купувайки версията Pro ще имате достъп до тази &lt;strong&gt;тема&lt;/strong&gt; и особено ще помогнете за &lt;strong&gt;изпълнението на проекти на общността&lt;/strong&gt;.</string>
<string name="html_text_donation">Като &lt;strong&gt;допринасяте&lt;/strong&gt; за проекта <i>(финансово, с код или преводи)</i> му помагате да живее и процъвтява, а също получавате процедурата за отключване на &lt;strong&gt;темите&lt;/strong&gt;.</string>
<string name="html_text_donation">Като &lt;strong&gt;допринасяте&lt;/strong&gt; за проекта &lt;i&gt;(финансово, с код или преводи)&lt;/i&gt; му помагате да живее и процъвтява, а също получавате процедурата за отключване на &lt;strong&gt;темите&lt;/strong&gt;.</string>
<string name="hint_keyfile">Файл с ключ</string>
<string name="invalid_algorithm">Грешен алгоритъм.</string>
<string name="description_app_properties">Свойства за управление на настройките на KeePassDX</string>
@@ -521,33 +519,32 @@
<string name="database_data_remove_unlinked_attachments_summary">Премахва от хранилището прикачени файлове без връзка със запис</string>
<string name="warning_empty_keyfile_explanation">Съдържанието на файла с ключ не трябва да бъде променяно и най-добре е да съдържа случайна стойност.</string>
<string name="warning_database_info_changed_options">Обединете данните, презапишете външните промени или презаредете хранилището с последните промени.</string>
<string name="temp_advanced_unlock_timeout_summary">Време на живот на съдържанието, което се използва за отключване</string>
<string name="advanced_unlock_delete_all_key_warning">Да бъдат ли премахнати всички ключове за шифроване, свързани с разпознаването на отключване на устройството?</string>
<string name="temp_device_unlock_timeout_summary">Време на живот на съдържанието, което се използва за отключване</string>
<string name="device_unlock_delete_all_key_warning">Да бъдат ли премахнати всички ключове за шифроване, свързани с разпознаването на отключване на устройството?</string>
<string name="biometric_delete_all_key_summary">Премахване на всички ключове за шифроване, свързани с разпознаването на отключване на устройството</string>
<string name="unavailable_feature_text">Тази възможност не може да бъде използвана.</string>
<string name="unavailable_feature_version">Устройството разполага с Андроид %1$s, но е необходим %2$s или по-нов.</string>
<string name="templates_group_enable_title">Използване на шаблони</string>
<string name="advanced_unlock_prompt_extract_credential_title">Разпознаване на отключване на устройството</string>
<string name="credential_before_click_advanced_unlock_button">Въведете паролата и докоснете бутона.</string>
<string name="device_unlock_prompt_extract_credential_title">Разпознаване на отключване на устройството</string>
<string name="credential_before_click_device_unlock_button">Въведете паролата и докоснете бутона.</string>
<string name="lock_database_screen_off_summary">Заключва хранилището нколко секунди след изключване на екрана</string>
<string name="temp_advanced_unlock_enable_summary">За да се възползвате от отключване на устройството не пазете шифровано съдържание</string>
<string name="temp_advanced_unlock_timeout_title">Време на действие</string>
<string name="advanced_unlock_timeout">Времетраене на отключването на устройството</string>
<string name="temp_device_unlock_enable_summary">За да се възползвате от отключване на устройството не пазете шифровано съдържание</string>
<string name="temp_device_unlock_timeout_title">Време на действие</string>
<string name="device_unlock_timeout">Времетраене на отключването на устройството</string>
<string name="recycle_bin_title">Използване на кошчето</string>
<string name="recycle_bin_summary">Премества групите и записите в групата „Кошче“ вместо да ги премахва директно</string>
<string name="advanced_unlock_prompt_store_credential_title">Отключване с устройството</string>
<string name="advanced_unlock_scanning_error">Грешка при отключване на устройството: %1$s</string>
<string name="advanced_unlock_not_recognized">Не може да бъде разпознато кога устройството е отключено</string>
<string name="advanced_unlock_prompt_not_initialized">Заявката за отключване не може да бъде подготвена.</string>
<string name="device_unlock_prompt_store_credential_title">Отключване с устройството</string>
<string name="device_unlock_not_recognized">Не може да бъде разпознато кога устройството е отключено</string>
<string name="device_unlock_prompt_not_initialized">Заявката за отключване не може да бъде подготвена.</string>
<string name="password_size_summary">Подразбирана дължина на създаваните пароли</string>
<string name="advanced_unlock_tap_delete">Докоснете, за да премахнете ключовете за отключване на устройството</string>
<string name="temp_advanced_unlock_enable_title">Временно отключване на устройството</string>
<string name="advanced_unlock_explanation_summary">За по-лесно отключване на хранилището използвайте отключване на устройството</string>
<string name="device_unlock_tap_delete">Докоснете, за да премахнете ключовете за отключване на устройството</string>
<string name="temp_device_unlock_enable_title">Временно отключване на устройството</string>
<string name="device_unlock_explanation_summary">За по-лесно отключване на хранилището използвайте отключване на устройството</string>
<string name="recycle_bin_group_title">Група „Кошче“</string>
<string name="templates_group_uuid_title">Група „Шаблони“</string>
<string name="advanced_unlock_prompt_extract_credential_message">Извличане на главната парола на хранилището при отключване на устройството</string>
<string name="advanced_unlock_invalid_key">Ключът за отключване на устройството не може да бъде прочетен. Премахнете го и повторете процедурата по разпознаване.</string>
<string name="advanced_unlock_keystore_warning">Това свойство на приложението ще пази шифровани данни за достъп в защитеното хранилище за ключове на устройството.
<string name="device_unlock_prompt_extract_credential_message">Извличане на главната парола на хранилището при отключване на устройството</string>
<string name="device_unlock_invalid_key">Ключът за отключване на устройството не може да бъде прочетен. Премахнете го и повторете процедурата по разпознаване.</string>
<string name="device_unlock_keystore_warning">Това свойство на приложението ще пази шифровани данни за достъп в защитеното хранилище за ключове на устройството.
\n
\nВ зависимост реализацията на ППИ на операционната система то може да не е пълнофункционално.
\n
@@ -685,4 +682,5 @@
<string name="warning_large_keyfile">Не се препоръчва използването на голям файл с ключ, защото може да попречи на отварянето на хранилището.</string>
<string name="hide_templates_summary">Шаблоните не се показват</string>
<string name="hide_templates_title">Скриване на шаблоните</string>
<string name="error_otp_secret_length">Тайният ключ трябва да бъде най-малко %1$d знаци.</string>
</resources>

View File

@@ -188,7 +188,7 @@
<string name="loading_database">ডাটাবেস লোড হচ্ছে…</string>
<string name="copy_field">%1$s এর কপি</string>
<string name="menu_form_filling_settings">ফরম পূরণ</string>
<string name="menu_advanced_unlock_settings">উন্নত আনলকিং</string>
<string name="menu_device_unlock_settings">উন্নত আনলকিং</string>
<string name="menu_database_settings">ডাটাবেস সেটিংস</string>
<string name="menu_security_settings">নিরাপত্তা বিন্যাস</string>
<string name="menu_master_key_settings">মাস্টার কী সেটিংস</string>

View File

@@ -222,7 +222,7 @@
<string name="menu_copy">Copiar</string>
<string name="menu_master_key_settings">Paràmetres de la contrasenya mestra</string>
<string name="menu_security_settings">Paràmetres de seguretat</string>
<string name="menu_advanced_unlock_settings">Desblocatge de dispositiu</string>
<string name="menu_device_unlock_settings">Desblocatge de dispositiu</string>
<string name="menu_form_filling_settings">Emplenat de formularis</string>
<string name="copy_field">Còpia de %1$s</string>
<string name="creating_database">Es crea la base de dades…</string>
@@ -362,7 +362,7 @@
<string name="html_about_privacy">&lt;strong&gt;No s\'agafa cap dada d\'usuari&lt;/strong&gt;, aquesta aplicació no connecta a cap servidor, només treballa localment i respecta la privacitat dels usuaris en la seva totalitat.</string>
<string name="notification">Notificació</string>
<string name="content_description_entry_foreground_color">Color de primer pla d\'entrada</string>
<string name="advanced_unlock">Desbloqueja dispositiu</string>
<string name="device_unlock">Desbloqueja dispositiu</string>
<string name="template">Plantilla</string>
<string name="title_case">Primera Majúscula</string>
<string name="navigation_drawer_open">El calaix de navegació està obert</string>
@@ -414,7 +414,7 @@
<string name="compression">Compressió</string>
<string name="id_card">Targeta d\'identificació</string>
<string name="error_hardware_key_unsupported">Clau física no suportada.</string>
<string name="menu_advanced_unlock_settings_summary">Biometria, credencial de dispositiu</string>
<string name="menu_device_unlock_settings_summary">Biometria, credencial de dispositiu</string>
<string name="standard">Estàndard</string>
<string name="error_XML_malformed">XML mal format.</string>
<string name="remember_hardware_key_summary">Recorda les claus físiques que s\'han usat</string>
@@ -456,7 +456,7 @@
<string name="error_upload_file">S\'ha produït un error en pujar les dades del fitxer.</string>
<string name="error_duplicate_file">Les dades del fitxer ja existeixen.</string>
<string name="hint_icon_name">Nom de la icona</string>
<string name="advanced_unlock_prompt_store_credential_message">Us haureu de recordar de la credencial principal de la caixa forta en el cas que feu servir el reconeixement del dispositiu pel desbloqueig.</string>
<string name="device_unlock_prompt_store_credential_message">Us haureu de recordar de la credencial principal de la caixa forta en el cas que feu servir el reconeixement del dispositiu pel desbloqueig.</string>
<string name="secure_note">Nota segura</string>
<string name="error_file_to_big">El fitxer que esteu intentant pujar és massa gros.</string>
<string name="error_challenge_already_requested">El desafiament ja s\'ha sol·licitat.</string>
@@ -471,15 +471,13 @@
<string name="menu_database_settings_summary">Metadades, paperera de reciclatge, plantilles, historial</string>
<string name="encryption_explanation">Algorisme de xifratge de la base de dades utilitzat per a totes les dades</string>
<string name="delete_entered_password_summary">Suprimeix la contrasenya introduïda després d\'un intent de connexió a una base de dades</string>
<string name="enable_read_only_title">Protegit contra l\'escriptura</string>
<string name="enable_read_only_summary">Obre la base de dades en mode només de lectura per defecte</string>
<string name="enable_screenshot_mode_summary">Permet que les aplicacions de tercers gravin o facin captures de pantalla de l\'aplicació</string>
<string name="enable_education_screens_summary">Ressalta els elements per saber com funciona l\'aplicació</string>
<string name="reset_education_screens_title">Reinicia els consells educatius</string>
<string name="enable_education_screens_title">Consells educatius</string>
<string name="education_new_node_title">Afegeix elements a la base de dades</string>
<string name="education_search_summary">Introduïu el títol, el nom d\'usuari o el contingut d\'altres camps per recuperar les contrasenyes.</string>
<string name="education_advanced_unlock_title">Desbloqueig de la base de dades dels dispositius</string>
<string name="education_device_unlock_title">Desbloqueig de la base de dades dels dispositius</string>
<string name="autofill_save_search_info_title">Desa la informació de cerca</string>
<string name="education_entry_edit_summary">Editeu l\'entrada amb camps personalitzats. Les dades del fons es poden referenciar entre diferents camps d\'entrada.</string>
<string name="education_generate_password_title">Crea una contrasenya forta</string>
@@ -504,10 +502,10 @@
<string name="autofill_inline_suggestions_summary">Intenta mostrar els suggeriments d\'emplenament automàtic directament des d\'un teclat compatible</string>
<string name="warning_database_already_opened">Ja hi ha oberta una base de dades, tanqueu-la primer abans d\'obrir-ne una de nova</string>
<string name="build_label">Construeix 2%1$s</string>
<string name="advanced_unlock_prompt_extract_credential_title">Reconeixement de desbloqueig del dispositiu</string>
<string name="device_unlock_prompt_extract_credential_title">Reconeixement de desbloqueig del dispositiu</string>
<string name="clipboard_explanation_summary">Copia els camps d\'entrada utilitzant el porta-retalls del dispositiu</string>
<string name="temp_advanced_unlock_enable_title">Desbloqueig temporal del dispositiu</string>
<string name="temp_advanced_unlock_enable_summary">No emmagatzemeu cap contingut xifrat per utilitzar el desbloqueig del dispositiu</string>
<string name="temp_device_unlock_enable_title">Desbloqueig temporal del dispositiu</string>
<string name="temp_device_unlock_enable_summary">No emmagatzemeu cap contingut xifrat per utilitzar el desbloqueig del dispositiu</string>
<string name="database_data_remove_unlinked_attachments_summary">Elimina els adjunts continguts a la base de dades però no vinculats a una entrada</string>
<string name="keyboard_label">Magikeyboard (KeePassDX)</string>
<string name="keyboard_selection_entry_title">Selecció d\'entrada</string>
@@ -525,13 +523,13 @@
<string name="warning_database_read_only">Concedeix accés d\'escriptura al fitxer per a desar els canvis a la base de dades</string>
<string name="warning_database_info_changed_options">Fusiona les dades, sobreescriu les modificacions externes desant la base de dades o torna-la a carregar amb els últims canvis.</string>
<string name="warning_database_info_reloaded">En tornar a carregar la base de dades se suprimiran les dades modificades localment.</string>
<string name="advanced_unlock_invalid_key">No es pot llegir la clau de desbloqueig del dispositiu. Si us plau, suprimiu-la i repetiu el procediment de reconeixement de desbloqueig.</string>
<string name="advanced_unlock_not_recognized">No s\'ha pogut reconèixer l\'empremta digital per desbloquejar el dispositiu</string>
<string name="device_unlock_invalid_key">No es pot llegir la clau de desbloqueig del dispositiu. Si us plau, suprimiu-la i repetiu el procediment de reconeixement de desbloqueig.</string>
<string name="device_unlock_not_recognized">No s\'ha pogut reconèixer l\'empremta digital per desbloquejar el dispositiu</string>
<string name="autofill_select_entry">Selecciona una entrada…</string>
<string name="advanced_unlock_tap_delete">Toca per suprimir les claus de desbloqueig del dispositiu</string>
<string name="temp_advanced_unlock_timeout_title">Venciment del desbloqueig del dispositiu</string>
<string name="temp_advanced_unlock_timeout_summary">Durada de l\'ús del desbloqueig del dispositiu abans de suprimir el seu contingut</string>
<string name="advanced_unlock_timeout">Temps d\'espera per desbloquejar el dispositiu</string>
<string name="device_unlock_tap_delete">Toca per suprimir les claus de desbloqueig del dispositiu</string>
<string name="temp_device_unlock_timeout_title">Venciment del desbloqueig del dispositiu</string>
<string name="temp_device_unlock_timeout_summary">Durada de l\'ús del desbloqueig del dispositiu abans de suprimir el seu contingut</string>
<string name="device_unlock_timeout">Temps d\'espera per desbloquejar el dispositiu</string>
<string name="database_custom_color_title">Color personalitzat de la base de dades</string>
<string name="database_version_title">Versió de la base de dades</string>
<string name="text_appearance">Text</string>
@@ -564,19 +562,19 @@
<string name="download_attachment">Baixa %1$s</string>
<string name="download_progression">En curs: %1$d%%</string>
<string name="download_complete">S\'ha completat!</string>
<string name="advanced_unlock_prompt_extract_credential_message">Extreu la credencial de la base de dades amb les dades de desbloqueig del dispositiu</string>
<string name="device_unlock_prompt_extract_credential_message">Extreu la credencial de la base de dades amb les dades de desbloqueig del dispositiu</string>
<string name="keyboard">Teclat</string>
<string name="magic_keyboard_title">Magikeyboard</string>
<string name="custom_fields">Camps personalitzats</string>
<string name="advanced_unlock_prompt_store_credential_title">Enllaç al desbloqueig del dispositiu</string>
<string name="device_unlock_prompt_store_credential_title">Enllaç al desbloqueig del dispositiu</string>
<string name="education_entry_edit_title">Edita l\'entrada</string>
<string name="filter">Filtra</string>
<string name="keyboard_auto_go_action_title">Acció de la tecla automàtica</string>
<string name="configure_biometric">No hi ha cap credencial biomètrica ni de dispositiu inscrita.</string>
<string name="advanced_unlock_explanation_summary">Utilitza el desbloqueig del dispositiu per obrir una base de dades més fàcilment</string>
<string name="device_unlock_explanation_summary">Utilitza el desbloqueig del dispositiu per obrir una base de dades més fàcilment</string>
<string name="device_credential_unlock_enable_summary">Us permet utilitzar la credencial del dispositiu per obrir la base de dades</string>
<string name="biometric_auto_open_prompt_summary">Sol·licita automàticament el desbloqueig del dispositiu si la base de dades està configurada per utilitzar-lo</string>
<string name="advanced_unlock_delete_all_key_warning">Voleu suprimir totes les claus de xifratge relacionades amb el reconeixement de desbloqueig del dispositiu?</string>
<string name="device_unlock_delete_all_key_warning">Voleu suprimir totes les claus de xifratge relacionades amb el reconeixement de desbloqueig del dispositiu?</string>
<string name="biometric_unlock_enable_title">Desbloqueig biomètric</string>
<string name="biometric_unlock_enable_summary">Us permet escanejar la vostra biomètrica per obrir la base de dades</string>
<string name="autofill_application_id_blocklist_title">Llista de bloqueig d\'aplicacions</string>
@@ -613,10 +611,9 @@
<string name="configure">Configura</string>
<string name="biometric_security_update_required">Cal actualitzar la seguretat biomètrica.</string>
<string name="unlock_and_link_biometric">Enllaç de desbloqueig del dispositiu</string>
<string name="advanced_unlock_scanning_error">Error en desbloquejar el dispositiu: %1$s</string>
<string name="unavailable">No disponible</string>
<string name="advanced_unlock_prompt_not_initialized">No s\'ha pogut inicialitzar l\'indicador de desbloqueig del dispositiu.</string>
<string name="credential_before_click_advanced_unlock_button">Escriviu la contrasenya i, a continuació, feu clic en aquest botó.</string>
<string name="device_unlock_prompt_not_initialized">No s\'ha pogut inicialitzar l\'indicador de desbloqueig del dispositiu.</string>
<string name="credential_before_click_device_unlock_button">Escriviu la contrasenya i, a continuació, feu clic en aquest botó.</string>
<string name="menu_appearance_settings_summary">Temes, colors, atributs</string>
<string name="clipboard_notifications_summary">Mostra les notificacions del porta-retalls per a copiar camps en visualitzar una entrada</string>
<string name="content">Contingut</string>
@@ -652,7 +649,7 @@
<string name="reset_education_screens_text">Reinicialitza els consells educatius</string>
<string name="education_select_database_title">Obre una base de dades existent</string>
<string name="education_select_database_summary">Obriu el fitxer anterior de la base de dades des del navegador de fitxers per a continuar utilitzant-lo.</string>
<string name="education_advanced_unlock_summary">Enllaça la contrasenya a una credencial biomètrica escanejada o de dispositiu per desbloquejar ràpidament la base de dades.</string>
<string name="education_device_unlock_summary">Enllaça la contrasenya a una credencial biomètrica escanejada o de dispositiu per desbloquejar ràpidament la base de dades.</string>
<string name="education_validate_entry_title">Valida l\'entrada</string>
<string name="education_entry_new_field_title">Afegeix camps personalitzats</string>
<string name="education_add_attachment_title">Afegeix un adjunt</string>
@@ -660,7 +657,7 @@
<string name="education_unlock_title">Desbloqueja la base de dades</string>
<string name="education_setup_OTP_summary">Configureu la gestió de contrasenyes d\'un sol ús (HOTP / TOTP) per generar un testimoni sol·licitat per a l\'autenticació de dos factors (2FA).</string>
<string name="education_field_copy_title">Copia un camp</string>
<string name="html_text_donation">Al &lt;strong&gt;contribuir&lt;/strong&gt; al projecte <i>(monetàriament, codi, traducció)</i>, l\'ajudareu a continuar vivint i prosperant, i també podreu optar al procediment de desbloqueig del &lt;strong&gt;tema&lt;/strong&gt;.</string>
<string name="html_text_donation">Al &lt;strong&gt;contribuir&lt;/strong&gt; al projecte &lt;i&gt;(monetàriament, codi, traducció)&lt;/i&gt;, l\'ajudareu a continuar vivint i prosperant, i també podreu optar al procediment de desbloqueig del &lt;strong&gt;tema&lt;/strong&gt;.</string>
<string name="upload_attachment">Puja %1$s</string>
<string name="download_finalization">S\'està finalitzant…</string>
<string name="entropy">Entropia: %1$s bit</string>
@@ -674,7 +671,7 @@
<string name="warning_large_keyfile">No es recomana afegir un fitxer de claus gran, això pot impedir que s\'obri la base de dades.</string>
<string name="education_lock_summary">Bloqueja la base de dades ràpidament, pots configurar l\'aplicació per bloquejar-la al cap d\'un temps, i quan la pantalla s\'apagui.</string>
<string name="recursive_number_entries_title">Nombre recursiu d\'entrades</string>
<string name="advanced_unlock_keystore_warning">Aquesta característica emmagatzemarà dades de credencials encriptades a l\'espai segur KeyStore del vostre dispositiu.\n\nDepenent de la implementació nativa de l\'API del sistema operatiu, pot no ser completament funcional.\n\nComprova la compatibilitat i seguretat de KeyStore amb el fabricant del teu dispositiu i el creador de la ROM que estàs utilitzant.</string>
<string name="device_unlock_keystore_warning">Aquesta característica emmagatzemarà dades de credencials encriptades a l\'espai segur KeyStore del vostre dispositiu.\n\nDepenent de la implementació nativa de l\'API del sistema operatiu, pot no ser completament funcional.\n\nComprova la compatibilitat i seguretat de KeyStore amb el fabricant del teu dispositiu i el creador de la ROM que estàs utilitzant.</string>
<string name="kdf_explanation">Per a generar la clau per a l\'algorisme d\'encriptació, la clau mestra es transforma utilitzant una funció de derivació de clau sal aleatòria.</string>
<string name="education_validate_entry_summary">Recordeu validar la vostra entrada i desar la vostra base de dades.\n\nSi s\'activa un bloqueig automàtic i t\'oblides que estaves fent una modificació, t\'arrisques a perdre les teves dades.</string>
<string name="education_read_only_summary">Canvieu el mode inaugural per a la sessió. \n \n\"Escriu-emparat\" impedeix canvis involuntaris a la base de dades. \n\"Modificable\" us permet afegir, eliminar o modificar tots els elements com vulgueu.</string>

View File

@@ -19,7 +19,7 @@
Czech translation by Jan Vaněk
--><resources>
<string name="homepage">Domovská stránka</string>
<string name="about_description">Implementace správce hesel KeePass pro Android</string>
<string name="about_description">Implementace správce hesel KeePass pro Android.</string>
<string name="accept">Přijmout</string>
<string name="add_entry">Přidat záznam</string>
<string name="add_group">Přidat skupinu</string>
@@ -194,7 +194,7 @@
<string name="lock">Zamknout</string>
<string name="lock_database_screen_off_title">Zámek obrazovky</string>
<string name="lock_database_screen_off_summary">Několik vteřin po zhasnutí obrazovky uzamknout databázi</string>
<string name="advanced_unlock">Odemykání zařízení</string>
<string name="device_unlock">Odemykání zařízení</string>
<string name="biometric_unlock_enable_title">Biometrické odemknutí</string>
<string name="biometric_unlock_enable_summary">Nechá otevřít databázi snímáním biometrického údaje</string>
<string name="biometric_delete_all_key_title">Smazat šifrovací klíče</string>
@@ -224,8 +224,6 @@
<string name="magic_keyboard_explanation_summary">Aktivovat vlastní klávesnici, která snadno vyplní hesla a další položky identity</string>
<string name="allow_no_password_title">Umožnit bez hlavního klíče</string>
<string name="allow_no_password_summary">Povolit klepnutí na \"Otevřít\", i když není vybráno žádné heslo</string>
<string name="enable_read_only_title">Chráněno před zápisem</string>
<string name="enable_read_only_summary">Ve výchozím stavu otevřít databázi pouze pro čtení</string>
<string name="enable_education_screens_title">Vzdělávací nápovědy</string>
<string name="enable_education_screens_summary">Zvýraznit prvky k pochopení práce s aplikací</string>
<string name="reset_education_screens_title">Nastavit vzdělávací nápovědy do výchozího stavu</string>
@@ -266,7 +264,7 @@
<string name="html_text_ad_free">Na rozdíl od mnoha aplikací pro správu hesel je tato &lt;strong&gt;bez reklam&lt;/strong&gt;, je &lt;strong&gt;svobodný software pod copyleft licencí&lt;/strong&gt; a nesbírá žádné osobní údaje na svých serverech bez ohledu na to, jakou verzi používáte.</string>
<string name="html_text_buy_pro">Zakoupením varianty \"pro\" získáte přístup k tomuto &lt;strong&gt;vizuálnímu stylu&lt;/strong&gt; a hlavně pomůžete &lt;strong&gt;uskutečnění komunitních projektů.&lt;/strong&gt;</string>
<string name="html_text_feature_generosity">Tento &lt;strong&gt;vizuální styl&lt;/strong&gt; je k dispozici díky vaší štědrosti.</string>
<string name="html_text_donation">&lt;strong&gt;Přispěním&lt;/strong&gt; projektu <i>(peněžně, kódem, překlady)</i> mu pomůžete žít a prosperovat a dostanete přístup k postupu odemčení &lt;strong&gt;motivů&lt;/strong&gt;.</string>
<string name="html_text_donation">&lt;strong&gt;Přispěním&lt;/strong&gt; do projektu &lt;i&gt;(peněžně, kódem, překlady)&lt;/i&gt; mu pomůžete žít a prosperovat a dostanete přístup k postupu odemčení &lt;strong&gt;motivů&lt;/strong&gt;.</string>
<string name="html_text_dev_feature">Tato funkce je &lt;strong&gt;ve vývoji&lt;/strong&gt; a potřebuje Váš &lt;strong&gt;příspěvek&lt;/strong&gt;, aby byla brzy k dispozici.</string>
<string name="html_text_dev_feature_buy_pro">Zakoupením &lt;strong&gt;pro&lt;/strong&gt; varianty,</string>
<string name="html_text_dev_feature_contibute">&lt;strong&gt;Podpořením vývoje&lt;/strong&gt;,</string>
@@ -333,7 +331,7 @@
<string name="content_description_update_from_list">Aktualizovat</string>
<string name="content_description_keyboard_close_fields">Zavřít kolonky</string>
<string name="error_create_database_file">Nepodařilo se vytvořit databázi s tímto heslem a souborem klíče.</string>
<string name="menu_advanced_unlock_settings">Odemknutí zařízení</string>
<string name="menu_device_unlock_settings">Odemknutí zařízení</string>
<string name="biometric">Biometrika</string>
<string name="biometric_auto_open_prompt_title">Automaticky otevřít pobídku</string>
<string name="biometric_auto_open_prompt_summary">Automaticky žádat odemykání zařízení, je-li databáze nastavena k jejímu použití</string>
@@ -365,7 +363,7 @@
<string name="contains_duplicate_uuid_procedure">Opravit chybu založením nového UUID pro duplikáty a pokračovat\?</string>
<string name="database_opened">Databáze otevřena</string>
<string name="clipboard_explanation_summary">Kopírovat kolonky záznamů pomocí schránky Vašeho zařízení</string>
<string name="advanced_unlock_explanation_summary">Pro snadnější otevření databáze použít odemykání zařízení</string>
<string name="device_unlock_explanation_summary">Pro snadnější otevření databáze použít odemykání zařízení</string>
<string name="database_data_compression_title">Komprese dat</string>
<string name="database_data_compression_summary">Komprese dat snižuje velikost databáze</string>
<string name="max_history_items_title">Maximální počet</string>
@@ -484,7 +482,7 @@
<string name="configure_biometric">Žádné přihlašovací ani biometrické údaje nejsou registrovány.</string>
<string name="warning_empty_recycle_bin">Trvale odstranit všechny uzly z koše\?</string>
<string name="registration_mode">Registrace</string>
<string name="save_mode">Uložit</string>
<string name="save_mode">Režim ukládání</string>
<string name="search_mode">Vyhledávání</string>
<string name="error_field_name_already_exists">Jméno kolonky již existuje.</string>
<string name="error_registration_read_only">Uložení nové položky v režimu databáze pouze pro čtení není dovoleno.</string>
@@ -493,28 +491,27 @@
<string name="select_entry">Vybrat záznam</string>
<string name="back_to_previous_keyboard">Zpět na předchozí klávesnici</string>
<string name="custom_fields">Vlastní kolonky</string>
<string name="advanced_unlock_delete_all_key_warning">Odstranit všechny šifrovací klíče související s rozpoznáním odemykání zařízení\?</string>
<string name="device_unlock_delete_all_key_warning">Odstranit všechny šifrovací klíče související s rozpoznáním odemykání zařízení\?</string>
<string name="device_credential_unlock_enable_summary">Dovolí pro otevření databáze použít heslo Vašeho zařízení</string>
<string name="device_credential_unlock_enable_title">Odemknutí heslem zařízení</string>
<string name="device_credential">Heslo zařízení</string>
<string name="credential_before_click_advanced_unlock_button">Zadejte heslo a pak klepněte na toto tlačítko.</string>
<string name="advanced_unlock_prompt_not_initialized">Nepodařilo se inicializovat nabídku pro odemykání zařízení.</string>
<string name="advanced_unlock_scanning_error">Chyba při odemykání zařízení: %1$s</string>
<string name="advanced_unlock_not_recognized">Otisk pro odemykání zařízení nebyl rozpoznán</string>
<string name="advanced_unlock_invalid_key">Nepodařilo se načíst klíč odemykání zařízení. Odstraňte ho a opakujte proces rozpoznání odemknutí.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Načíst údaj z databáze pomocí dat odemykání zařízení</string>
<string name="advanced_unlock_prompt_extract_credential_title">Rozpoznání odemykání zařízení</string>
<string name="advanced_unlock_prompt_store_credential_message">Pokud použijete rozpoznání odemykání zařízení, musíte si i nadále pamatovat hlavní heslo trezoru.</string>
<string name="advanced_unlock_prompt_store_credential_title">Propojit s odemykáním zařízení</string>
<string name="credential_before_click_device_unlock_button">Zadejte heslo a pak klepněte na toto tlačítko.</string>
<string name="device_unlock_prompt_not_initialized">Nepodařilo se inicializovat nabídku pro odemykání zařízení.</string>
<string name="device_unlock_not_recognized">Otisk pro odemykání zařízení nebyl rozpoznán</string>
<string name="device_unlock_invalid_key">Nepodařilo se načíst klíč odemykání zařízení. Odstraňte ho a opakujte proces rozpoznání odemknutí.</string>
<string name="device_unlock_prompt_extract_credential_message">Načíst údaj z databáze pomocí dat odemykání zařízení</string>
<string name="device_unlock_prompt_extract_credential_title">Rozpoznání odemykání zařízení</string>
<string name="device_unlock_prompt_store_credential_message">Pokud použijete rozpoznání odemykání zařízení, musíte si i nadále pamatovat hlavní heslo trezoru.</string>
<string name="device_unlock_prompt_store_credential_title">Propojit s odemykáním zařízení</string>
<string name="menu_keystore_remove_key">Smazat klíč odemknutí zařízení</string>
<string name="education_advanced_unlock_title">Odemykání databáze zařízením</string>
<string name="advanced_unlock_timeout">Časový limit odemykání zařízení</string>
<string name="temp_advanced_unlock_timeout_summary">Trvání použití odemykání zařízení, než bude obsah smazán</string>
<string name="temp_advanced_unlock_enable_summary">Za účelem odemykání zařízení neukládat žádný šifrovaný obsah</string>
<string name="temp_advanced_unlock_enable_title">Dočasné odemykání zařízení</string>
<string name="advanced_unlock_tap_delete">Klepněte pro odstranění klíčů odemykání zařízení</string>
<string name="education_advanced_unlock_summary">Abyste rychle odemknuli databázi, propojte své heslo s naskenovanou biometrikou nebo údaji zámku zařízení.</string>
<string name="temp_advanced_unlock_timeout_title">Vypršení odemykání zařízení</string>
<string name="education_device_unlock_title">Odemykání databáze zařízením</string>
<string name="device_unlock_timeout">Časový limit odemykání zařízení</string>
<string name="temp_device_unlock_timeout_summary">Trvání použití odemykání zařízení, než bude obsah smazán</string>
<string name="temp_device_unlock_enable_summary">Za účelem odemykání zařízení neukládat žádný šifrovaný obsah</string>
<string name="temp_device_unlock_enable_title">Dočasné odemykání zařízení</string>
<string name="device_unlock_tap_delete">Klepněte pro odstranění klíčů odemykání zařízení</string>
<string name="education_device_unlock_summary">Abyste rychle odemknuli databázi, propojte své heslo s naskenovanou biometrikou nebo údaji zámku zařízení.</string>
<string name="temp_device_unlock_timeout_title">Vypršení odemykání zařízení</string>
<string name="content">Obsah</string>
<string name="error_rebuild_list">Seznam nelze řádně sestavit.</string>
<string name="error_database_uri_null">URI databáze nelze načíst.</string>
@@ -625,7 +622,7 @@
<string name="colorize_password_title">Zabarvit hesla</string>
<string name="colorize_password_summary">Zabarvit znaky hesla podle typu</string>
<string name="warning_database_already_opened">Databáze je již otevřená, zavřete ji, než otevřete jinou</string>
<string name="advanced_unlock_keystore_warning">Tato funkce uloží přihlašovací údaje v bezpečném úložišti klíčů Vašeho zařízení.
<string name="device_unlock_keystore_warning">Tato funkce uloží přihlašovací údaje v bezpečném úložišti klíčů Vašeho zařízení.
\n
\nV závislosti na implementaci nativního API operačního systému nemusí být plně funkční.
\n
@@ -672,7 +669,7 @@
<string name="info">Informace</string>
<string name="menu_app_settings_summary">Vyhledávání, uzamčení, historie, vlastnosti</string>
<string name="menu_form_filling_settings_summary">Klávesnice, automatické vyplnění, schránka</string>
<string name="menu_advanced_unlock_settings_summary">Biometrie, údaje zařízení</string>
<string name="menu_device_unlock_settings_summary">Biometrie, údaje zařízení</string>
<string name="menu_database_settings_summary">Metadata, koš, šablony, historie</string>
<string name="menu_security_settings_summary">Šifrování, funkce derivace klíče</string>
<string name="master_key_settings_summary">Změna, obnovení</string>
@@ -709,4 +706,5 @@
<string name="warning_large_keyfile">Nedoporučuje se přidávat velký klíčový soubor, mohlo by to zabránit otevření databáze.</string>
<string name="hide_templates_title">Skrýt šablony</string>
<string name="hide_templates_summary">Šablony nejsou zobrazeny</string>
<string name="error_otp_secret_length">Tajný klíč musí obsahovat alespoň %1$d znaků.</string>
</resources>

View File

@@ -193,7 +193,7 @@
<string name="lock">Lås</string>
<string name="lock_database_screen_off_title">Skærmlås</string>
<string name="lock_database_screen_off_summary">Lås databasen få sekunder efter at skærmen slukkes</string>
<string name="advanced_unlock">Enhedsoplåsning</string>
<string name="device_unlock">Enhedsoplåsning</string>
<string name="biometric_unlock_enable_title">Biometrisk oplåsning</string>
<string name="biometric_unlock_enable_summary">Giver mulighed for at scanne dine biometriske data for at åbne databasen</string>
<string name="biometric_delete_all_key_title">Slet krypteringsnøgler</string>
@@ -223,8 +223,6 @@
<string name="magic_keyboard_explanation_summary">Aktiver et brugerdefineret tastatur, der udfylder adgangskoder og alle identitetsfelter</string>
<string name="allow_no_password_title">Tillad ingen hovednøgle</string>
<string name="allow_no_password_summary">Tillader at trykke på knappen \"Åbn\", hvis der ikke er valgt nogen legitimationsoplysninger</string>
<string name="enable_read_only_title">Skrivebeskyttet</string>
<string name="enable_read_only_summary">Åbn som standard databasen skrivebeskyttet</string>
<string name="enable_education_screens_title">Praktiske tips</string>
<string name="enable_education_screens_summary">Fremhæv elementer for at lære, hvordan appen fungerer</string>
<string name="reset_education_screens_title">Nulstil praktiske tips</string>
@@ -333,7 +331,7 @@
<string name="content_description_update_from_list">Opdater</string>
<string name="content_description_keyboard_close_fields">Luk felter</string>
<string name="error_create_database_file">Kan ikke oprette database med denne adgangskode og nøglefil.</string>
<string name="menu_advanced_unlock_settings">Oplåsning af enhed</string>
<string name="menu_device_unlock_settings">Oplåsning af enhed</string>
<string name="biometric">Biometrisk</string>
<string name="biometric_auto_open_prompt_title">Prompt til automatisk åbning</string>
<string name="biometric_auto_open_prompt_summary">Anmod automatisk om oplåsning af enheden, hvis databasen er konfigureret til at bruge den</string>
@@ -365,7 +363,7 @@
<string name="contains_duplicate_uuid_procedure">Løs problemet ved at generere nye UUID\'er for dubletter og fortsætte\?</string>
<string name="database_opened">Database åbnet</string>
<string name="clipboard_explanation_summary">Kopier indtastningsfelter ved hjælp af enhedens udklipsholder</string>
<string name="advanced_unlock_explanation_summary">Brug enhedsoplåsning til at åbne en database nemmere</string>
<string name="device_unlock_explanation_summary">Brug enhedsoplåsning til at åbne en database nemmere</string>
<string name="database_data_compression_title">Datakomprimering</string>
<string name="database_data_compression_summary">Datakomprimering reducerer databasens størrelse</string>
<string name="max_history_items_title">Maksimalt antal</string>
@@ -497,21 +495,20 @@
<string name="unit_kibibyte">KiB</string>
<string name="unit_byte">B</string>
<string name="download_canceled">Annulleret!</string>
<string name="education_advanced_unlock_title">Database-oplåsning</string>
<string name="education_device_unlock_title">Database-oplåsning</string>
<string name="autofill_inline_suggestions_keyboard">Forslag til autofyld tilføjet.</string>
<string name="select_entry">Vælg post</string>
<string name="back_to_previous_keyboard">Tilbage til forrige tastatur</string>
<string name="custom_fields">Brugerdefinerede felter</string>
<string name="advanced_unlock_delete_all_key_warning">Seletealle krypteringsnøgler relateret til enhedsoplåsningsgenkendelse?</string>
<string name="advanced_unlock_tap_delete">Tryk for at slette enhedens oplåsningsnøgler</string>
<string name="device_unlock_delete_all_key_warning">Seletealle krypteringsnøgler relateret til enhedsoplåsningsgenkendelse?</string>
<string name="device_unlock_tap_delete">Tryk for at slette enhedens oplåsningsnøgler</string>
<string name="content">Indhold</string>
<string name="credential_before_click_advanced_unlock_button">Indtast adgangskoden, og klik derefter på denne knap.</string>
<string name="advanced_unlock_prompt_not_initialized">Kunne ikke initialisere oplåsningsprompt.</string>
<string name="advanced_unlock_scanning_error">Fejl ved oplåsning: %1$s</string>
<string name="advanced_unlock_not_recognized">Kunne ikke genkende aftryk til oplåsning</string>
<string name="advanced_unlock_invalid_key">Oplåsningsnøgle kan ikke læses. Slet den og gentag proceduren for genkendelse af oplåsning.</string>
<string name="advanced_unlock_prompt_extract_credential_title">Enhedsoplåsningsgenkendelse</string>
<string name="advanced_unlock_prompt_store_credential_title">Link til enhedsoplåsning</string>
<string name="credential_before_click_device_unlock_button">Indtast adgangskoden, og klik derefter på denne knap.</string>
<string name="device_unlock_prompt_not_initialized">Kunne ikke initialisere oplåsningsprompt.</string>
<string name="device_unlock_not_recognized">Kunne ikke genkende aftryk til oplåsning</string>
<string name="device_unlock_invalid_key">Oplåsningsnøgle kan ikke læses. Slet den og gentag proceduren for genkendelse af oplåsning.</string>
<string name="device_unlock_prompt_extract_credential_title">Enhedsoplåsningsgenkendelse</string>
<string name="device_unlock_prompt_store_credential_title">Link til enhedsoplåsning</string>
<string name="warning_database_info_changed_options">Flet data, overskriv de eksterne ændringer ved at gemme databasen eller genindlæs den med de seneste ændringer.</string>
<string name="warning_database_info_changed">Oplysningerne i databasefilen er blevet ændret uden for appen.</string>
<string name="menu_keystore_remove_key">Slet enheds oplåsningsnøgle</string>
@@ -522,24 +519,24 @@
<string name="error_rebuild_list">Listen kan ikke genopbygges korrekt.</string>
<string name="error_database_uri_null">Database-URI kan ikke hentes.</string>
<string name="content_description_otp_information">Oplysninger om engangsadgangskode</string>
<string name="advanced_unlock_prompt_extract_credential_message">Udtræk databases legitimationsoplysninger med enheds oplåsningdata</string>
<string name="advanced_unlock_prompt_store_credential_message">Du skal stadig huske din boks primære legitimationsoplysning, hvis du bruger oplåsningsgenkendelse på enheden.</string>
<string name="device_unlock_prompt_extract_credential_message">Udtræk databases legitimationsoplysninger med enheds oplåsningdata</string>
<string name="device_unlock_prompt_store_credential_message">Du skal stadig huske din boks primære legitimationsoplysning, hvis du bruger oplåsningsgenkendelse på enheden.</string>
<string name="warning_database_revoked">Adgang til filen tilbagekaldt af filhåndteringsprogrammet, luk databasen og genåbn den fra dens placering.</string>
<string name="error_start_database_action">Der opstod en fejl under udførelsen af en handling på databasen.</string>
<string name="error_remove_file">Der opstod en fejl under fjernelsen af fildata.</string>
<string name="error_otp_type">Den existerende OTP-type kunne ikke genkendes. Det kan være, at dens validering ikke længere genererer token korrekt.</string>
<string name="education_advanced_unlock_summary">Sammenkæd din adgangskode med din scannede biometriske data eller enhedens legitimationsoplysninger for hurtigt at låse din database op.</string>
<string name="education_device_unlock_summary">Sammenkæd din adgangskode med din scannede biometriske data eller enhedens legitimationsoplysninger for hurtigt at låse din database op.</string>
<string name="enter">Enter</string>
<string name="temp_advanced_unlock_timeout_summary">Varigheden af oplåsning, før indholdet slettes</string>
<string name="temp_device_unlock_timeout_summary">Varigheden af oplåsning, før indholdet slettes</string>
<string name="device_credential_unlock_enable_summary">Giver dig mulighed for at bruge dine enhedsoplysninger til at åbne databasen</string>
<string name="device_credential_unlock_enable_title">Oplåsning via enhedsoplysninger</string>
<string name="autofill_inline_suggestions_summary">Forsøg at vise forslag til automatisk udfyldning direkte fra et kompatibelt tastatur</string>
<string name="autofill_inline_suggestions_title">Indbyggede forslag</string>
<string name="backspace">Tilbagetast</string>
<string name="advanced_unlock_timeout">Tidsudløb for oplåsning</string>
<string name="temp_advanced_unlock_timeout_title">Udløb af oplåsning af enhed</string>
<string name="temp_advanced_unlock_enable_summary">Gem ikke krypteret indhold for at bruge enhedsoplåsning</string>
<string name="temp_advanced_unlock_enable_title">Midlertidig oplåsning af enhed</string>
<string name="device_unlock_timeout">Tidsudløb for oplåsning</string>
<string name="temp_device_unlock_timeout_title">Udløb af oplåsning af enhed</string>
<string name="temp_device_unlock_enable_summary">Gem ikke krypteret indhold for at bruge enhedsoplåsning</string>
<string name="temp_device_unlock_enable_title">Midlertidig oplåsning af enhed</string>
<string name="device_credential">Enhedens legitimation</string>
<string name="properties">Egenskaber</string>
<string name="error_export_app_properties">Fejl under eksport af app-indstillinger.</string>
@@ -643,7 +640,7 @@
<string name="show_otp_token_summary">Viser OTP-tokens på listen over poster</string>
<string name="show_entry_colors_summary">Viser forgrund- og baggrundsfarver for en post</string>
<string name="templates_group_enable_summary">Brug dynamiske skabeloner til at udfylde felterne i en post</string>
<string name="advanced_unlock_keystore_warning">Denne funktion gemmer krypterede legitimationsdata i den sikre KeyStore på din enhed.
<string name="device_unlock_keystore_warning">Denne funktion gemmer krypterede legitimationsdata i den sikre KeyStore på din enhed.
\n
\nAfhængigt af operativsystemets indbyggede API-implementering er funktionen muligvis ikke fuldt funktionsdygtig.
\nKontroller kompatibiliteten og sikkerheden af KeyStore med producenten af din enhed og skaberen af den ROM, du bruger.</string>
@@ -674,7 +671,7 @@
<string name="menu_form_filling_settings_summary">Tastatur, autofyld, udklipsholder</string>
<string name="configure">Konfigurér</string>
<string name="menu_security_settings_summary">Kryptering, Nøgleafledningsfunktion</string>
<string name="menu_advanced_unlock_settings_summary">Biometri, enhedens legitimation</string>
<string name="menu_device_unlock_settings_summary">Biometri, enhedens legitimation</string>
<string name="warning_database_notification_permission">Meddelelsestilladelsen giver dig mulighed for at vise status for databasen og låse den med en let tilgængelig knap.
\n
\nHvis du ikke aktiverer denne tilladelse, vil den database, der er åben i baggrunden, ikke være synlig, hvis et andet program er i forgrunden.</string>

View File

@@ -25,7 +25,7 @@
<string name="contribution">Beiträge</string>
<string name="feedback">Feedback</string>
<string name="homepage">Webseite</string>
<string name="about_description">Android-Implementierung des Passwortmanagers KeePass</string>
<string name="about_description">Android-Implementierung des Passwortmanagers KeePass.</string>
<string name="accept">Akzeptieren</string>
<string name="add_entry">Eintrag hinzufügen</string>
<string name="add_group">Gruppe hinzufügen</string>
@@ -163,7 +163,7 @@
<string name="file_name">Dateiname</string>
<string name="unavailable_feature_text">Diese Funktion konnte nicht gestartet werden.</string>
<string name="biometric_unlock_enable_summary">Ermöglicht das Scannen biometrischer Merkmale, um die Datenbank zu öffnen</string>
<string name="advanced_unlock">Gerät entsperren</string>
<string name="device_unlock">Gerät entsperren</string>
<string name="biometric_unlock_enable_title">Biometrisches Entsperren</string>
<string name="lock">Sperren</string>
<string name="list_password_generator_options_summary">Erlaubte Zeichen für Passwortgenerator festlegen</string>
@@ -253,7 +253,7 @@
<string name="html_text_ad_free">Anders als viele Passwortmanager ist dieser &lt;strong&gt;werbefrei&lt;/strong&gt;, &lt;strong&gt;quelloffen&lt;/strong&gt;, &lt;strong&gt;freie Copyleft-Software&lt;/strong&gt; und keine persönlichen Daten werden auf Servern gesammelt, egal welche Version man verwendet.</string>
<string name="html_text_buy_pro">Mit dem Kauf der Pro-Version erhältst du Zugriff auf diesen &lt;strong&gt;visuellen Stil&lt;/strong&gt; und unterstützt insbesondere &lt;strong&gt;die Umsetzung gemeinschaftlicher Projekte.&lt;/strong&gt;</string>
<string name="html_text_feature_generosity">Dieser &lt;strong&gt;visuelle Stil&lt;/strong&gt; ist dank deiner Großzügigkeit verfügbar.</string>
<string name="html_text_donation">Mit &lt;strong&gt;Beitragen&lt;/strong&gt; zum Projekt <i>(finanziell, Code, Übersetzung)</i> wird sichergestellt, dass es weiterlebt und gedeiht, und außerdem berechtigt das für den Vorgang der &lt;strong&gt;Design&lt;/strong&gt;-Freischaltung.</string>
<string name="html_text_donation">Mit &lt;strong&gt;Beitragen&lt;/strong&gt; zum Projekt &lt;i&gt;(finanziell, Code, Übersetzung)&lt;/i&gt; wird sichergestellt, dass es weiterlebt und gedeiht, und außerdem berechtigt das für den Vorgang der &lt;strong&gt;Design&lt;/strong&gt;-Freischaltung.</string>
<string name="html_text_dev_feature">Diese Funktion ist &lt;strong&gt;in Entwicklung&lt;/strong&gt; und erfordert &lt;strong&gt;deinen Beitrag&lt;/strong&gt;, um bald verfügbar zu sein.</string>
<string name="html_text_dev_feature_buy_pro">Durch den Kauf der &lt;strong&gt;Pro-Version&lt;/strong&gt;,</string>
<string name="html_text_dev_feature_contibute">Durch deinen &lt;strong&gt;Beitrag&lt;/strong&gt;,</string>
@@ -277,13 +277,8 @@
<string name="enable_education_screens_summary">Bedienelemente hervorheben, um die Funktionsweise der App zu lernen</string>
<string name="menu_open_file_read_and_write">Änderbar</string>
<string name="menu_file_selection_read_only">Schreibgeschützt</string>
<string name="enable_read_only_title">Schreibgeschützt</string>
<string name="education_read_only_title">Datenbank-Schreibschutz aktivieren</string>
<string name="enable_read_only_summary">Datenbank standardmäßig schreibgeschützt öffnen</string>
<string name="education_read_only_summary">Den Öffnungsmodus für die Sitzung ändern.
\n
\n„Schreibgeschützt“ verhindert unbeabsichtigte Änderungen.
\nMit „Änderbar“ lässt sich jedes Element frei bearbeiten, hinzufügen oder löschen.</string>
<string name="education_read_only_summary">Den Öffnungsmodus für die Sitzung ändern. \n \n„Schreibgeschützt“ verhindert unbeabsichtigte Änderungen an der Datenbank. \nMit „Änderbar“ lässt sich jedes Element frei bearbeiten, hinzufügen oder löschen.</string>
<string name="edit_entry">Eintrag bearbeiten</string>
<string name="error_load_database">Die Datenbank konnte nicht geladen werden.</string>
<string name="error_load_database_KDF_memory">Laden des Schlüssels fehlgeschlagen. Bitte versuchen, die „Arbeitsspeichernutzung“ der Schlüsselableitungsfunktion zu verringern.</string>
@@ -350,7 +345,7 @@
<string name="content_description_update_from_list">Aktualisieren</string>
<string name="content_description_keyboard_close_fields">Felder schließen</string>
<string name="error_create_database_file">Die Datenbank kann mit diesem Passwort und dieser Schlüsseldatei nicht erstellt werden.</string>
<string name="menu_advanced_unlock_settings">Geräteentsperrung</string>
<string name="menu_device_unlock_settings">Geräteentsperrung</string>
<string name="biometric">Biometrisch</string>
<string name="enable">Aktivieren</string>
<string name="disable">Deaktivieren</string>
@@ -385,7 +380,7 @@
<string name="contains_duplicate_uuid_procedure">Problem lösen, indem neue UUIDs für Duplikate generiert werden, um fortzufahren?</string>
<string name="database_opened">Datenbank geöffnet</string>
<string name="clipboard_explanation_summary">Eintragsfelder mit der Zwischenablage des Geräts kopieren</string>
<string name="advanced_unlock_explanation_summary">Geräteentsperrung verwenden, um eine Datenbank einfacher zu öffnen</string>
<string name="device_unlock_explanation_summary">Geräteentsperrung verwenden, um eine Datenbank einfacher zu öffnen</string>
<string name="database_data_compression_title">Datenkomprimierung</string>
<string name="database_data_compression_summary">Datenkomprimierung reduziert die Datenbankgröße</string>
<string name="max_history_items_title">Maximale Anzahl</string>
@@ -505,34 +500,33 @@
<string name="keyboard_save_search_info_title">Geteilte Informationen speichern</string>
<string name="warning_empty_recycle_bin">Alle Knoten unwiderruflich aus dem Papierkorb löschen\?</string>
<string name="error_field_name_already_exists">Der Feldname existiert bereits.</string>
<string name="advanced_unlock_prompt_store_credential_message">Du musst dich weiterhin an deinen Hauptschlüssel erinnern, wenn du die Geräteentsperrung verwendest.</string>
<string name="device_unlock_prompt_store_credential_message">Du musst dich weiterhin an deinen Hauptschlüssel erinnern, wenn du die Geräteentsperrung verwendest.</string>
<string name="menu_keystore_remove_key">Schlüssel für Geräteentsperrung löschen</string>
<string name="advanced_unlock_prompt_store_credential_title">Verknüpfung mit Geräteentsperrung</string>
<string name="education_advanced_unlock_summary">Eigenes Passwort mit Biometrie- oder Geräteanmeldedaten verknüpfen, um die Datenbank schnell zu entsperren.</string>
<string name="education_advanced_unlock_title">Geräteentsperrung der Datenbank</string>
<string name="advanced_unlock_timeout">Zeitlimit für Geräteentsperrung</string>
<string name="temp_advanced_unlock_timeout_summary">Dauer der Geräteentsperrung, bis sie zurückgesetzt wird</string>
<string name="temp_advanced_unlock_timeout_title">Ablauf der Geräteentsperrung</string>
<string name="temp_advanced_unlock_enable_summary">Bei Nutzung der Geräteentsperrung keine verschlüsselten Inhalte speichern</string>
<string name="temp_advanced_unlock_enable_title">Zeitlich begrenzte Geräteentsperrung</string>
<string name="device_unlock_prompt_store_credential_title">Verknüpfung mit Geräteentsperrung</string>
<string name="education_device_unlock_summary">Eigenes Passwort mit Biometrie- oder Geräteanmeldedaten verknüpfen, um die Datenbank schnell zu entsperren.</string>
<string name="education_device_unlock_title">Geräteentsperrung der Datenbank</string>
<string name="device_unlock_timeout">Zeitlimit für Geräteentsperrung</string>
<string name="temp_device_unlock_timeout_summary">Dauer der Geräteentsperrung, bis sie zurückgesetzt wird</string>
<string name="temp_device_unlock_timeout_title">Ablauf der Geräteentsperrung</string>
<string name="temp_device_unlock_enable_summary">Bei Nutzung der Geräteentsperrung keine verschlüsselten Inhalte speichern</string>
<string name="temp_device_unlock_enable_title">Zeitlich begrenzte Geräteentsperrung</string>
<string name="device_credential_unlock_enable_summary">Ermöglicht das Öffnen der Datenbank mit deinen Geräteanmeldedaten</string>
<string name="advanced_unlock_tap_delete">Drücken, um alle Geräteentsperrschlüssel zu löschen</string>
<string name="device_unlock_tap_delete">Drücken, um alle Geräteentsperrschlüssel zu löschen</string>
<string name="content">Inhalt</string>
<string name="advanced_unlock_prompt_extract_credential_title">Datenbank mit Geräteentsperrdaten öffnen</string>
<string name="device_unlock_prompt_extract_credential_title">Datenbank mit Geräteentsperrdaten öffnen</string>
<string name="enter">Eingabetaste</string>
<string name="backspace">Rücktaste</string>
<string name="select_entry">Eintrag auswählen</string>
<string name="back_to_previous_keyboard">Zurück zur vorherigen Tastatur</string>
<string name="custom_fields">Benutzerdefinierte Felder</string>
<string name="advanced_unlock_delete_all_key_warning">Alle zur Geräteentsperrung zugehörigen Verschlüsselungsschlüssel löschen\?</string>
<string name="device_unlock_delete_all_key_warning">Alle zur Geräteentsperrung zugehörigen Verschlüsselungsschlüssel löschen\?</string>
<string name="device_credential_unlock_enable_title">Entsperrung mit Geräteanmeldedaten</string>
<string name="device_credential">Geräteanmeldedaten</string>
<string name="credential_before_click_advanced_unlock_button">Passwort eingeben und dann diese Taste drücken.</string>
<string name="advanced_unlock_prompt_not_initialized">Geräteentsperrungsabfrage konnte nicht gestartet werden.</string>
<string name="advanced_unlock_scanning_error">Fehler bei Geräteentsperrung: %1$s</string>
<string name="advanced_unlock_not_recognized">Fingerabdruck für Geräteentsperrung wurde nicht erkannt</string>
<string name="advanced_unlock_invalid_key">Der Geräteentsperrschlüssel ist nicht lesbar. Bitte diesen löschen und den Vorgang zur Entsperr-Erkennung wiederholen.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Datenbankanmeldedaten aus Geräteentsperrdaten gewinnen</string>
<string name="credential_before_click_device_unlock_button">Passwort eingeben und dann diese Taste drücken.</string>
<string name="device_unlock_prompt_not_initialized">Geräteentsperrungsabfrage konnte nicht gestartet werden.</string>
<string name="device_unlock_not_recognized">Fingerabdruck für Geräteentsperrung wurde nicht erkannt</string>
<string name="device_unlock_invalid_key">Der Geräteentsperrschlüssel ist nicht lesbar. Bitte diesen löschen und den Vorgang zur Entsperr-Erkennung wiederholen.</string>
<string name="device_unlock_prompt_extract_credential_message">Datenbankanmeldedaten aus Geräteentsperrdaten gewinnen</string>
<string name="error_rebuild_list">Die Liste kann nicht ordnungsgemäß neu erstellt werden.</string>
<string name="error_database_uri_null">Datenbank-URI kann nicht abgerufen werden.</string>
<string name="menu_reload_database">Daten neu laden</string>
@@ -633,7 +627,7 @@
<string name="navigation_drawer_open">Navigationsleiste öffnen</string>
<string name="expired">Abgelaufen</string>
<string name="warning_database_already_opened">Eine Datenbank ist bereits geöffnet. Schließe sie, um eine neue zu öffnen</string>
<string name="advanced_unlock_keystore_warning">Diese Funktion speichert verschlüsselte Anmeldedaten im sicheren Schlüsselspeicher dieses Geräts.
<string name="device_unlock_keystore_warning">Diese Funktion speichert verschlüsselte Anmeldedaten im sicheren Schlüsselspeicher dieses Geräts.
\n
\nJe nach der internen API-Implementierung des Betriebssystems kann sie eingeschränkt sein.
\n
@@ -681,7 +675,7 @@
<string name="html_about_privacy">&lt;strong&gt;Es werden keine Benutzerdaten ausgelesen&lt;/strong&gt;, diese Anwendung stellt keine Verbindung zu einem Server her, arbeitet nur lokal und respektiert vollständig die Privatsphäre der Benutzer.</string>
<string name="merge_success">Zusammenführung erfolgreich abgeschlossen</string>
<string name="menu_form_filling_settings_summary">Tastatur, automatisches Ausfüllen, Zwischenablage</string>
<string name="menu_advanced_unlock_settings_summary">Biometrie, Geräteanmeldedaten</string>
<string name="menu_device_unlock_settings_summary">Biometrie, Geräteanmeldedaten</string>
<string name="menu_database_settings_summary">Metadaten, Papierkorb, Vorlagen, Verlauf</string>
<string name="menu_app_settings_summary">Suche, Sperre, Verlauf, Eigenschaften</string>
<string name="menu_security_settings_summary">Verschlüsselung, Schlüsselableitungsfunktion</string>
@@ -711,4 +705,5 @@
<string name="warning_large_keyfile">Es wird nicht empfohlen, eine große Schlüsseldatei hinzuzufügen, da dies das Öffnen der Datenbank verhindern kann.</string>
<string name="recursive_number_entries_title">Rekursive Anzahl der Einträge</string>
<string name="generate_keyfile">Schlüsseldatei generieren</string>
<string name="error_otp_secret_length">Geheimschlüssel muss mindestens %1$d Zeichen lang sein.</string>
</resources>

View File

@@ -19,7 +19,7 @@
--><resources>
<string name="feedback">Σχόλια</string>
<string name="homepage">Αρχική Σελίδα</string>
<string name="about_description">Το KeePassDX είναι μία εφαρμογή Android του διαχειριστή κωδικών KeePass</string>
<string name="about_description">Υλοποίηση του διαχειριστή κωδικών πρόσβασης KeePass για Android.</string>
<string name="accept">Αποδοχή</string>
<string name="add_entry">Προσθήκη καταχώρησης</string>
<string name="add_group">Προσθήκη ομάδας</string>
@@ -233,7 +233,7 @@
<string name="html_text_ad_free">Σε αντίθεση με πολλές άλλες εφαρμογές διαχείρισης κωδικών πρόσβασης, αυτή είναι &lt;strong&gt;χωρίς διαφημίσεις&lt;/strong&gt;, &lt;strong&gt;copylefted libre λογισμικό&lt;/strong&gt; και δεν συλλέγει προσωπικά δεδομένα στους διακομιστές της, ανεξάρτητα από την έκδοση που χρησιμοποιείτε.</string>
<string name="html_text_buy_pro">Με την αγορά της επαγγελματικής έκδοσης, θα έχετε πρόσβαση σε αυτό το &lt;strong&gt;οπτικό στοιχείο&lt;/strong&gt; και θα βοηθήσετε ιδιαίτερα την &lt;strong&gt;υλοποίηση ιδεών της κοινότητας.&lt;/strong&gt;</string>
<string name="html_text_feature_generosity">Αυτό το &lt;strong&gt;οπτικό στυλ&lt;/strong&gt; είναι διαθέσιμο χάρη στη γενναιοδωρία σας.</string>
<string name="html_text_donation">Με τη &lt;strong&gt;συνεισφορά σας&lt;/strong&gt; στο έργο <i>(χρηματικά, κώδικα, μετάφραση)</i>, θα το βοηθήσετε να συνεχίσει να ζει και να ευδοκιμεί και θα είστε επίσης επιλέξιμοι για τη διαδικασία ξεκλειδώματος &lt;strong&gt;θεμάτων &lt;/strong&gt; .</string>
<string name="html_text_donation">Με τη &lt;strong&gt;συνεισφορά σας&lt;/strong&gt; στο έργο &lt;i&gt;(χρηματικά, κώδικα, μετάφραση)&lt;/i&gt;, θα το βοηθήσετε να συνεχίσει να ζει και να ευδοκιμεί και θα είστε επίσης επιλέξιμοι για τη διαδικασία ξεκλειδώματος &lt;strong&gt;θεμάτων &lt;/strong&gt; .</string>
<string name="html_text_dev_feature">Αυτή η λειτουργία είναι &lt;strong&gt;υπό ανάπτυξη&lt;/strong&gt; και απαιτεί την &lt;strong&gt;συνεισφοράς&lt;/strong&gt; σας για να είναι σύντομα διαθέσιμη.</string>
<string name="html_text_dev_feature_buy_pro">Με την αγορά της έκδοσης &lt;strong&gt;pro&lt;/strong&gt;,</string>
<string name="html_text_dev_feature_contibute">Με την &lt;strong&gt;συνεισφορά&lt;/strong&gt; σας,</string>
@@ -259,8 +259,6 @@
<string name="enable_education_screens_summary">Επισήμανση στοιχείων για να μάθετε πώς λειτουργεί η εφαρμογή</string>
<string name="menu_file_selection_read_only">Προστασία εγγραφής</string>
<string name="menu_open_file_read_and_write">Τροποποιήσιμο</string>
<string name="enable_read_only_title">Προστασία Εγγραφής</string>
<string name="enable_read_only_summary">Ανοίξτε τη βάση δεδομένων μόνο για ανάγνωση από προεπιλογή</string>
<string name="education_read_only_title">Προστασία Εγγραφής της βάσης δεδομένων σας</string>
<string name="education_read_only_summary">Αλλάξτε τη λειτουργία ανοίγματος για το session.
\n
@@ -325,11 +323,11 @@
<string name="content_description_update_from_list">Ενημέρωση</string>
<string name="content_description_keyboard_close_fields">Κλείσιμο πεδίων</string>
<string name="error_create_database_file">Δεν είναι δυνατή η δημιουργία βάσης δεδομένων με αυτόν τον κωδικό πρόσβασης και το αρχείο κλειδί.</string>
<string name="menu_advanced_unlock_settings">Ξεκλείδωμα συσκευής</string>
<string name="menu_device_unlock_settings">Ξεκλείδωμα συσκευής</string>
<string name="unavailable">Μη διαθέσιμο</string>
<string name="menu_appearance_settings">Εμφάνιση</string>
<string name="biometric">Βιομετρία</string>
<string name="advanced_unlock">Ξεκλείδωμα συσκευής</string>
<string name="device_unlock">Ξεκλείδωμα συσκευής</string>
<string name="biometric_unlock_enable_title">Βιομετρικό ξεκλείδωμα</string>
<string name="biometric_unlock_enable_summary">Σας επιτρέπει να σαρώσετε το βιομετρικό σας για να ανοίξετε τη βάση δεδομένων</string>
<string name="biometric_auto_open_prompt_title">Αυτόματο άνοιγμα προτροπής</string>
@@ -366,7 +364,7 @@
<string name="autofill_explanation_summary">Ενεργοποιήστε την αυτόματη συμπλήρωση για να συμπληρώσετε γρήγορα φόρμες σε άλλες εφαρμογές</string>
<string name="database_opened">Η Βάση Δεδομένων άνοιξε</string>
<string name="clipboard_explanation_summary">Αντιγράψτε τα πεδία εισαγωγής χρησιμοποιώντας το πρόχειρο της συσκευής σας</string>
<string name="advanced_unlock_explanation_summary">Χρησιμοποιήστε το ξεκλείδωμα συσκευής για να ανοίξετε μια βάση δεδομένων πιο εύκολα</string>
<string name="device_unlock_explanation_summary">Χρησιμοποιήστε το ξεκλείδωμα συσκευής για να ανοίξετε μια βάση δεδομένων πιο εύκολα</string>
<string name="database_data_compression_title">Συμπίεση Δεδομένων</string>
<string name="database_data_compression_summary">Η συμπίεση δεδομένων μειώνει το μέγεθος της βάσης δεδομένων</string>
<string name="max_history_items_title">Μέγιστος αριθμός</string>
@@ -487,33 +485,32 @@
<string name="search_mode">Λειτουργία αναζήτησης</string>
<string name="error_registration_read_only">Η αποθήκευση ενός νέου αντικειμένου δεν επιτρέπεται σε μια βάση δεδομένων μόνο για ανάγνωση.</string>
<string name="error_field_name_already_exists">Το όνομα πεδίου υπάρχει ήδη.</string>
<string name="advanced_unlock_prompt_store_credential_title">Σύνδεσμος για ξεκλείδωμα συσκευής</string>
<string name="advanced_unlock_prompt_store_credential_message">Θα πρέπει ακόμα να θυμάστε τα κύρια διαπιστευτήρια της κρύπτης εάν χρησιμοποιείτε την αναγνώριση ξεκλειδώματος συσκευής.</string>
<string name="advanced_unlock_prompt_extract_credential_title">Αναγνώριση ξεκλειδώματος συσκευής</string>
<string name="device_unlock_prompt_store_credential_title">Σύνδεσμος για ξεκλείδωμα συσκευής</string>
<string name="device_unlock_prompt_store_credential_message">Θα πρέπει ακόμα να θυμάστε τα κύρια διαπιστευτήρια της κρύπτης εάν χρησιμοποιείτε την αναγνώριση ξεκλειδώματος συσκευής.</string>
<string name="device_unlock_prompt_extract_credential_title">Αναγνώριση ξεκλειδώματος συσκευής</string>
<string name="menu_keystore_remove_key">Διαγραφή κλειδιού ξεκλειδώματος συσκευής</string>
<string name="enter">Enter</string>
<string name="backspace">Backspace</string>
<string name="select_entry">Επιλέξτε καταχώριση</string>
<string name="back_to_previous_keyboard">Επιστροφή στο προηγούμενο πληκτρολόγιο</string>
<string name="custom_fields">Προσαρμοσμένα πεδία</string>
<string name="advanced_unlock_delete_all_key_warning">Διαγραφή όλων των κλειδιών κρυπτογράφησης που σχετίζονται με την αναγνώριση ξεκλειδώματος συσκευής;</string>
<string name="device_unlock_delete_all_key_warning">Διαγραφή όλων των κλειδιών κρυπτογράφησης που σχετίζονται με την αναγνώριση ξεκλειδώματος συσκευής;</string>
<string name="device_credential_unlock_enable_summary">Σας επιτρέπει να χρησιμοποιήσετε τα διαπιστευτήρια της συσκευής σας για να ανοίξετε τη βάση δεδομένων</string>
<string name="device_credential_unlock_enable_title">Ξεκλείδωμα διαπιστευτηρίων συσκευής</string>
<string name="device_credential">Διαπιστευτήρια συσκευής</string>
<string name="credential_before_click_advanced_unlock_button">Πληκτρολογήστε τον κωδικό πρόσβασης, και στη συνέχεια κάντε κλικ αυτό το κουμπί.</string>
<string name="advanced_unlock_prompt_not_initialized">Δεν είναι δυνατή η προετοιμασία της προτροπής ξεκλειδώματος συσκευής.</string>
<string name="advanced_unlock_not_recognized">Δεν ήταν δυνατή η αναγνώριση αποτυπώματος ξεκλειδώματος συσκευής</string>
<string name="advanced_unlock_scanning_error">Σφάλμα ξεκλειδώματος συσκευής: %1$s</string>
<string name="advanced_unlock_invalid_key">Δεν είναι δυνατή η ανάγνωση του κλειδιού ξεκλειδώματος της συσκευής. Διαγράψτε το και επαναλάβετε τη διαδικασία αναγνώρισης ξεκλειδώματος.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Εξαγωγή διαπιστευτηρίων βάσης δεδομένων με δεδομένα ξεκλειδώματος συσκευής</string>
<string name="education_advanced_unlock_summary">Συνδέστε τον κωδικό πρόσβασής σας με το σαρωμένο βιομετρικό ή τα διαπιστευτήρια της συσκευής σας για να ξεκλειδώσετε γρήγορα τη βάση δεδομένων σας.</string>
<string name="education_advanced_unlock_title">Ξεκλείδωμα βάσης δεδομένων συσκευής</string>
<string name="advanced_unlock_timeout">Χρονικό όριο ξεκλειδώματος συσκευής</string>
<string name="temp_advanced_unlock_enable_title">Προσωρινό ξεκλείδωμα συσκευής</string>
<string name="temp_advanced_unlock_enable_summary">Μην αποθηκεύετε κρυπτογραφημένο περιεχόμενο για να χρησιμοποιήσετε το ξεκλείδωμα της συσκευής</string>
<string name="temp_advanced_unlock_timeout_summary">Διάρκεια χρήσης ξεκλειδώματος συσκευής πριν από τη διαγραφή του περιεχομένου της</string>
<string name="temp_advanced_unlock_timeout_title">Λήξη ξεκλειδώματος συσκευής</string>
<string name="advanced_unlock_tap_delete">Πατήστε για να διαγράψετε τα κλειδιά ξεκλειδώματος της συσκευής</string>
<string name="credential_before_click_device_unlock_button">Πληκτρολογήστε τον κωδικό πρόσβασης, και στη συνέχεια κάντε κλικ αυτό το κουμπί.</string>
<string name="device_unlock_prompt_not_initialized">Δεν είναι δυνατή η προετοιμασία της προτροπής ξεκλειδώματος συσκευής.</string>
<string name="device_unlock_not_recognized">Δεν ήταν δυνατή η αναγνώριση αποτυπώματος ξεκλειδώματος συσκευής</string>
<string name="device_unlock_invalid_key">Δεν είναι δυνατή η ανάγνωση του κλειδιού ξεκλειδώματος της συσκευής. Διαγράψτε το και επαναλάβετε τη διαδικασία αναγνώρισης ξεκλειδώματος.</string>
<string name="device_unlock_prompt_extract_credential_message">Εξαγωγή διαπιστευτηρίων βάσης δεδομένων με δεδομένα ξεκλειδώματος συσκευής</string>
<string name="education_device_unlock_summary">Συνδέστε τον κωδικό πρόσβασής σας με το σαρωμένο βιομετρικό ή τα διαπιστευτήρια της συσκευής σας για να ξεκλειδώσετε γρήγορα τη βάση δεδομένων σας.</string>
<string name="education_device_unlock_title">Ξεκλείδωμα βάσης δεδομένων συσκευής</string>
<string name="device_unlock_timeout">Χρονικό όριο ξεκλειδώματος συσκευής</string>
<string name="temp_device_unlock_enable_title">Προσωρινό ξεκλείδωμα συσκευής</string>
<string name="temp_device_unlock_enable_summary">Μην αποθηκεύετε κρυπτογραφημένο περιεχόμενο για να χρησιμοποιήσετε το ξεκλείδωμα της συσκευής</string>
<string name="temp_device_unlock_timeout_summary">Διάρκεια χρήσης ξεκλειδώματος συσκευής πριν από τη διαγραφή του περιεχομένου της</string>
<string name="temp_device_unlock_timeout_title">Λήξη ξεκλειδώματος συσκευής</string>
<string name="device_unlock_tap_delete">Πατήστε για να διαγράψετε τα κλειδιά ξεκλειδώματος της συσκευής</string>
<string name="content">Περιεχόμενα</string>
<string name="error_rebuild_list">Δεν είναι δυνατή η σωστή αναδημιουργία της λίστας.</string>
<string name="error_database_uri_null">Δεν είναι δυνατή η ανάκτηση του URI βάσης δεδομένων.</string>
@@ -621,7 +618,7 @@
<string name="menu_save_copy_to">Αποθήκευση αντιγράφου στο …</string>
<string name="expired">Ληγμένο</string>
<string name="warning_database_already_opened">Μια βάση δεδομένων είναι ήδη ανοιχτή, κλείστε την πρώτα για να ανοίξετε τη νέα</string>
<string name="advanced_unlock_keystore_warning">Αυτή η δυνατότητα θα αποθηκεύσει κρυπτογραφημένα δεδομένα διαπιστευτηρίων στο ασφαλές KeyStore της συσκευής σας.
<string name="device_unlock_keystore_warning">Αυτή η δυνατότητα θα αποθηκεύσει κρυπτογραφημένα δεδομένα διαπιστευτηρίων στο ασφαλές KeyStore της συσκευής σας.
\n
\nΑνάλογα με την εγγενή υλοποίηση API του λειτουργικού συστήματος, ενδέχεται να μην είναι πλήρως λειτουργικό.
\n
@@ -671,7 +668,7 @@
<string name="info">Πληροφορίες</string>
<string name="menu_app_settings_summary">Αναζήτηση, κλείδωμα, ιστορικό, ιδιότητες</string>
<string name="menu_form_filling_settings_summary">Πληκτρολόγιο, αυτόματη συμπλήρωση, πρόχειρο</string>
<string name="menu_advanced_unlock_settings_summary">Βιομετρία, διαπιστευτήριο συσκευής</string>
<string name="menu_device_unlock_settings_summary">Βιομετρία, διαπιστευτήριο συσκευής</string>
<string name="menu_database_settings_summary">Μεταδεδομένα, κάδος ανακύκλωσης, πρότυπα, ιστορικό</string>
<string name="menu_security_settings_summary">Κρυπτογράφηση, λειτουργία παραγωγής κλειδιού</string>
<string name="master_key_settings_summary">Αλλαγή, ανανέωση</string>
@@ -708,4 +705,5 @@
<string name="warning_large_keyfile">Δεν συνιστάται η προσθήκη μεγάλου αρχείου κλειδιού, αυτό μπορεί να εμποδίσει το άνοιγμα της βάσης δεδομένων.</string>
<string name="hide_templates_summary">Τα πρότυπα δεν εμφανίζονται</string>
<string name="recursive_number_entries_title">Αναδρομικός αριθμός καταχωρήσεων</string>
<string name="error_otp_secret_length">Το μυστικό κλειδί πρέπει να έχει τουλάχιστον %1$d χαρακτήρες.</string>
</resources>

View File

@@ -5,8 +5,8 @@
<string name="colorize_password_summary">Colourise password characters by type</string>
<string name="content_description_entry_background_color">Entry background colour</string>
<string name="invalid_db_sig">Could not recognise the database format.</string>
<string name="advanced_unlock_not_recognized">Could not recognise advanced unlock print</string>
<string name="advanced_unlock_prompt_not_initialized">Unable to initialise advanced unlock prompt.</string>
<string name="device_unlock_not_recognized">Could not recognise device unlock print</string>
<string name="device_unlock_prompt_not_initialized">Unable to initialise device unlock prompt.</string>
<string name="download_initialization">Initialising…</string>
<string name="download_finalization">Finalising…</string>
<string name="download_canceled">Cancelled!</string>
@@ -33,10 +33,10 @@
<string name="encryption">Encryption</string>
<string name="contact">Contact</string>
<string name="contribution">Contribution</string>
<string name="about_description">password</string>
<string name="encryption_algorithm">Encryption</string>
<string name="about_description">Android implementation of the KeePass password manager</string>
<string name="encryption_algorithm">Encryption algorithm</string>
<string name="app_timeout">Timeout</string>
<string name="app_timeout_summary">database</string>
<string name="app_timeout_summary">Idle time before locking the database</string>
<string name="application">App</string>
<string name="brackets">Brackets</string>
<string name="extended_ASCII">Extended ASCII</string>

View File

@@ -21,7 +21,7 @@
--><resources>
<string name="feedback">Comentarios</string>
<string name="homepage">Página de inicio</string>
<string name="about_description">Implementación para Android del gestor de contraseñas KeePass</string>
<string name="about_description">Implementación para Android del gestor de contraseñas KeePass.</string>
<string name="accept">Aceptar</string>
<string name="add_entry">Añadir apunte</string>
<string name="add_group">Añadir grupo</string>
@@ -73,7 +73,7 @@
<string name="hint_conf_pass">Confirmar contraseña</string>
<string name="hint_generated_password">Contraseña generada</string>
<string name="hint_group_name">Nombre del grupo</string>
<string name="hint_keyfile">Cerrojo</string>
<string name="hint_keyfile">Archivo de clave</string>
<string name="hint_length">Longitud</string>
<string name="password">Contraseña</string>
<string name="hint_pass">Contraseña</string>
@@ -118,7 +118,7 @@
<string name="unsupported_db_version">Versión de base de datos incompatible.</string>
<string name="uppercase">Mayúsculas</string>
<string name="version_label">Versión %1$s</string>
<string name="education_unlock_summary">Introduzca la contraseña y/o el cerrojo para desbloquear su base de datos.\n\nRespalde su base de datos en un lugar seguro tras cada cambio.</string>
<string name="education_unlock_summary">Introduzca la contraseña y/o el archivo de clave para desbloquear su base de datos.\n\nRespalde su base de datos en un lugar seguro tras cada cambio.</string>
<string-array name="list_size_options">
<item>Pequeño</item>
<item>Mediano</item>
@@ -137,7 +137,7 @@
<string name="field_value">Valor del campo</string>
<string name="file_not_found_content">No se ha podido encontrar el archivo. Intente volver a abrirlo en el explorador de archivos.</string>
<string name="invalid_algorithm">Algoritmo incorrecto.</string>
<string name="keyfile_is_empty">El cerrojo está vacío.</string>
<string name="keyfile_is_empty">El archivo de clave está vacío.</string>
<string name="copy_field">Copia de %1$s</string>
<string name="menu_form_filling_settings">Rellenado de formularios</string>
<string name="protection">Protección</string>
@@ -183,7 +183,7 @@
<string name="lock">Bloquear</string>
<string name="lock_database_screen_off_title">Bloqueo de pantalla</string>
<string name="lock_database_screen_off_summary">Bloquear la base de datos después de unos segundos cuando la pantalla esté apagada</string>
<string name="advanced_unlock">Desbloqueo del dispositivo</string>
<string name="device_unlock">Desbloqueo del dispositivo</string>
<string name="biometric_unlock_enable_title">Desbloqueo biométrico</string>
<string name="biometric_unlock_enable_summary">Le permite analizar sus datos biométricos para abrir la base de datos</string>
<string name="biometric_delete_all_key_title">Eliminar claves de cifrado</string>
@@ -239,7 +239,7 @@
<string name="html_text_ad_free">A diferencia de muchas aplicaciones de administración de contraseñas, esta es &lt;strong&gt;sin anuncios&lt;/strong&gt;, &lt;strong&gt;software libre de copylefted&lt;/strong&gt; y no recopila datos personales en sus servidores, sin importar la versión que use.</string>
<string name="html_text_buy_pro">Al comprar la versión Pro, tendrá acceso a este &lt;strong&gt;estilo visual&lt;/strong&gt; y ayudará especialmente &lt;strong&gt;la realización de proyectos comunitarios.&lt;/strong&gt;</string>
<string name="html_text_feature_generosity">Este &lt;strong&gt;estilo visual&lt;/strong&gt; está disponible gracias a su generosidad.</string>
<string name="html_text_donation">Al &lt;strong&gt;colaborar&lt;/strong&gt; en el proyecto <i>(monetariamente, código, traducción)</i>, ayudará a que siga existiendo y prosperando, y también será la elección para el procedimiento de desbloqueo del &lt;strong&gt;tema&lt;/strong&gt;.</string>
<string name="html_text_donation">Al &lt;strong&gt;colaborar&lt;/strong&gt; en el proyecto &lt;i&gt;(monetariamente, código, traducción)&lt;/i&gt;, ayudará a que siga existiendo y prosperando, y también será la elección para el procedimiento de desbloqueo del &lt;strong&gt;tema&lt;/strong&gt;.</string>
<string name="html_text_dev_feature">Esta función está &lt;strong&gt;en desarrollo&lt;/strong&gt; y requiere de tu &lt;strong&gt;contribución&lt;/strong&gt; para estar disponible dentro de poco.</string>
<string name="html_text_dev_feature_buy_pro">Al comprar la versión &lt;strong&gt;Pro&lt;/strong&gt;,</string>
<string name="html_text_dev_feature_contibute">Al &lt;strong&gt;contribuir&lt;/strong&gt;,</string>
@@ -271,8 +271,6 @@
<string name="allow_no_password_summary">Permite pulsar el botón \"Abrir\" si no son seleccionadas las credenciales</string>
<string name="enable_education_screens_title">Consejos educativos</string>
<string name="enable_education_screens_summary">Destaca los elementos para aprender cómo funciona la aplicación</string>
<string name="enable_read_only_title">Protegida contra escritura</string>
<string name="enable_read_only_summary">Abre la base de datos como solo lectura por defecto</string>
<string name="education_read_only_title">Proteja la base de datos contra escritura</string>
<string name="keyboard_name">Magikeyboard</string>
<string name="keyboard_label">Magikeyboard (KeePassDX)</string>
@@ -324,7 +322,7 @@
<string name="content_description_update_from_list">Actualizar</string>
<string name="content_description_keyboard_close_fields">Cerrar campos</string>
<string name="error_create_database_file">No se puede crear la base de datos con esta contraseña y este cerrojo.</string>
<string name="menu_advanced_unlock_settings">Desbloqueo de dispositivos</string>
<string name="menu_device_unlock_settings">Desbloqueo de dispositivos</string>
<string name="biometric">Biometría</string>
<string name="biometric_auto_open_prompt_title">Abrir solicitud automáticamente</string>
<string name="biometric_auto_open_prompt_summary">Solicita auto-desbloqueo del dispositivo si la base de datos está configurada para utilizarlo</string>
@@ -372,7 +370,7 @@
<string name="settings_database_force_changing_master_key_summary">Requiere cambiar la clave maestra (días)</string>
<string name="settings_database_force_changing_master_key_title">Forzar renovación</string>
<string name="max_history_size_title">Tamaño máximo</string>
<string name="advanced_unlock_explanation_summary">Utiliza el desbloqueo del dispositivo avanzado para abrir una base de datos más fácilmente</string>
<string name="device_unlock_explanation_summary">Utiliza el desbloqueo del dispositivo avanzado para abrir una base de datos más fácilmente</string>
<string name="lock_database_show_button_summary">Muestra el botón de bloqueo en la interfaz de usuario</string>
<string name="lock_database_show_button_title">Mostrar botón de bloqueo</string>
<string name="autofill_preference_title">Configuración de autocompletado</string>
@@ -399,7 +397,7 @@
<string name="error_copy_group_here">No puede copiar un grupo aquí.</string>
<string name="database_data_compression_summary">La compresión de datos reduce el tamaño de la base de datos</string>
<string name="database_data_compression_title">Compresión de datos</string>
<string name="warning_empty_keyfile">No se recomienda agregar un cerrojo vacío.</string>
<string name="warning_empty_keyfile">No se recomienda agregar un archivo de clave vacío.</string>
<string name="warning_sure_remove_data">¿Eliminar estos datos de todos modos\?</string>
<string name="warning_sure_add_file">¿Agregar el archivo de todos modos\?</string>
<string name="warning_replace_file">Al cargar este archivo, se reemplazará el existente.</string>
@@ -408,7 +406,7 @@
<string name="command_execution">Ejecutando el comando…</string>
<string name="hide_broken_locations_summary">Oculta los enlaces rotos en la lista de bases de datos recientes</string>
<string name="hide_broken_locations_title">Ocultar enlaces rotos de la base de datos</string>
<string name="remember_keyfile_locations_summary">Mantiene seguimiento de dónde los cerrojos son almacenados</string>
<string name="remember_keyfile_locations_summary">Mantiene seguimiento de dónde los archivos de claves son almacenados</string>
<string name="remember_keyfile_locations_title">Recordar las ubicaciones de los archivos clave</string>
<string name="subdomain_search_summary">Busca dominios web con restricciones de subdominios</string>
<string name="subdomain_search_title">Búsqueda de subdominio</string>
@@ -430,31 +428,30 @@
<string name="database_data_remove_unlinked_attachments_summary">Elimina los adjuntos contenidos en la base de datos pero no vinculados a un apunte</string>
<string name="database_data_remove_unlinked_attachments_title">Eliminar datos no vinculados</string>
<string name="data">Datos</string>
<string name="advanced_unlock_delete_all_key_warning">¿Borrar todas las claves de cifrado relacionadas con el reconocimiento de desbloqueo avanzado?</string>
<string name="advanced_unlock_timeout">Tiempo de espera de desbloqueo del dispositivo</string>
<string name="temp_advanced_unlock_timeout_summary">Duración del uso del desbloqueo del dispositivo antes de borrar su contenido</string>
<string name="temp_advanced_unlock_timeout_title">Caducidad del desbloqueo del dispositivo</string>
<string name="temp_advanced_unlock_enable_summary">No almacenar ningún contenido cifrado para usar el desbloqueo avanzado</string>
<string name="temp_advanced_unlock_enable_title">Desbloqueo temporal de los dispositivos</string>
<string name="device_unlock_delete_all_key_warning">¿Borrar todas las claves de cifrado relacionadas con el reconocimiento de desbloqueo avanzado?</string>
<string name="device_unlock_timeout">Tiempo de espera de desbloqueo del dispositivo</string>
<string name="temp_device_unlock_timeout_summary">Duración del uso del desbloqueo del dispositivo antes de borrar su contenido</string>
<string name="temp_device_unlock_timeout_title">Caducidad del desbloqueo del dispositivo</string>
<string name="temp_device_unlock_enable_summary">No almacenar ningún contenido cifrado para usar el desbloqueo avanzado</string>
<string name="temp_device_unlock_enable_title">Desbloqueo temporal de los dispositivos</string>
<string name="device_credential_unlock_enable_summary">Le permite usar la credenciales de su dispositivo para abrir la base de datos</string>
<string name="device_credential_unlock_enable_title">Desbloqueo de credenciales del dispositivo</string>
<string name="advanced_unlock_tap_delete">Pulsa para eliminar las teclas de desbloqueo avanzado</string>
<string name="device_unlock_tap_delete">Pulsa para eliminar las teclas de desbloqueo avanzado</string>
<string name="content">Contenido</string>
<string name="clipboard_explanation_summary">Copia los campos del apunte usando el portapapeles de su dispositivo</string>
<string name="device_credential">Credenciales del dispositivo</string>
<string name="credential_before_click_advanced_unlock_button">Teclee la contraseña y luego pulse sobre este botón.</string>
<string name="advanced_unlock_prompt_not_initialized">No se puede inicializar el aviso de desbloqueo avanzado.</string>
<string name="advanced_unlock_scanning_error">Error de desbloqueo del dispositivo: %1$s</string>
<string name="advanced_unlock_not_recognized">No se ha podido reconocer la impresión de desbloqueo avanzado</string>
<string name="advanced_unlock_invalid_key">No se puede leer la clave de desbloqueo del dispositivo. Por favor, bórrala y repite el procedimiento de reconocimiento del desbloqueo.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Extraer la credencial de la base de datos con los datos de desbloqueo del dispositivo</string>
<string name="advanced_unlock_prompt_extract_credential_title">Reconocimiento de desbloqueo del dispositivo</string>
<string name="advanced_unlock_prompt_store_credential_message">Aún debes recordar la credencial principal de tu caja fuerte si usas el reconocimiento para el desbloqueo del dispositivo.</string>
<string name="advanced_unlock_prompt_store_credential_title">Enlace para el desbloqueo del dispositivo</string>
<string name="credential_before_click_device_unlock_button">Teclee la contraseña y luego pulse sobre este botón.</string>
<string name="device_unlock_prompt_not_initialized">No se puede inicializar el aviso de desbloqueo avanzado.</string>
<string name="device_unlock_not_recognized">No se ha podido reconocer la impresión de desbloqueo avanzado</string>
<string name="device_unlock_invalid_key">No se puede leer la clave de desbloqueo del dispositivo. Por favor, bórrala y repite el procedimiento de reconocimiento del desbloqueo.</string>
<string name="device_unlock_prompt_extract_credential_message">Extraer la credencial de la base de datos con los datos de desbloqueo del dispositivo</string>
<string name="device_unlock_prompt_extract_credential_title">Reconocimiento de desbloqueo del dispositivo</string>
<string name="device_unlock_prompt_store_credential_message">Aún debes recordar la credencial principal de tu caja fuerte si usas el reconocimiento para el desbloqueo del dispositivo.</string>
<string name="device_unlock_prompt_store_credential_title">Enlace para el desbloqueo del dispositivo</string>
<string name="keystore_not_accessible">El almacén de claves no está debidamente inicializado.</string>
<string name="biometric_security_update_required">Se requiere actualización de seguridad biométrica.</string>
<string name="configure_biometric">No se ha inscrito ninguna credencial biométrica o del dispositivo.</string>
<string name="warning_empty_keyfile_explanation">El contenido del cerrojo nunca debe modificarse y, en el mejor de los casos, debe contener datos generados al azar.</string>
<string name="warning_empty_keyfile_explanation">El contenido del archivo de clave nunca debe modificarse y, en el mejor de los casos, debe contener datos generados al azar.</string>
<string name="warning_empty_recycle_bin">¿Borrar permanentemente todos los nodos de la papelera de reciclaje\?</string>
<string name="registration_mode">Modo de registro</string>
<string name="save_mode">Modo de guardado</string>
@@ -462,7 +459,7 @@
<string name="contains_duplicate_uuid_procedure">¿Solucionar el problema generando nuevos UUID para que los duplicados continúen?</string>
<string name="menu_keystore_remove_key">Eliminar la clave de desbloqueo del dispositivo</string>
<string name="error_field_name_already_exists">El nombre del campo ya existe.</string>
<string name="error_registration_read_only">Guardar un nuevo elemento no está permitido en una base de datos de sólo lectura</string>
<string name="error_registration_read_only">Guardar un nuevo elemento no está permitido en una base de datos de sólo lectura.</string>
<string name="settings_database_recommend_changing_master_key_title">Recomendar renovación</string>
<string name="max_history_size_summary">Limitar el tamaño del historial por apunte</string>
<string name="max_history_items_summary">Limitar el número de elementos del historial por apunte</string>
@@ -475,8 +472,8 @@
<string name="upload_attachment">Subir %1$s</string>
<string name="education_setup_OTP_summary">Configura la gestión de contraseñas de un solo uso (HOTP / TOTP) para generar un testigo solicitado para la autenticación de dos factores (2FA).</string>
<string name="education_setup_OTP_title">Establecer contraseña de un solo uso</string>
<string name="education_advanced_unlock_summary">Vincule su contraseña con su credencial biométrica o del dispositivo escaneada para desbloquear rápidamente su base de datos.</string>
<string name="education_advanced_unlock_title">Desbloqueo de la base de datos de los dispositivos</string>
<string name="education_device_unlock_summary">Vincule su contraseña con su credencial biométrica o del dispositivo escaneada para desbloquear rápidamente su base de datos.</string>
<string name="education_device_unlock_title">Desbloqueo de la base de datos de los dispositivos</string>
<string name="autofill_read_only_save">No se permite guardar datos en una base de datos abierta como de solo lectura.</string>
<string name="autofill_block_restart">Reinicia la aplicación que contiene el formulario para activar el bloqueo.</string>
<string name="autofill_web_domain_blocklist_summary">Lista de dominios web en los que se impide el autocompletado</string>
@@ -618,7 +615,7 @@
<string name="consider_chars_filter">Considerar caracteres</string>
<string name="entropy_calculate">Entropía: Calcular…</string>
<string name="word_separator">Separador</string>
<string name="advanced_unlock_keystore_warning">Esta función almacenará datos de credenciales cifrados en el almacén de claves seguro del dispositivo.
<string name="device_unlock_keystore_warning">Esta función almacenará datos de credenciales cifrados en el almacén de claves seguro del dispositivo.
\n
\nDependiendo de la implementación de la API nativa del sistema operativo, puede que no sea totalmente funcional.
\n
@@ -639,7 +636,7 @@
<string name="screenshot_mode_banner_text">Modo de captura de pantalla</string>
<string name="error_hardware_key_unsupported">La llave por hardware no es compatible.</string>
<string name="html_about_privacy">&lt;strong&gt;No se recupera ningún dato del usuario&lt;/strong&gt;, esta aplicación no se conecta a ningún servidor y funciona solo localmente y respeta plenamente la privacidad de los usuarios.</string>
<string name="error_unable_merge_database_kdb">No se puede fusionar con un archivo de base de datos kdb</string>
<string name="error_unable_merge_database_kdb">No se puede fusionar con un archivo de base de datos kdb.</string>
<string name="error_cancel_by_user">Cancelado por el usuario.</string>
<string name="error_no_response_from_challenge">No se puede obtener la respuesta del desafío.</string>
<string name="auto_type">Auto-teclear</string>
@@ -662,7 +659,7 @@
<string name="menu_app_settings_summary">Buscar, bloquear, historial, propiedades</string>
<string name="menu_form_filling_settings_summary">Teclado, autocompletar, portapapeles</string>
<string name="menu_database_settings_summary">Metadatos, papelera de reciclaje, plantillas, historial</string>
<string name="menu_advanced_unlock_settings_summary">Biometría, credencial del dispositivo</string>
<string name="menu_device_unlock_settings_summary">Biometría, credencial del dispositivo</string>
<string name="menu_security_settings_summary">Cifrado, función de derivación de las claves</string>
<string name="master_key_settings_summary">Cambio, renovación</string>
<string name="warning_database_notification_permission">El permiso de notificación te permite mostrar el estado de la base de datos y bloquearla con un botón de fácil acceso.\n\nSi no activas este permiso, la base de datos abierta en segundo plano no será visible si hay otra aplicación en primer plano.</string>
@@ -694,4 +691,5 @@
<string name="generate_keyfile">Generar archivo de claves</string>
<string name="recursive_number_entries_title">Número recursivo de entradas</string>
<string name="hide_templates_summary">Las plantillas no se muestran</string>
<string name="error_otp_secret_length">La clave secreta debe tener al menos %1$d caracteres.</string>
</resources>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="homepage">Meie veebisait</string>
<string name="about_description">KeePassi salasõnahalduri Androidi variant</string>
<string name="about_description">KeePassi salasõnahalduri variant Androidile.</string>
<string name="contact">Meie kontaktid</string>
<string name="info">Teave</string>
<string name="accept">Nõustu</string>
@@ -84,7 +84,7 @@
<string name="content_description_hardware_key_checkbox">Füüsilise võtme märkruut</string>
<string name="content_description_credentials_information">Mandaatide info</string>
<string name="content_description_nav_header">Navigatsiooni päis</string>
<string name="retrieving_db_key">Laadime andmebaasi võtme</string>
<string name="retrieving_db_key">Laadin andmebaasi võtit</string>
<string name="content_description_passphrase_word_count">Sõnu salafraasis</string>
<string name="default_checkbox">Kasuta vaikeandmebaasina</string>
<string name="entry_accessed">Viimati kasutatud</string>
@@ -128,8 +128,8 @@
<string name="error_nokeyfile">Vali võtmefail.</string>
<string name="error_pass_match">Salasõnad ei klapi.</string>
<string name="error_create_database">Andmebaasifaili loomine ei õnnestunud.</string>
<string name="entry_url">URL</string>
<string name="error_file_not_create">Faili loomine ei õnnestunud</string>
<string name="entry_url">Võrguaadress</string>
<string name="error_file_not_create">Faili loomine ei õnnestunud.</string>
<string name="entry_otp">Ühekordne salasõna</string>
<string name="clipboard_timeout_summary">Lõikelauale kopeeritud andmete hoidmise aeg (kui sinu seade sellist võimalust toetab)</string>
<string name="content_description_keyboard_close_fields">Sulge väljad</string>
@@ -234,7 +234,7 @@
<string name="menu_delete">Kustuta</string>
<string name="menu_paste">Aseta</string>
<string name="menu_cancel">Katkesta</string>
<string name="error_unable_merge_database_kdb">Mestimine teise kdb andmebaasifailiga ei õnnestu</string>
<string name="error_unable_merge_database_kdb">Mestimine teise kdb andmebaasifailiga ei õnnestu.</string>
<string name="error_location_unknown">Andmebaasi asukoht pole teada ja toimingut andmebaasiga ei saa teha.</string>
<string name="menu_empty_recycle_bin">Tühjenda prügikast</string>
<string name="menu_restore_entry_history">Taasta ajalugu</string>
@@ -245,7 +245,7 @@
<string name="list_size_title">Loendite suurus</string>
<string name="list_size_summary">Teksti suurus loendites</string>
<string name="creating_database">Loome salasõnade andmebaasi…</string>
<string name="loading_database">Laadime salasõnade andmebaasi…</string>
<string name="loading_database">Laadin salasõnade andmebaasi…</string>
<string name="lowercase">väiketähed</string>
<string name="about">Rakenduse teave</string>
<string name="menu_change_key_settings">Muuda peavõtit</string>
@@ -255,8 +255,8 @@
<string name="menu_app_settings_summary">Otsing, lukustus, ajalugu, omadused</string>
<string name="menu_form_filling_settings">Vormide täitmine</string>
<string name="menu_form_filling_settings_summary">Klahvistik, automaattäide, lõikelaud</string>
<string name="menu_advanced_unlock_settings">Seadme lukustuse eemaldamine</string>
<string name="menu_advanced_unlock_settings_summary">Biomeetriline, nutiseadme reeglitega</string>
<string name="menu_device_unlock_settings">Seadme lukustuse eemaldamine</string>
<string name="menu_device_unlock_settings_summary">Biomeetriline, nutiseadme reeglitega</string>
<string name="menu_database_settings">Andmebaasi seadistused</string>
<string name="menu_database_settings_summary">Metateave, prügikast, mallid, ajalugu</string>
<string name="menu_security_settings">Turvalisuse seadistused</string>
@@ -274,7 +274,7 @@
<string name="import_app_properties_summary">Rakenduse seadistuste importimiseks vali fail</string>
<string name="export_app_properties_title">Ekspordi rakenduse seadistused</string>
<string name="success_export_app_properties">Rakenduse seadistused on eksporditud</string>
<string name="error_export_app_properties">Rakenduse seadistuste eksportimisel tekkis viga</string>
<string name="error_export_app_properties">Rakenduse seadistuste eksportimisel tekkis viga.</string>
<string name="root">Juurkaust</string>
<string name="memory_usage">Mälukasutus</string>
<string name="error_string_type">See tekst ei vasta päringule.</string>
@@ -295,7 +295,7 @@
<string name="hide_broken_locations_title">Peida katkised andmebaaside lingid</string>
<string name="hide_broken_locations_summary">Peida hiljutikasutatud andmebaaside loendist need kirjed, mille lingid enam ei toimi</string>
<string name="success_import_app_properties">Rakenduse seadistused on imporditud</string>
<string name="error_import_app_properties">Viga rakenduse seadistuste importimisel</string>
<string name="error_import_app_properties">Viga rakenduse seadistuste importimisel.</string>
<string name="description_app_properties">KeePassDX võimalused rakenduse seadistuste haldamiseks</string>
<string name="encryption_explanation">Salasõnalaeka andmebaasi puhul kasutatud krüptoalgoritm</string>
<string name="kdf_explanation">Krüptoalgoritmi jaoks võtme loomisel peavõtit muudetakse võtetuletusfunktsiooniga, mis kasutab juhuslikke soolaterakesi.</string>
@@ -314,7 +314,7 @@
<string name="sort_last_access_time">Viimati kasutamise aja alusel</string>
<string name="version_label">Versioon: %1$s</string>
<string name="configure">Seadista</string>
<string name="advanced_unlock_prompt_store_credential_message">Sa pead igal juhul oma salasõnalaeka salasõna meeles pidama - seda ka siis, kui kasutad muid seadmes leiduvaid lukustuse eemaldamise võimalusi.</string>
<string name="device_unlock_prompt_store_credential_message">Sa pead igal juhul oma salasõnalaeka salasõna meeles pidama - seda ka siis, kui kasutad muid seadmes leiduvaid lukustuse eemaldamise võimalusi.</string>
<string name="file_name">Failinimi</string>
<string name="path">Asukoht</string>
<string name="assign_master_key">Seadista peavõti</string>
@@ -440,9 +440,8 @@
<string name="merge_success">Mestimine õnnestus</string>
<string name="biometric_security_update_required">Vajalik on biomeetrilise turvalisuse uuendus.</string>
<string name="encrypted_value_stored">Krüptitud salasõna on salvestatud</string>
<string name="advanced_unlock_scanning_error">Viga seadme lukustuse eemaldamisel: %1$s</string>
<string name="advanced_unlock_not_recognized">Ei õnnestunud tuvastada lukustuse eemaldamiseks vajalikku tunnust</string>
<string name="advanced_unlock_prompt_not_initialized">Seadme lukustuse eemaldamise päringu käivitamine ei õnnestu.</string>
<string name="device_unlock_not_recognized">Ei õnnestunud tuvastada lukustuse eemaldamiseks vajalikku tunnust</string>
<string name="device_unlock_prompt_not_initialized">Seadme lukustuse eemaldamise päringu käivitamine ei õnnestu.</string>
<string name="biometric">Biomeetriline</string>
<string name="device_credential">Seadme autentimine</string>
<string name="autofill">Automaattäide</string>
@@ -466,7 +465,7 @@
<string name="warning_database_info_changed_options">Sa võid kas andmed mestida, kirjutada välised muudatused üle või laadida viimased välised muudatused.</string>
<string name="unlock_and_link_biometric">Seadme lukustuse eemaldamise link</string>
<string name="later">Hiljem</string>
<string name="credential_before_click_advanced_unlock_button">Sisesta salasõna ja siis klõpsi seda nuppu.</string>
<string name="credential_before_click_device_unlock_button">Sisesta salasõna ja siis klõpsi seda nuppu.</string>
<string name="html_text_dev_feature_work_hard">Me näeme hoolega vaeva, et see funktsionaalsus leiduks üsna pea mõnes rakenduse järgmises versioonis.</string>
<string name="list_password_generator_options_title">Tähemärgid salasõnas</string>
<string name="allow_copy_password_warning">Hoiatus: süsteemiülene lõikelaud on kõikide rakenduste kasutuses. Kui sa kopeerid sinna delikaatseid andmeid, siis muu tarkvara võib seda seal näha. Kui sa kasutad KDE Connecti või muud lõikelaua jagamise teenust, siis sõltuvalt seadistustest võivad need delikaatsed andmed olla nähtavad ka muudes seadmetes.</string>
@@ -532,7 +531,6 @@
<string name="autofill_inline_suggestions_keyboard">Automaattäite soovitused on lisatud.</string>
<string name="autofill_read_only_save">Kui andmebaas on avatud ainult lugemiseks, siis andmete salvestamine pole võimalik.</string>
<string name="delete_entered_password_summary">Kustutab salasõna, mis oli kasutusel andmebaasiga ühenduse loomise ajal</string>
<string name="enable_read_only_summary">Vaikimisi ava andmebaas vaid lugemiseks</string>
<string name="enable_screenshot_mode_summary">Luba teistel rakendusel teha sellest rakendusest ekraanitõmmist või salvestada tema ekraanivaadet</string>
<string name="autofill_close_database_title">Sulge andmebaas</string>
<string name="autofill_close_database_summary">Peale automaattäite kasutamist sulega andmebaas</string>
@@ -548,7 +546,6 @@
<string name="allow_no_password_title">Ära kasuta peavõtit</string>
<string name="allow_no_password_summary">Kui kasutajanimi või salasõna pole valitud, siis võimaldab klõpsida „Ava“ nuppu</string>
<string name="delete_entered_password_title">Kustuta salasõna</string>
<string name="enable_read_only_title">Kirjutuskaitstud</string>
<string name="enable_screenshot_mode_title">Ekraanitõmmiste lubamine</string>
<string name="enable_education_screens_title">Koolitusvihjed</string>
<string name="enable_education_screens_summary">Õppimaks, kuidas rakendus toimib, tõsta esile kasutajaliidese elemente</string>
@@ -564,23 +561,23 @@
<string name="education_new_node_summary">Sinu digitaalsed identiteedid on vormistatud kirjetena.\n\nÜlevaatlikkuse mõttes saad neid rühmitada gruppidena (kaustadena).</string>
<string name="education_create_database_summary">Loo oma esimene andmebaasifail, mis on mõeldud salasõnade halduseks.</string>
<string name="education_select_database_summary">Ava varemloodud andmebaasifail, mis on mõeldud salasõnade halduseks.</string>
<string name="advanced_unlock_prompt_store_credential_title">Link seadme lukustuse eemaldamisele</string>
<string name="device_unlock_prompt_store_credential_title">Link seadme lukustuse eemaldamisele</string>
<string name="unlock">Eemalda lukustus</string>
<string name="advanced_unlock_tap_delete">Seadme lukustuse eemaldamise võtmete kustutamiseks klõpsi</string>
<string name="advanced_unlock_explanation_summary">Andmebaasi mugavamaks avamiseks kasuta nutiseadme lukustuse eemaldamise võimalusi</string>
<string name="device_unlock_tap_delete">Seadme lukustuse eemaldamise võtmete kustutamiseks klõpsi</string>
<string name="device_unlock_explanation_summary">Andmebaasi mugavamaks avamiseks kasuta nutiseadme lukustuse eemaldamise võimalusi</string>
<string name="device_credential_unlock_enable_title">Lukustuse eemaldamine nutiseadme autentimisega</string>
<string name="biometric_unlock_enable_title">Biomeetriline lukustuse eemaldamine</string>
<string name="biometric_unlock_enable_summary">Saad andmebaasi avamiseks kasutada nutiseadme biomeetrilise autentimise võimalusi</string>
<string name="temp_advanced_unlock_timeout_title">Seadme lukustuse eemaldamise aegumine</string>
<string name="temp_advanced_unlock_timeout_summary">Lukustuse eemaldamise kestus enne kui tema sisu kustutatakse</string>
<string name="temp_advanced_unlock_enable_summary">Ära salvesta mitte mingit krüptitud sisu nutiseadme lukustuse eemaldamiseks</string>
<string name="advanced_unlock_timeout">Seadme lukustuse eemaldamise ajalõpp</string>
<string name="temp_device_unlock_timeout_title">Seadme lukustuse eemaldamise aegumine</string>
<string name="temp_device_unlock_timeout_summary">Lukustuse eemaldamise kestus enne kui tema sisu kustutatakse</string>
<string name="temp_device_unlock_enable_summary">Ära salvesta mitte mingit krüptitud sisu nutiseadme lukustuse eemaldamiseks</string>
<string name="device_unlock_timeout">Seadme lukustuse eemaldamise ajalõpp</string>
<string name="device_credential_unlock_enable_summary">Saad andmebaasi avamiseks kasutada nutiseadme tavaautentimise võimalusi</string>
<string name="biometric_auto_open_prompt_title">Ava viip automaatselt</string>
<string name="biometric_delete_all_key_summary">Kustuta kõik krüptovõtmed, mis on kasutusel nutiseadme-põhise autentimise alusel andmebaasi lukustuse eemaldamisega</string>
<string name="advanced_unlock_delete_all_key_warning">Kas kustutame kõik krüptovõtmed, mis on kasutusel nutiseadme-põhise autentimise alusel andmebaasi lukustuse eemaldamisega?</string>
<string name="device_unlock_delete_all_key_warning">Kas kustutame kõik krüptovõtmed, mis on kasutusel nutiseadme-põhise autentimise alusel andmebaasi lukustuse eemaldamisega?</string>
<string name="biometric_delete_all_key_title">Kustuta krüptovõtmed</string>
<string name="education_advanced_unlock_title">Nutiseadme-põhine andmebaasi lukustuse eemaldamine</string>
<string name="education_device_unlock_title">Nutiseadme-põhine andmebaasi lukustuse eemaldamine</string>
<string name="education_new_node_title">Lisa kirjeid andmebaasi</string>
<string name="education_search_title">Otsi kirjete seast</string>
<string name="education_search_summary">Vajaliku salasõna otsimiseks kasuta pealkirja, kasutajanime või muid kirje välju.</string>
@@ -589,12 +586,12 @@
<string name="education_sort_summary">Vali kirjete ja gruppide järjestamise viis.</string>
<string name="education_donation_title">Osale</string>
<string name="education_donation_summary">Aita parandada rakenduse töökindlust ja turvalisust ning lisada uusi funktsionaalsuseid.</string>
<string name="temp_advanced_unlock_enable_title">Seadme lukustuse ajutine eemaldamine</string>
<string name="temp_device_unlock_enable_title">Seadme lukustuse ajutine eemaldamine</string>
<string name="biometric_auto_open_prompt_summary">Kui andmebaas on seadistatud kasutama nutiseadme-põhist lukustuse eemaldamist, siis ava autentimisvaade automaatselt</string>
<string name="education_field_copy_title">Välja kopeerimine</string>
<string name="education_field_copy_summary">Kopeeritud väljade sisu saad asetada kõikjale.\n\nVäljade täitmiseks kasuta meetodist, mis sulle sobib. Ära unusta kopeeritud saalsõna lõikelaualt kustutada.</string>
<string name="unavailable">Pole saadaval</string>
<string name="error_challenge_already_requested">Autentimispäring on juba esitatud</string>
<string name="error_challenge_already_requested">Autentimispäring on juba esitatud.</string>
<string name="error_response_already_provided">Autentimisvastus on juba antud.</string>
<string name="error_no_response_from_challenge">Autentimisvastust ei õnnestu autentimispäringust tuletada.</string>
<string name="warning_database_notification_permission">Teevituste saatmise õigused võimaldavad sulle kuvada andmebaasi olekut ning lukustada seda lihtsalt ligipääsetvast nupust.\n\nKui sa seda õigust ei anna, siis taustal olev andmebaas pole nähtav, kui mõni muu rakendus on parasjagu esiplaanil.</string>
@@ -603,10 +600,10 @@
<string name="keystore_not_accessible">Võtmehoidla pole korrektselt valmendatud.</string>
<string name="special">Eriteave</string>
<string name="warning_remove_unlinked_attachment">Linkimata andmete eemaldamine võib vähendada andmebaasi suurust, aga samaga võivad kaduda ka andmed, mida kasutavad KeePassi lisamoodulid.</string>
<string name="advanced_unlock_prompt_extract_credential_title">Seadmekohane lukustuse eemaldamine</string>
<string name="advanced_unlock_prompt_extract_credential_message">Ava andmebaas kasutades nutiseadme-põhist autentimist</string>
<string name="advanced_unlock_invalid_key">Seadme lukustuse eemaldamise võtit ei õnnestu lugeda. Palun kustuta ta ja korda lukustuse eemaldamist tuvastamise alusel.</string>
<string name="advanced_unlock">Nutiseadme-põhine lukustuse eemaldamine</string>
<string name="device_unlock_prompt_extract_credential_title">Seadmekohane lukustuse eemaldamine</string>
<string name="device_unlock_prompt_extract_credential_message">Ava andmebaas kasutades nutiseadme-põhist autentimist</string>
<string name="device_unlock_invalid_key">Seadme lukustuse eemaldamise võtit ei õnnestu lugeda. Palun kustuta ta ja korda lukustuse eemaldamist tuvastamise alusel.</string>
<string name="device_unlock">Nutiseadme-põhine lukustuse eemaldamine</string>
<string name="magic_keyboard_title">Maagiklahvistik</string>
<string name="device_keyboard_setting_title">Nutiseadme klahvistiku seadistused</string>
<string name="keyboard_entry_category">Sisestus</string>
@@ -644,7 +641,7 @@
<string name="custom_fields">Kohandatud väljad</string>
<string name="keyboard_previous_lock_title">Andmebaasi lukustamine</string>
<string name="keyboard_previous_lock_summary">Peale andmebaasi lukustamist lülita automaatselt tagasi eelmisele klahvistikule</string>
<string name="education_advanced_unlock_summary">Andmebaasi lukustuse kiireks eemaldamiseks seo oma andmebaasi salasõna nutiseadme biomeetrilise või tavatuvastusega.</string>
<string name="education_device_unlock_summary">Andmebaasi lukustuse kiireks eemaldamiseks seo oma andmebaasi salasõna nutiseadme biomeetrilise või tavatuvastusega.</string>
<string name="education_entry_edit_title">Kirje muutmine</string>
<string name="education_entry_edit_summary">Võid kirjele lisada omaloodud välju ning ka neid omavahel siduda.</string>
<string name="education_generate_password_summary">Sisestusvormil leiduvate eelmistuste alusel saad antud kirje jaoks luua tugeva salasõna ning seda andmebaasis hoides tagad, et korralik salasõna ei unune.</string>
@@ -662,8 +659,9 @@
<string name="enter">Sisestusklahv (Enter)</string>
<string name="education_validate_entry_summary">Ära unusta kirje sisu kontrollida ja salvestada.\n\nKui automaatne lukustus käivitub ja sa unustad, et muutmine oli pooleli, siis võid kaotada oma muudatused.</string>
<string name="html_text_ad_free">Erinevalt paljudest teistest salasõnahalduritest, on meie oma &lt;strong&gt;reklaamivaba&lt;/strong&gt; ja &lt;strong&gt;avatud lähtekoodiga vaba tarkvara&lt;/strong&gt;, mis ei kogu kasutajate isiklikke andmeid oma serveritesse ja seda kõikide versioonide puhul.</string>
<string name="html_text_donation">&lt;strong&gt;Aidates kaasa&lt;/strong&gt; selle projekti tegevusele <i>(rahaliselt, koodi kirjutades või tõlkides)</i> aitad kogu ettevõtmisel areneda ning soovi korral võid kasutada ka &lt;strong&gt;seda kujundust&lt;/strong&gt;.</string>
<string name="advanced_unlock_keystore_warning">See funktsionaalsus salvestab krüptitud salasõnad ja kasutajanimed sinu nutiseadme turvalises võtmehoidlas.\n\nSõltuvalt sinu nutiseadme operatsioonisüstemi konkreetsest implementatsioonist, ei pruugi see lahendus siiski täismahus toimida.\n\nPalun kontrolli oma seadme võtmehoidla (KeyStore) ühilduvust ja turvalisust tootjalt ja/või tarkvara loojalt.</string>
<string name="html_text_donation">&lt;strong&gt;Aidates kaasa&lt;/strong&gt; selle projekti tegevusele &lt;i&gt;(rahaliselt, koodi kirjutades või tõlkides)&lt;/i&gt;, aitad kogu ettevõtmisel areneda ning soovi korral võid kasutada ka &lt;strong&gt;seda kujundust&lt;/strong&gt;.</string>
<string name="device_unlock_keystore_warning">See funktsionaalsus salvestab krüptitud salasõnad ja kasutajanimed sinu nutiseadme turvalises võtmehoidlas.\n\nSõltuvalt sinu nutiseadme operatsioonisüstemi konkreetsest implementatsioonist, ei pruugi see lahendus siiski täismahus toimida.\n\nPalun kontrolli oma seadme võtmehoidla (KeyStore) ühilduvust ja turvalisust tootjalt ja/või tarkvara loojalt.</string>
<string name="keyboard_previous_fill_in_summary">Peale tegevust „Automaatne võtmetoiming“ lülita automaatselt tagasi eelmisele klahvistikule</string>
<string name="education_read_only_summary">Saad juhtida sessioonil kasutatavat avamisviisi.\n\n„Kirjutuskaitstud“ tagab, et juhuslike muudatustega ei läheks andmeid kaotsi.\n„Muudetav“ võimaldab sul lisada, kustutada või muuta kõiki andmebaasi kirjeid.</string>
<string name="error_otp_secret_length">Salavõti peab olema vähemalt %1$d tähemärki pikk.</string>
</resources>

View File

@@ -397,7 +397,6 @@
<string name="memory_usage_explanation">Gakoaren eratorpen funtzioak erabiliko duen memoria kopurua.</string>
<string name="autofill_ask_to_save_data_summary">Datuak gordetzeko eskatu formulario bat betetzean</string>
<string name="education_select_database_summary">Ireki zure aurreko datu-base fitxategia zure fitxategi kudeatzailetik erabiltzen jarraitzeko.</string>
<string name="enable_read_only_title">Idazketaren aurka babestuta</string>
<string name="autofill_application_id_blocklist_title">Aplikazioen blokeo zerrenda</string>
<string name="keyboard_previous_fill_in_title">Tekla automatikoaren akzioa</string>
<string name="keyboard_previous_database_credentials_summary">Aldatu automatikoki aurreko teklatura datu-basearen kredentzialen pantailan</string>
@@ -423,7 +422,7 @@
<string name="menu_security_settings">Segurtasun ezarpenak</string>
<string name="menu_cancel">Deuseztu</string>
<string name="menu_paste">Itsatsi</string>
<string name="menu_advanced_unlock_settings">Gailu blokeatzailea</string>
<string name="menu_device_unlock_settings">Gailu blokeatzailea</string>
<string name="list_groups_show_number_entries_summary">Talde bateko sarrera kopurua erakusten du</string>
<string name="invalid_db_same_uuid">%1$sk %2$sren UUID bera du.</string>
<string name="sort_ascending">Baxuena lehenbizi↓</string>
@@ -478,7 +477,6 @@
<string name="kdf_explanation">Zifraketa algoritmorako gakoa sortzeko, gako nagusia itxuraldatu egiten da eratorpen funtzio eta ausazko gatz baten bidez.</string>
<string name="keyboard_previous_search_title">Bilaketa pantaila</string>
<string name="autofill_manual_selection_summary">Erabiltzaileari datu-baseko sarrera hautatzeko aukera erakutsi</string>
<string name="enable_read_only_summary">Lehenetsi irakurketa soilerako datu-basea irekitzea</string>
<string name="reset_education_screens_title">Berrezarri hezkuntza-pistak</string>
<string name="education_new_node_summary">Sarrerek zure identitate digitalak administratzen laguntzen dute.
\n
@@ -486,33 +484,32 @@
<string name="warning_keyfile_integrity">Ezin da fitxategiaren hasha bermatu Androidek aldaketak egin ditzakeelako sortu ahala. Aldatu fitxategiaren luzapena .binera integritate zuzen baterako.</string>
<string name="warning_database_info_changed_options">Fusionatu datuak, gain idatzi kanpo aldaketak datu-basean gordez edo birkargatu azken aldaketekin.</string>
<string name="warning_exact_alarm">Ez diozu aplikazioari alarma zehatz bat erabiltzen utzi, Hori dela eta, tenporizadore bat behar dituzten ezaugarriak ez dira ordu zehatz batean egingo.</string>
<string name="advanced_unlock_prompt_store_credential_message">Zure kutxa gotorraren pasahitz-nagusia gogoratu behar duzu naiz eta desblokeo aurreratuko ezagutzea erabili arren.</string>
<string name="device_unlock_prompt_store_credential_message">Zure kutxa gotorraren pasahitz-nagusia gogoratu behar duzu naiz eta desblokeo aurreratuko ezagutzea erabili arren.</string>
<string name="encrypted_value_stored">Zifratutako pasahitza gordeta</string>
<string name="unavailable">Datu-base honek ez du biltegiratuta kredentzialik.</string>
<string name="advanced_unlock_scanning_error">Gailuaren desblokeatze errorea: %1$s</string>
<string name="menu_appearance_settings">Itxura</string>
<string name="autofill_sign_in_prompt">KeePassDXekin erregistratu</string>
<string name="autofill_explanation_summary">Gaitu betetze automatikoa beste aplikazioetako formularioak errez betetzeko</string>
<string name="advanced_unlock">Gailua desblokeatu</string>
<string name="advanced_unlock_delete_all_key_warning">Ezabatu ezagutze desblokeo aurreratuaren zifraketa gako guztiak\?</string>
<string name="device_unlock">Gailua desblokeatu</string>
<string name="device_unlock_delete_all_key_warning">Ezabatu ezagutze desblokeo aurreratuaren zifraketa gako guztiak\?</string>
<string name="path">Bidea</string>
<string name="keyboard_auto_go_action_summary">\"Aurrera\" teklaren akzioa \"Eremu\" tekla zapaltzean</string>
<string name="education_entry_edit_summary">Editatu zure sarrera eremu pertsonalizatuekin. Taldeko datuak sarrera eremu ezberdinen artean erreferentzia daitezke.</string>
<string name="education_entry_new_field_title">Gehitu eremu pertsonalizatuak</string>
<string name="education_advanced_unlock_summary">Lotu zure pasahitza zure eskaneatutako biometriara edo gailuaren kredentzialetara datu-basea azkar desblokeatzeko.</string>
<string name="education_device_unlock_summary">Lotu zure pasahitza zure eskaneatutako biometriara edo gailuaren kredentzialetara datu-basea azkar desblokeatzeko.</string>
<string name="education_entry_edit_title">Sarrera editatu</string>
<string name="hide_expired_entries_title">Ezkutatu iraungitako sarrerak</string>
<string name="permission">Baimena</string>
<string name="build_label">Konpilazio bertsioa%1$s</string>
<string name="database_history">Historiala</string>
<string name="advanced_unlock_tap_delete">Ukitu gailua desblokeatzeko gakoak ezabatzeko</string>
<string name="device_unlock_tap_delete">Ukitu gailua desblokeatzeko gakoak ezabatzeko</string>
<string name="file_name">Fitxategiaren izena</string>
<string name="recycle_bin_group_title">Zakarrontziaren taldea</string>
<string name="assign_master_key">Esleitu gako nagusia</string>
<string name="icon_pack_choose_summary">Aplikazioak erabilitako ikono paketea</string>
<string name="advanced_unlock_invalid_key">Ezin da irakurri desblokeatze gakoa. Mesedez ezabatu ezatu eta errepikatu desblokeatze prozedura.</string>
<string name="device_unlock_invalid_key">Ezin da irakurri desblokeatze gakoa. Mesedez ezabatu ezatu eta errepikatu desblokeatze prozedura.</string>
<string name="device_credential_unlock_enable_title">Gailuaren kredentzialen desblokeoa</string>
<string name="advanced_unlock_keystore_warning">Ezaugarri honek zifratutako kredentzialen informazioa zure gailuaren KeyStorean gordeko ditu.
<string name="device_unlock_keystore_warning">Ezaugarri honek zifratutako kredentzialen informazioa zure gailuaren KeyStorean gordeko ditu.
\n
\nSistema eragilearen APIaren inplementazioaren arabera, posible litzake guztiz ondo ez funtzionatzea.
\nBegiratu KeyStorearen bateragarritasuna eta segurtasuna zure gailuaren fabrikatzailearekin eta erabiltzen ari zaren ROMaren sortzailearekin.</string>
@@ -530,8 +527,8 @@
<string name="show_entry_colors_title">Sarrerako koloreak</string>
<string name="show_entry_colors_summary">Erakutsi sarreraren aurreko eta atzeko planoen koloreak</string>
<string name="hide_expired_entries_summary">Iraungitako sarrerak ez dira erakusten</string>
<string name="advanced_unlock_prompt_extract_credential_title">Gailuaren desblokeo ezagutza</string>
<string name="advanced_unlock_prompt_extract_credential_message">Atera datu-baseko kredentzialak desblokeo datuekin</string>
<string name="device_unlock_prompt_extract_credential_title">Gailuaren desblokeo ezagutza</string>
<string name="device_unlock_prompt_extract_credential_message">Atera datu-baseko kredentzialak desblokeo datuekin</string>
<string name="education_setup_OTP_summary">Ezarri erabilera bakarreko pasahitzen kudeaketa (HOTP/TOTP) bi faktoreko autentifikazioak (2FA) eskatzen duen tokena sortzeko.</string>
<string name="education_read_only_summary">Aldatu saioaren irekiera modua.
\n
@@ -540,9 +537,9 @@
<string name="education_donation_summary">Parte hartu egonkortasuna, segurtasuna eta ezaugarri gehiago gehitzeko.</string>
<string name="html_text_ad_free">Pasahitzak kudeatzeko aplikazio asko ez bezala, hau &lt;strong&gt; iragarkirik gabekoa&lt;/strong&gt; eta &lt;strong&gt; copyleft software libreako&lt;/strong&gt; da eta ez du datu pertsonalik biltzen zerbitzarietan, aplikazioaren edozein bertsiotan.</string>
<string name="html_text_dev_feature">Ezaugarri hau &lt;strong&gt;garapen prozesuan &lt;/strong&gt; dago eta zure &lt;strong&gt; ekarpena&lt;/strong&gt; behar du ahalik eta lehen eskuragarri egoteko.</string>
<string name="credential_before_click_advanced_unlock_button">Idatzi pasahitza eta klikatu botoi hau.</string>
<string name="credential_before_click_device_unlock_button">Idatzi pasahitza eta klikatu botoi hau.</string>
<string name="properties">Propietateak</string>
<string name="temp_advanced_unlock_timeout_summary">Desblokeatze aurreratua erabiltzeko denbora bere edukia ezabatu aurretik</string>
<string name="temp_device_unlock_timeout_summary">Desblokeatze aurreratua erabiltzeko denbora bere edukia ezabatu aurretik</string>
<string name="warning_empty_keyfile_explanation">Fitxategi-gakoko edukia ez litzake inoiz aldatu beharko, eta kasu hoberenetan, ausaz sortutako datuak eduki beharko lituzke.</string>
<string name="warning_empty_recycle_bin">Ezabatu betirako nodo guztiak zakarrontzitik\?</string>
<string name="warning_database_info_changed">Zure datu-base fitxategiko informazioa aplikaziotik kanpo aldatu da.</string>
@@ -553,9 +550,9 @@
<string name="warning_database_already_opened">Dagoeneko datu-base bat irekita dago, itxi ezazu beste bat ireki ahal izateko</string>
<string name="warning_permanently_delete_nodes">Ezabatu betiko hautatutako nodoak\?</string>
<string name="warning_sure_add_file">Gehitu fitxategia edonola ere\?</string>
<string name="temp_advanced_unlock_enable_summary">Ez gorde zifratutako edukirik gailu desblokeatzea erabiltzeko</string>
<string name="temp_advanced_unlock_timeout_title">Gailu desblokeatzearen iraungitzea</string>
<string name="advanced_unlock_timeout">Gailu desblokeatzea erabiltzeko denbora muga</string>
<string name="temp_device_unlock_enable_summary">Ez gorde zifratutako edukirik gailu desblokeatzea erabiltzeko</string>
<string name="temp_device_unlock_timeout_title">Gailu desblokeatzearen iraungitzea</string>
<string name="device_unlock_timeout">Gailu desblokeatzea erabiltzeko denbora muga</string>
<string name="lock">Blokeatu</string>
<string name="html_text_donation">Gure askatasuna mantentzeko eta beti aktibo egoteko, aintzat dugu zure &lt;strong&gt;ekarpena.&lt;/strong&gt;</string>
<string name="education_read_only_title">Babestu zure datu-basea idazketen aurka</string>
@@ -576,11 +573,11 @@
<string name="warning_database_read_only">Eman idazketa baimena datu-basean aldaketak gordetzeko</string>
<string name="warning_password_encoding">Saihestu kodetze formatutik kanpoko karaktereak datu-baseko pasahitz fitxategietan (ezagutzen ez diren karaktereak letra berarengatik ordezten dira).</string>
<string name="warning_database_revoked">Fitxategirako atzipena baliogabetu du fitxategi kudeatzaileak, itxi datu-basea eta berriro ireki ezazu bere lokalizaziotik.</string>
<string name="advanced_unlock_prompt_store_credential_title">Gailuaren desblokeorako esteka</string>
<string name="advanced_unlock_prompt_not_initialized">Ezin izan da hasieratu gailuaren desblokeatze menua.</string>
<string name="device_unlock_prompt_store_credential_title">Gailuaren desblokeorako esteka</string>
<string name="device_unlock_prompt_not_initialized">Ezin izan da hasieratu gailuaren desblokeatze menua.</string>
<string name="set_autofill_service_title">Lehenetsi betetze automatiko zerbitzua</string>
<string name="content">Edukia</string>
<string name="education_advanced_unlock_title">Datu-basearen desblokeatze automatikoa</string>
<string name="education_device_unlock_title">Datu-basearen desblokeatze automatikoa</string>
<string name="screenshot_mode_banner_text">Pantaila-argazki modua</string>
<string name="list_password_generator_options_summary">Ezarri pasahitza sortzeko onartutako karaktereak</string>
<string name="list_password_generator_options_title">Pasahitzerako karaktereak</string>
@@ -594,12 +591,12 @@
<string name="lock_database_back_root_summary">Blokeatu datu-basea erabiltzaileak atzera botoia sakatzen duenean hasierako pantailan</string>
<string name="lock_database_show_button_title">Erakutsi blokeatzeko botoia</string>
<string name="lock_database_show_button_summary">Blokeatzeko botoia erakusten du interfazean</string>
<string name="advanced_unlock_explanation_summary">Erabili gailu desblokeatzea datu-base bat errazago irekitzeko</string>
<string name="device_unlock_explanation_summary">Erabili gailu desblokeatzea datu-base bat errazago irekitzeko</string>
<string name="biometric_unlock_enable_title">Desblokeo biometrikoa</string>
<string name="biometric_unlock_enable_summary">Zure datu biometrikoak eskaneatzen uzten dizu datu-basea irekitzeko</string>
<string name="device_credential_unlock_enable_summary">Zure gailuaren kredentzialak datu-basea irekitzeko erabiltzen uzten dizu</string>
<string name="biometric_auto_open_prompt_summary">Automatikoki eskatu gailu desblokeatzea datu-basea horrela erabiltzeko prestatu bada</string>
<string name="temp_advanced_unlock_enable_title">Denboraz mugatutako gailu desblokeatze</string>
<string name="temp_device_unlock_enable_title">Denboraz mugatutako gailu desblokeatze</string>
<string name="biometric_delete_all_key_title">Ezabatu zifraketa gakoak</string>
<string name="biometric_delete_all_key_summary">Ezabatu gailu desblokeoari lotutako zifraketa gako guztiak</string>
<string name="unavailable_feature_text">Ezin izan da ezaugarri hau hasieratu.</string>
@@ -619,7 +616,7 @@
<string name="education_unlock_title">Desblokeatu zure datu-basea</string>
<string name="autofill_preference_title">Betetze automatikoaren ezarpenak</string>
<string name="biometric_security_update_required">Segurtasun biometrikoko eguneraketa behar da.</string>
<string name="advanced_unlock_not_recognized">Ezin izan da errekonozitu desblokeatze aztarna</string>
<string name="device_unlock_not_recognized">Ezin izan da errekonozitu desblokeatze aztarna</string>
<string name="biometric">Biometria</string>
<string name="device_credential">Gailuaren kredentzialak</string>
<string name="general">Orokor</string>
@@ -671,7 +668,7 @@
<string name="info">Info</string>
<string name="menu_app_settings_summary">Bilatu, blokeoatu, historiala,ezaugarriak</string>
<string name="menu_form_filling_settings_summary">Teklatua,beteze automatikoa,arbela</string>
<string name="menu_advanced_unlock_settings_summary">Biometria, gailuaren egiztagiria</string>
<string name="menu_device_unlock_settings_summary">Biometria, gailuaren egiztagiria</string>
<string name="menu_database_settings_summary">Metadatuak, zakarrontzia, txantilioiak, historiala</string>
<string name="menu_security_settings_summary">Zifraketa, gakoen deribazio funtzioa</string>
<string name="master_key_settings_summary">Aldaketa,berriztapena</string>

View File

@@ -90,7 +90,7 @@
<string name="menu_master_key_settings">تنظیمات کلید اصلی</string>
<string name="menu_security_settings">تنظیمات امنیتی</string>
<string name="menu_database_settings">تنظیمات پایگاه داده</string>
<string name="menu_advanced_unlock_settings">باز کردن قفل پیشرفته</string>
<string name="menu_device_unlock_settings">باز کردن قفل پیشرفته</string>
<string name="menu_form_filling_settings">پر کردن فرم</string>
<string name="menu_app_settings">تنظیمات برنامه</string>
<string name="settings">تنظیمات</string>
@@ -246,8 +246,8 @@
<string name="keyboard_previous_database_credentials_title">صفحه اعتبار نامه پایگاه داده</string>
<string name="biometric_security_update_required">به روز رسانی امنیتی بیومتریک مورد نیاز است.</string>
<string name="configure_biometric">هیچ بیومتریک یا اعتبار دستگاه ثبت نشده است.</string>
<string name="advanced_unlock_tap_delete">برای حذف کلیدهای پیشرفته باز کردن قفل ضربه بزنید</string>
<string name="advanced_unlock">باز کردن قفل پیشرفته</string>
<string name="device_unlock_tap_delete">برای حذف کلیدهای پیشرفته باز کردن قفل ضربه بزنید</string>
<string name="device_unlock">باز کردن قفل پیشرفته</string>
<string name="content">محتوا</string>
<string name="warning_database_revoked">دسترسی به پرونده توسط مدیر فایل لغو شده ، پایگاه داده را ببندید و مجدداً از محل آن باز کنید.</string>
<string name="warning_database_info_changed_options">با ذخیره کردن پایگاه داده ، تغییرات خارجی را بازنویسی کنید یا با جدیدترین تغییرات آن را بارگیری کنید.</string>

View File

@@ -283,7 +283,7 @@
<string name="menu_copy">Kopioi</string>
<string name="menu_master_key_settings">Pääavainasetukset</string>
<string name="menu_security_settings">Turvallisuusasetukset</string>
<string name="menu_advanced_unlock_settings">Edistynyt lukituksen avaaminen</string>
<string name="menu_device_unlock_settings">Edistynyt lukituksen avaaminen</string>
<string name="menu_form_filling_settings">Lomakkeen täyttö</string>
<string name="copy_field">Kopio %1$s:sta</string>
<string name="creating_database">Luodaan tietokantaa…</string>
@@ -412,7 +412,7 @@
<string name="warning_empty_keyfile">Tyhjän avaintiedoston lisääminen ei ole suositeltavaa.</string>
<string name="menu_app_settings_summary">Haku, lukitus, historia, oninaisuudet</string>
<string name="menu_form_filling_settings_summary">Näppäimistö, automaattinen täyttö, leikepöytä</string>
<string name="menu_advanced_unlock_settings_summary">Biometria, laitevaltuutus</string>
<string name="menu_device_unlock_settings_summary">Biometria, laitevaltuutus</string>
<string name="menu_database_settings_summary">Metadata, roskakori, pohjat, historia</string>
<string name="menu_security_settings_summary">Salaus, avaimen johtamisfunktio</string>
<string name="master_key_settings_summary">Muutos, uudistus</string>

View File

@@ -75,7 +75,7 @@
<string name="content_description_update_from_list">I-update</string>
<string name="content_description_keyboard_close_fields">Isara ang mga field</string>
<string name="select_to_copy">Piliin para kopyahin ang %1$s sa clipboard</string>
<string name="html_about_licence">KeePassDX © %1$d Ang Kunzisoft ay &lt;strong&gt;open source&lt;/strong&gt; at &lt;strong&gt;walang advertising&lt;/strong&gt;. \nIbinigay ito nang as is, sa ilalim &lt;strong&gt;GPLv3&lt;/strong&gt; na lisensya, nang walang anumang warranty.</string>
<string name="html_about_licence">Ang KeePassDX © Kunzisoft ay open source at walang kasamang patalastas.\nIbinibigay ito nang buo sa ilalim ng lisensiyang GPLv3, nang walang anumang garantiya.</string>
<string name="html_about_privacy">&lt;strong&gt;Walang user data ay kinukuha&lt;/strong&gt;, ang aplikasyon na ito ay hindi kumokonekta sa anumang server, gumanagana ng lokal at ganap na ginagalang ang pagkapribado ng mga gumagamit.</string>
<string name="html_about_contribution">Para &lt;strong&gt;panatilihin ang aming kalayaan&lt;/strong&gt;, &lt;strong&gt;ayusin ang mga bug&lt;/strong&gt;, &lt;strong&gt;magdagdag ng mga feature&lt;/strong&gt; at &lt;strong&gt;maging palaging aktibo&lt;/strong&gt;, umaasa kami sa iyong &lt;strong&gt;kontribusyon&lt;/strong&gt;.</string>
<string name="entry_accessed">Na-access</string>
@@ -243,8 +243,8 @@
<string name="menu_app_settings_summary">Paghahanap, lock, history, mga property</string>
<string name="menu_form_filling_settings">Pagpuno ng form</string>
<string name="menu_form_filling_settings_summary">Keyboard, pag-autofill, clipboard</string>
<string name="menu_advanced_unlock_settings">Pag-unlock gamit ang device</string>
<string name="menu_advanced_unlock_settings_summary">Biometry, kredensyal ng device</string>
<string name="menu_device_unlock_settings">Pag-unlock gamit ang device</string>
<string name="menu_device_unlock_settings_summary">Biometry, kredensyal ng device</string>
<string name="menu_database_settings">Mga setting ng database</string>
<string name="menu_database_settings_summary">Metadata, recycle bin, mga template, history</string>
<string name="menu_security_settings">Mga setting ng seguridad</string>

View File

@@ -179,7 +179,7 @@
<string name="lock">Verrouiller</string>
<string name="lock_database_screen_off_title">Verrouillage décran</string>
<string name="lock_database_screen_off_summary">Verrouille la base de données après quelques secondes une fois lécran éteint</string>
<string name="advanced_unlock">Déverrouillage avancé</string>
<string name="device_unlock">Déverrouillage avancé</string>
<string name="biometric_unlock_enable_title">Déverrouillage biométrique</string>
<string name="biometric_unlock_enable_summary">Permet de numériser votre empreinte biométrique pour ouvrir la base de données</string>
<string name="biometric_delete_all_key_title">Supprimer les clés de chiffrement</string>
@@ -245,7 +245,7 @@
<string name="html_text_ad_free">Contrairement à beaucoup dapplications de gestion de mots de passe, cette application est &lt;strong&gt;sans publicité&lt;/strong&gt;, &lt;strong&gt;libre sous licence copyleft&lt;/strong&gt; et ne collecte pas de données personnelles sur ses serveurs, peu importe la version que vous utilisez.</string>
<string name="html_text_buy_pro">En achetant la version pro, vous aurez accès à ce &lt;strong&gt;style visuelle&lt;/strong&gt; et vous aiderez notamment &lt;strong&gt;la réalisation de projets communautaires.&lt;/strong&gt;</string>
<string name="html_text_feature_generosity">Ce &lt;strong&gt;style visuel&lt;/strong&gt; est disponible grâce à votre générosité.</string>
<string name="html_text_donation">En &lt;strong&gt;contribuant&lt;/strong&gt; au projet <i>(financièrement, code, traduction)</i>, vous l\'aiderez à continuer à vivre et à prospérer, et vous serez également éligible à la procédure de déblocage du &lt;strong&gt;theme&lt;/strong&gt;.</string>
<string name="html_text_donation">En &lt;strong&gt;contribuant&lt;/strong&gt; au projet &lt;i&gt;(financièrement, code, traduction)&lt;/i&gt;, vous l\'aiderez à continuer à vivre et à prospérer, et vous serez également éligible à la procédure de déblocage du &lt;strong&gt;theme&lt;/strong&gt;.</string>
<string name="html_text_dev_feature">Cette fonctionnalité est &lt;strong&gt;en cours de développement&lt;/strong&gt; et nécessite votre &lt;strong&gt;contribution&lt;/strong&gt; pour être bientôt disponible.</string>
<string name="html_text_dev_feature_buy_pro">En achetant la version &lt;strong&gt;pro&lt;/strong&gt;,</string>
<string name="html_text_dev_feature_contibute">En &lt;strong&gt;contribuant&lt;/strong&gt;,</string>
@@ -283,8 +283,6 @@
<string name="allow_no_password_summary">Autorise lappui du bouton \"Ouvrir\" si aucun identifiant nest sélectionné</string>
<string name="menu_file_selection_read_only">Protéger en écriture</string>
<string name="menu_open_file_read_and_write">Modifiable</string>
<string name="enable_read_only_title">Protéger en écriture</string>
<string name="enable_read_only_summary">Ouvre la base de données en lecture seule par défaut</string>
<string name="education_read_only_title">Protégez en écriture votre base de données</string>
<string name="education_read_only_summary">Changez le mode douverture pour la session.
\n
@@ -353,7 +351,7 @@
<string name="content_description_update_from_list">Mise à jour</string>
<string name="content_description_keyboard_close_fields">Fermer les champs</string>
<string name="error_create_database_file">Impossible de créer une base de données avec ce mot de passe et ce fichier clé.</string>
<string name="menu_advanced_unlock_settings">Déverrouillage de l\'appareil</string>
<string name="menu_device_unlock_settings">Déverrouillage de l\'appareil</string>
<string name="enable">Activer</string>
<string name="disable">Désactiver</string>
<string name="biometric">Biométrie</string>
@@ -389,7 +387,7 @@
<string name="contains_duplicate_uuid_procedure">Résoudre le problème en générant de nouveaux UUID pour les doublons et continuer \?</string>
<string name="database_opened">Base de données ouverte</string>
<string name="clipboard_explanation_summary">Copier les champs dune entrée à laide du presse-papier de votre appareil</string>
<string name="advanced_unlock_explanation_summary">Utiliser le déverrouillage de l\'appareil pour ouvrir plus facilement une base de données</string>
<string name="device_unlock_explanation_summary">Utiliser le déverrouillage de l\'appareil pour ouvrir plus facilement une base de données</string>
<string name="database_data_compression_title">Compression de données</string>
<string name="database_data_compression_summary">La compression des données réduit la taille de la base de données</string>
<string name="max_history_items_title">Nombre maximum</string>
@@ -503,33 +501,32 @@
<string name="search_mode">Mode recherche</string>
<string name="error_registration_read_only">Lenregistrement dun nouvel élément nest pas autorisé dans une base de données en lecture seule.</string>
<string name="error_field_name_already_exists">Le nom du champ existe déjà.</string>
<string name="advanced_unlock_delete_all_key_warning">Supprimer toutes les clés de chiffrement liées à la reconnaissance de déverrouillage de l\'appareil \?</string>
<string name="device_unlock_delete_all_key_warning">Supprimer toutes les clés de chiffrement liées à la reconnaissance de déverrouillage de l\'appareil \?</string>
<string name="device_credential_unlock_enable_summary">Vous permet d\'utiliser les informations d\'identification de votre appareil pour ouvrir la base de données</string>
<string name="device_credential_unlock_enable_title">Déverrouillage par identifiants de l\'appareil</string>
<string name="device_credential">Identifiant de l\'appareil</string>
<string name="credential_before_click_advanced_unlock_button">Tapez le mot de passe, puis cliquez sur ce bouton.</string>
<string name="advanced_unlock_prompt_not_initialized">Impossible d\'initialiser l\'invite de déverrouillage avancé.</string>
<string name="advanced_unlock_scanning_error">Erreur de déverrouillage avancé : %1$s</string>
<string name="advanced_unlock_not_recognized">Impossible de reconnaître l\'empreinte de déverrouillage de l\'appareil</string>
<string name="advanced_unlock_invalid_key">Impossible de lire la clé de déverrouillage de l\'appareil. Veuillez la supprimer et répéter la procédure de reconnaissance de déverrouillage.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Extraire les identifiants de la base de données avec des données de déverrouillage de l\'appareil</string>
<string name="advanced_unlock_prompt_extract_credential_title">Reconnaissance du déverrouillage de l\'appareil</string>
<string name="advanced_unlock_prompt_store_credential_message">Vous devez toujours vous souvenir de l\'identifiant principal du coffre-fort si vous utilisez le déverrouillage de l\'appareil.</string>
<string name="advanced_unlock_prompt_store_credential_title">Liaison vers le déverrouillage de l\'appareil</string>
<string name="credential_before_click_device_unlock_button">Tapez le mot de passe, puis cliquez sur ce bouton.</string>
<string name="device_unlock_prompt_not_initialized">Impossible d\'initialiser l\'invite de déverrouillage avancé.</string>
<string name="device_unlock_not_recognized">Impossible de reconnaître l\'empreinte de déverrouillage de l\'appareil</string>
<string name="device_unlock_invalid_key">Impossible de lire la clé de déverrouillage de l\'appareil. Veuillez la supprimer et répéter la procédure de reconnaissance de déverrouillage.</string>
<string name="device_unlock_prompt_extract_credential_message">Extraire les identifiants de la base de données avec des données de déverrouillage de l\'appareil</string>
<string name="device_unlock_prompt_extract_credential_title">Reconnaissance du déverrouillage de l\'appareil</string>
<string name="device_unlock_prompt_store_credential_message">Vous devez toujours vous souvenir de l\'identifiant principal du coffre-fort si vous utilisez le déverrouillage de l\'appareil.</string>
<string name="device_unlock_prompt_store_credential_title">Liaison vers le déverrouillage de l\'appareil</string>
<string name="menu_keystore_remove_key">Supprimer la clé de déverrouillage avancée</string>
<string name="enter">Entrer</string>
<string name="backspace">Retour arrière</string>
<string name="select_entry">Sélection d\'une entrée</string>
<string name="back_to_previous_keyboard">Retour au clavier précédent</string>
<string name="custom_fields">Champs customisés</string>
<string name="education_advanced_unlock_summary">Lier votre mot de passe à vos informations d\'identification biométriques ou de périphérique scannées pour déverrouiller rapidement votre base de données.</string>
<string name="education_advanced_unlock_title">Déverrouillage avancé de la base de données</string>
<string name="advanced_unlock_timeout">Délai du déverrouillage de l\'appareil</string>
<string name="temp_advanced_unlock_timeout_summary">Durée d\'utilisation du déverrouillage de l\'appareil avant de supprimer son contenu</string>
<string name="temp_advanced_unlock_timeout_title">Expiration du déverrouillage de l\'appareil</string>
<string name="temp_advanced_unlock_enable_summary">Ne stocker aucun contenu crypté pour utiliser le déverrouillage de l\'appareil</string>
<string name="temp_advanced_unlock_enable_title">Déverrouillage de l\'appareil temporaire</string>
<string name="advanced_unlock_tap_delete">Appuyez pour supprimer les clés de déverrouillage de l\'appareil</string>
<string name="education_device_unlock_summary">Lier votre mot de passe à vos informations d\'identification biométriques ou de périphérique scannées pour déverrouiller rapidement votre base de données.</string>
<string name="education_device_unlock_title">Déverrouillage avancé de la base de données</string>
<string name="device_unlock_timeout">Délai du déverrouillage de l\'appareil</string>
<string name="temp_device_unlock_timeout_summary">Durée d\'utilisation du déverrouillage de l\'appareil avant de supprimer son contenu</string>
<string name="temp_device_unlock_timeout_title">Expiration du déverrouillage de l\'appareil</string>
<string name="temp_device_unlock_enable_summary">Ne stocker aucun contenu crypté pour utiliser le déverrouillage de l\'appareil</string>
<string name="temp_device_unlock_enable_title">Déverrouillage de l\'appareil temporaire</string>
<string name="device_unlock_tap_delete">Appuyez pour supprimer les clés de déverrouillage de l\'appareil</string>
<string name="content">Contenu</string>
<string name="error_rebuild_list">Impossible de reconstruire correctement la liste.</string>
<string name="error_database_uri_null">L\'URI de la base de données ne peut pas être récupéré.</string>
@@ -636,7 +633,7 @@
<string name="case_sensitive">Sensible à la casse</string>
<string name="expired">Expiré</string>
<string name="warning_database_already_opened">Une base de données est déjà ouverte, fermez-la d\'abord pour ouvrir la nouvelle base</string>
<string name="advanced_unlock_keystore_warning">Cette fonction permet de stocker des données d\'identification chiffrées dans le KeyStore sécurisé de votre appareil.
<string name="device_unlock_keystore_warning">Cette fonction permet de stocker des données d\'identification chiffrées dans le KeyStore sécurisé de votre appareil.
\n
\nSelon l\'implémentation de l\'API native du système d\'exploitation, il se peut qu\'elle ne soit pas entièrement fonctionnelle.
\n
@@ -687,7 +684,7 @@
<string name="menu_app_settings_summary">Recherche, verrouillage, historique, propriétés</string>
<string name="menu_form_filling_settings_summary">Clavier, remplissage automatique, presse-papiers</string>
<string name="master_key_settings_summary">Changement, renouvellement</string>
<string name="menu_advanced_unlock_settings_summary">Biométrie, identifiant de l\'appareil</string>
<string name="menu_device_unlock_settings_summary">Biométrie, identifiant de l\'appareil</string>
<string name="unlock_and_link_biometric">Liaison avec déverouillage de l\'appareil</string>
<string name="unlock">Déverrouiller</string>
<string name="configure">Configurer</string>
@@ -704,6 +701,7 @@
<string name="recursive_number_entries_title">Nombre d\'entrées récursif</string>
<string name="recursive_number_entries_summary">Calcule récursivement le nombre d\'entrées dans un groupe</string>
<string name="warning_large_keyfile">Il n\'est pas recommandé d\'ajouter un fichier clé volumineux, car cela pourrait empêcher l\'ouverture de la base de données.</string>
<string name="hide_templates_title">Cacher les modèles</string>
<string name="hide_templates_summary">Les modèles ne sont pas affichés</string>
<string name="hide_templates_title">Cacher les gabarits</string>
<string name="hide_templates_summary">Les gabarits ne sont pas affichés</string>
<string name="error_otp_secret_length">La clé secrète doit avoir ai moins %1$d caractères.</string>
</resources>

View File

@@ -219,7 +219,7 @@
<string name="password">Contrasinal</string>
<string name="invalid_algorithm">Algoritmo errado.</string>
<string name="invalid_db_same_uuid">%1$s co mesmo UUID %2$s xa existe.</string>
<string name="menu_advanced_unlock_settings">Desbloqueo avanzado</string>
<string name="menu_device_unlock_settings">Desbloqueo avanzado</string>
<string name="error_otp_secret_key">A clave secreta debe estar en formato Base32.</string>
<string name="hint_length">Lonxitude</string>
<string name="menu_change_key_settings">Cambiar clave mestra</string>
@@ -367,9 +367,9 @@
<string name="content">Contido</string>
<string name="permission">Permiso</string>
<string name="autofill_preference_title">Configuracións de autocompletado</string>
<string name="advanced_unlock_prompt_store_credential_title">Recoñecemento de desbloqueo avanzado</string>
<string name="device_unlock_prompt_store_credential_title">Recoñecemento de desbloqueo avanzado</string>
<string name="biometric_security_update_required">É necesaria unha actualización da seguranza biométrica.</string>
<string name="advanced_unlock_prompt_extract_credential_title">Abrir a base de datos co recoñecemento de desbloqueo avanzado</string>
<string name="device_unlock_prompt_extract_credential_title">Abrir a base de datos co recoñecemento de desbloqueo avanzado</string>
<string name="biometric">Biométrico</string>
<string name="autofill_explanation_summary">Habilite o servizo para autocompletar rapidamente os formularios de outras aplicacións</string>
<string name="clipboard_notifications_title">Notificacións do portapapeis</string>
@@ -377,7 +377,7 @@
<string name="lock_database_back_root_summary">Bloquear a base de datos cando o usuario faga click no botón de volver á pantalla principal</string>
<string name="lock_database_show_button_title">Mostrar botón de bloqueo</string>
<string name="clipboard_notifications_summary">Mostrar notificacións do portapapeis ao visualizar unha entrada</string>
<string name="advanced_unlock_tap_delete">Tocar para borrar as claves de desbloqueo avanzado</string>
<string name="device_unlock_tap_delete">Tocar para borrar as claves de desbloqueo avanzado</string>
<string name="device_credential_unlock_enable_summary">Permitelle usar as credenciais do dispositivo para abrir a base de datos</string>
<string name="device_credential_unlock_enable_title">Desbloqueo coas credenciais do dispositivo</string>
<string name="lock_database_screen_off_summary">Bloquear a base de datos após uns segundos da pantalla apagar</string>
@@ -395,16 +395,16 @@
<string name="build_label">Compilación %1$s</string>
<string name="configure_biometric">Non hai rexistro de ningún credencial biométrico ou de dispositivo.</string>
<string name="keystore_not_accessible">O almacén de claves non foi iniciado correctamente.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Extraer a credencial da base de datos cos datos de desbloqueo avanzado</string>
<string name="device_unlock_prompt_extract_credential_message">Extraer a credencial da base de datos cos datos de desbloqueo avanzado</string>
<string name="unavailable">Esta base de datos non ten credenciais almacenadas aínda.</string>
<string name="advanced_unlock_prompt_not_initialized">Non foi posíbel inciar o desbloqueo avanzado.</string>
<string name="credential_before_click_advanced_unlock_button">Escriba o contrasinal, e logo faga click neste botón.</string>
<string name="device_unlock_prompt_not_initialized">Non foi posíbel inciar o desbloqueo avanzado.</string>
<string name="credential_before_click_device_unlock_button">Escriba o contrasinal, e logo faga click neste botón.</string>
<string name="properties">Propiedades</string>
<string name="menu_appearance_settings">Aparencia</string>
<string name="device_credential">Credenciais do dispositivo</string>
<string name="general">Xeral</string>
<string name="autofill">Autocompletado</string>
<string name="advanced_unlock_explanation_summary">Usar o desbloqueo avanzado para abrir a base de datos dun xeito máis sinxelo</string>
<string name="device_unlock_explanation_summary">Usar o desbloqueo avanzado para abrir a base de datos dun xeito máis sinxelo</string>
<string name="autofill_sign_in_prompt">Inciar sesión con KeePassDX</string>
<string name="autofill_select_entry">Seleccione entrada…</string>
<string name="password_size_title">Tamaño do contrasinal xerado</string>
@@ -419,21 +419,20 @@
<string name="lock_database_screen_off_title">Bloqueo de pantalla</string>
<string name="lock_database_back_root_title">Presione \'Atrás\' para bloquear</string>
<string name="lock_database_show_button_summary">Mostrar o botón de bloqueo na interface do usuario</string>
<string name="advanced_unlock">Desbloqueo avanzado</string>
<string name="device_unlock">Desbloqueo avanzado</string>
<string name="biometric_unlock_enable_title">Desbloqueo biométrico</string>
<string name="biometric_unlock_enable_summary">Permite o escaneo dos datos biomérifos para abrir a base de datos</string>
<string name="advanced_unlock_invalid_key">Non foi posíbel ler a clave de desbloqueo avanzado. Por favor, bórrea e repita o procedemento de recoñecemento do desbloqueo.</string>
<string name="device_unlock_invalid_key">Non foi posíbel ler a clave de desbloqueo avanzado. Por favor, bórrea e repita o procedemento de recoñecemento do desbloqueo.</string>
<string name="encrypted_value_stored">Contrasinal cifrado almacenado</string>
<string name="advanced_unlock_not_recognized">Non foi posíbel recoñecer a pegada do desbloqueo avanzado</string>
<string name="advanced_unlock_scanning_error">Erro de desbloqueo avanzado: %1$s</string>
<string name="device_unlock_not_recognized">Non foi posíbel recoñecer a pegada do desbloqueo avanzado</string>
<string name="autofill_service_name">Servizo de autocompletado do KeePassDX</string>
<string name="database_history">Historial</string>
<string name="advanced_unlock_prompt_store_credential_message">Aínda precisa lembrar a súa credencial principal se usar o recoñecemento de desbloqueo avanzado.</string>
<string name="temp_advanced_unlock_enable_title">Desbloqueo avanzado temporal</string>
<string name="device_unlock_prompt_store_credential_message">Aínda precisa lembrar a súa credencial principal se usar o recoñecemento de desbloqueo avanzado.</string>
<string name="temp_device_unlock_enable_title">Desbloqueo avanzado temporal</string>
<string name="file_name">Nome do arquivo</string>
<string name="temp_advanced_unlock_timeout_title">Duración do desbloqueo avanzado</string>
<string name="temp_advanced_unlock_timeout_summary">Duración do uso do desbloqueo avanzado antes de borrar os seus contidos</string>
<string name="advanced_unlock_timeout">Tempo límite de desbloqueo avanzado</string>
<string name="temp_device_unlock_timeout_title">Duración do desbloqueo avanzado</string>
<string name="temp_device_unlock_timeout_summary">Duración do uso do desbloqueo avanzado antes de borrar os seus contidos</string>
<string name="device_unlock_timeout">Tempo límite de desbloqueo avanzado</string>
<string name="biometric_delete_all_key_summary">Borrar todas as claves de cifrado relacionadas co desbloqueo de recoñecemento avanzado</string>
<string name="assign_master_key">Asignar unha clave mestra</string>
<string name="data">Datos</string>
@@ -443,9 +442,9 @@
<string name="unavailable_feature_text">Non foi posíbel iniciar esta funcionalidade.</string>
<string name="database_data_compression_title">Compresión de datos</string>
<string name="biometric_auto_open_prompt_summary">Pedir automaticamente o desbloqueo avanzado se a base de datos estiver configurada para o seu uso</string>
<string name="temp_advanced_unlock_enable_summary">Non almacenar ningún contido cifrado para o desbloqueo avanzado</string>
<string name="advanced_unlock_delete_all_key_warning">Borrar todas as claves de cifrado relacionadas co desbloqueo de recoñecemento avanzado\?</string>
<string name="advanced_unlock_keystore_warning">Esta funcionalidade almacenará os datos de credenciais cifrados na KeyStore do seu dispositivo.
<string name="temp_device_unlock_enable_summary">Non almacenar ningún contido cifrado para o desbloqueo avanzado</string>
<string name="device_unlock_delete_all_key_warning">Borrar todas as claves de cifrado relacionadas co desbloqueo de recoñecemento avanzado\?</string>
<string name="device_unlock_keystore_warning">Esta funcionalidade almacenará os datos de credenciais cifrados na KeyStore do seu dispositivo.
\n
\nDependendo da implementación da API nativa do seu sistema operativo, pode non ser completamente funcional.
\nRevise a compatibilidade e seguranza da KeyStore co fabricante do seu dispositivo e co creador da ROM que está a usar.</string>
@@ -552,12 +551,11 @@
<string name="autofill_ask_to_save_data_summary">Pedir para gardar datos cando terminar de autocompletar un formulario</string>
<string name="delete_entered_password_summary">Borrar o contrasinal introducido após un intento de conexión a unha base de datos</string>
<string name="reset_education_screens_title">Restabelecer suxestións educativas</string>
<string name="education_advanced_unlock_title">Desbloqueo avanzado da base de datos</string>
<string name="education_advanced_unlock_summary">Ligue o seu contrasinal á súa credencial biométrica ou credenciais do dispositivo para desbloquear rapidamente a súa base de datos.</string>
<string name="education_device_unlock_title">Desbloqueo avanzado da base de datos</string>
<string name="education_device_unlock_summary">Ligue o seu contrasinal á súa credencial biométrica ou credenciais do dispositivo para desbloquear rapidamente a súa base de datos.</string>
<string name="enable_auto_save_database_title">Gardar base de datos automaticamente</string>
<string name="enable_keep_screen_on_title">Manter a pantalla acesa</string>
<string name="allow_no_password_summary">Permitir pulsar o botón \"Abrir\" se non seleccionar ningunha credencial</string>
<string name="enable_read_only_title">Só lectura</string>
<string name="enable_education_screens_summary">Destacar elementos para saber como funciona a aplicación</string>
<string name="reset_education_screens_text">Suxestións educativas restabelecidas</string>
<string name="education_create_database_title">Crear o teu arquivo de base de datos</string>
@@ -594,7 +592,6 @@
<string name="education_entry_new_field_title">Engadir campos personalizados</string>
<string name="menu_form_filling_settings">Completado de formularios</string>
<string name="keyboard_notification_entry_content_title">%1$s dispoñíbel no Magikeyboard</string>
<string name="enable_read_only_summary">Abrir a base de datos en modo de só lectura por defecto</string>
<string name="education_setup_OTP_summary">Configure a xestión do contrasinal dun só uso (HOTP / TOTP) para xerar un token solicitado para a autenticación de dous factores (2FA).</string>
<string name="education_unlock_title">Desbloquee a súa base de datos</string>
<string name="delete_entered_password_title">Eliminar contrasinal</string>

View File

@@ -17,7 +17,7 @@
You should have received a copy of the GNU General Public License
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
--><resources>
<string name="about_description">Android implementacija KeePass upravljača lozinki</string>
<string name="about_description">Android implementacija KeePass upravljača lozinki.</string>
<string name="accept">Prihvati</string>
<string name="add_entry">Dodaj unos</string>
<string name="edit_entry">Uredi unos</string>
@@ -118,7 +118,7 @@
<string name="settings">Postavke</string>
<string name="menu_app_settings">Postavke aplikacije</string>
<string name="menu_form_filling_settings">Ispunjavanje obrasca</string>
<string name="menu_advanced_unlock_settings">Otključavanje uređaja</string>
<string name="menu_device_unlock_settings">Otključavanje uređaja</string>
<string name="menu_database_settings">Postavke baze podataka</string>
<string name="menu_security_settings">Postavke sigurnosti</string>
<string name="menu_master_key_settings">Postavke glavnog ključa</string>
@@ -187,8 +187,8 @@
<string name="clipboard_warning">Ako automatsko brisanje međuspremnika ne uspije, izbriši njegovu povijest ručno.</string>
<string name="lock_database_screen_off_summary">Zaključaj bazu podataka nakon par sekundi kad se ekran ugasi</string>
<string name="lock_database_back_root_title">Pritisni \'Natrag\' za zaključavanje</string>
<string name="advanced_unlock">Otključavanje uređaja</string>
<string name="advanced_unlock_explanation_summary">Koristi otključavanje uređaja za jednostavnije otvaranje baze podataka</string>
<string name="device_unlock">Otključaj uređaj</string>
<string name="device_unlock_explanation_summary">Koristi otključavanje uređaja za jednostavnije otvaranje baze podataka</string>
<string name="biometric_unlock_enable_title">Biometrijsko otključavanje</string>
<string name="biometric_unlock_enable_summary">Otvaranje baze podataka skeniranjem biometrike</string>
<string name="biometric_delete_all_key_title">Izbriši ključeve šifriranja</string>
@@ -310,8 +310,6 @@
<string name="allow_no_password_summary">Dozvoljava dodir gumba „Otvori”, ako nisu odabrani nikoji podaci za prijavu</string>
<string name="delete_entered_password_title">Izbriši lozinku</string>
<string name="delete_entered_password_summary">Briše upisanu lozinku nakon pokušaja povezivanja s bazom podataka</string>
<string name="enable_read_only_title">Zaštićeno od pisanja</string>
<string name="enable_read_only_summary">Standardno otvori bazu podataka u zaštićenom stanju</string>
<string name="enable_auto_save_database_title">Automatski spremi bazu podataka</string>
<string name="enable_auto_save_database_summary">Automatski spremi bazu podataka nakon svake važne radnje (samo u modusu „Promjenjivo”)</string>
<string name="enable_education_screens_title">Edukativne poruke</string>
@@ -384,8 +382,8 @@
<string name="education_entry_new_field_title">Dodaj prilagođena polja</string>
<string name="education_lock_summary">Zaključaj bazu podataka brzo, aplikaciju možeš postaviti tako da bazu nakon nekog vremena zaključa i kad se ekran isključi.</string>
<string name="show_recent_files_summary">Prikaži mjesto nedavnih baza podataka</string>
<string name="education_advanced_unlock_summary">Za brzo otključavanje baze podataka, poveži lozinku sa skeniranom biometrijom ili podacima za prijavu uređaja.</string>
<string name="html_text_donation">Kako bismo zadržali našu slobodu i uvijek bili aktivni, računamo na tvoj&lt;strong&gt;doprinos.&lt;/strong&gt;</string>
<string name="education_device_unlock_summary">Za brzo otključavanje baze podataka, poveži lozinku sa skeniranom biometrijom ili podacima za prijavu uređaja.</string>
<string name="html_text_donation">&lt;strong&gt;Doprinosom&lt;/strong&gt; projektu &lt;i&gt;(novčano, kodom, prijevodom)&lt;/i&gt; pomažeš mu da živi i napreduje, a također stječeš pravo na postupak otključavanja &lt;strong&gt;tema&lt;/strong&gt;.</string>
<string name="kdf_explanation">Za stvaranje ključa za algoritam šifriranja, glavni ključ se transformira pomoću funkcije za generiranje ključeva koja sadrži slučajnu komponentu.</string>
<string name="lock_database_back_root_summary">Zaključaj bazu podataka kad korisnik pritisne gumb za natrag na glavnom ekranu</string>
<string name="hide_broken_locations_title">Sakrij pokvarene poveznice baze podataka</string>
@@ -483,17 +481,16 @@
<string name="save_mode">Modus spremanja</string>
<string name="search_mode">Modus pretrage</string>
<string name="error_field_name_already_exists">Ime polja već postoji.</string>
<string name="advanced_unlock_delete_all_key_warning">Izbrisati sve ključeve šifriranja povezane s prepoznavanjem otključavanja uređaja\?</string>
<string name="credential_before_click_advanced_unlock_button">Upiši lozinku, zatim pritisni ovaj gumb.</string>
<string name="advanced_unlock_prompt_extract_credential_title">Prepoznavanje otključavanja uređaja</string>
<string name="advanced_unlock_prompt_store_credential_message">Ako koristiš prepoznavanje otključavanja uređaja morat ćeš i dalje znati tvoj glavni podatak za prijavu za trezor.</string>
<string name="device_unlock_delete_all_key_warning">Izbrisati sve ključeve šifriranja povezane s prepoznavanjem otključavanja uređaja\?</string>
<string name="credential_before_click_device_unlock_button">Upiši lozinku, zatim pritisni ovaj gumb.</string>
<string name="device_unlock_prompt_extract_credential_title">Prepoznavanje otključavanja uređaja</string>
<string name="device_unlock_prompt_store_credential_message">Ako koristiš prepoznavanje otključavanja uređaja morat ćeš i dalje znati tvoj glavni podatak za prijavu za trezor.</string>
<string name="menu_keystore_remove_key">Izbriši ključ za otključavanje uređaja</string>
<string name="advanced_unlock_prompt_store_credential_title">Poveznica za otključavanje uređaja</string>
<string name="advanced_unlock_prompt_not_initialized">Nije moguće pokrenuti prozor za otključavanje uređaja.</string>
<string name="advanced_unlock_scanning_error">Greška otključavanja uređaja: %1$s</string>
<string name="advanced_unlock_prompt_extract_credential_message">Izdvoji podatake za prijavu na bazu podataka pomoću podataka za otključavanje uređaja</string>
<string name="advanced_unlock_not_recognized">Nije bilo moguće prepoznati ispis za otključavanje uređaja</string>
<string name="advanced_unlock_invalid_key">Nije moguće pročitati ključ za otključavanje uređaja. Izbriši ga i ponovi postupak prepoznavanja otključavanja.</string>
<string name="device_unlock_prompt_store_credential_title">Poveznica za otključavanje uređaja</string>
<string name="device_unlock_prompt_not_initialized">Nije moguće pokrenuti prozor za otključavanje uređaja.</string>
<string name="device_unlock_prompt_extract_credential_message">Izdvoji podatake za prijavu na bazu podataka pomoću podataka za otključavanje uređaja</string>
<string name="device_unlock_not_recognized">Nije bilo moguće prepoznati ispis za otključavanje uređaja</string>
<string name="device_unlock_invalid_key">Nije moguće pročitati ključ za otključavanje uređaja. Izbriši ga i ponovi postupak prepoznavanja otključavanja.</string>
<string name="enter">Tipka Enter</string>
<string name="backspace">Tipka Backspace</string>
<string name="select_entry">Odaberi unos</string>
@@ -502,14 +499,14 @@
<string name="device_credential_unlock_enable_summary">Omogućuje otvaranje baze podataka pomoću podataka za prijavu</string>
<string name="device_credential_unlock_enable_title">Otključavanje s podacima za prijavu uređaja</string>
<string name="device_credential">Podaci za prijavu uređaja</string>
<string name="advanced_unlock_tap_delete">Dodirni za brisanje ključeva za otključavanje uređaja</string>
<string name="education_advanced_unlock_title">Otključavanje uređaja baze podataka</string>
<string name="advanced_unlock_timeout">Vremensko ograničenje otključavanja uređaja</string>
<string name="temp_advanced_unlock_timeout_summary">Trajanje korištenja otključavanja uređaja prije brisanja njegovog sadržaja</string>
<string name="temp_advanced_unlock_timeout_title">Istek otključavanja uređaja</string>
<string name="temp_advanced_unlock_enable_summary">Nemoj spremati šifrirani sadržaj za otključavanje uređaja</string>
<string name="device_unlock_tap_delete">Dodirni za brisanje ključeva za otključavanje uređaja</string>
<string name="education_device_unlock_title">Otključavanje uređaja baze podataka</string>
<string name="device_unlock_timeout">Vremensko ograničenje otključavanja uređaja</string>
<string name="temp_device_unlock_timeout_summary">Trajanje korištenja otključavanja uređaja prije brisanja njegovog sadržaja</string>
<string name="temp_device_unlock_timeout_title">Istek otključavanja uređaja</string>
<string name="temp_device_unlock_enable_summary">Nemoj spremati šifrirani sadržaj za otključavanje uređaja</string>
<string name="content">Sadržaj</string>
<string name="temp_advanced_unlock_enable_title">Privremeno otključavanje uređaja</string>
<string name="temp_device_unlock_enable_title">Privremeno otključavanje uređaja</string>
<string name="error_rebuild_list">Nije moguće ispravno obnoviti popis.</string>
<string name="error_database_uri_null">URI baze podataka nije moguće dobiti.</string>
<string name="autofill_inline_suggestions_title">Umetnuti prijedlozi</string>
@@ -614,7 +611,7 @@
<string name="menu_save_copy_to">Spremi kopiju u …</string>
<string name="navigation_drawer_open">Ploča navigacije otvorena</string>
<string name="navigation_drawer_close">Ploča navigacije zatvorena</string>
<string name="advanced_unlock_keystore_warning">Ova će funckija spremiti šifrirane podatke za prijavu u sigurni KeyStore tvog uređaja.
<string name="device_unlock_keystore_warning">Ova će funckija spremiti šifrirane podatke za prijavu u sigurni KeyStore tvog uređaja.
\n
\nOvisno o izvornoj API implementaciji operacijskog sustava, funcionalsnost možda neće biti potpuna.
\n
@@ -677,7 +674,7 @@
<string name="unlock_and_link_biometric">Poveznica za otključavanje uređaja</string>
<string name="menu_appearance_settings_summary">Teme, boje, atributi</string>
<string name="unlock">Otključaj</string>
<string name="menu_advanced_unlock_settings_summary">Biometrija, podatak za prijavu uređaja</string>
<string name="menu_device_unlock_settings_summary">Biometrija, podatak za prijavu uređaja</string>
<string name="info">Informacije</string>
<string name="master_key_settings_summary">Promjena, obnova</string>
<string name="education_validate_entry_title">Potvrdi unos</string>
@@ -701,4 +698,7 @@
<string name="recursive_number_entries_summary">Rekurzivno izračunava broj unosa u grupi</string>
<string name="hide_templates_title">Sakrij predloške</string>
<string name="hide_templates_summary">Predlošci se ne prikazuju</string>
<string name="error_otp_secret_length">Tajni ključ mora sadržati barem %1$d znakova.</string>
<string name="generate_keyfile">Generiraj datoteku ključeva</string>
<string name="warning_large_keyfile">Ne preporučuje se dodavanje velike datoteke ključeva, jer to može spriječiti otvaranje baze podataka.</string>
</resources>

View File

@@ -19,7 +19,7 @@
--><resources>
<string name="feedback">Visszajelzés</string>
<string name="homepage">Honlap</string>
<string name="about_description">A KeePass jelszókezelő androidos megvalósítása</string>
<string name="about_description">A KeePass jelszókezelő androidos megvalósítása.</string>
<string name="accept">Elfogadás</string>
<string name="add_entry">Bejegyzés hozzáadása</string>
<string name="add_group">Csoport hozzáadása</string>
@@ -198,7 +198,7 @@
<string name="lock">Zárolás</string>
<string name="lock_database_screen_off_title">Képernyőzár</string>
<string name="lock_database_screen_off_summary">Az adatbázis zárolása néhány másodperc után, ha a képernyő kikapcsol</string>
<string name="advanced_unlock">Eszközfeloldás</string>
<string name="device_unlock">Eszközfeloldás</string>
<string name="biometric_unlock_enable_title">Ujjlenyomat-alapú feloldás</string>
<string name="biometric_unlock_enable_summary">Lehetővé teszi, hogy leolvassa az ujjlenyomatát az adatbázis megnyitásához</string>
<string name="biometric_delete_all_key_title">Titkosítási kulcsok törlése</string>
@@ -245,8 +245,6 @@
<string name="keyboard_key_sound_title">Hang gombnyomáskor</string>
<string name="allow_no_password_title">Mesterkulcs elhagyásának engedélyezése</string>
<string name="allow_no_password_summary">A „Megnyitás” gomb engedélyezése, ha nincsenek hitelesítő adatok kiválasztva</string>
<string name="enable_read_only_title">Írásvédett</string>
<string name="enable_read_only_summary">Az adatbázis megnyitása alapértelmezetten írásvédett módban</string>
<string name="enable_education_screens_title">Oktatóképernyők</string>
<string name="enable_education_screens_summary">Elemek kiemelése, hogy megtudja hogyan működik az alkalmazás</string>
<string name="reset_education_screens_title">Oktatóképernyők visszaállítása</string>
@@ -287,7 +285,7 @@
<string name="html_text_ad_free">Számos más jelszókezelő alkalmazással ellentétben, ez egy &lt;strong&gt;reklámmentes&lt;/strong&gt;, &lt;strong&gt;copyleft licencelésű szabad szoftver&lt;/strong&gt;, amely nem gyűjt személyes adatokat a kiszolgálókon, bármelyik verziót is használja.</string>
<string name="html_text_buy_pro">A pro verzió megvásárlásával hozzáférést kap ehhez a &lt;strong&gt;vizuális stílushoz&lt;/strong&gt;, és segít a &lt;strong&gt;közösségi projektek megvalósulásában.&lt;/strong&gt;</string>
<string name="html_text_feature_generosity">Ez a &lt;strong&gt;vizuális stílus&lt;/strong&gt; az Ön nagylelkűségének köszönhetően érhető el.</string>
<string name="html_text_donation">Azzal, hogy &lt;strong&gt;hozzájárul&lt;/strong&gt; a projekthez <i>(pénzzel, kóddal, fordítással)</i>, segít abban, hogy a projekt tovább éljen és gyarapodjon, továbbá Ön jogosulttá válik a &lt;strong&gt;téma&lt;/strong&gt; feloldási eljárásra is.</string>
<string name="html_text_donation">Azzal, hogy &lt;strong&gt;hozzájárul&lt;/strong&gt; a projekthez &lt;i&gt;(pénzzel, kóddal, fordítással)&lt;/i&gt;, segít abban, hogy a projekt tovább éljen és gyarapodjon, továbbá Ön jogosulttá válik a &lt;strong&gt;téma&lt;/strong&gt;feloldásának lehetősége.</string>
<string name="html_text_dev_feature">Ez a funkció &lt;strong&gt;fejlesztés alatt áll&lt;/strong&gt;, és az Ön &lt;strong&gt;támogatására&lt;/strong&gt; van szükség, hogy hamarosan elérhető legyen.</string>
<string name="html_text_dev_feature_buy_pro">A &lt;strong&gt;pro&lt;/strong&gt; verzió megvásárlásával,</string>
<string name="html_text_dev_feature_contibute">A &lt;strong&gt;támogatással&lt;/strong&gt;</string>
@@ -382,7 +380,7 @@
<string name="max_history_items_title">Maximális szám</string>
<string name="database_data_compression_summary">Az adattömörítés csökkenti az adatbázis méretét</string>
<string name="database_data_compression_title">Adattömörítés</string>
<string name="advanced_unlock_explanation_summary">Eszközfeloldás használata az adatbázis könnyebb megnyitásához</string>
<string name="device_unlock_explanation_summary">Eszközfeloldás használata az adatbázis könnyebb megnyitásához</string>
<string name="clipboard_explanation_summary">A bejegyzésmezők másolása az eszköz vágólapjának használatával</string>
<string name="database_opened">Adatbázis megnyitva</string>
<string name="contains_duplicate_uuid_procedure">Megoldja a problémát azzal, hogy új UUID-t állít elő az ismétlődések számára\?</string>
@@ -412,7 +410,7 @@
<string name="biometric_auto_open_prompt_summary">Az eszközfeloldás automatikus kérése, ha az adatbázis úgy van beállítva, hogy használja</string>
<string name="biometric_auto_open_prompt_title">Automatikus megnyitási képernyő</string>
<string name="biometric">Ujjlenyomat</string>
<string name="menu_advanced_unlock_settings">Eszköz feloldása</string>
<string name="menu_device_unlock_settings">Eszköz feloldása</string>
<string name="content_description_keyboard_close_fields">Mezők bezárása</string>
<string name="content_description_update_from_list">Frissítés</string>
<string name="list_groups_show_number_entries_summary">A csoportban szereplő bejegyzések számának megjelenítése</string>
@@ -521,32 +519,31 @@
<string name="hint_icon_name">Ikon neve</string>
<string name="autofill_select_entry">Válasszon bejegyzést…</string>
<string name="warning_database_info_changed_options">Adatok egyesítése, majd a külső módosítások felülírása az adatbázis mentésével, vagy újratöltés a legfrissebb változtatásokkal.</string>
<string name="advanced_unlock_prompt_store_credential_title">Hivatkozás az eszköz feloldásához</string>
<string name="advanced_unlock_prompt_store_credential_message">Továbbra is meg kell jegyeznie a széf fő jelszavát, ha az eszköz feloldásfelismerését használja.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Adatbázis hitelesítő adatainak kinyerése az eszköz adatfeloldásával</string>
<string name="advanced_unlock_invalid_key">Az eszközfeloldási kulcs nem olvasható. Törölje, és ismételje meg a feloldásfelismerési folyamatot.</string>
<string name="advanced_unlock_not_recognized">Az eszközfeloldási ujjlenyomat nem ismerhető fel</string>
<string name="advanced_unlock_prompt_not_initialized">Az eszközfeloldási képernyő előkészítése sikertelen.</string>
<string name="device_unlock_prompt_store_credential_title">Hivatkozás az eszköz feloldásához</string>
<string name="device_unlock_prompt_store_credential_message">Továbbra is meg kell jegyeznie a széf fő jelszavát, ha az eszköz feloldásfelismerését használja.</string>
<string name="device_unlock_prompt_extract_credential_message">Adatbázis hitelesítő adatainak kinyerése az eszköz adatfeloldásával</string>
<string name="device_unlock_invalid_key">Az eszközfeloldási kulcs nem olvasható. Törölje, és ismételje meg a feloldásfelismerési folyamatot.</string>
<string name="device_unlock_not_recognized">Az eszközfeloldási ujjlenyomat nem ismerhető fel</string>
<string name="device_unlock_prompt_not_initialized">Az eszközfeloldási képernyő előkészítése sikertelen.</string>
<string name="properties">Tulajdonságok</string>
<string name="device_credential">Eszköz hitelesítő adatai</string>
<string name="temp_advanced_unlock_enable_summary">Ne tároljon semmilyen titkosított tartalmat az eszközfeloldás használatához</string>
<string name="temp_advanced_unlock_timeout_title">Eszközfeloldás lejárati ideje</string>
<string name="temp_device_unlock_enable_summary">Ne tároljon semmilyen titkosított tartalmat az eszközfeloldás használatához</string>
<string name="temp_device_unlock_timeout_title">Eszközfeloldás lejárati ideje</string>
<string name="warning_database_revoked">A fájl elérését visszavonta a fájlkezelő, zárja be az adatbázist és nyissa meg újra a helyéről.</string>
<string name="warning_exact_alarm">Nem engedélyezte az alkalmazásnak, hogy pontos riasztást használjon. Ezért az időzítőt használó funkciók nem a pontos időt fogják használni.</string>
<string name="advanced_unlock_prompt_extract_credential_title">Eszköz feloldásfelismerése</string>
<string name="credential_before_click_advanced_unlock_button">Írja be a jelszót, majd kattintson erre a gombra.</string>
<string name="temp_advanced_unlock_enable_title">Ideiglenes eszközfeloldás</string>
<string name="device_unlock_prompt_extract_credential_title">Eszköz feloldásfelismerése</string>
<string name="credential_before_click_device_unlock_button">Írja be a jelszót, majd kattintson erre a gombra.</string>
<string name="temp_device_unlock_enable_title">Ideiglenes eszközfeloldás</string>
<string name="permission">Engedély</string>
<string name="advanced_unlock_scanning_error">Eszközfeloldási hiba: %1$s</string>
<string name="content">Tartalom</string>
<string name="advanced_unlock_tap_delete">Koppintson az eszközfeloldási kulcsok törléséhez</string>
<string name="device_unlock_tap_delete">Koppintson az eszközfeloldási kulcsok törléséhez</string>
<string name="device_credential_unlock_enable_title">Eszköz hitelesítő adataival történő feloldás</string>
<string name="device_credential_unlock_enable_summary">Lehetővé teszi, hogy az eszköz hitelesítő adataival nyissa meg az adatbázist</string>
<string name="autofill_application_id_blocklist_title">Letiltott alkalmazások</string>
<string name="menu_merge_database">Adatok egyesítése</string>
<string name="autofill_close_database_title">Adatbázis bezárása</string>
<string name="temp_advanced_unlock_timeout_summary">Az eszközfeloldás használata ideje, mielőtt a tartalma törölve lesz</string>
<string name="advanced_unlock_timeout">Eszközfeloldás időtúllépése</string>
<string name="temp_device_unlock_timeout_summary">Az eszközfeloldás használata ideje, mielőtt a tartalma törölve lesz</string>
<string name="device_unlock_timeout">Eszközfeloldás időtúllépése</string>
<string name="templates_group_enable_title">Sablonok használata</string>
<string name="templates_group_enable_summary">Dinamikus sablonok használata a bejegyzés mezőinek kitöltéséhez</string>
<string name="templates_group_uuid_title">Sabloncsoport</string>
@@ -580,7 +577,7 @@
<string name="style_brightness_title">Téma fényereje</string>
<string name="show_uuid_summary">Megjeleníti a bejegyzéshez vagy csoporthoz tartozó UUID-t</string>
<string name="show_otp_token_title">OTP token megjelenítése</string>
<string name="advanced_unlock_delete_all_key_warning">Törli az összes, az eszközfeloldás-felismeréshez tartozó titkosítási kulcsot\?</string>
<string name="device_unlock_delete_all_key_warning">Törli az összes, az eszközfeloldás-felismeréshez tartozó titkosítási kulcsot\?</string>
<string name="keyboard_save_search_info_summary">A könnyebb jövőbeli használat érdekében próbálja menteni a megosztott információkat a kézi bejegyzéskiválasztásnál</string>
<string name="custom_fields">Egyéni mezők</string>
<string name="back_to_previous_keyboard">Vissza az előző billentyűzethez</string>
@@ -591,8 +588,8 @@
<string name="autofill_application_id_blocklist_summary">Tiltólista, amely megakadályozza az alkalmazások automatikus kitöltését</string>
<string name="autofill_web_domain_blocklist_title">Letiltott webes domainek</string>
<string name="autofill_ask_to_save_data_title">Adatok mentésének kérése</string>
<string name="education_advanced_unlock_title">Eszközadatbázis feloldása</string>
<string name="education_advanced_unlock_summary">A jelszó összekötése a leolvasott biometrikus adatokkal vagy eszköz-hitelesítőadatokkal, hogy gyorsan feloldhassa az adatbázist.</string>
<string name="education_device_unlock_title">Eszközadatbázis feloldása</string>
<string name="education_device_unlock_summary">A jelszó összekötése a leolvasott biometrikus adatokkal vagy eszköz-hitelesítőadatokkal, hogy gyorsan feloldhassa az adatbázist.</string>
<string name="show_otp_token_summary">Megjeleníti az OTP tokeneket a bejegyzések között</string>
<string name="education_add_attachment_title">Melléklet hozzáadása</string>
<string name="keyboard_previous_database_credentials_summary">Automatikus visszaváltás az előző billentyűzetre az adatbázis-hitelesítőadatok képernyőn</string>
@@ -657,7 +654,7 @@
<string name="wireless">Wi-Fi</string>
<string name="error_hardware_key_unsupported">A hardverkulcs nem támogatott.</string>
<string name="colorize_password_title">Jelszavak színezése</string>
<string name="menu_advanced_unlock_settings_summary">Biometrikus adatok, eszköz-hitelesítőadatok</string>
<string name="menu_device_unlock_settings_summary">Biometrikus adatok, eszköz-hitelesítőadatok</string>
<string name="error_XML_malformed">Hibásan formázott XML.</string>
<string name="remember_hardware_key_summary">Követi a használt hardverkulcsokat</string>
<string name="warning_database_already_opened">Egy adatbázis már nyitva van, előbb zárja be, hogy újat nyisson meg</string>
@@ -667,7 +664,7 @@
<string name="warning_database_notification_permission">Az értesítési engedély lehetővé teszi az adatbázis állapotának megjelenítését, és az egyszerű ikonnal történő zárolást.
\n
\nHa nem aktiválja az engedélyt, akkor a háttérben nyitott adatbázis nem lesz látható, ha egy másik alkalmazás van előtérben.</string>
<string name="advanced_unlock_keystore_warning">A funkció eltárolja a titkosított hitelesítőadatokat az eszköz biztonságos kulcstárában.
<string name="device_unlock_keystore_warning">A funkció eltárolja a titkosított hitelesítőadatokat az eszköz biztonságos kulcstárában.
\n
\nAz operációs rendszer natív API megvalósításától függően lehet, hogy nem lesz teljes értékű.
\n
@@ -708,4 +705,5 @@
<string name="hide_templates_summary">A sablonok nem jelennek meg</string>
<string name="generate_keyfile">Kulcsfájl előállítása</string>
<string name="hide_templates_title">Sablonok elrejtése</string>
<string name="error_otp_secret_length">A titkos kulcsnak legalább %1$d karakterből kell állnia.</string>
</resources>

View File

@@ -26,7 +26,7 @@
<string name="menu_security_settings">Pengaturan Keamanan</string>
<string name="menu_app_settings">Pengaturan Aplikasi</string>
<string name="menu_database_settings">Pengaturan Basis Data</string>
<string name="menu_advanced_unlock_settings">Membuka kunci perangkat</string>
<string name="menu_device_unlock_settings">Membuka kunci perangkat</string>
<string name="menu_form_filling_settings">Pengisian Formulir</string>
<string name="settings">Pengaturan</string>
<string name="copy_field">Salinan dari %1$s</string>
@@ -170,7 +170,7 @@
<string name="edit_entry">Rubah Entri</string>
<string name="add_entry">Tambahkan Entri</string>
<string name="accept">Terima</string>
<string name="about_description">Implementasi Android dari pengelola kata sandi KeePass</string>
<string name="about_description">Implementasi Android dari pengelola kata sandi KeePass.</string>
<string name="homepage">Beranda</string>
<string name="feedback">Umpan Balik</string>
<string name="contribution">Kontribusi</string>
@@ -237,7 +237,7 @@
<string name="compression">Kompresi</string>
<string name="other">Lainnya</string>
<string name="application_appearance">Tampilan</string>
<string name="advanced_unlock_prompt_store_credential_title">Tautan ke pembukaan kunci perangkat</string>
<string name="device_unlock_prompt_store_credential_title">Tautan ke pembukaan kunci perangkat</string>
<string name="keystore_not_accessible">Keystore tidak diinisialisasi dengan benar.</string>
<string name="biometric_security_update_required">Pembaruan keamanan biometrik diperlukan.</string>
<string name="configure_biometric">Tidak ada kredensial biometrik atau perangkat yang terdaftar.</string>
@@ -248,8 +248,8 @@
\n
\nBasis data Anda mungkin menjadi sangat besar dan mengurangi kinerja dengan unggahan ini.</string>
<string name="warning_empty_recycle_bin">Hapus permanen semua node dari keranjang sampah\?</string>
<string name="advanced_unlock_tap_delete">Ketuk untuk menghapus tombol pembuka kunci perangkat</string>
<string name="advanced_unlock">Buka kunci perangkat</string>
<string name="device_unlock_tap_delete">Ketuk untuk menghapus tombol pembuka kunci perangkat</string>
<string name="device_unlock">Buka kunci perangkat</string>
<string name="content">Konten</string>
<string name="lock_database_show_button_summary">Tampilkan tombol kunci di antarmuka pengguna</string>
<string name="lock_database_show_button_title">Tampilkan tombol kunci</string>
@@ -390,8 +390,8 @@
<string name="education_field_copy_title">Salin bidang</string>
<string name="education_setup_OTP_title">Atur OTP</string>
<string name="education_donation_title">Partisipasi</string>
<string name="advanced_unlock_prompt_extract_credential_title">Pengenalan pembuka kunci perangkat</string>
<string name="advanced_unlock_prompt_store_credential_message">Anda masih perlu mengingat kredensial utama vault Anda jika Anda menggunakan pengenalan kunci perangkat.</string>
<string name="device_unlock_prompt_extract_credential_title">Pengenalan pembuka kunci perangkat</string>
<string name="device_unlock_prompt_store_credential_message">Anda masih perlu mengingat kredensial utama vault Anda jika Anda menggunakan pengenalan kunci perangkat.</string>
<string name="warning_database_revoked">Akses ke berkas dicabut oleh pengelola berkas, tutup basis data dan buka kembali dari lokasi tempatnya.</string>
<string name="warning_database_info_changed_options">Gabungkan data, timpa perubahan dengan cara menyimpan basis data atau muat ulang dengan perubahan terbaru.</string>
<string name="warning_database_info_changed">Informasi yang tersimpan di berkas basis data Anda sudah diubah di luar aplikasi.</string>
@@ -414,13 +414,13 @@
<string name="device_credential_unlock_enable_title">Membuka kredensial perangkat</string>
<string name="biometric_unlock_enable_summary">Memperbolehkan Anda memindai biometrik Anda untuk membuka basis data</string>
<string name="biometric_unlock_enable_title">Membuka kunci biometrik</string>
<string name="advanced_unlock_explanation_summary">Gunakan buka kunci perangkat untuk membuka basis data dengan lebih mudah</string>
<string name="device_unlock_explanation_summary">Gunakan buka kunci perangkat untuk membuka basis data dengan lebih mudah</string>
<string name="unavailable">Tidak tersedia</string>
<string name="advanced_unlock_not_recognized">Tidak dapat mengenali cetakan buka kunci perangkat</string>
<string name="advanced_unlock_invalid_key">Tidak dapat membaca kunci pembuka perangkat. Harap hapus dan ulangi prosedur pengenalan buka kunci.</string>
<string name="advanced_unlock_prompt_extract_credential_message">Ekstrak kredensial basis data dengan pembuka kunci data perangkat</string>
<string name="device_unlock_not_recognized">Tidak dapat mengenali cetakan buka kunci perangkat</string>
<string name="device_unlock_invalid_key">Tidak dapat membaca kunci pembuka perangkat. Harap hapus dan ulangi prosedur pengenalan buka kunci.</string>
<string name="device_unlock_prompt_extract_credential_message">Ekstrak kredensial basis data dengan pembuka kunci data perangkat</string>
<string name="error_word_reserved">Kata ini telah dipakai dan tidak bisa digunakan.</string>
<string name="credential_before_click_advanced_unlock_button">Ketik kata sandi, lalu klik tombol ini.</string>
<string name="credential_before_click_device_unlock_button">Ketik kata sandi, lalu klik tombol ini.</string>
<string name="autofill_service_name">Isi formulir KeePassDX otomatis</string>
<string name="autofill_preference_title">Pengaturan isi otomatis</string>
<string name="set_autofill_service_title">Setel layanan isi otomatis secara default</string>
@@ -462,11 +462,11 @@
<string name="holder">Penyangga</string>
<string name="autofill_select_entry">Pilih entri…</string>
<string name="biometric_auto_open_prompt_summary">Secara otomatis meminta buka kunci perangkat jika basis data diatur menggunakan itu</string>
<string name="temp_advanced_unlock_enable_title">Buka kunci perangkat sementara</string>
<string name="temp_advanced_unlock_enable_summary">Jangan simpan konten terenkripsi apa pun untuk menggunakan buka kunci perangkat</string>
<string name="temp_advanced_unlock_timeout_summary">Durasi penggunaan buka kunci perangkat sebelum menghapus konten tersebut</string>
<string name="advanced_unlock_timeout">Batas waktu membuka kunci perangkat</string>
<string name="advanced_unlock_delete_all_key_warning">Hapus semua kunci enkripsi yang terkait pengenalan buka kunci perangkat\?</string>
<string name="temp_device_unlock_enable_title">Buka kunci perangkat sementara</string>
<string name="temp_device_unlock_enable_summary">Jangan simpan konten terenkripsi apa pun untuk menggunakan buka kunci perangkat</string>
<string name="temp_device_unlock_timeout_summary">Durasi penggunaan buka kunci perangkat sebelum menghapus konten tersebut</string>
<string name="device_unlock_timeout">Batas waktu membuka kunci perangkat</string>
<string name="device_unlock_delete_all_key_warning">Hapus semua kunci enkripsi yang terkait pengenalan buka kunci perangkat\?</string>
<string name="templates_group_enable_title">Penggunaan templat</string>
<string name="biometric_delete_all_key_summary">Hapus semua kunci enkripsi yang terkait pengenalan buka kunci perangkat</string>
<string name="max_history_items_summary">Batasi jumlah item riwayat per entri</string>
@@ -480,7 +480,7 @@
<string name="max_history_size_summary">Batasi ukuran riwayat per entri</string>
<string name="max_history_size_title">Ukuran maksimum</string>
<string name="biometric_delete_all_key_title">Hapus kunci enkripsi</string>
<string name="temp_advanced_unlock_timeout_title">Kedaluwarsa pembuka kunci perangkat</string>
<string name="temp_device_unlock_timeout_title">Kedaluwarsa pembuka kunci perangkat</string>
<string name="templates_group_enable_summary">Gunakan templat dinamis untuk mengisi bidang entri</string>
<string name="education_read_only_summary">Ubah mode pembuka untuk sesi.
\n
@@ -515,7 +515,7 @@
<string name="education_donation_summary">Bantu meningkatkan stabilitas, keamanan, dan menambahkan lebih banyak fitur.</string>
<string name="html_text_ad_free">Tidak seperti banyak aplikasi pengelola kata sandi, ini &lt;strong&gt;bebas iklan&lt;/strong&gt;, &lt;strong&gt;perangkat lunak libre copyleft&lt;/strong&gt;, dan tidak mengumpulkan data pribadi di peladennya, tidak peduli versi apa yang Anda gunakan.</string>
<string name="html_text_feature_generosity">&lt;strong&gt;Gaya visual&lt;/strong&gt; ini tersedia berkat kemurahan hati Anda.</string>
<string name="html_text_donation">Dengan &lt;strong&gt;berkontribusi&lt;strong&gt; kepada proyek &lt;i&gt;(dalam bentuk uang, kode, penerjemahan)&lt;i&gt;, Anda akan membantu proyek tersebut supaya terus hidup dan berkembang, dan Anda juga akan memenuhi syarat untuk prosedur pembukaan kunci &lt;strong&gt;tema&lt;strong&gt;.</string>
<string name="html_text_donation">Dengan &lt;strong&gt;berkontribusi&lt;/strong&gt; kepada proyek &lt;i&gt;(dalam bentuk uang, kode, penerjemahan)&lt;/i&gt;, Anda akan membantu proyek tersebut supaya terus hidup dan berkembang, dan Anda juga akan memenuhi syarat untuk prosedur pembukaan kunci &lt;strong&gt;tema&lt;/strong&gt;.</string>
<string name="html_text_dev_feature">Fitur ini &lt;strong&gt;sedang dalam pengembangan&lt;/strong&gt; dan memerlukan &lt;strong&gt;kontribusi&lt;/strong&gt; Anda untuk bisa tersedia segera.</string>
<string name="show_otp_token_title">Tampilkan Token OTP</string>
<string name="text_appearance">Teks</string>
@@ -554,7 +554,6 @@
<string name="allow_no_password_title">Izinkan tidak ada kunci utama</string>
<string name="allow_no_password_summary">Memungkinkan mengetuk tombol \"Buka\" jika tidak ada kredensial yang dipilih</string>
<string name="delete_entered_password_summary">Menghapus kata sandi yang dimasukkan setelah upaya koneksi ke basis data</string>
<string name="enable_read_only_summary">Buka basis data baca-saja secara baku</string>
<string name="enable_keep_screen_on_title">Biarkan layar nyala</string>
<string name="enable_education_screens_summary">Sorot elemen untuk mempelajari cara kerja aplikasi</string>
<string name="education_create_database_summary">Buat file pengelola kata sandi pertama Anda.</string>
@@ -562,8 +561,8 @@
\n
\nGrup (~folder) mengatur entri dalam basis data Anda.</string>
<string name="education_search_summary">Masukkan judul, nama pengguna atau konten bidang lain untuk mengambil kata sandi Anda.</string>
<string name="education_advanced_unlock_title">Pembukaan kunci basis data perangkat</string>
<string name="education_advanced_unlock_summary">Tautkan kata sandi Anda ke kredensial biometrik atau perangkat yang dipindai untuk membuka kunci basis data Anda dengan cepat.</string>
<string name="education_device_unlock_title">Pembukaan kunci basis data perangkat</string>
<string name="education_device_unlock_summary">Tautkan kata sandi Anda ke kredensial biometrik atau perangkat yang dipindai untuk membuka kunci basis data Anda dengan cepat.</string>
<string name="education_entry_new_field_title">Tambahkan bidang kustom</string>
<string name="education_entry_new_field_summary">Daftarkan bidang tambahan, tambahkan nilai, dan lindungi secara opsional.</string>
<string name="education_setup_OTP_summary">Siapkan pengelola kata sandi satu kali (HOTP / TOTP) untuk menghasilkan token yang diminta untuk otentikasi dua faktor (2FA).</string>
@@ -582,8 +581,7 @@
<string name="upper_case">HURUF BESAR</string>
<string name="title_case">Huruf Judul</string>
<string name="character_count">Jumlah karakter: %1$d</string>
<string name="advanced_unlock_scanning_error">Terjadi kesalahan buka kunci perangkat: %1$s</string>
<string name="advanced_unlock_prompt_not_initialized">Tidak dapat menginisialisasi perintah buka kunci perangkat.</string>
<string name="device_unlock_prompt_not_initialized">Tidak dapat menginisialisasi perintah buka kunci perangkat.</string>
<string name="monospace_font_fields_enable_title">Bidang tipe huruf</string>
<string name="keyboard_save_search_info_title">Simpan info terbagi</string>
<string name="keyboard_previous_fill_in_title">Ganti kembali</string>
@@ -612,14 +610,13 @@
<string name="enable_auto_save_database_summary">Simpan basis data setelah setiap tindakan penting (dalam mode \"Bisa dimodifikasi\")</string>
<string name="custom_data">Data kustom</string>
<string name="warning_database_already_opened">Sebuah basis data sudah dibuka, tutup terlebih dahulu untuk membuka yang baru</string>
<string name="advanced_unlock_keystore_warning">Fitur ini akan menyimpan data kredensial terenkripsi di KeyStore perangkat Anda yang aman.
<string name="device_unlock_keystore_warning">Fitur ini akan menyimpan data kredensial terenkripsi di KeyStore perangkat Anda yang aman.
\n
\nBergantung pada implementasi API asli dari sistem operasi, mungkin tidak berfungsi penuh.
\n
\nPeriksa kompatibilitas dan keamanan KeyStore dengan produsen perangkat Anda dan pembuat ROM yang Anda gunakan.</string>
<string name="education_read_only_title">Lindungi basis data Anda dari penulisan</string>
<string name="keyboard_save_search_info_summary">Coba simpan informasi terbagi ketika membuat sebuah pilihan entri manual untuk penggunaan mudah di waktu mendatang</string>
<string name="enable_read_only_title">Terlindungi-tulis</string>
<string name="enable_keep_screen_on_summary">Jaga layar tetap menyala saat melihat atau menyunting sebuah entri</string>
<string name="content_description_hardware_key_checkbox">Kotak centang kunci perangkat keras</string>
<string name="waiting_challenge_request">Menunggu untuk permintaan tantangan…</string>
@@ -649,7 +646,7 @@
<string name="info">Info</string>
<string name="menu_app_settings_summary">Cari, kunci, riwayat, properti</string>
<string name="menu_form_filling_settings_summary">Papan ketik, isi otomatis, papan klip</string>
<string name="menu_advanced_unlock_settings_summary">Biometri, kredensial perangkat</string>
<string name="menu_device_unlock_settings_summary">Biometri, kredensial perangkat</string>
<string name="menu_database_settings_summary">Metadata, tempat sampah, templat, riwayat</string>
<string name="menu_security_settings_summary">Enkripsi, fungsi derivasi kunci</string>
<string name="master_key_settings_summary">Perubahan, pembaruan</string>
@@ -686,4 +683,5 @@
<string name="recursive_number_entries_title">Jumlah entri rekursif</string>
<string name="warning_large_keyfile">Tidak disarankan menambahkan berkas kunci yang besar, ini dapat mencegah pembukaan basis data.</string>
<string name="hide_templates_title">Sembunyikan templat</string>
<string name="error_otp_secret_length">Kunci rahasia minimal harus %1$d karakter.</string>
</resources>

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