Skip to content

Commit

Permalink
Close #296: Proper plurals
Browse files Browse the repository at this point in the history
Use the provided plural mechanisms of QT.
The "PO" translation also works smoothly and
the translation mechanisms between .po <-> .qt
was tested successfully.

The new english translation file translates
the single phrase:
 "Delete the %n revocation list(s): '%1'?"
into
 "Delete the revocation list: '%1'?" for one item
and
 "Delete the %n revocation lists: '%1'?" otherwise
  • Loading branch information
chris2511 committed Sep 14, 2024
1 parent 7376cce commit c6304a0
Show file tree
Hide file tree
Showing 18 changed files with 151 additions and 63 deletions.
8 changes: 6 additions & 2 deletions lang/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
set(S "${PROJECT_SOURCE_DIR}/lang")
set(D "${PROJECT_BINARY_DIR}")

list(APPEND XCA_QT_LANGUAGES de fr ja pl ru tr es it sk bg)
list(APPEND XCA_LANGUAGES id hr ko nl pt_BR zh_CN fa ${XCA_QT_LANGUAGES})
# English (en) must be first for Info.plist
list(APPEND XCA_LANGUAGES en bg de es fa fr hr id it ja ko nl pl pt_BR ru sk tr zh_CN)
list(JOIN XCA_LANGUAGES "</string>\n <string>" LANGUAGES_PLIST)

foreach(lang ${XCA_LANGUAGES})
Expand Down Expand Up @@ -33,9 +33,13 @@ if (${QT_VERSION} VERSION_LESS 6.0.0 )
else()
get_target_property(LIBSRC xcalib SOURCES)
get_target_property(XCASRC xca SOURCES)
if (${QT_VERSION} VERSION_LESS 6.7.0 )
message(STATUS "At least QT 6.7.0 required for PLURALS_TS_FILE")
endif()
qt_add_translations(xca TS_FILES ${TS_FILES} ${S}/xca.ts
LRELEASE_OPTIONS -silent
QM_FILES_OUTPUT_VARIABLE QM_FILES
PLURALS_TS_FILE ${S}/xca_en.ts
SOURCES ${LIBSRC} ${XCASRC}
)
add_custom_target(trans DEPENDS xca_lupdate "${D}/xca.pot")
Expand Down
106 changes: 106 additions & 0 deletions lang/xca_en.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en">
<context>
<name>ExportDialog</name>
<message numerus="yes">
<location filename="../widgets/ExportDialog.cpp" line="43"/>
<source>%n selected item(s)</source>
<translation>
<numerusform>selected item</numerusform>
<numerusform>%n selected items</numerusform>
</translation>
</message>
</context>
<context>
<name>XcaTreeView</name>
<message numerus="yes">
<location filename="../widgets/XcaTreeView.cpp" line="510"/>
<source>Please enter the password to encrypt all %n exported private key(s) in:
%1</source>
<comment>Singular form for 0 or 1 item can be ignored. Will always be called with n &gt;= 2</comment>
<translation>
<numerusform>Please enter the password to encrypt the exported private key in:
%1</numerusform>
<numerusform>Please enter the password to encrypt all %n exported private keys in:
%1</numerusform>
</translation>
</message>
</context>
<context>
<name>pki_crl</name>
<message numerus="yes">
<location filename="../lib/pki_crl.cpp" line="60"/>
<source>Delete the %n revocation list(s): &apos;%1&apos;?</source>
<translation>
<numerusform>Delete the revocation list: &apos;%1&apos;?</numerusform>
<numerusform>Delete the %n revocation lists: &apos;%1&apos;?</numerusform>
</translation>
</message>
</context>
<context>
<name>pki_key</name>
<message numerus="yes">
<location filename="../lib/pki_key.cpp" line="214"/>
<source>Delete the %n %1 public key(s) &apos;%2&apos;?</source>
<comment>%1 will be replaced by &apos;RSA&apos;, &apos;DSA&apos;, &apos;EC&apos;. %2 is/are the internal name(s) of the key(s)</comment>
<translation>
<numerusform>Delete the %1 public key &apos;%2&apos;?</numerusform>
<numerusform>Delete the %n %1 public keys &apos;%2&apos;?</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="../lib/pki_key.cpp" line="222"/>
<source>Delete the %n %1 private key(s) &apos;%2&apos;?</source>
<comment>%1 will be replaced by &apos;RSA&apos;, &apos;DSA&apos;, &apos;EC&apos;. %2 is/are the internal name(s) of the key(s)</comment>
<translation>
<numerusform>Delete the %1 private key &apos;%2&apos;?</numerusform>
<numerusform>Delete the %n %1 private keys &apos;%2&apos;?</numerusform>
</translation>
</message>
</context>
<context>
<name>pki_scard</name>
<message numerus="yes">
<location filename="../lib/pki_scard.cpp" line="47"/>
<source>Delete the %n token key(s): &apos;%1&apos;?</source>
<translation>
<numerusform>Delete the token key: &apos;%1&apos;?</numerusform>
<numerusform>Delete the %n token keys: &apos;%1&apos;?</numerusform>
</translation>
</message>
</context>
<context>
<name>pki_temp</name>
<message numerus="yes">
<location filename="../lib/pki_temp.cpp" line="159"/>
<source>Delete the %n XCA template(s): &apos;%1&apos;?</source>
<translation>
<numerusform>Delete the XCA template: &apos;%1&apos;?</numerusform>
<numerusform>Delete the %n XCA templates: &apos;%1&apos;?</numerusform>
</translation>
</message>
</context>
<context>
<name>pki_x509</name>
<message numerus="yes">
<location filename="../lib/pki_x509.cpp" line="63"/>
<source>Delete the %n certificate(s): &apos;%1&apos;?</source>
<translation>
<numerusform>Delete the certificate: &apos;%1&apos;?</numerusform>
<numerusform>Delete the %n certificates: &apos;%1&apos;?</numerusform>
</translation>
</message>
</context>
<context>
<name>pki_x509req</name>
<message numerus="yes">
<location filename="../lib/pki_x509req.cpp" line="148"/>
<source>Delete the %n PKCS#10 certificate request(s): &apos;%1&apos;?</source>
<translation>
<numerusform>Delete the PKCS#10 certificate request: &apos;%1&apos;?</numerusform>
<numerusform>Delete the %n PKCS#10 certificate requests: &apos;%1&apos;?</numerusform>
</translation>
</message>
</context>
</TS>
2 changes: 1 addition & 1 deletion lib/pki_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ int pki_base::isVisible()
return iamvisible;
}

