From 09d719d48f67abdbaff7b4208b69bdb58658b400 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 7 Sep 2025 20:16:36 -0400 Subject: [PATCH] Update base translations and improve consistency (#12432) * Improve confirmation prompts and tooltips for delete actions in the GUI * Fixes #10543 --- share/translations/keepassxc_en.ts | 302 +++++++++++--------- src/autotype/AutoTypeSelectDialog.ui | 24 +- src/cli/DatabaseInfo.cpp | 4 +- src/core/Tools.cpp | 12 +- src/gui/DatabaseWidget.cpp | 8 +- src/gui/GuiTools.cpp | 27 +- src/gui/MainWindow.cpp | 11 + src/gui/MainWindow.ui | 24 +- src/gui/entry/EditEntryWidget.cpp | 24 +- src/gui/entry/EntryView.cpp | 2 +- src/gui/export/ExportDialog.cpp | 4 +- src/gui/passkeys/PasskeyExporter.cpp | 2 +- src/gui/passkeys/PasskeyImporter.cpp | 8 +- src/gui/reports/ReportsWidgetStatistics.cpp | 2 +- src/keys/drivers/YubiKey.cpp | 2 +- src/keys/drivers/YubiKeyInterfacePCSC.cpp | 8 +- src/keys/drivers/YubiKeyInterfaceUSB.cpp | 2 +- tests/TestCli.cpp | 2 +- 18 files changed, 276 insertions(+), 192 deletions(-) diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index dad529bb7..643bf9c55 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -844,16 +844,6 @@ Use Virtual Keyboard - - <p>You can use advanced search queries to find any entry in your open databases. The following shortcuts are useful:<br/> -Ctrl+F - Toggle database search<br/> -Ctrl+1 - Type username<br/> -Ctrl+2 - Type password<br/> -Ctrl+3 - Type TOTP<br/> -Ctrl+4 - Type URL<br/> -Ctrl+5 - Use Virtual Keyboard (Windows Only)</p> - - Type {URL} @@ -862,6 +852,25 @@ Ctrl+5 - Use Virtual Keyboard (Windows Only)</p> Copy URL + + <p>The following shortcuts are available:<br/> +Ctrl+F - Focus search<br/> +Ctrl+1 - Type username<br/> +Ctrl+2 - Type password<br/> +Ctrl+3 - Type TOTP<br/> +Ctrl+4 - Type URL<br/> +Ctrl+5 - Use Virtual Keyboard (Windows Only)<br/> +Ctrl+Shift+1 - Copy username<br/> +Ctrl+Shift+2 - Copy password<br/> +Ctrl+Shift+3 - Copy TOTP<br/> +Ctrl+Shift+4 - Copy URL<br/> +</p> + + + + You can use advanced search queries to find any entry in your open databases. + + BrowserAccessControlDialog @@ -2561,18 +2570,6 @@ This is definitely a bug, please report it to the developers. Remember my choice - - Delete group - - - - Do you really want to delete the group "%1" for good? - - - - Move group to recycle bin? - - Do you really want to move the group "%1" to the recycle bin? @@ -2664,10 +2661,6 @@ Disable safe saves and try again? KeePass 2 Database - - Save database backup - - Empty recycle bin? @@ -2760,6 +2753,22 @@ Disable safe saves and try again? Failed to save backup database: %1 + + Save Database Backup + + + + Confirm Delete Group + + + + Do you really want to permanently delete the group "%1"? + + + + Confirm Recycle Group + + EditEntryAttachmentsDialog @@ -4367,10 +4376,6 @@ This will leave your passwords and sensitive information vulnerable! name (descending) - - unknown - - Export database to HTML file @@ -4379,6 +4384,10 @@ This will leave your passwords and sensitive information vulnerable! HTML file + + invalid sort order + + FdoSecrets::DBusMgr @@ -5575,22 +5584,10 @@ Are you sure you want to continue with this file? &New Entry… - - Add a new entry - - &Edit Entry… - - View or edit entry - - - - &Delete Entry… - - &New Group… @@ -5996,6 +5993,10 @@ Expect some bugs and minor issues, this version is meant for testing purposes.Import Passkey + + Delete Entry + + Remove Passkey From Entry @@ -6020,14 +6021,6 @@ Expect some bugs and minor issues, this version is meant for testing purposes.Password Generator - - E&xpire Entry… - - - - Copy Password and TOTP - - Clear SSH Agent @@ -6036,6 +6029,48 @@ Expect some bugs and minor issues, this version is meant for testing purposes.Clear all identities in ssh-agent + + New Entry + + + + Edit Entry… + + + + E&xpire Entry + + + + Expire Entry + + + + &Delete Entry + + + + Move selected entry(s) to the recycle bin + + + + + + + Permanently delete the selected entry(s) + + + + + + + View or edit entry + + + + Copy Password and TOTP + + ManageDatabase @@ -6431,10 +6466,6 @@ Expect some bugs and minor issues, this version is meant for testing purposes. PasskeyExporter - - KeePassXC: Passkey Export - - File "%1.passkey" already exists. Do you want to overwrite it? @@ -6453,6 +6484,10 @@ Do you want to overwrite it? Cannot write to file + + Overwrite Existing File? + + PasskeyImportDialog @@ -6527,14 +6562,6 @@ Do you want to overwrite it? Cannot open file "%1" for reading. - - Open passkey file - - - - Cannot import passkey - - Cannot import passkey file "%1". Data is missing. @@ -6549,6 +6576,14 @@ The following data is missing: Cannot import passkey file "%1". Private key is missing or malformed. + + Open Passkey File + + + + Passkey Import Failed + + PasswordEditWidget @@ -7630,14 +7665,6 @@ Do you want to overwrite it? Type: Spatial(Rep) - - Type: Date(Rep) - - - - Type: Unknown (%1) - - Entropy %1 (%2) @@ -7846,10 +7873,6 @@ Do you want to overwrite it? Average password length - - %1 characters - - Unknown command %1 @@ -8439,24 +8462,6 @@ Kernel: %3 %4 - - Do you really want to delete the entry "%1" for good? - - - - Do you really want to delete %n entry(s) for good? - - - - - - - Delete entry(s)? - - - - - Do you really want to move entry "%1" to the recycle bin? @@ -8468,17 +8473,6 @@ Kernel: %3 %4 - - Move entry(s) to recycle bin? - - - - - - - Replace references to entry? - - Entry "%1" has %2 reference(s). Do you want to overwrite references with values, skip this entry, or delete anyway? @@ -8811,17 +8805,6 @@ This option is deprecated, use --set-key-file instead. Proton Pass Import - - Delete plugin data? - - - - Delete plugin data from Entry(s)? - - - - - Passkey @@ -8868,6 +8851,61 @@ This option is deprecated, use --set-key-file instead. Fit + + %1 character(s) + + + + + + + Do you really want to permanently delete the entry "%1"? + + + + Do you really want to permanently delete %n entry(s)? + + + + + + + Confirm Delete Entry(s) + + + + + + + Confirm Recycle Entry(s) + + + + + + + Confirm Delete Plugin Data + + + + Delete plugin data from the selected entry(s)? + + + + + + + Confirm Replace Entry References + + + + Type: Date(Rep) + + + + Type: Unknown (%1) + + Unsupported format, ensure your Bitwarden export is password-protected @@ -9393,14 +9431,17 @@ This option is deprecated, use --set-key-file instead. Average password length - - %1 characters - - Average password length is less than ten characters. Longer passwords provide more security. + + %1 character(s) + + + + + SSHAgent @@ -10095,10 +10136,6 @@ Example: JBSWY3DPEHPK3PXP YubiKeyInterfacePCSC - - The YubiKey PCSC interface has not been initialized. - - Could not find or access hardware key with serial number %1. Please present it to continue. @@ -10111,10 +10148,6 @@ Example: JBSWY3DPEHPK3PXP Hardware key was not found or is not configured. - - Failed to complete a challenge-response, the PCSC error code was: %1 - - (NFC) %1 [%2] - Slot %3, %4 YubiKey display fields @@ -10130,13 +10163,17 @@ Example: JBSWY3DPEHPK3PXP USB Challenge-Response Key no interaction required + + The YubiKey PC/SC interface has not been initialized. + + + + Failed to complete a challenge-response, the PC/SC error code was: %1 + + YubiKeyInterfaceUSB - - Unknown - - Press USB Challenge-Response Key interaction request @@ -10177,5 +10214,10 @@ Example: JBSWY3DPEHPK3PXP YubiKey display fields + + Unknown + Unknown hardware key name + + diff --git a/src/autotype/AutoTypeSelectDialog.ui b/src/autotype/AutoTypeSelectDialog.ui index 0c0f6561e..07a200842 100644 --- a/src/autotype/AutoTypeSelectDialog.ui +++ b/src/autotype/AutoTypeSelectDialog.ui @@ -50,14 +50,19 @@ Qt::NoFocus - - <p>You can use advanced search queries to find any entry in your open databases. The following shortcuts are useful:<br/> -Ctrl+F - Toggle database search<br/> -Ctrl+1 - Type username<br/> -Ctrl+2 - Type password<br/> -Ctrl+3 - Type TOTP<br/> -Ctrl+4 - Type URL<br/> -Ctrl+5 - Use Virtual Keyboard (Windows Only)</p> + + <p>The following shortcuts are available:<br/> +Ctrl+F - Focus search<br/> +Ctrl+1 - Type username<br/> +Ctrl+2 - Type password<br/> +Ctrl+3 - Type TOTP<br/> +Ctrl+4 - Type URL<br/> +Ctrl+5 - Use Virtual Keyboard (Windows Only)<br/> +Ctrl+Shift+1 - Copy username<br/> +Ctrl+Shift+2 - Copy password<br/> +Ctrl+Shift+3 - Copy TOTP<br/> +Ctrl+Shift+4 - Copy URL<br/> +</p> QToolButton { @@ -173,6 +178,9 @@ Ctrl+5 - Use Virtual Keyboard (Windows Only)</p> 0 + + You can use advanced search queries to find any entry in your open databases. + Search… diff --git a/src/cli/DatabaseInfo.cpp b/src/cli/DatabaseInfo.cpp index 0b205157c..44030d5e1 100644 --- a/src/cli/DatabaseInfo.cpp +++ b/src/cli/DatabaseInfo.cpp @@ -67,8 +67,8 @@ int DatabaseInfo::executeWithDatabase(QSharedPointer database, QShared out << QObject::tr("Number of short passwords") << ": " << QString::number(stats.shortPasswords) << Qt::endl; out << QObject::tr("Number of weak passwords") << ": " << QString::number(stats.weakPasswords) << Qt::endl; out << QObject::tr("Entries excluded from reports") << ": " << QString::number(stats.excludedEntries) << Qt::endl; - out << QObject::tr("Average password length") << ": " << QObject::tr("%1 characters").arg(stats.averagePwdLength()) - << Qt::endl; + out << QObject::tr("Average password length") << ": " + << QObject::tr("%1 character(s)", "", stats.averagePwdLength()).arg(stats.averagePwdLength()) << Qt::endl; return EXIT_SUCCESS; } diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp index 814233941..1d0bb1ba0 100644 --- a/src/core/Tools.cpp +++ b/src/core/Tools.cpp @@ -151,23 +151,23 @@ namespace Tools if (seconds >= secondsInYear) { auto years = std::floor(seconds / secondsInYear); - return QObject::tr("over %1 year(s)", nullptr, years).arg(years); + return QObject::tr("over %1 year(s)", "", years).arg(years); } else if (seconds >= secondsInMonth) { auto months = std::round(seconds / secondsInMonth); - return QObject::tr("about %1 month(s)", nullptr, months).arg(months); + return QObject::tr("about %1 month(s)", "", months).arg(months); } else if (seconds >= secondsInWeek) { auto weeks = std::round(seconds / secondsInWeek); - return QObject::tr("%1 week(s)", nullptr, weeks).arg(weeks); + return QObject::tr("%1 week(s)", "", weeks).arg(weeks); } else if (seconds >= secondsInDay) { auto days = std::floor(seconds / secondsInDay); - return QObject::tr("%1 day(s)", nullptr, days).arg(days); + return QObject::tr("%1 day(s)", "", days).arg(days); } else if (seconds >= secondsInHour) { auto hours = std::floor(seconds / secondsInHour); - return QObject::tr("%1 hour(s)", nullptr, hours).arg(hours); + return QObject::tr("%1 hour(s)", "", hours).arg(hours); } auto minutes = std::floor(seconds / 60); - return QObject::tr("%1 minute(s)", nullptr, minutes).arg(minutes); + return QObject::tr("%1 minute(s)", "", minutes).arg(minutes); } bool readFromDevice(QIODevice* device, QByteArray& data, int size) diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 2edbfe839..0ed8c1d23 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -1115,8 +1115,8 @@ void DatabaseWidget::deleteGroup() if (inRecycleBin || isRecycleBin || isRecycleBinSubgroup || !m_db->metadata()->recycleBinEnabled()) { auto result = MessageBox::question( this, - tr("Delete group"), - tr("Do you really want to delete the group \"%1\" for good?").arg(currentGroup->name().toHtmlEscaped()), + tr("Confirm Delete Group"), + tr("Do you really want to permanently delete the group \"%1\"?").arg(currentGroup->name().toHtmlEscaped()), MessageBox::Delete | MessageBox::Cancel, MessageBox::Cancel); @@ -1125,7 +1125,7 @@ void DatabaseWidget::deleteGroup() } } else { auto result = MessageBox::question(this, - tr("Move group to recycle bin?"), + tr("Confirm Recycle Group"), tr("Do you really want to move the group " "\"%1\" to the recycle bin?") .arg(currentGroup->name().toHtmlEscaped()), @@ -2483,7 +2483,7 @@ bool DatabaseWidget::saveBackup() } const QString newFilePath = fileDialog()->getSaveFileName(this, - tr("Save database backup"), + tr("Save Database Backup"), FileDialog::getLastDir("backup", oldFilePath), tr("KeePass 2 Database").append(" (*.kdbx)")); diff --git a/src/gui/GuiTools.cpp b/src/gui/GuiTools.cpp index b2dfa63f3..b448e87e7 100644 --- a/src/gui/GuiTools.cpp +++ b/src/gui/GuiTools.cpp @@ -32,14 +32,15 @@ namespace GuiTools if (permanent) { QString prompt; if (entries.size() == 1) { - prompt = QObject::tr("Do you really want to delete the entry \"%1\" for good?") - .arg(entries.first()->title().toHtmlEscaped()); + auto entry = entries.first(); + prompt = QObject::tr("Do you really want to permanently delete the entry \"%1\"?") + .arg(entry->resolvePlaceholder(entry->title()).toHtmlEscaped()); } else { - prompt = QObject::tr("Do you really want to delete %n entry(s) for good?", "", entries.size()); + prompt = QObject::tr("Do you really want to permanently delete %n entry(s)?", "", entries.size()); } auto answer = MessageBox::question(parent, - QObject::tr("Delete entry(s)?", "", entries.size()), + QObject::tr("Confirm Delete Entry(s)", "", entries.size()), prompt, MessageBox::Delete | MessageBox::Cancel, MessageBox::Cancel); @@ -50,14 +51,15 @@ namespace GuiTools } else { QString prompt; if (entries.size() == 1) { + auto entry = entries.first(); prompt = QObject::tr("Do you really want to move entry \"%1\" to the recycle bin?") - .arg(entries.first()->title().toHtmlEscaped()); + .arg(entry->resolvePlaceholder(entry->title()).toHtmlEscaped()); } else { prompt = QObject::tr("Do you really want to move %n entry(s) to the recycle bin?", "", entries.size()); } auto answer = MessageBox::question(parent, - QObject::tr("Move entry(s) to recycle bin?", "", entries.size()), + QObject::tr("Confirm Recycle Entry(s)", "", entries.size()), prompt, MessageBox::Move | MessageBox::Cancel, MessageBox::Cancel); @@ -72,11 +74,12 @@ namespace GuiTools return false; } - auto answer = MessageBox::question(parent, - QObject::tr("Delete plugin data?"), - QObject::tr("Delete plugin data from Entry(s)?", "", entries.size()), - MessageBox::Delete | MessageBox::Cancel, - MessageBox::Cancel); + auto answer = + MessageBox::question(parent, + QObject::tr("Confirm Delete Plugin Data"), + QObject::tr("Delete plugin data from the selected entry(s)?", "", entries.size()), + MessageBox::Delete | MessageBox::Cancel, + MessageBox::Cancel); return answer == MessageBox::Delete; } @@ -100,7 +103,7 @@ namespace GuiTools // Prompt the user on what to do with the reference (Overwrite, Delete, Skip) auto result = MessageBox::question( parent, - QObject::tr("Replace references to entry?"), + QObject::tr("Confirm Replace Entry References"), QObject::tr( "Entry \"%1\" has %2 reference(s). " "Do you want to overwrite references with values, skip this entry, or delete anyway?", diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index e25b02470..a2b946563 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -971,6 +971,17 @@ void MainWindow::updateMenuActionState() m_ui->actionEntryEdit->setEnabled(singleEntrySelected); m_ui->actionEntryExpire->setEnabled(multiEntrySelected); m_ui->actionEntryDelete->setEnabled(multiEntrySelected); + if (dbWidget) { + if (dbWidget->database()->metadata()->recycleBinEnabled() && !inRecycleBin) { + m_ui->actionEntryDelete->setToolTip( + tr("Move selected entry(s) to the recycle bin", "", dbWidget->numberOfSelectedEntries())); + } else { + m_ui->actionEntryDelete->setToolTip( + tr("Permanently delete the selected entry(s)", "", dbWidget->numberOfSelectedEntries())); + } + } else { + m_ui->actionEntryDelete->setToolTip(tr("Delete Entry")); + } m_ui->actionEntryRestore->setVisible(multiEntrySelected && inRecycleBin); m_ui->actionEntryRestore->setEnabled(multiEntrySelected && inRecycleBin); if (dbWidget) { diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index bc0f0535b..39994bbe6 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -501,13 +501,16 @@ &New Entry… - Add a new entry + New Entry &Edit Entry… + + Edit Entry… + View or edit entry @@ -517,12 +520,27 @@ false - E&xpire Entry… + E&xpire Entry + + + Expire Entry + + + Expire Entry - &Delete Entry… + &Delete Entry + + + Delete Entry + + + Delete Entry + + + Del diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index a56ae291e..4eb12820f 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -1651,21 +1651,21 @@ void EditEntryWidget::deleteAllHistoryEntries() QMenu* EditEntryWidget::createPresetsMenu() { auto* expirePresetsMenu = new QMenu(this); - expirePresetsMenu->addAction(tr("%n hour(s)", nullptr, 12))->setData(QVariant::fromValue(TimeDelta::fromHours(12))); - expirePresetsMenu->addAction(tr("%n hour(s)", nullptr, 24))->setData(QVariant::fromValue(TimeDelta::fromHours(24))); + expirePresetsMenu->addAction(tr("%n hour(s)", "", 12))->setData(QVariant::fromValue(TimeDelta::fromHours(12))); + expirePresetsMenu->addAction(tr("%n hour(s)", "", 24))->setData(QVariant::fromValue(TimeDelta::fromHours(24))); expirePresetsMenu->addSeparator(); - expirePresetsMenu->addAction(tr("%n week(s)", nullptr, 1))->setData(QVariant::fromValue(TimeDelta::fromDays(7))); - expirePresetsMenu->addAction(tr("%n week(s)", nullptr, 2))->setData(QVariant::fromValue(TimeDelta::fromDays(14))); - expirePresetsMenu->addAction(tr("%n week(s)", nullptr, 3))->setData(QVariant::fromValue(TimeDelta::fromDays(21))); + expirePresetsMenu->addAction(tr("%n week(s)", "", 1))->setData(QVariant::fromValue(TimeDelta::fromDays(7))); + expirePresetsMenu->addAction(tr("%n week(s)", "", 2))->setData(QVariant::fromValue(TimeDelta::fromDays(14))); + expirePresetsMenu->addAction(tr("%n week(s)", "", 3))->setData(QVariant::fromValue(TimeDelta::fromDays(21))); expirePresetsMenu->addSeparator(); - expirePresetsMenu->addAction(tr("%n month(s)", nullptr, 1))->setData(QVariant::fromValue(TimeDelta::fromMonths(1))); - expirePresetsMenu->addAction(tr("%n month(s)", nullptr, 2))->setData(QVariant::fromValue(TimeDelta::fromMonths(2))); - expirePresetsMenu->addAction(tr("%n month(s)", nullptr, 3))->setData(QVariant::fromValue(TimeDelta::fromMonths(3))); - expirePresetsMenu->addAction(tr("%n month(s)", nullptr, 6))->setData(QVariant::fromValue(TimeDelta::fromMonths(6))); + expirePresetsMenu->addAction(tr("%n month(s)", "", 1))->setData(QVariant::fromValue(TimeDelta::fromMonths(1))); + expirePresetsMenu->addAction(tr("%n month(s)", "", 2))->setData(QVariant::fromValue(TimeDelta::fromMonths(2))); + expirePresetsMenu->addAction(tr("%n month(s)", "", 3))->setData(QVariant::fromValue(TimeDelta::fromMonths(3))); + expirePresetsMenu->addAction(tr("%n month(s)", "", 6))->setData(QVariant::fromValue(TimeDelta::fromMonths(6))); expirePresetsMenu->addSeparator(); - expirePresetsMenu->addAction(tr("%n year(s)", nullptr, 1))->setData(QVariant::fromValue(TimeDelta::fromYears(1))); - expirePresetsMenu->addAction(tr("%n year(s)", nullptr, 2))->setData(QVariant::fromValue(TimeDelta::fromYears(2))); - expirePresetsMenu->addAction(tr("%n year(s)", nullptr, 3))->setData(QVariant::fromValue(TimeDelta::fromYears(3))); + expirePresetsMenu->addAction(tr("%n year(s)", "", 1))->setData(QVariant::fromValue(TimeDelta::fromYears(1))); + expirePresetsMenu->addAction(tr("%n year(s)", "", 2))->setData(QVariant::fromValue(TimeDelta::fromYears(2))); + expirePresetsMenu->addAction(tr("%n year(s)", "", 3))->setData(QVariant::fromValue(TimeDelta::fromYears(3))); return expirePresetsMenu; } diff --git a/src/gui/entry/EntryView.cpp b/src/gui/entry/EntryView.cpp index 74dd2a60f..bacf0c05f 100644 --- a/src/gui/entry/EntryView.cpp +++ b/src/gui/entry/EntryView.cpp @@ -548,7 +548,7 @@ void EntryView::startDrag(Qt::DropActions supportedActions) for (auto& index : selectedIndexes) { if (++i > 4) { int remaining = selectedIndexes.size() - i + 1; - listWidget.addItem(tr("+ %1 entry(s)...", nullptr, remaining).arg(remaining)); + listWidget.addItem(tr("+ %1 entry(s)...", "", remaining).arg(remaining)); break; } diff --git a/src/gui/export/ExportDialog.cpp b/src/gui/export/ExportDialog.cpp index 36e6f4b41..2140b9bf0 100644 --- a/src/gui/export/ExportDialog.cpp +++ b/src/gui/export/ExportDialog.cpp @@ -57,8 +57,10 @@ QString ExportDialog::getStrategyName(ExportSortingStrategy strategy) return tr("name (ascending)"); case ExportSortingStrategy::BY_NAME_DESC: return tr("name (descending)"); + default: + Q_ASSERT(false); + return tr("invalid sort order"); } - return tr("unknown"); } void ExportDialog::exportDatabase() diff --git a/src/gui/passkeys/PasskeyExporter.cpp b/src/gui/passkeys/PasskeyExporter.cpp index 4ff84e5f8..5d0b0c586 100644 --- a/src/gui/passkeys/PasskeyExporter.cpp +++ b/src/gui/passkeys/PasskeyExporter.cpp @@ -76,7 +76,7 @@ void PasskeyExporter::exportSelectedEntry(const Entry* entry, const QString& fol const auto fullPath = QString("%1/%2.passkey").arg(folder, Tools::cleanFilename(entry->title())); if (QFile::exists(fullPath)) { auto dialogResult = MessageBox::warning(m_parent, - tr("KeePassXC: Passkey Export"), + tr("Overwrite Existing File?"), tr("File \"%1.passkey\" already exists.\n" "Do you want to overwrite it?\n") .arg(entry->title()), diff --git a/src/gui/passkeys/PasskeyImporter.cpp b/src/gui/passkeys/PasskeyImporter.cpp index df4042069..f55751740 100644 --- a/src/gui/passkeys/PasskeyImporter.cpp +++ b/src/gui/passkeys/PasskeyImporter.cpp @@ -39,7 +39,7 @@ void PasskeyImporter::importPasskey(QSharedPointer& database, Entry* e { auto filter = QString("%1 (*.passkey);;%2 (*)").arg(tr("Passkey file"), tr("All files")); auto fileName = - fileDialog()->getOpenFileName(m_parent, tr("Open passkey file"), FileDialog::getLastDir("passkey"), filter); + fileDialog()->getOpenFileName(m_parent, tr("Open Passkey File"), FileDialog::getLastDir("passkey"), filter); if (fileName.isEmpty()) { return; } @@ -62,7 +62,7 @@ void PasskeyImporter::importSelectedFile(QFile& file, QSharedPointer& const auto passkeyObject = browserMessageBuilder()->getJsonObject(fileData); if (passkeyObject.isEmpty()) { MessageBox::information(m_parent, - tr("Cannot import passkey"), + tr("Passkey Import Failed"), tr("Cannot import passkey file \"%1\". Data is missing.").arg(file.fileName())); return; } @@ -73,14 +73,14 @@ void PasskeyImporter::importSelectedFile(QFile& file, QSharedPointer& QStringList() << "relyingParty" << "url" << "username" << "credentialId" << "userHandle" << "privateKey"); if (!missingKeys.isEmpty()) { MessageBox::information(m_parent, - tr("Cannot import passkey"), + tr("Passkey Import Failed"), tr("Cannot import passkey file \"%1\".\nThe following data is missing:\n%2") .arg(file.fileName(), missingKeys.join(", "))); } else if (!privateKey.startsWith(EntryAttributes::KPEX_PASSKEY_PRIVATE_KEY_START) || !privateKey.trimmed().endsWith(EntryAttributes::KPEX_PASSKEY_PRIVATE_KEY_END)) { MessageBox::information( m_parent, - tr("Cannot import passkey"), + tr("Passkey Import Failed"), tr("Cannot import passkey file \"%1\". Private key is missing or malformed.").arg(file.fileName())); } else { const auto relyingParty = passkeyObject["relyingParty"].toString(); diff --git a/src/gui/reports/ReportsWidgetStatistics.cpp b/src/gui/reports/ReportsWidgetStatistics.cpp index 4eeaffe29..cb95dfb9f 100644 --- a/src/gui/reports/ReportsWidgetStatistics.cpp +++ b/src/gui/reports/ReportsWidgetStatistics.cpp @@ -124,7 +124,7 @@ void ReportsWidgetStatistics::calculateStats() tr("Excluding entries from reports, e. g. because they are known to have a poor password, isn't " "necessarily a problem but you should keep an eye on them.")); addStatsRow(tr("Average password length"), - tr("%1 characters").arg(stats->averagePwdLength()), + tr("%1 character(s)", "", stats->averagePwdLength()).arg(stats->averagePwdLength()), stats->isAvgPwdTooShort(), tr("Average password length is less than ten characters. Longer passwords provide more security.")); } diff --git a/src/keys/drivers/YubiKey.cpp b/src/keys/drivers/YubiKey.cpp index c07bcc072..dfc4b6b13 100644 --- a/src/keys/drivers/YubiKey.cpp +++ b/src/keys/drivers/YubiKey.cpp @@ -43,7 +43,7 @@ YubiKey::YubiKey() connect(YubiKeyInterfacePCSC::instance(), SIGNAL(challengeStarted()), this, SIGNAL(challengeStarted())); connect(YubiKeyInterfacePCSC::instance(), SIGNAL(challengeCompleted()), this, SIGNAL(challengeCompleted())); } else { - qDebug("YubiKey: PCSC interface is disabled or not initialized."); + qDebug("YubiKey: PC/SC interface is disabled or not initialized."); } m_initialized = num_interfaces > 0; diff --git a/src/keys/drivers/YubiKeyInterfacePCSC.cpp b/src/keys/drivers/YubiKeyInterfacePCSC.cpp index 612451dd2..d2f9c0536 100644 --- a/src/keys/drivers/YubiKeyInterfacePCSC.cpp +++ b/src/keys/drivers/YubiKeyInterfacePCSC.cpp @@ -519,7 +519,7 @@ YubiKeyInterfacePCSC::YubiKeyInterfacePCSC() : YubiKeyInterface() { if (ensureValidContext(m_sc_context) != SCARD_S_SUCCESS) { - qDebug("YubiKey: Failed to establish PCSC context."); + qDebug("YubiKey: Failed to establish PC/SC context."); } else { m_initialized = true; } @@ -528,7 +528,7 @@ YubiKeyInterfacePCSC::YubiKeyInterfacePCSC() YubiKeyInterfacePCSC::~YubiKeyInterfacePCSC() { if (m_initialized && SCardReleaseContext(m_sc_context) != SCARD_S_SUCCESS) { - qDebug("YubiKey: Failed to release PCSC context."); + qDebug("YubiKey: Failed to release PC/SC context."); } } @@ -678,7 +678,7 @@ YubiKeyInterfacePCSC::challenge(YubiKeySlot slot, const QByteArray& challenge, B { m_error.clear(); if (!m_initialized) { - m_error = tr("The YubiKey PCSC interface has not been initialized."); + m_error = tr("The YubiKey PC/SC interface has not been initialized."); return YubiKey::ChallengeResult::YCR_ERROR; } @@ -762,7 +762,7 @@ YubiKey::ChallengeResult YubiKeyInterfacePCSC::performChallenge(void* key, m_error = tr("Hardware key was not found or is not configured."); } else { m_error = - tr("Failed to complete a challenge-response, the PCSC error code was: %1").arg(QString::number(rv)); + tr("Failed to complete a challenge-response, the PC/SC error code was: %1").arg(QString::number(rv)); } return YubiKey::ChallengeResult::YCR_ERROR; diff --git a/src/keys/drivers/YubiKeyInterfaceUSB.cpp b/src/keys/drivers/YubiKeyInterfaceUSB.cpp index a39b39dce..dba27d370 100644 --- a/src/keys/drivers/YubiKeyInterfaceUSB.cpp +++ b/src/keys/drivers/YubiKeyInterfaceUSB.cpp @@ -144,7 +144,7 @@ YubiKey::KeyMap YubiKeyInterfaceUSB::findValidKeys(int& connectedKeys) int vid, pid; yk_get_key_vid_pid(yk_key.get(), &vid, &pid); - QString name = m_pid_names.value(pid, tr("Unknown")); + QString name = m_pid_names.value(pid, tr("Unknown", "Unknown hardware key name")); if (vid == ONLYKEY_VID) { name = QStringLiteral("OnlyKey %ver"); } diff --git a/tests/TestCli.cpp b/tests/TestCli.cpp index 8f92f4412..2178ecd5a 100644 --- a/tests/TestCli.cpp +++ b/tests/TestCli.cpp @@ -1023,7 +1023,7 @@ void TestCli::testInfo() QCOMPARE(m_stdout->readLine(), QByteArray("Number of short passwords: 0\n")); QCOMPARE(m_stdout->readLine(), QByteArray("Number of weak passwords: 2\n")); QCOMPARE(m_stdout->readLine(), QByteArray("Entries excluded from reports: 0\n")); - QCOMPARE(m_stdout->readLine(), QByteArray("Average password length: 11 characters\n")); + QCOMPARE(m_stdout->readLine(), QByteArray("Average password length: 11 character(s)\n")); // Test with quiet option. setInput("a");