#89 Fix Mailvelope hasPrivateKey() detection

Proper rename OpenPGP Key viewer
This commit is contained in:
the-djmaze 2022-01-29 21:42:56 +01:00
parent b06b04a579
commit 76226f45ca
41 changed files with 252 additions and 200 deletions

View file

@ -36,9 +36,7 @@ export const Scope = {
Compose: 'Compose', Compose: 'Compose',
Settings: 'Settings', Settings: 'Settings',
Menu: 'Menu', Menu: 'Menu',
ComposeOpenPgp: 'ComposeOpenPgp', OpenPgpKey: 'OpenPgpKey',
MessageOpenPgp: 'MessageOpenPgp',
ViewOpenPgpKey: 'ViewOpenPgpKey',
KeyboardShortcutsHelp: 'KeyboardShortcutsHelp', KeyboardShortcutsHelp: 'KeyboardShortcutsHelp',
Ask: 'Ask' Ask: 'Ask'
}; };

View file

@ -8,19 +8,28 @@ import { delegateRunOnDestroy } from 'Common/UtilsUser';
//import { showScreenPopup } from 'Knoin/Knoin'; //import { showScreenPopup } from 'Knoin/Knoin';
//import { MessageOpenPgpPopupView } from 'View/Popup/MessageOpenPgp';
//import { EmailModel } from 'Model/Email'; //import { EmailModel } from 'Model/Email';
//import { OpenPgpKeyModel } from 'Model/OpenPgpKey'; //import { OpenPgpKeyModel } from 'Model/OpenPgpKey';
import Remote from 'Remote/User/Fetch'; import Remote from 'Remote/User/Fetch';
import { showScreenPopup } from 'Knoin/Knoin'; import { showScreenPopup } from 'Knoin/Knoin';
import { ViewOpenPgpKeyPopupView } from 'View/Popup/ViewOpenPgpKey'; import { OpenPgpKeyPopupView } from 'View/Popup/OpenPgpKey';
const const
findKeyByHex = (keys, hash) => findKeyByHex = (keys, hash) =>
keys.find(item => item && (hash === item.id || item.ids.includes(hash))); keys.find(item => item && (hash === item.id || item.ids.includes(hash))),
findGnuPGKey = (keys, query, sign) =>
keys.find(key =>
key[sign ? 'can_sign' : 'can_decrypt']
&& (key.emails.includes(query) || key.subkeys.find(key => query == key.keyid || query == key.fingerprint))
),
findOpenPGPKey = (keys, query/*, sign*/) =>
keys.find(key =>
key.emails.includes(query) || query == key.id || query == key.fingerprint
);
/** /**
* OpenPGP.js v5 removed the localStorage (keyring) * OpenPGP.js v5 removed the localStorage (keyring)
@ -34,12 +43,10 @@ const
let keys = [], key, let keys = [], key,
armoredKeys = JSON.parse(storage.getItem(itemname)), armoredKeys = JSON.parse(storage.getItem(itemname)),
i = arrayLength(armoredKeys); i = arrayLength(armoredKeys);
if (i) { while (i--) {
while (i--) { key = await openpgp.readKey({armoredKey:armoredKeys[i]});
key = await openpgp.readKey({armoredKey:armoredKeys[i]}); if (!key.err) {
if (!key.err) { keys.push(new OpenPgpKeyModel(armoredKeys[i], key));
keys.push(new OpenPgpKeyModel(armoredKeys[i], key));
}
} }
} }
return keys; return keys;
@ -73,7 +80,7 @@ class OpenPgpKeyModel {
} }
view() { view() {
showScreenPopup(ViewOpenPgpKeyPopupView, [this]); showScreenPopup(OpenPgpKeyPopupView, [this]);
} }
remove() { remove() {
@ -88,6 +95,11 @@ class OpenPgpKeyModel {
delegateRunOnDestroy(this); delegateRunOnDestroy(this);
} }
} }
/*
toJSON() {
return this.armor;
}
*/
} }
export const PgpUserStore = new class { export const PgpUserStore = new class {
@ -165,6 +177,7 @@ export const PgpUserStore = new class {
const initKey = (key, isPrivate) => { const initKey = (key, isPrivate) => {
const aEmails = []; const aEmails = [];
key.id = key.subkeys[0].keyid; key.id = key.subkeys[0].keyid;
key.fingerprint = key.subkeys[0].fingerprint;
key.uids.forEach(uid => uid.email && aEmails.push(uid.email)); key.uids.forEach(uid => uid.email && aEmails.push(uid.email));
key.emails = aEmails; key.emails = aEmails;
key.askDelete = ko.observable(false); key.askDelete = ko.observable(false);
@ -195,7 +208,7 @@ export const PgpUserStore = new class {
(iError, oData) => { (iError, oData) => {
if (oData && oData.Result) { if (oData && oData.Result) {
key.armor = oData.Result; key.armor = oData.Result;
showScreenPopup(ViewOpenPgpKeyPopupView, [key]); showScreenPopup(OpenPgpKeyPopupView, [key]);
} }
}, { }, {
KeyId: key.id, KeyId: key.id,
@ -260,6 +273,14 @@ export const PgpUserStore = new class {
keyPair.inGnuPG keyPair.inGnuPG
*/ */
storeKeyPair(keyPair, callback) { storeKeyPair(keyPair, callback) {
openpgp.readKey({armoredKey:keyPair.publicKey}).then(key => {
PgpUserStore.openpgpPublicKeys.push(new OpenPgpKeyModel(keyPair.publicKey, key));
storeOpenPgpKeys(PgpUserStore.openpgpPublicKeys, publicKeysItem);
});
openpgp.readKey({armoredKey:keyPair.privateKey}).then(key => {
PgpUserStore.openpgpPrivateKeys.push(new OpenPgpKeyModel(keyPair.privateKey, key));
storeOpenPgpKeys(PgpUserStore.openpgpPrivateKeys, privateKeysItem);
});
// if (Settings.capa(Capa.GnuPG)) { // if (Settings.capa(Capa.GnuPG)) {
Remote.request('PgpStoreKeyPair', Remote.request('PgpStoreKeyPair',
(iError, oData) => { (iError, oData) => {
@ -269,14 +290,6 @@ export const PgpUserStore = new class {
callback && callback(iError, oData); callback && callback(iError, oData);
}, keyPair }, keyPair
); );
openpgp.readKey({armoredKey:keyPair.publicKey}).then(key => {
PgpUserStore.openpgpPublicKeys.push(new OpenPgpKeyModel(keyPair.publicKey, key));
storeOpenPgpKeys(PgpUserStore.openpgpPublicKeys, publicKeysItem);
});
openpgp.readKey({armoredKey:keyPair.privateKey}).then(key => {
PgpUserStore.openpgpPrivateKeys.push(new OpenPgpKeyModel(keyPair.privateKey, key));
storeOpenPgpKeys(PgpUserStore.openpgpPrivateKeys, privateKeysItem);
});
} }
/** /**
@ -287,7 +300,9 @@ export const PgpUserStore = new class {
const count = recipients.length; const count = recipients.length;
if (count) { if (count) {
let length = this.gnupgKeyring && recipients.filter(email => let length = this.gnupgKeyring && recipients.filter(email =>
this.gnupgKeyring[email] && this.gnupgKeyring[email].can_encrypt).length; // (key.can_verify || key.can_encrypt) &&
this.gnupgPublicKeys.find(key => key.emails.includes(email))
).length;
if (length && (!all || length === count)) { if (length && (!all || length === count)) {
return 'gnupg'; return 'gnupg';
} }
@ -299,52 +314,50 @@ export const PgpUserStore = new class {
return 'openpgp'; return 'openpgp';
} }
let mailvelope = this.mailvelopeKeyring && await this.mailvelopeKeyring.validKeyForAddress(recipients) let keyring = this.mailvelopeKeyring,
mailvelope = keyring && await keyring.validKeyForAddress(recipients)
/*.then(LookupResult => Object.entries(LookupResult))*/; /*.then(LookupResult => Object.entries(LookupResult))*/;
mailvelope = Object.entries(mailvelope); mailvelope = mailvelope && Object.entries(mailvelope);
if (mailvelope && mailvelope.length if (mailvelope && (all ? (mailvelope.filter(([, value]) => value).length === count) : mailvelope.length)) {
&& (all ? (mailvelope.filter(([, value]) => value).length === count) : mailvelope.find(([, value]) => value))
) {
return 'mailvelope'; return 'mailvelope';
} }
} }
return false; return false;
} }
getGnuPGPrivateKeyFor(email, sign) { getGnuPGPrivateKeyFor(query, sign) {
let key = this.gnupgKeyring && this.gnupgKeyring[email]; let key = findGnuPGKey(this.gnupgPrivateKeys, query, sign);
if (key && key[sign?'can_sign':'can_decrypt']) { if (key) {
return ['gnupg', key]; return ['gnupg', key];
} }
} }
getOpenPGPPrivateKeyFor(email/*, sign*/) { getGnuPGPublicKeyFor(query, sign) {
let key = this.openpgpPrivateKeys().find(key => key.emails.includes(email)); let key = findGnuPGKey(this.gnupgPublicKeys, query, sign);
if (key && key.length) { if (key) {
return ['openpgp', key[0]]; return ['gnupg', key];
} }
} }
getOpenPGPPublicKeyFor(email/*, sign*/) { getOpenPGPPrivateKeyFor(query/*, sign*/) {
return this.gnupgKeyring && this.openpgpKeyring.publicKeys.getForAddress(email); let key = findOpenPGPKey(this.openpgpPrivateKeys, query/*, sign*/);
if (key) {
return ['openpgp', key];
}
}
getOpenPGPPublicKeyFor(query/*, sign*/) {
let key = findOpenPGPKey(this.openpgpPublicKeys, query/*, sign*/);
if (key) {
return ['openpgp', key];
}
} }
/**
* Checks if signing a message is possible with given email address.
* Returns the first library that can.
*/
async getMailvelopePrivateKeyFor(email/*, sign*/) { async getMailvelopePrivateKeyFor(email/*, sign*/) {
let keyring = this.mailvelopeKeyring; let keyring = this.mailvelopeKeyring;
if (keyring) { if (keyring && await keyring.hasPrivateKey({email:email})) {
/** return ['mailvelope', email];
* Mailvelope can't find by email, so we must get the fingerprint and use that instead
*/
let keys = await keyring.validKeyForAddress([email]);
if (keys && keys[email] && await keyring.hasPrivateKey(keys[email].keys[0].fingerprint)) {
return ['mailvelope', keys[email].keys[0].fingerprint];
}
} }
return false; return false;
} }
@ -359,13 +372,41 @@ export const PgpUserStore = new class {
} }
/** /**
* Checks if decrypting a message is possible with given email address. * Checks if decrypting a message is possible with given keyIds or email address.
* Returns the first library that can. * Returns the first library that can.
*/ */
async getKeyForDecrypting(email) { async getKeyForDecryption(ids, email) {
return await this.getMailvelopePrivateKeyFor(email) ids = [email].concat(ids);
|| this.getGnuPGPrivateKeyFor(email) let i = ids.length,
|| this.getOpenPGPPrivateKeyFor(email); key = await this.getMailvelopePrivateKeyFor({email:email});
if (key) {
return key;
}
/* Not working, needs full fingerprint
while (i--) {
key = await this.getMailvelopePrivateKeyFor(ids[i]);
if (key) {
return key;
}
if (await keyring.hasPrivateKey(ids[i])) {
return ['mailvelope', ids[i]];
}
}
i = ids.length;
*/
while (i--) {
key = this.getGnuPGPrivateKeyFor(ids[i]);
if (key) {
return key;
}
}
i = ids.length;
while (i--) {
key = this.getOpenPGPPrivateKeyFor(ids[i]);
if (key) {
return key;
}
}
} }
/** /**
@ -394,7 +435,7 @@ export const PgpUserStore = new class {
} }
if (privateKeys && privateKeys.length) { if (privateKeys && privateKeys.length) {
showScreenPopup(MessageOpenPgpPopupView, [ showScreenPopup(OpenPgpSelectorPopupView, [
(decryptedKey) => { (decryptedKey) => {
if (decryptedKey) { if (decryptedKey) {
message.decrypt(decryptedKey).then( message.decrypt(decryptedKey).then(

View file

@ -1,9 +1,10 @@
#V-PopupsViewOpenPgpKey, #V-PopupsOpenPgpGenerate { #V-PopupsOpenPgpKey, #V-PopupsOpenPgpGenerate {
max-width: 570px; max-width: 570px;
} }
#V-PopupsViewOpenPgpKey { #V-PopupsOpenPgpKey {
.key-viewer { .key-viewer {
margin: 0;
max-height: 500px; max-height: 500px;
overflow: auto; overflow: auto;
} }

View file

@ -2,9 +2,9 @@ import { Scope } from 'Common/Enums';
import { doc } from 'Common/Globals'; import { doc } from 'Common/Globals';
import { AbstractViewPopup } from 'Knoin/AbstractViews'; import { AbstractViewPopup } from 'Knoin/AbstractViews';
class ViewOpenPgpKeyPopupView extends AbstractViewPopup { class OpenPgpKeyPopupView extends AbstractViewPopup {
constructor() { constructor() {
super('ViewOpenPgpKey'); super('OpenPgpKey');
this.addObservables({ this.addObservables({
key: '', key: '',
@ -21,18 +21,25 @@ class ViewOpenPgpKeyPopupView extends AbstractViewPopup {
range.selectNodeContents(el); range.selectNodeContents(el);
sel.addRange(range); sel.addRange(range);
} }
if (navigator.clipboard) {
navigator.clipboard.writeText(this.key()).then(
() => console.log('Copied to clipboard'),
err => console.error(err)
);
}
} }
onShow(openPgpKey) { onShow(openPgpKey) {
// TODO: show more info
this.key(openPgpKey ? openPgpKey.armor : ''); this.key(openPgpKey ? openPgpKey.armor : '');
} }
onBuild() { onBuild() {
shortcuts.add('a', 'meta', Scope.ViewOpenPgpKey, () => { shortcuts.add('a', 'meta', Scope.OpenPgpKey, () => {
this.selectKey(); this.selectKey();
return false; return false;
}); });
} }
} }
export { ViewOpenPgpKeyPopupView, ViewOpenPgpKeyPopupView as default }; export { OpenPgpKeyPopupView, OpenPgpKeyPopupView as default };

View file

@ -625,72 +625,71 @@ export class MailMessageView extends AbstractViewRight {
} }
pgpDecrypt(self) { pgpDecrypt(self) {
const pgpInfo = self.pgpEncrypted(); const message = self.message(),
pgpInfo = message && message.pgpEncrypted();
if (pgpInfo) { if (pgpInfo) {
const message = self.message(); // Also check message.from[0].email
if (window.mailvelope) { PgpUserStore.getKeyForDecryption(pgpInfo.KeyIds, message.to[0].email).then(result => {
/** if (!result) {
* https://mailvelope.github.io/mailvelope/Mailvelope.html#createEncryptedFormContainer // TODO: show error
* Creates an iframe to display an encrypted form alert('No decrypt key found for ids:\n\n' + pgpInfo.KeyIds.join('\n'));
*/ return;
// mailvelope.createEncryptedFormContainer('#mailvelope-form');
/**
* https://mailvelope.github.io/mailvelope/Mailvelope.html#createDisplayContainer
* Creates an iframe to display the decrypted content of the encrypted mail.
*/
let body = message.body;
body.textContent = '';
mailvelope.createDisplayContainer(
'#'+body.id,
message.plain(),
PgpUserStore.mailvelopeKeyring,
{
senderAddress: message.from[0].email
}
).then(status => {
if (status.error && status.error.message) {
alert(status.error.code + ': ' + status.error.message);
} else {
body.classList.add('mailvelope');
}
}, error => {
console.error(error);
});
}
/*
else {
// TODO: which key to decrypt, use pgpInfo.KeyIds
PgpUserStore.getKeyForDecrypting(message.email()).then(result => {
console.log({canPgpSign:result});
this.canPgpSign(!!result)
});
else if (window.openpgp) {
decryptMessage(message, recipients, fCallback)
}
else if (Settings.capa(Capa.GnuPG)) {
message.
let params = {
Folder: message.folder,
Uid: message.uid,
PartId: message.pgpEncrypted().PartId,
KeyId: '',
Passphrase: prompt("Passphrase", ''),
Data: '' // optional
} }
rl.app.Remote.post('GnupgDecrypt', null, params) if ('mailvelope' === result[0]) {
.then(data => { /**
// TODO * https://mailvelope.github.io/mailvelope/Mailvelope.html#createEncryptedFormContainer
console.dir(data); * Creates an iframe to display an encrypted form
}) */
.catch(error => { // mailvelope.createEncryptedFormContainer('#mailvelope-form');
// TODO /**
console.dir(error); * https://mailvelope.github.io/mailvelope/Mailvelope.html#createDisplayContainer
* Creates an iframe to display the decrypted content of the encrypted mail.
*/
let body = message.body;
body.textContent = '';
mailvelope.createDisplayContainer(
'#'+body.id,
message.plain(),
PgpUserStore.mailvelopeKeyring,
{
senderAddress: message.from[0].email
}
).then(status => {
if (status.error && status.error.message) {
alert(status.error.code + ': ' + status.error.message);
} else {
body.classList.add('mailvelope');
}
}, error => {
console.error(error);
}); });
} }
*/ else if ('openpgp' === result[0]) {
// TODO
// PgpUserStore.decryptMessage(message, recipients, fCallback)
}
else if ('gnupg' === result[0]) {
let params = {
Folder: message.folder,
Uid: message.uid,
PartId: pgpInfo.PartId,
KeyId: result[1].id,
Passphrase: prompt('Passphrase for ' + result[1].id + ' ' + result[1].uids[0].uid),
Data: '' // optional
}
if (params.Passphrase) {
rl.app.Remote.post('GnupgDecrypt', null, params)
.then(data => {
// TODO
console.dir(data);
})
.catch(error => {
// TODO
console.dir(error);
});
}
}
});
} }
} }

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "الافتراضي" "DEFAULT_IDENTITY_LABEL": "الافتراضي"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "OpenPGP إستيراد مفتاح", "BUTTON_IMPORT_KEY": " إستيراد مفتاح",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "OpenPGP توليد مفتاح", "BUTTON_GENERATE_KEY_PAIR": " توليد مفتاح",
"TITLE_PRIVATE": "خاص", "TITLE_PRIVATE": "خاص",
"TITLE_PUBLIC": "عام", "TITLE_PUBLIC": "عام",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "по подразбиране" "DEFAULT_IDENTITY_LABEL": "по подразбиране"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Внеси OpenPGP ключ", "BUTTON_IMPORT_KEY": "Внеси ключ",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Генерирай OpenPGP ключ", "BUTTON_GENERATE_KEY_PAIR": "Генерирай ключ",
"TITLE_PRIVATE": "Частен", "TITLE_PRIVATE": "Частен",
"TITLE_PUBLIC": "Публичен", "TITLE_PUBLIC": "Публичен",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Автоматично запазване на чернова" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Автоматично запазване на чернова"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "výchozí" "DEFAULT_IDENTITY_LABEL": "výchozí"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importovat OpenPGP klíč", "BUTTON_IMPORT_KEY": "Importovat klíč",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Generovat OpenPGP klíče", "BUTTON_GENERATE_KEY_PAIR": "Generovat klíče",
"TITLE_PRIVATE": "Soukromý", "TITLE_PRIVATE": "Soukromý",
"TITLE_PUBLIC": "Veřejný", "TITLE_PUBLIC": "Veřejný",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automaticky uložit koncept" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automaticky uložit koncept"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "standard" "DEFAULT_IDENTITY_LABEL": "standard"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importer OpenPGP nøgle", "BUTTON_IMPORT_KEY": "Importer nøgle",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Generer OpenPGP nøgler", "BUTTON_GENERATE_KEY_PAIR": "Generer nøgler",
"TITLE_PRIVATE": "Privat", "TITLE_PRIVATE": "Privat",
"TITLE_PUBLIC": "Offentlig", "TITLE_PUBLIC": "Offentlig",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Gem kladde automatisk" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Gem kladde automatisk"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "Standard" "DEFAULT_IDENTITY_LABEL": "Standard"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "OpenPGP-Schlüssel importieren", "BUTTON_IMPORT_KEY": "Schlüssel importieren",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "OpenPGP-Schlüssel generieren", "BUTTON_GENERATE_KEY_PAIR": "Schlüssel generieren",
"TITLE_PRIVATE": "Privat", "TITLE_PRIVATE": "Privat",
"TITLE_PUBLIC": "Öffentlich", "TITLE_PUBLIC": "Öffentlich",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "default" "DEFAULT_IDENTITY_LABEL": "default"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Import OpenPGP Key", "BUTTON_IMPORT_KEY": "Import Key",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Generate OpenPGP Keys", "BUTTON_GENERATE_KEY_PAIR": "Generate Keys",
"TITLE_PRIVATE": "Private", "TITLE_PRIVATE": "Private",
"TITLE_PUBLIC": "Public", "TITLE_PUBLIC": "Public",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -257,7 +257,7 @@
"POPUP_IMPORT_BUTTON": "Import", "POPUP_IMPORT_BUTTON": "Import",
"POPUP_VIEW_TITLE": "View OpenPGP key", "POPUP_VIEW_TITLE": "View OpenPGP key",
"POPUP_VIEW_BUTTON": "Select", "POPUP_VIEW_BUTTON": "Select",
"POPUP_GENERATE_TITLE": "Generate OpenPGP keys", "POPUP_GENERATE_TITLE": "Generate OpenPGP key pair",
"POPUP_GENERATE_BUTTON": "Generate", "POPUP_GENERATE_BUTTON": "Generate",
"LABEL_KEY_TYPE": "Type", "LABEL_KEY_TYPE": "Type",
"LABEL_SIGN": "Sign", "LABEL_SIGN": "Sign",
@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "default" "DEFAULT_IDENTITY_LABEL": "default"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Import OpenPGP Key", "BUTTON_IMPORT_KEY": "Import Key",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Generate OpenPGP Keys", "BUTTON_GENERATE_KEY_PAIR": "Generate Key Pair",
"TITLE_PRIVATE": "Private", "TITLE_PRIVATE": "Private",
"TITLE_PUBLIC": "Public", "TITLE_PUBLIC": "Public",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "predeterminado" "DEFAULT_IDENTITY_LABEL": "predeterminado"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importar llave OpenPGP", "BUTTON_IMPORT_KEY": "Importar llave",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Generar llaves OpenPGP", "BUTTON_GENERATE_KEY_PAIR": "Generar llaves",
"TITLE_PRIVATE": "Privado", "TITLE_PRIVATE": "Privado",
"TITLE_PUBLIC": "Público", "TITLE_PUBLIC": "Público",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "vaikimisi" "DEFAULT_IDENTITY_LABEL": "vaikimisi"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Impordi OpenPGP võti", "BUTTON_IMPORT_KEY": "Impordi võti",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Genereeri OpenPGP võti", "BUTTON_GENERATE_KEY_PAIR": "Genereeri võti",
"TITLE_PRIVATE": "Privaatne", "TITLE_PRIVATE": "Privaatne",
"TITLE_PUBLIC": "Avalik", "TITLE_PUBLIC": "Avalik",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "پیش‌فرض" "DEFAULT_IDENTITY_LABEL": "پیش‌فرض"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "وارد کردن کلید OpenPGP", "BUTTON_IMPORT_KEY": "وارد کردن کلید",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "تولید کلیدهای OpenPGP", "BUTTON_GENERATE_KEY_PAIR": "تولید کلیدهای",
"TITLE_PRIVATE": "خصوصی", "TITLE_PRIVATE": "خصوصی",
"TITLE_PUBLIC": "عمومی", "TITLE_PUBLIC": "عمومی",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "ذخیره خودکار پیش‌نویس" "LABEL_ALLOW_DRAFT_AUTOSAVE": "ذخیره خودکار پیش‌نویس"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "oletus" "DEFAULT_IDENTITY_LABEL": "oletus"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Tuo OpenPGP avain", "BUTTON_IMPORT_KEY": "Tuo avain",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Luo OpenPGP avain", "BUTTON_GENERATE_KEY_PAIR": "Luo avain",
"TITLE_PRIVATE": "Yksityinen", "TITLE_PRIVATE": "Yksityinen",
"TITLE_PUBLIC": "Julkinen", "TITLE_PUBLIC": "Julkinen",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "défaut" "DEFAULT_IDENTITY_LABEL": "défaut"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importer la clé OpenPGP", "BUTTON_IMPORT_KEY": "Importer la clé",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Générer les clés OpenPGP", "BUTTON_GENERATE_KEY_PAIR": "Générer les clés",
"TITLE_PRIVATE": "Privée", "TITLE_PRIVATE": "Privée",
"TITLE_PUBLIC": "Publique", "TITLE_PUBLIC": "Publique",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Brouillon sauvegardé automatiquement" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Brouillon sauvegardé automatiquement"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "default" "DEFAULT_IDENTITY_LABEL": "default"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "OpenPGP kulcs importálás", "BUTTON_IMPORT_KEY": "Kulcs importálás",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "OpenPGP kulcs generálás", "BUTTON_GENERATE_KEY_PAIR": "Kulcs generálás",
"TITLE_PRIVATE": "Privát", "TITLE_PRIVATE": "Privát",
"TITLE_PUBLIC": "Publikus", "TITLE_PUBLIC": "Publikus",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Piszkozat automatikus mentése" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Piszkozat automatikus mentése"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "Bawaan" "DEFAULT_IDENTITY_LABEL": "Bawaan"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Impor kunci OpenPGP", "BUTTON_IMPORT_KEY": "Impor kunci",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Buat kunci OpenPGP", "BUTTON_GENERATE_KEY_PAIR": "Buat kunci",
"TITLE_PRIVATE": "Pribadi", "TITLE_PRIVATE": "Pribadi",
"TITLE_PUBLIC": "Publik", "TITLE_PUBLIC": "Publik",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Simpan konsep otomatis" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Simpan konsep otomatis"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "sjálfgefið" "DEFAULT_IDENTITY_LABEL": "sjálfgefið"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Flytja inn OpenPGP-lykil", "BUTTON_IMPORT_KEY": "Flytja inn lykil",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Búa til OpenPGP-lykla", "BUTTON_GENERATE_KEY_PAIR": "Búa til lykla",
"TITLE_PRIVATE": "Einkalykill", "TITLE_PRIVATE": "Einkalykill",
"TITLE_PUBLIC": "Dreifilykill", "TITLE_PUBLIC": "Dreifilykill",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Vista drög sjálfkrafa" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Vista drög sjálfkrafa"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "predefinito" "DEFAULT_IDENTITY_LABEL": "predefinito"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importa chiave OpenPGP", "BUTTON_IMPORT_KEY": "Importa chiave",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Genera chiave OpenPGP", "BUTTON_GENERATE_KEY_PAIR": "Genera chiave",
"TITLE_PRIVATE": "Privata", "TITLE_PRIVATE": "Privata",
"TITLE_PUBLIC": "Pubblica", "TITLE_PUBLIC": "Pubblica",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Salva automaticamente la bozza" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Salva automaticamente la bozza"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "デフォルト" "DEFAULT_IDENTITY_LABEL": "デフォルト"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "OpenPGP キーをインポート", "BUTTON_IMPORT_KEY": "キーをインポート",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "OpenPGP キーを生成", "BUTTON_GENERATE_KEY_PAIR": "キーを生成",
"TITLE_PRIVATE": "プライベート", "TITLE_PRIVATE": "プライベート",
"TITLE_PUBLIC": "パブリック", "TITLE_PUBLIC": "パブリック",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "下書きを自動的に保存する" "LABEL_ALLOW_DRAFT_AUTOSAVE": "下書きを自動的に保存する"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "default" "DEFAULT_IDENTITY_LABEL": "default"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "OpenPGP 키 가져오기", "BUTTON_IMPORT_KEY": "키 가져오기",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "OpenPGP 키 생성", "BUTTON_GENERATE_KEY_PAIR": "키 생성",
"TITLE_PRIVATE": "비공개", "TITLE_PRIVATE": "비공개",
"TITLE_PUBLIC": "공개", "TITLE_PUBLIC": "공개",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "작성 중인 메시지 자동 저장" "LABEL_ALLOW_DRAFT_AUTOSAVE": "작성 중인 메시지 자동 저장"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "numatytasis" "DEFAULT_IDENTITY_LABEL": "numatytasis"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importuoti OpenPGP raktą", "BUTTON_IMPORT_KEY": "Importuoti raktą",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Sukurti OpenPGP raktus", "BUTTON_GENERATE_KEY_PAIR": "Sukurti raktus",
"TITLE_PRIVATE": "Privatus", "TITLE_PRIVATE": "Privatus",
"TITLE_PUBLIC": "Viešas", "TITLE_PUBLIC": "Viešas",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "default" "DEFAULT_IDENTITY_LABEL": "default"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Import OpenPGP Key", "BUTTON_IMPORT_KEY": "Import Key",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Generate OpenPGP Keys", "BUTTON_GENERATE_KEY_PAIR": "Generate Keys",
"TITLE_PRIVATE": "Private", "TITLE_PRIVATE": "Private",
"TITLE_PUBLIC": "Public", "TITLE_PUBLIC": "Public",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "Standard" "DEFAULT_IDENTITY_LABEL": "Standard"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importer OpenPGP-nøkkel", "BUTTON_IMPORT_KEY": "Importer nøkkel",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Lag OpenPGP-nøkler", "BUTTON_GENERATE_KEY_PAIR": "Lag nøkler",
"TITLE_PRIVATE": "Privat", "TITLE_PRIVATE": "Privat",
"TITLE_PUBLIC": "Offentlig", "TITLE_PUBLIC": "Offentlig",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Lagre utkast automatisk" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Lagre utkast automatisk"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "standaard" "DEFAULT_IDENTITY_LABEL": "standaard"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importeer OpenPGP sleutel", "BUTTON_IMPORT_KEY": "Importeer sleutel",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Genereer OpenPGP sleutels", "BUTTON_GENERATE_KEY_PAIR": "Genereer sleutels",
"TITLE_PRIVATE": "Privé sleutel", "TITLE_PRIVATE": "Privé sleutel",
"TITLE_PUBLIC": "Publieke sleutel", "TITLE_PUBLIC": "Publieke sleutel",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "domyślna" "DEFAULT_IDENTITY_LABEL": "domyślna"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importuj klucz OpenPGP", "BUTTON_IMPORT_KEY": "Importuj klucz",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Generuj klucz OpenPGP", "BUTTON_GENERATE_KEY_PAIR": "Generuj klucz",
"TITLE_PRIVATE": "Prywatny", "TITLE_PRIVATE": "Prywatny",
"TITLE_PUBLIC": "Publiczny", "TITLE_PUBLIC": "Publiczny",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatycznie zapisuj szkic" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatycznie zapisuj szkic"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "padrão" "DEFAULT_IDENTITY_LABEL": "padrão"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importa chave OpenPGP", "BUTTON_IMPORT_KEY": "Importa chave",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Gerar chave OpenPGP", "BUTTON_GENERATE_KEY_PAIR": "Gerar chave",
"TITLE_PRIVATE": "Privado", "TITLE_PRIVATE": "Privado",
"TITLE_PUBLIC": "Público", "TITLE_PUBLIC": "Público",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Salvar automaticamente rascunho" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Salvar automaticamente rascunho"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "predefinida" "DEFAULT_IDENTITY_LABEL": "predefinida"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importar chave OpenPGP", "BUTTON_IMPORT_KEY": "Importar chave",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Gerar chaves OpenPGP", "BUTTON_GENERATE_KEY_PAIR": "Gerar chaves",
"TITLE_PRIVATE": "Privada", "TITLE_PRIVATE": "Privada",
"TITLE_PUBLIC": "Pública", "TITLE_PUBLIC": "Pública",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "default" "DEFAULT_IDENTITY_LABEL": "default"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Import OpenPGP Key", "BUTTON_IMPORT_KEY": "Import Key",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Generate OpenPGP Keys", "BUTTON_GENERATE_KEY_PAIR": "Generate Keys",
"TITLE_PRIVATE": "Private", "TITLE_PRIVATE": "Private",
"TITLE_PUBLIC": "Public", "TITLE_PUBLIC": "Public",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Salvează ciorna automat" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Salvează ciorna automat"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "основной" "DEFAULT_IDENTITY_LABEL": "основной"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Ипортировать OpenPGP ключ", "BUTTON_IMPORT_KEY": "Ипортировать ключ",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Новый OpenPGP ключ", "BUTTON_GENERATE_KEY_PAIR": "Новый ключ",
"TITLE_PRIVATE": "Приватный", "TITLE_PRIVATE": "Приватный",
"TITLE_PUBLIC": "Публичный", "TITLE_PUBLIC": "Публичный",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Автоматически сохранять черновик" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Автоматически сохранять черновик"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "default" "DEFAULT_IDENTITY_LABEL": "default"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Import OpenPGP Key", "BUTTON_IMPORT_KEY": "Import Key",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Generate OpenPGP Keys", "BUTTON_GENERATE_KEY_PAIR": "Generate Keys",
"TITLE_PRIVATE": "Private", "TITLE_PRIVATE": "Private",
"TITLE_PUBLIC": "Public", "TITLE_PUBLIC": "Public",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automaticky uložiť koncept." "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automaticky uložiť koncept."

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "privzeto" "DEFAULT_IDENTITY_LABEL": "privzeto"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Uvozi OpenPGP ključ", "BUTTON_IMPORT_KEY": "Uvozi ključ",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Generiraj OpenPGP ključe", "BUTTON_GENERATE_KEY_PAIR": "Generiraj ključe",
"TITLE_PRIVATE": "Zasebni", "TITLE_PRIVATE": "Zasebni",
"TITLE_PUBLIC": "Javni", "TITLE_PUBLIC": "Javni",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Samodejno shrani osnutek" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Samodejno shrani osnutek"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "standard" "DEFAULT_IDENTITY_LABEL": "standard"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Importera OpenPGP-nyckel", "BUTTON_IMPORT_KEY": "Importera nyckel",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Skapa OpenPGP-nycklar", "BUTTON_GENERATE_KEY_PAIR": "Skapa nycklar",
"TITLE_PRIVATE": "Privat", "TITLE_PRIVATE": "Privat",
"TITLE_PUBLIC": "Publik", "TITLE_PUBLIC": "Publik",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Spara utkast automatiskt" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Spara utkast automatiskt"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "default" "DEFAULT_IDENTITY_LABEL": "default"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "OpenPGP Key İçe Aktar", "BUTTON_IMPORT_KEY": "Key İçe Aktar",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "OpenPGP Key Oluştur", "BUTTON_GENERATE_KEY_PAIR": "Key Oluştur",
"TITLE_PRIVATE": "Private", "TITLE_PRIVATE": "Private",
"TITLE_PUBLIC": "Public", "TITLE_PUBLIC": "Public",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "default" "DEFAULT_IDENTITY_LABEL": "default"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "Імпортувати OpenPGP ключ", "BUTTON_IMPORT_KEY": "Імпортувати ключ",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "Новий OpenPGP ключ", "BUTTON_GENERATE_KEY_PAIR": "Новий ключ",
"TITLE_PRIVATE": "Приватний", "TITLE_PRIVATE": "Приватний",
"TITLE_PUBLIC": "Публічний", "TITLE_PUBLIC": "Публічний",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "默认" "DEFAULT_IDENTITY_LABEL": "默认"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "导入 OpenPGP 密钥", "BUTTON_IMPORT_KEY": "导入 密钥",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "生成 OpenPGP 密钥", "BUTTON_GENERATE_KEY_PAIR": "生成 密钥",
"TITLE_PRIVATE": "私有", "TITLE_PRIVATE": "私有",
"TITLE_PUBLIC": "公开", "TITLE_PUBLIC": "公开",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "自动保存草稿" "LABEL_ALLOW_DRAFT_AUTOSAVE": "自动保存草稿"