QString pki_base::getMsg(msg_type msg) const
QString pki_base::getMsg(msg_type msg, int) const
{
return tr("Internal error: Unexpected message: %1 %2")
.arg(getClassName()).arg(msg);
Expand Down
3 changes: 1 addition & 2 deletions lib/pki_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ class pki_base : public QObject
enum msg_type {
msg_import,
msg_delete,
msg_delete_multi,
msg_create,
};
enum print_opt {
Expand Down Expand Up @@ -156,7 +155,7 @@ class pki_base : public QObject
}
virtual QByteArray i2d() const;
virtual bool compare(const pki_base *) const;
virtual QString getMsg(msg_type msg) const;
virtual QString getMsg(msg_type msg, int n = 1) const;
virtual const char *getClassName() const;

/* Tree View management */
Expand Down
6 changes: 2 additions & 4 deletions lib/pki_crl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void pki_crl::fromPEM_BIO(BIO *bio, const QString &name)
crl = _crl;
}

QString pki_crl::getMsg(msg_type msg) const
QString pki_crl::getMsg(msg_type msg, int n) const
{
/*
* We do not construct english sentences from fragments
Expand All @@ -57,10 +57,8 @@ QString pki_crl::getMsg(msg_type msg) const
*/
switch (msg) {
case msg_import: return tr("Successfully imported the revocation list '%1'");
case msg_delete: return tr("Delete the revocation list '%1'?");
case msg_delete: return tr("Delete the %n revocation list(s): '%1'?", "", n);
case msg_create: return tr("Successfully created the revocation list '%1'");
/* %1: Number of CRLs; %2: list of CRL names */
case msg_delete_multi: return tr("Delete the %1 revocation lists: %2?");
}
return pki_base::getMsg(msg);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/pki_crl.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class pki_crl: public pki_x509name
QVariant column_data(const dbheader *hd) const;
QVariant getIcon(const dbheader *hd) const;
a1time column_a1time(const dbheader *hd) const;
QString getMsg(msg_type msg) const;
QString getMsg(msg_type msg, int n = 1) const;
void d2i(QByteArray &ba);
QByteArray i2d() const;
void setCrlNumber(a1int num);
Expand Down
24 changes: 11 additions & 13 deletions lib/pki_key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,35 +199,33 @@ QString pki_key::getTypeString() const
return getKeyTypeString();
}

