changeset 7209:c1227f883177

Implement password hash testing using new roundup-admin perftest. Add new anypy/time_.py to provide a suitable definition for perf_counter for python2 or 3. Also update examples in upgrading.txt, man page, new translatable strings in locale.
author John Rouillard <rouilj@ieee.org>
date Fri, 03 Mar 2023 17:37:44 -0500
parents c9fa0ffb0f94
children 7147a4c833e9
files doc/upgrading.txt locale/de.po locale/en.po locale/es.po locale/fr.po locale/hu.po locale/it.po locale/ja.po locale/lt.po locale/nb.po locale/roundup.pot locale/ru.po locale/zh_CN.po locale/zh_TW.po roundup/admin.py roundup/anypy/time_.py share/man/man1/roundup-admin.1
diffstat 17 files changed, 871 insertions(+), 259 deletions(-) [+]
line wrap: on
line diff
--- a/doc/upgrading.txt	Fri Mar 03 14:31:29 2023 -0500
+++ b/doc/upgrading.txt	Fri Mar 03 17:37:44 2023 -0500
@@ -204,21 +204,41 @@
 set to ``yes``, passwords will be automatically re-hashed using
 the new higher value when the user logs in.
 
-This re-hashing might result in a slight delay (under 1
-second). If you see a large slowdown, check to see if you can
-execute::
+Increasing the number of rounds will slow down re-hashing. That's the
+whole point.  Sadly it will also slow down logins.  Usually the hash
+takes under 1 second, but if you are using a slow chip (e.g. an ARM V6
+at 700 bogo mips) it can take 30 seconds to compute the 2000000
+rounds. The slowdown is linear. So what takes .001 seconds at 10000
+rounds will take: ``2000000/10000 * .001 = 200 * .001`` seconds or 0.2
+seconds.
+
+You can see how long it will take by using the new ``roundup-admin``
+``perftest`` command. After you have finished migrating your database,
+run::
+
+   roundup-admin -i <tracker_home> perftest password rounds=10000
+
+and then::
+
+   roundup-admin -i <tracker_home> perftest password rounds=2,000,000
+
+so see the difference. Output from this command looks like::
+
+   Hash time: 0.203151849s scheme: PBKDF2 rounds: 10000
+
+If your testing reports a hash time in the 0.5 second range for 10000
+rounds, there may be another issue. See if executing::
 
   python3 -c 'from hashlib import pbkdf2_hmac'
 
-without an error.
-
-If you get an ImportError, you are using Roundup's fallback
-PBKDF2 implementation. It is written in Python and is much slower
-than the library version.  As a result re-encrypting the password
-(and logging in which requires calculating the encrypted
-password) will be very slow.
-
-You should find out how to make this succeed. You may need to
+produces an error.
+
+If you get an ImportError, you are using Roundup's fallback PBKDF2
+implementation. It is much slower than the library version.  As a
+result re-encrypting the password (and logging in, which requires
+calculating the encrypted password) will be very slow.
+
+You should find out how to make the import succeed. You may need to
 install an OS vendor package or some other library.
 
 .. _recommended setting of 1,300,000: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2
--- a/locale/de.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/de.po	Fri Mar 03 17:37:44 2023 -0500
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2016-04-11 09:13+0200\n"
 "Last-Translator: Tobias Herp <tobias.herp@gmx.de>\n"
 "Language-Team: German Translators <roundup-devel@lists.sourceforge.net>\n"
@@ -1253,41 +1253,78 @@
 "        "
 
 #: ../roundup/admin.py:1742
-msgid "Tracker updated"
-msgstr "Tracker aktualisiert"
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, fuzzy, python-format
+msgid "No migration action required. At schema version %s."
 msgstr "Keine Migration notwendig"
 