View file

@ -449,8 +449,8 @@
"DEFAULT_IDENTITY_LABEL": "default" "DEFAULT_IDENTITY_LABEL": "default"
}, },
"SETTINGS_OPEN_PGP": { "SETTINGS_OPEN_PGP": {
"BUTTON_ADD_OPEN_PGP_KEY": "導入 OpenPGP Key", "BUTTON_IMPORT_KEY": "導入 Key",
"BUTTON_GENERATE_OPEN_PGP_KEYS": "生成 OpenPGP 密鑰", "BUTTON_GENERATE_KEY_PAIR": "生成 密鑰",
"TITLE_PRIVATE": "私有", "TITLE_PRIVATE": "私有",
"TITLE_PUBLIC": "公開", "TITLE_PUBLIC": "公開",
"LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft" "LABEL_ALLOW_DRAFT_AUTOSAVE": "Automatically save draft"

View file

@ -1,8 +1,8 @@
<div class="legend">OpenPGP</div> <div class="legend">OpenPGP</div>
<button class="btn" data-bind="click: addOpenPgpKey" data-icon="✚" data-i18n="SETTINGS_OPEN_PGP/BUTTON_ADD_OPEN_PGP_KEY"></button> <button class="btn" data-bind="click: addOpenPgpKey" data-icon="✚" data-i18n="SETTINGS_OPEN_PGP/BUTTON_IMPORT_KEY"></button>
<!-- ko if: canOpenPGP || canGnuPG --> <!-- ko if: canOpenPGP || canGnuPG -->
&nbsp;&nbsp; &nbsp;&nbsp;
<button class="btn" data-bind="click: generateOpenPgpKey" data-icon="🔑" data-i18n="SETTINGS_OPEN_PGP/BUTTON_GENERATE_OPEN_PGP_KEYS"></button> <button class="btn" data-bind="click: generateOpenPgpKey" data-icon="🔑" data-i18n="SETTINGS_OPEN_PGP/BUTTON_GENERATE_KEY_PAIR"></button>
<!-- /ko --> <!-- /ko -->
<br /> <br />
@ -18,7 +18,8 @@
</div> </div>
<br /> <br />
<details data-bind="if: canGnuPG"> <!-- ko if: canGnuPG -->
<details>
<summary class="legend">GnuPG</summary> <summary class="legend">GnuPG</summary>
<table class="table table-hover list-table"> <table class="table table-hover list-table">
<tbody><tr><th colspan="4" data-i18n="SETTINGS_OPEN_PGP/TITLE_PRIVATE">Private keys</th></tr></tbody> <tbody><tr><th colspan="4" data-i18n="SETTINGS_OPEN_PGP/TITLE_PRIVATE">Private keys</th></tr></tbody>
@ -63,8 +64,10 @@
</tbody> </tbody>
</table> </table>
</details> </details>
<!-- /ko -->
<details data-bind="if: canOpenPGP"> <!-- ko if: canOpenPGP -->
<details>
<summary class="legend">OpenPGP.js</summary> <summary class="legend">OpenPGP.js</summary>
<table class="table table-hover list-table"> <table class="table table-hover list-table">
<tbody><tr><th colspan="4" data-i18n="SETTINGS_OPEN_PGP/TITLE_PRIVATE">Private keys</th></tr></tbody> <tbody><tr><th colspan="4" data-i18n="SETTINGS_OPEN_PGP/TITLE_PRIVATE">Private keys</th></tr></tbody>
@ -107,8 +110,11 @@
</tbody> </tbody>
</table> </table>
</details> </details>
<!-- /ko -->
<details data-bind="if: canMailvelope"> <!-- ko if: canMailvelope -->
<details>
<summary class="legend">Mailvelope</summary> <summary class="legend">Mailvelope</summary>
<div id="mailvelope-settings" style="height:40em"></div> <div id="mailvelope-settings" style="height:40em"></div>
</details> </details>
<!-- /ko -->