QString pki_key::getMsg(msg_type msg) const
QString pki_key::getMsg(msg_type msg, int n) const
{
/*
* We do not construct english sentences (just a little bit)
* from fragments to allow proper translations.
* The drawback are all the slightly different duplicated messages
*
* %1 will be replaced by "RSA", "DSA", "EC"
* %2 is the internal name of the key
*/
QString ktype = getTypeString();
if (isPubKey()) {
switch (msg) {
case msg_import: return tr("Successfully imported the %1 public key '%2'").arg(ktype);
case msg_delete: return tr("Delete the %1 public key '%2'?").arg(ktype);
case msg_import: return tr("Successfully imported the %1 public key '%2'",
"%1 will be replaced by 'RSA', 'DSA', 'EC'. %2 is the internal name of the key").arg(ktype);
case msg_delete: return tr("Delete the %n %1 public key(s) '%2'?",
"%1 will be replaced by 'RSA', 'DSA', 'EC'. %2 is/are the internal name(s) of the key(s)", n).arg(ktype);
default: break;
}
} else {
switch (msg) {
case msg_import: return tr("Successfully imported the %1 private key '%2'").arg(ktype);
case msg_delete: return tr("Delete the %1 private key '%2'?").arg(ktype);
case msg_create: return tr("Successfully created the %1 private key '%2'").arg(ktype);
case msg_import: return tr("Successfully imported the %1 private key '%2'",
"%1 will be replaced by 'RSA', 'DSA', 'EC'. %2 is the internal name of the key").arg(ktype);
case msg_delete: return tr("Delete the %n %1 private key(s) '%2'?",
"%1 will be replaced by 'RSA', 'DSA', 'EC'. %2 is/are the internal name(s) of the key(s)", n).arg(ktype);
case msg_create: return tr("Successfully created the %1 private key '%2'",
"%1 will be replaced by 'RSA', 'DSA', 'EC'. %2 is the internal name of the key").arg(ktype);
default: break;
}
}
if (msg == msg_delete_multi) {
/* %1: Number of keys; %2: list of keynames */
return tr("Delete the %1 keys: %2?");
}
return pki_base::getMsg(msg);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/pki_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ class pki_key: public pki_base
virtual bool isToken();
virtual QString getTypeString(void) const;
virtual QList<int> possibleHashNids();
QString getMsg(msg_type msg) const;
QString getMsg(msg_type msg, int n = 1) const;

void writePublic(XFile &file, bool pem) const;
QString getJWKcrv() const;
Expand Down
6 changes: 2 additions & 4 deletions lib/pki_scard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pki_scard::pki_scard(const QString &name)
init();
}

QString pki_scard::getMsg(msg_type msg) const
QString pki_scard::getMsg(msg_type msg, int n) const
{
/*
* We do not construct english sentences from fragments
Expand All @@ -44,10 +44,8 @@ QString pki_scard::getMsg(msg_type msg) const
*/
switch (msg) {
case msg_import: return tr("Successfully imported the token key '%1'");
case msg_delete: return tr("Delete the token key '%1'?");
case msg_delete: return tr("Delete the %n token key(s): '%1'?", "", n);
case msg_create: return tr("Successfully created the token key '%1'");
/* %1: Number of ktemplates; %2: list of templatenames */
case msg_delete_multi: return tr("Delete the %1 keys: %2?");
}
return pki_base::getMsg(msg);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/pki_scard.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class pki_scard: public pki_key
void deleteFromToken(const slotid &slot);
void store_token(const slotid &slot, EVP_PKEY *pkey);
int renameOnToken(const slotid &slot, const QString &name);
QString getMsg(msg_type msg) const;
QString getMsg(msg_type msg, int n = 1) const;
bool visible() const;
QSqlError insertSqlData();
QSqlError deleteSqlData();
Expand Down
6 changes: 2 additions & 4 deletions lib/pki_temp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ QSqlError pki_temp::deleteSqlData()
return q.lastError();
}