-#: ../roundup/admin.py:1771
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr "Der Befehl \"%(command)s\" existiert nicht (siehe \"help commands\")"
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr "Zur Abkürzung \"%(command)s\" passen mehrere Befehle: %(list)s"
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr "Tracker-Verzeichnis: "
 
 # ../roundup/admin.py:1263 :1269 :1289
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr "Fehler: %(message)s"
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr "Fehler: Die Tracker-Instanz konnte nicht geöffnet werden: %(message)s"
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
@@ -1296,15 +1333,15 @@
 "Roundup %s ist bereit.\n"
 "Schreiben Sie \"help\", um zur Hilfe zu gelangen."
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr "Bemerkung: Befehlsverlauf/-bearbeitung möglicherweise nicht verfügbar"
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr "beenden..."
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr "Es gibt noch ungespeicherte Änderungen. Änderungen speichern (y/N)?"
 
@@ -5663,6 +5700,9 @@
 msgid "Password"
 msgstr "Passwort"
 
+#~ msgid "Tracker updated"
+#~ msgstr "Tracker aktualisiert"
+
 #~ msgid "roundup> "
 #~ msgstr "roundup> "
 
--- a/locale/en.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/en.po	Fri Mar 03 17:37:44 2023 -0500
@@ -11,7 +11,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2004-11-20 13:47+0200\n"
 "Last-Translator: Not applicable\n"
 "Language-Team: English\n"
@@ -846,55 +846,92 @@
 msgstr ""
 
 #: ../roundup/admin.py:1742
-msgid "Tracker updated"
-msgstr ""
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
-msgstr ""
-
-#: ../roundup/admin.py:1771
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, python-format
+msgid "No migration action required. At schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr ""
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr ""
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr ""
 
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr ""
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr ""
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
 "Type \"help\" for help."
 msgstr ""
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr ""
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr ""
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr ""
 
--- a/locale/es.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/es.po	Fri Mar 03 17:37:44 2023 -0500
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2013-10-31 10:45+0100\n"
 "Last-Translator: Ramiro Morales <rm0@gmx.net>\n"
 "Language-Team: Spanish Translators <roundup-devel@lists.sourceforge.net>\n"
@@ -1272,44 +1272,80 @@
 msgstr ""
 
 #: ../roundup/admin.py:1742
-#, fuzzy
-msgid "Tracker updated"
-msgstr "Directorio base del tracker"
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
-msgstr ""
-
-#: ../roundup/admin.py:1771
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, python-format
+msgid "No migration action required. At schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr ""
 "Comando desconocido \"%(command)s\" (tipee \"help commands\" para obtener "
 "una lista)"
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr "Coinciden mas de un comando \"%(command)s\": %(list)s"
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr "Ingrese directorio base del tracker: "
 
 # ../roundup/admin.py:1296 :1302 :1322
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr "Error: %(message)s"
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr "Error: No se pudo abrir el tracker: %(message)s"
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
@@ -1318,15 +1354,15 @@
 "Roundup %s listo para comandos.\n"
 "Tipee \"help\" para ayuda."
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr "Nota: historia y edicin de comandos no disponible"
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr "salir..."
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr "Hay cambios sin guardar. Debo guardar los mismos (y/N)? "
 
@@ -5707,6 +5743,10 @@
 msgid "Password"
 msgstr "Contrasea para Login"
 
+#, fuzzy
+#~ msgid "Tracker updated"
+#~ msgstr "Directorio base del tracker"
+
 #~ msgid "roundup> "
 #~ msgstr "roundup> "
 
--- a/locale/fr.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/fr.po	Fri Mar 03 17:37:44 2023 -0500
@@ -10,7 +10,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2013-10-31 12:19+0100\n"
 "Last-Translator: Stephane Raimbault <stephane.raimbault@gmail.com>\n"
 "Language-Team: GNOME French Team <gnomefr@traduc.org>\n"
@@ -1278,43 +1278,79 @@
 msgstr ""
 
 #: ../roundup/admin.py:1742
-#, fuzzy
-msgid "Tracker updated"
-msgstr "Accueil de Tracker"
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
-msgstr ""
-
-#: ../roundup/admin.py:1771
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, python-format
+msgid "No migration action required. At schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr "Commande inconnue %(command)s (help commands pour la liste)"
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr "Plusieurs commandes correspondent  %(command)s: %(list)s"
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr "Saisissez le rpertoire racine du pisteur: "
 
 # ../roundup/admin.py:1332 :1338 :1358
 # ../roundup/admin.py:1335:1341:1361
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr "Erreur: %(message)s"
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr "Erreur: impossible d'ouvrir le pisteur, %(message)s"
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
@@ -1323,15 +1359,15 @@
 "Roundup %s est prt pour la saisie.\n"
 "Saisissez help pour l'aide."
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr "Note: l'historique et l'dition des commandes n'est pas disponible"
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr "sortie..."
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr "Des changements n'ont pas t enregistrs, les valider (y/N)?"
 
@@ -5739,6 +5775,10 @@
 msgid "Password"
 msgstr "Mot de passe"
 
+#, fuzzy
+#~ msgid "Tracker updated"
+#~ msgstr "Accueil de Tracker"
+
 #~ msgid "roundup> "
 #~ msgstr "roundup> "
 
--- a/locale/hu.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/hu.po	Fri Mar 03 17:37:44 2023 -0500
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2013-10-31 12:19+0100\n"
 "Last-Translator: kilo aka Gabor Kmetyko <kg_kilo@freemail.hu>\n"
 "Language-Team: Hungarian\n"
@@ -949,45 +949,81 @@
 msgstr ""
 
 #: ../roundup/admin.py:1742
-#, fuzzy
-msgid "Tracker updated"
-msgstr "Hibakövető"
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
-msgstr ""
-
-#: ../roundup/admin.py:1771
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, python-format
+msgid "No migration action required. At schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr ""
 "\"%(command)s\": ismeretlen parancs (\"help commands\" parancsok "
 "listázásához)"
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr ""
 "Több parancs is illeszkedik a megadott \"%(command)s\" parancsra: %(list)s"
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr "Adja meg a hibakövető könyvtárát: "
 
 # ../roundup/admin.py:1335 :1341 :1361
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr "Hiba: %(message)s"
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr "Hiba: Hibakövető megnyitása sikertelen: %(message)s"
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
@@ -996,15 +1032,15 @@
 "A Roundup %s fogadókész.\n"
 "Segítségért gépeljen \"help\"-et."
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr "Megjegyzés: a parancsok története és szerkesztése nem elérhető"
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr "kilépés..."
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr "Vannak nem mentett változtatások. Elmenti őket (y/N)? "
 
@@ -5219,6 +5255,10 @@
 msgid "Password"
 msgstr "Bejelentkezési jelszó"
 
+#, fuzzy
+#~ msgid "Tracker updated"
+#~ msgstr "Hibakövető"
+
 #~ msgid "roundup> "
 #~ msgstr "roundup> "
 
--- a/locale/it.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/it.po	Fri Mar 03 17:37:44 2023 -0500
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2013-10-31 12:20+0100\n"
 "Last-Translator: Marco Ghidinelli <marco.ghidinelli@ing.unibs.it>\n"
 "Language-Team: italian <it@li.org>\n"
@@ -865,56 +865,93 @@
 msgstr ""
 
 #: ../roundup/admin.py:1742
-msgid "Tracker updated"
-msgstr ""
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
-msgstr ""
-
-#: ../roundup/admin.py:1771
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, python-format
+msgid "No migration action required. At schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr ""
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr ""
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr ""
 
 # ../roundup/admin.py:1371:1377 :1397
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr ""
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr ""
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
 "Type \"help\" for help."
 msgstr ""
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr ""
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr ""
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr ""
 
--- a/locale/ja.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/ja.po	Fri Mar 03 17:37:44 2023 -0500
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2013-10-31 12:20+0100\n"
 "Last-Translator: Yasushi Iwata <iwata@know-net.co.jp>\n"
 "Language-Team: Yasushi Iwata <iwata@know-net.co.jp>\n"
@@ -843,55 +843,92 @@
 msgstr ""
 
 #: ../roundup/admin.py:1742
-msgid "Tracker updated"
-msgstr ""
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
-msgstr ""
-
-#: ../roundup/admin.py:1771
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, python-format
+msgid "No migration action required. At schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr ""
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr ""
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr ""
 
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr ""
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr ""
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
 "Type \"help\" for help."
 msgstr ""
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr ""
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr ""
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr ""
 