QString pki_temp::getMsg(msg_type msg) const
QString pki_temp::getMsg(msg_type msg, int n) const
{
/*
* We do not construct english sentences from fragments
Expand All @@ -156,10 +156,8 @@ QString pki_temp::getMsg(msg_type msg) const
*/
switch (msg) {
case msg_import: return tr("Successfully imported the XCA template '%1'");
case msg_delete: return tr("Delete the XCA template '%1'?");
case msg_delete: return tr("Delete the %n XCA template(s): '%1'?", "", n);
case msg_create: return tr("Successfully created the XCA template '%1'");
/* %1: Number of ktemplates; %2: list of templatenames */
case msg_delete_multi: return tr("Delete the %1 XCA templates: %2?");
}
return pki_base::getMsg(msg);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/pki_temp.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class pki_temp: public pki_x509name
bool compare(const pki_base *ref) const;
void writeTemp(XFile &file) const;
QVariant getIcon(const dbheader *hd) const;
QString getMsg(msg_type msg) const;
QString getMsg(msg_type msg, int n = 1) const;
x509name getSubject() const;
void setSubject(x509name n)
{
Expand Down
6 changes: 2 additions & 4 deletions lib/pki_x509.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pki_x509::pki_x509(const QString &name)
pki_openssl_error();
}

QString pki_x509::getMsg(msg_type msg) const
QString pki_x509::getMsg(msg_type msg, int n) const
{
/*
* We do not construct english sentences from fragments
Expand All @@ -60,10 +60,8 @@ QString pki_x509::getMsg(msg_type msg) const
*/
switch (msg) {
case msg_import: return tr("Successfully imported the certificate '%1'");
case msg_delete: return tr("Delete the certificate '%1'?");
case msg_delete: return tr("Delete the %n certificate(s): '%1'?", "", n);
case msg_create: return tr("Successfully created the certificate '%1'");
/* %1: Number of certs; %2: list of cert names */
case msg_delete_multi: return tr("Delete the %1 certificates: %2?");
}
return pki_base::getMsg(msg);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/pki_x509.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class pki_x509 : public pki_x509super
void d2i(QByteArray &ba);
void deleteFromToken();
void deleteFromToken(const slotid &slot);
QString getMsg(msg_type msg) const;
QString getMsg(msg_type msg, int n = 1) const;
int renameOnToken(const slotid &slot, const QString &name);
bool pem(BioByteArray &);
QVariant bg_color(const dbheader *hd) const;
Expand Down
15 changes: 5 additions & 10 deletions lib/pki_x509req.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,25 +133,20 @@ void pki_x509req::createReq(pki_key *key, const x509name &dn,
EVP_PKEY_free(privkey);
}

QString pki_x509req::getMsg(msg_type msg) const
QString pki_x509req::getMsg(msg_type msg, int n) const
{
/*
* We do not construct english sentences from fragments
* to allow proper translations.
* The drawback are all the slightly different duplicated messages
*
* %1 will be replaced by either "SPKAC" or "PKCS#10"
* %2 will be replaced by the internal name of the request
* %1 will be replaced by the internal name of the request
*/

QString type = "PKCS#10";

switch (msg) {
case msg_import: return tr("Successfully imported the %1 certificate request '%2'").arg(type);
case msg_delete: return tr("Delete the %1 certificate request '%2'?").arg(type);
case msg_create: return tr("Successfully created the %1 certificate request '%2'").arg(type);
/* %1: Number of requests; %2: list of request names */
case msg_delete_multi: return tr("Delete the %1 certificate requests: %2?");
case msg_import: return tr("Successfully imported the PKCS#10 certificate request '%2'");
case msg_delete: return tr("Delete the %n PKCS#10 certificate request(s): '%1'?", "", n);
case msg_create: return tr("Successfully created the PKCS#10 certificate request '%1'");
}
return pki_base::getMsg(msg);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/pki_x509req.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class pki_x509req : public pki_x509super
{
x509count = -1;
}
virtual QString getMsg(msg_type msg) const;
virtual QString getMsg(msg_type msg, int n = 1) const;
void d2i(QByteArray &ba);
QByteArray i2d() const;
bool pem(BioByteArray &);
Expand Down
1 change: 0 additions & 1 deletion misc/Info.plist.in
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
<string>no</string>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>@LANGUAGES_PLIST@</string>
</array>
<key>CFBundleDocumentTypes</key>
Expand Down
Loading

0 comments on commit c6304a0

Please sign in to comment.