--- a/locale/lt.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/lt.po	Fri Mar 03 17:37:44 2023 -0500
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2013-10-31 12:21+0100\n"
 "Last-Translator: Nerijus Baliunas <nerijus@users.sourceforge.net>\n"
 "Language-Team: \n"
@@ -1230,44 +1230,80 @@
 msgstr ""
 
 #: ../roundup/admin.py:1742
-#, fuzzy
-msgid "Tracker updated"
-msgstr "Tracker'io namų direktorija"
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
-msgstr ""
-
-#: ../roundup/admin.py:1771
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, python-format
+msgid "No migration action required. At schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr ""
 "Nežinoma komanda \"%(command)s\" (įveskite \"help commands\" komandų\n"
 "sąrašui gauti)"
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr "Kelios komandos atitinka \"%(command)s\": %(list)s"
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr "Įveskite tracker'io namų direktoriją: "
 
 # ../roundup/admin.py:1312 :1318 :1338
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr "Klaida: %(message)s"
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr "Klaida: Negaliu atidaryti tracker'io: %(message)s"
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
@@ -1276,15 +1312,15 @@
 "Roundup %s pasiruošęs priimti duomenis.\n"
 "Norėdami iškviesti pagalbą įveskite \"help\"."
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr "Pastaba: komandų archyvas ir redagavimas neprieinami"
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr "išeiti..."
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr "Yra neišsaugotų pakeitimų. Išsaugoti juos (y/N)? "
 
@@ -5614,6 +5650,10 @@
 msgid "Password"
 msgstr "Prisijungimo slaptažodis"
 
+#, fuzzy
+#~ msgid "Tracker updated"
+#~ msgstr "Tracker'io namų direktorija"
+
 #~ msgid "roundup> "
 #~ msgstr "roundup> "
 
--- a/locale/nb.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/nb.po	Fri Mar 03 17:37:44 2023 -0500
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2013-10-31 12:21+0100\n"
 "Last-Translator: Christian Aastorp <christian.aastorp@gmail.com>\n"
 "Language-Team: Norwegian Bokmal <LL@li.org>\n"
@@ -1230,40 +1230,77 @@
 "        "
 
 #: ../roundup/admin.py:1742
-msgid "Tracker updated"
-msgstr "Sporer oppdatert"
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, fuzzy, python-format
+msgid "No migration action required. At schema version %s."
 msgstr "Ingen migrasjon krevet"
 
-#: ../roundup/admin.py:1771
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr "Ukjent kommando \"%(command)s\" (\"help commands\" for liste)"
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr "Multiple kommandoer  matcher \"%(command)s\": %(list)s"
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr "Oppgi sporers plassering:"
 
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr "Feil: %(message)s"
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr "Feil: Kan ikke åpne sporer: %(message)s"
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
@@ -1272,15 +1309,15 @@
 "Roundup %s er klar til bruk.\n"
 "Skriv  \"help\" for hjelp."
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr "Merk: kommandohistorikk og redigering utilgjengelig"
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr "exit..."
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr "Det er ikkelagrede endringer. Lagre dem (y/N)? "
 
@@ -5592,6 +5629,9 @@
 msgid "Password"
 msgstr "Login passord"
 
+#~ msgid "Tracker updated"
+#~ msgstr "Sporer oppdatert"
+
 #~ msgid "roundup> "
 #~ msgstr "roundup> "
 
--- a/locale/roundup.pot	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/roundup.pot	Fri Mar 03 17:37:44 2023 -0500
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.2.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -839,55 +839,92 @@
 msgstr ""
 
 #: ../roundup/admin.py:1742
-msgid "Tracker updated"
-msgstr ""
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
-msgstr ""
-
-#: ../roundup/admin.py:1771
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, python-format
+msgid "No migration action required. At schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr ""
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr ""
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr ""
 
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801 :1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877 :1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr ""
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr ""
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
 "Type \"help\" for help."
 msgstr ""
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr ""
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr ""
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr ""
 
--- a/locale/ru.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/ru.po	Fri Mar 03 17:37:44 2023 -0500
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2013-10-31 12:21+0100\n"
 "Last-Translator: alexander smishlajev <alex@tycobka.lv>\n"
 "Language-Team: Russian\n"
@@ -1245,42 +1245,78 @@
 msgstr ""
 
 #: ../roundup/admin.py:1742
-#, fuzzy
-msgid "Tracker updated"
-msgstr "  "
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
-msgstr ""
-
-#: ../roundup/admin.py:1771
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, python-format
+msgid "No migration action required. At schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr ""
 " \"%(command)s\" . (\"help commands\"   )"
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr "\"%(command)s\"   : %(list)s"
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr "  : "
 
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr ": %(message)s"
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr ":   : %(message)s"
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
@@ -1289,15 +1325,15 @@
 "Roundup %s   .\n"
 " \"help\"  ."
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr ":     "
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr "   ..."
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr ",   .     (y/N)? "
 
@@ -5647,6 +5683,10 @@
 msgstr ""
 
 #, fuzzy
+#~ msgid "Tracker updated"
+#~ msgstr "  "
+
+#, fuzzy
 #~ msgid ""
 #~ "Usage: %(program)s [-v] [-c class] [[-C class] -S field=value]* [instance "
 #~ "home] [mail source [specification]]\n"
--- a/locale/zh_CN.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/zh_CN.po	Fri Mar 03 17:37:44 2023 -0500
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2013-10-31 12:22+0100\n"
 "Last-Translator: Cheer Xiao <xiaqqaix@gmail.com>\n"
 "Language-Team: Chinese Simplified <limodou@gmail.com>\n"
@@ -1160,41 +1160,78 @@
 msgstr ""
 
 #: ../roundup/admin.py:1742
-msgid "Tracker updated"
-msgstr "Tracker 已经更新"
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, fuzzy, python-format
+msgid "No migration action required. At schema version %s."
 msgstr "不必执行迁移"
 
-#: ../roundup/admin.py:1771
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr "未知命令 \"%(command)s\" (\"help commands\" 查看命令列表)"
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr "多命令匹配 \"%(command)s\": %(list)s"
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr "输入tracker起始目录:"
 
 # ../roundup/admin.py:1279 :1285 :1305
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr "错误:%(message)s"
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr "错误:不能打开tracker:%(message)s"
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
@@ -1203,15 +1240,15 @@
 "Roundup %s 输入就绪。\n"
 "敲入 \"help\" 获得帮助。"
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr "注意:命令历史和编辑无效"
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr "退出..."
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr "存在未被保存的改动。提交吗(y/N)?"
 
@@ -5359,6 +5396,9 @@
 msgid "Password"
 msgstr "登录密码"
 
+#~ msgid "Tracker updated"
+#~ msgstr "Tracker 已经更新"
+
 #~ msgid "roundup> "
 #~ msgstr "roundup>"
 
--- a/locale/zh_TW.po	Fri Mar 03 14:31:29 2023 -0500
+++ b/locale/zh_TW.po	Fri Mar 03 17:37:44 2023 -0500
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: Roundup 2.3.0\n"
 "Report-Msgid-Bugs-To: roundup-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2023-03-01 12:54-0500\n"
+"POT-Creation-Date: 2023-03-03 17:28-0500\n"
 "PO-Revision-Date: 2013-10-31 12:23+0100\n"
 "Last-Translator: Fred Lin <gasolin@gmail>\n"
 "Language-Team: Chinese Traditional <gasolin@gmail.com>\n"
@@ -1158,42 +1158,78 @@
 msgstr ""
 
 #: ../roundup/admin.py:1742
-#, fuzzy
-msgid "Tracker updated"
-msgstr "Tracker根目錄"
-
-#: ../roundup/admin.py:1745
-msgid "No migration action required"
-msgstr ""
-
-#: ../roundup/admin.py:1771
+#, python-format
+msgid "Tracker updated to schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1746
+#, python-format
+msgid "No migration action required. At schema version %s."
+msgstr ""
+
+#: ../roundup/admin.py:1751
+msgid ""
+"Usage: perftest [mode] [arguments]*\n"
+"\n"
+"        Time operations in Roundup. Supported arguments:\n"
+"\n"
+"            [password] [rounds=<integer>] [scheme=<scheme>]\n"
+"\n"
+"        'password' is the default mode.  The tracker's config.ini\n"
+"        setting for 'password_pbkdf2_default_rounds' is the default\n"
+"        value for 'rounds'. On the command line, 'rounds' can include\n"
+"        thousands separator of ',' or '.'.  'scheme' is the default\n"
+"        coded into Roundup. List supported schemes by using 'scheme='.\n"
+"\n"
+"        "
+msgstr ""
+
+#: ../roundup/admin.py:1785
+msgid "Invalid 'rounds'. Must be larger than 999."
+msgstr ""
+
+#: ../roundup/admin.py:1789
+#, python-format
+msgid "Invalid 'rounds'. It must be an integer not: %s"
+msgstr ""
+
+#: ../roundup/admin.py:1816
+msgid "scheme does not support rounds."
+msgstr ""
+
+#: ../roundup/admin.py:1819
+#, python-format
+msgid "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, rounds: %(rounds)s"
+msgstr ""
+
+#: ../roundup/admin.py:1847
 #, python-format
 msgid "Unknown command \"%(command)s\" (\"help commands\" for a list)"
 msgstr "未知命令 \"%(command)s\" (\"help commands\" 查看命令列表)"
 
-#: ../roundup/admin.py:1777
+#: ../roundup/admin.py:1853
 #, python-format
 msgid "Multiple commands match \"%(command)s\": %(list)s"
 msgstr "多命令匹配 \"%(command)s\": %(list)s"
 
-#: ../roundup/admin.py:1786
+#: ../roundup/admin.py:1862
 msgid "Enter tracker home: "
 msgstr "輸入tracker起始目錄:"
 
 # ../roundup/admin.py:1279 :1285 :1305
-#: ../roundup/admin.py:1795 ../roundup/admin.py:1801 ../roundup/admin.py:1838
-#: ../roundup/admin.py:1795:1801:1838
+#: ../roundup/admin.py:1871 ../roundup/admin.py:1877 ../roundup/admin.py:1914
+#: ../roundup/admin.py:1871:1877:1914
 #, python-format
 msgid "Error: %(message)s"
 msgstr "錯誤:%(message)s"
 
-#: ../roundup/admin.py:1811 ../roundup/admin.py:1815
-#: ../roundup/admin.py:1811:1815
+#: ../roundup/admin.py:1887 ../roundup/admin.py:1891
+#: ../roundup/admin.py:1887:1891
 #, python-format
 msgid "Error: Couldn't open tracker: %(message)s"
 msgstr "錯誤:不能打開tracker:%(message)s"
 
-#: ../roundup/admin.py:1851
+#: ../roundup/admin.py:1927
 #, python-format
 msgid ""
 "Roundup %s ready for input.\n"
@@ -1202,15 +1238,15 @@
 "Roundup %s 輸入就緒。\n"
 "敲入 \"help\" 獲得說明。"
 
-#: ../roundup/admin.py:1856
+#: ../roundup/admin.py:1932
 msgid "Note: command history and editing not available"
 msgstr "注意:命令歷史和編輯無效"
 
-#: ../roundup/admin.py:1862
+#: ../roundup/admin.py:1938
 msgid "exit..."
 msgstr "退出..."
 
-#: ../roundup/admin.py:1875
+#: ../roundup/admin.py:1951
 msgid "There are unsaved changes. Commit them (y/N)? "
 msgstr "存在未被保存的改動。提交嗎(y/N)?"
 
@@ -5373,6 +5409,10 @@
 msgstr "登錄口令"
 
 #, fuzzy
+#~ msgid "Tracker updated"
+#~ msgstr "Tracker根目錄"
+
+#, fuzzy
 #~ msgid ""
 #~ "Usage: %(program)s [-v] [-c class] [[-C class] -S field=value]* [instance "
 #~ "home] [mail source [specification]]\n"
--- a/roundup/admin.py	Fri Mar 03 14:31:29 2023 -0500
+++ b/roundup/admin.py	Fri Mar 03 17:37:44 2023 -0500
@@ -1747,6 +1747,80 @@
             self.db.database_schema['version'])
         return 0
 
+    def do_perftest(self, args):
+        ''"""Usage: perftest [mode] [arguments]*
+
+        Time operations in Roundup. Supported arguments:
+
+            [password] [rounds=<integer>] [scheme=<scheme>]
+
+        'password' is the default mode.  The tracker's config.ini
+        setting for 'password_pbkdf2_default_rounds' is the default
+        value for 'rounds'. On the command line, 'rounds' can include
+        thousands separator of ',' or '.'.  'scheme' is the default
+        coded into Roundup. List supported schemes by using 'scheme='.
+
+        """
+        from roundup.anypy.time_ import perf_counter
+
+        props = { "rounds": self.db.config.PASSWORD_PBKDF2_DEFAULT_ROUNDS,
+                  "scheme": password.Password.known_schemes[0]
+        }
+
+        print_supported_schemes = lambda: print(
+                    "Supported schemes (default is first, case "
+                    "sensitive):\n   %s." %
+                     ", ".join(password.Password.known_schemes))
+
+        if (args[0].find("=") != -1):
+            args.insert(0, 'password')
+
+        props.update(self.props_from_args(args[1:]))
+
+        if args[0] == "password":
+            try:
+                # convert 10,000,000 or 10.000.000 to 10000000
+                r = int(re.sub('[,.]','',props['rounds']))
+                if r < 1000:
+                    print(_("Invalid 'rounds'. Must be larger than 999."))
+                    return
+                props['rounds'] = r
+            except (TypeError, ValueError):
+                print(_("Invalid 'rounds'. It must be an integer not: %s") %
+                      props['rounds'])
+                return
+            if props['scheme'] == None:
+                print_supported_schemes()
+                return
+
+            self.db.config.PASSWORD_PBKDF2_DEFAULT_ROUNDS = props['rounds']
+
+            try:
+                tic = perf_counter()
+                pw_hash = password.encodePassword(
+                    "this is a long password to hash",
+                    props['scheme'],
+                    None,
+                    config=self.db.config
+                )
+                toc = perf_counter()
+            except password.PasswordValueError as e:
+                print(e)
+                print_supported_schemes()
+                return
+
+            if props['scheme'].startswith('PBKDF2'):
+                (rounds, salt, _raw_salt, digest) = password.pbkdf2_unpack(
+                    pw_hash)
+            else:
+                rounds = _("scheme does not support rounds.")
+
+            print(_(
+                "Hash time: %(time)0.9f seconds, scheme: %(scheme)s, "
+                "rounds: %(rounds)s") %
+                  { "time": toc-tic, "scheme": props['scheme'],
+                    "rounds": rounds})
+
     def run_command(self, args):
         """Run a single command
         """
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/roundup/anypy/time_.py	Fri Mar 03 17:37:44 2023 -0500
@@ -0,0 +1,6 @@
+try:
+    # Python 3+
+    from time import perf_counter
+except (ImportError, AttributeError):
+    # Python 2.5-2.7
+    from time import clock as perf_counter
--- a/share/man/man1/roundup-admin.1	Fri Mar 03 14:31:29 2023 -0500
+++ b/share/man/man1/roundup-admin.1	Fri Mar 03 17:37:44 2023 -0500
@@ -201,6 +201,10 @@
 Remove journal entries older than a period of time specified or
 before a certain date.
 .TP
+\fBperftest\fP \fI[mode] [arguments]*\fP
+Run performance test. For example test the effect
+of changing password hashing parameters.
+.TP
 \fBreindex\fP \fI[classname|designator]*\fP
 This will re-generate the search indexes for a tracker.
 .TP

Roundup Issue Tracker: http://roundup-tracker.org/