Bug 1638822 - convert openpgp strings to Fluent - part 6 -jsm files continue. r=mkmelin
authorKhushil Mistry <khushil324@gmail.com>
Mon, 29 Jun 2020 18:09:33 +0300
changeset 38880 abe41c82065282417721bf3dbac9ec7a7cc7ceaa
parent 38879 97ca0281509e4a0f24066b8fa0b876c5a6f2a9a8
child 38881 396baf34dbd96f2da4951c402cba1a5fe0a13928
push id2646
push userclokep@gmail.com
push dateMon, 29 Jun 2020 21:33:35 +0000
treeherdercomm-beta@b1e911288dbd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmkmelin
bugs1638822
Bug 1638822 - convert openpgp strings to Fluent - part 6 -jsm files continue. r=mkmelin
mail/extensions/openpgp/content/modules/decryption.jsm
mail/extensions/openpgp/content/modules/dialog.jsm
mail/extensions/openpgp/content/modules/keyRing.jsm
mail/extensions/openpgp/content/modules/keyUsability.jsm
mail/extensions/openpgp/content/modules/mimeDecrypt.jsm
mail/extensions/openpgp/content/modules/persistentCrypto.jsm
mail/extensions/openpgp/content/modules/windows.jsm
mail/extensions/openpgp/content/strings/bond.ftl
mail/extensions/openpgp/content/strings/enigmail.ftl
mail/extensions/openpgp/content/strings/enigmail.properties
mail/extensions/openpgp/content/ui/commonWorkflows.js
mail/extensions/openpgp/content/ui/enigmailCommon.js
mail/extensions/openpgp/content/ui/enigmailKeyManager.js
mail/extensions/openpgp/content/ui/enigmailKeygen.js
mail/extensions/openpgp/content/ui/enigmailMessengerOverlay.js
mail/extensions/openpgp/content/ui/enigmailMsgBox.js
mail/extensions/openpgp/content/ui/enigmailMsgComposeOverlay.js
mail/extensions/openpgp/content/ui/keyDetailsDlg.js
--- a/mail/extensions/openpgp/content/modules/decryption.jsm
+++ b/mail/extensions/openpgp/content/modules/decryption.jsm
@@ -17,19 +17,16 @@ const { EnigmailLog } = ChromeUtils.impo
   "chrome://openpgp/content/modules/log.jsm"
 );
 const { EnigmailPrefs } = ChromeUtils.import(
   "chrome://openpgp/content/modules/prefs.jsm"
 );
 const { EnigmailArmor } = ChromeUtils.import(
   "chrome://openpgp/content/modules/armor.jsm"
 );
-const { EnigmailLocale } = ChromeUtils.import(
-  "chrome://openpgp/content/modules/locale.jsm"
-);
 const { EnigmailData } = ChromeUtils.import(
   "chrome://openpgp/content/modules/data.jsm"
 );
 const { EnigmailDialog } = ChromeUtils.import(
   "chrome://openpgp/content/modules/dialog.jsm"
 );
 const { EnigmailHttpProxy } = ChromeUtils.import(
   "chrome://openpgp/content/modules/httpProxy.jsm"
@@ -452,17 +449,17 @@ var EnigmailDecryption = {
         );
 
         importedKey = exitStatus === 0;
 
         if (exitStatus > 0) {
           l10n.formatValue("cant-import").then(value => {
             EnigmailDialog.alert(
               parent,
-              value + importErrorMsgObj.value
+              value + "\n" + importErrorMsgObj.value
             );
           });
         }
       }
 
       if (importedKey) {
         // Recursive call; note that EnigmailConstants.UI_ALLOW_KEY_IMPORT is unset
         // to break the recursion
@@ -550,19 +547,19 @@ var EnigmailDecryption = {
 
     let attachmentHead = byteData.substr(0, 200);
     if (attachmentHead.match(/-----BEGIN PGP \w{5,10} KEY BLOCK-----/)) {
       // attachment appears to be a PGP key file
 
       if (
         EnigmailDialog.confirmDlg(
           parent,
-          EnigmailLocale.getString("attachmentPgpKey", [displayName]),
+          l10n.formatValueSync("attachment-pgp-key", { name: displayName }),
           l10n.formatValueSync("key-man-button-import"),
-          EnigmailLocale.getString("dlg.button.view")
+          l10n.formatValueSync("dlg-button-view")
         )
       ) {
         let preview = EnigmailKey.getKeyListFromKeyBlock(
           byteData,
           errorMsgObj,
           true,
           true,
           false
--- a/mail/extensions/openpgp/content/modules/dialog.jsm
+++ b/mail/extensions/openpgp/content/modules/dialog.jsm
@@ -5,32 +5,31 @@
  */
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["EnigmailDialog"];
 
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-const { EnigmailLocale } = ChromeUtils.import(
-  "chrome://openpgp/content/modules/locale.jsm"
-);
 const { EnigmailLog } = ChromeUtils.import(
   "chrome://openpgp/content/modules/log.jsm"
 );
 const { EnigmailWindows } = ChromeUtils.import(
   "chrome://openpgp/content/modules/windows.jsm"
 );
 const { EnigmailPrefs } = ChromeUtils.import(
   "chrome://openpgp/content/modules/prefs.jsm"
 );
 const { EnigmailConstants } = ChromeUtils.import(
   "chrome://openpgp/content/modules/constants.jsm"
 );
 
+const l10n = new Localization(["messenger/openpgp/enigmail.ftl"], true);
+
 const LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1";
 
 var EnigmailDialog = {
   /***
    * Confirmation dialog with OK / Cancel buttons (both customizable)
    *
    * @win:         nsIWindow - parent window to display modal dialog; can be null
    * @mesg:        String    - message text
@@ -39,22 +38,22 @@ var EnigmailDialog = {
    *
    * @return:      Boolean   - true: OK pressed / false: Cancel or ESC pressed
    */
   confirmDlg(win, mesg, okLabel, cancelLabel) {
     let buttonPressed = EnigmailDialog.msgBox(
       win,
       {
         msgtext: mesg,
-        button1: okLabel ? okLabel : EnigmailLocale.getString("dlg.button.ok"),
+        button1: okLabel ? okLabel : l10n.formatValueSync("dlg-button-ok"),
         cancelButton: cancelLabel
           ? cancelLabel
-          : EnigmailLocale.getString("dlg.button.cancel"),
+          : l10n.formatValueSync("dlg-button-cancel"),
         iconType: EnigmailConstants.ICONTYPE_QUESTION,
-        dialogTitle: EnigmailLocale.getString("enigConfirm2"),
+        dialogTitle: l10n.formatValueSync("enig-confirm"),
       },
       null
     );
 
     return buttonPressed === 0;
   },
 
   /**
@@ -65,19 +64,19 @@ var EnigmailDialog = {
    *
    * no return value
    */
   alert(win, mesg) {
     EnigmailDialog.msgBox(
       win,
       {
         msgtext: mesg,
-        button1: EnigmailLocale.getString("dlg.button.close"),
+        button1: l10n.formatValueSync("dlg-button-close"),
         iconType: EnigmailConstants.ICONTYPE_ALERT,
-        dialogTitle: EnigmailLocale.getString("enigAlert2"),
+        dialogTitle: l10n.formatValueSync("enig-alert"),
       },
       null
     );
   },
 
   /**
    * Displays an information dialog.
    *
@@ -86,19 +85,19 @@ var EnigmailDialog = {
    *
    * no return value
    */
   info(win, mesg) {
     EnigmailDialog.msgBox(
       win,
       {
         msgtext: mesg,
-        button1: EnigmailLocale.getString("dlg.button.close"),
+        button1: l10n.formatValueSync("dlg-button-close"),
         iconType: EnigmailConstants.ICONTYPE_INFO,
-        dialogTitle: EnigmailLocale.getString("enigInfo2"),
+        dialogTitle: l10n.formatValueSync("enig-info"),
       },
       null
     );
   },
 
   /**
    * Displays an alert dialog with 1-3 optional buttons.
    *
@@ -209,17 +208,17 @@ var EnigmailDialog = {
    * @mesg:     String    - message text
    * @valueObj: Object    - object to hold the entered text in .value
    *
    * @return:   Boolean - true if OK was pressed / false otherwise
    */
   promptValue(win, mesg, valueObj) {
     return Services.prompt.prompt(
       win,
-      EnigmailLocale.getString("enigPrompt2"),
+      l10n.formatValueSync("enig-prompt"),
       mesg,
       valueObj,
       "",
       {}
     );
   },
 
   /**
@@ -241,19 +240,19 @@ var EnigmailDialog = {
       let checkBoxObj = {
         value: false,
       };
 
       let buttonPressed = EnigmailDialog.msgBox(
         win,
         {
           msgtext: mesg,
-          dialogTitle: EnigmailLocale.getString("enigInfo2"),
+          dialogTitle: l10n.formatValueSync("enig-info"),
           iconType: EnigmailConstants.ICONTYPE_INFO,
-          checkboxLabel: EnigmailLocale.getString("dlgNoPrompt"),
+          checkboxLabel: l10n.formatValueSync("dlg-no-prompt"),
         },
         checkBoxObj
       );
 
       if (checkBoxObj.value && buttonPressed === 0) {
         EnigmailPrefs.setPref(prefText, dontDisplay);
       }
     }
@@ -276,23 +275,26 @@ var EnigmailDialog = {
     if (alertCount <= 0) {
       return;
     }
 
     alertCount--;
     EnigmailPrefs.setPref(countPrefName, alertCount);
 
     if (alertCount > 0) {
-      mesg += EnigmailLocale.getString("repeatPrefix", [alertCount]) + " ";
+      mesg +=
+        "\n" +
+        l10n.formatValueSync("repeat-prefix", { count: alertCount }) +
+        " ";
       mesg +=
         alertCount == 1
-          ? EnigmailLocale.getString("repeatSuffixSingular")
-          : EnigmailLocale.getString("repeatSuffixPlural");
+          ? l10n.formatValueSync("repeat-suffix-singular")
+          : l10n.formatValueSync("repeat-suffix-plural");
     } else {
-      mesg += EnigmailLocale.getString("noRepeat2");
+      mesg += "\n" + l10n.formatValueSync("no-repeat");
     }
 
     EnigmailDialog.alert(win, mesg);
   },
 
   /**
    * Display a confirmation dialog with OK / Cancel buttons (both customizable) and
    * a checkbox to remember the selected choice.
@@ -329,23 +331,23 @@ var EnigmailDialog = {
             value: false,
           };
           let buttonPressed = EnigmailDialog.msgBox(
             win,
             {
               msgtext: mesg,
               button1: okLabel
                 ? okLabel
-                : EnigmailLocale.getString("dlg.button.ok"),
+                : l10n.formatValueSync("dlg-button-ok"),
               cancelButton: cancelLabel
                 ? cancelLabel
-                : EnigmailLocale.getString("dlg.button.cancel"),
-              checkboxLabel: EnigmailLocale.getString("dlgKeepSetting"),
+                : l10n.formatValueSync("dlg-button-cancel"),
+              checkboxLabel: l10n.formatValueSync("dlg-keep-setting"),
               iconType: EnigmailConstants.ICONTYPE_QUESTION,
-              dialogTitle: EnigmailLocale.getString("enigConfirm2"),
+              dialogTitle: l10n.formatValueSync("enig-confirm"),
             },
             checkBoxObj
           );
 
           if (checkBoxObj.value) {
             EnigmailPrefs.setPref(prefText, buttonPressed === 0 ? yes : no);
           }
           return buttonPressed === 0 ? 1 : 0;
@@ -365,23 +367,23 @@ var EnigmailDialog = {
             value: false,
           };
           let buttonPressed = EnigmailDialog.msgBox(
             win,
             {
               msgtext: mesg,
               button1: okLabel
                 ? okLabel
-                : EnigmailLocale.getString("dlg.button.ok"),
+                : l10n.formatValueSync("dlg-button-ok"),
               cancelButton: cancelLabel
                 ? cancelLabel
-                : EnigmailLocale.getString("dlg.button.cancel"),
-              checkboxLabel: EnigmailLocale.getString("dlgNoPrompt"),
+                : l10n.formatValueSync("dlg-button-cancel"),
+              checkboxLabel: l10n.formatValueSync("dlg-no-prompt"),
               iconType: EnigmailConstants.ICONTYPE_QUESTION,
-              dialogTitle: EnigmailLocale.getString("enigConfirm2"),
+              dialogTitle: l10n.formatValueSync("enig-confirm"),
             },
             checkBoxObj
           );
 
           if (checkBoxObj.value) {
             EnigmailPrefs.setPref(prefText, false);
           }
           return buttonPressed === 0 ? 1 : 0;
--- a/mail/extensions/openpgp/content/modules/keyRing.jsm
+++ b/mail/extensions/openpgp/content/modules/keyRing.jsm
@@ -6,19 +6,16 @@
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["EnigmailKeyRing"];
 
 const { EnigmailLog } = ChromeUtils.import(
   "chrome://openpgp/content/modules/log.jsm"
 );
-const { EnigmailLocale } = ChromeUtils.import(
-  "chrome://openpgp/content/modules/locale.jsm"
-);
 const { EnigmailFiles } = ChromeUtils.import(
   "chrome://openpgp/content/modules/files.jsm"
 );
 const { EnigmailTrust } = ChromeUtils.import(
   "chrome://openpgp/content/modules/trust.jsm"
 );
 const { EnigmailArmor } = ChromeUtils.import(
   "chrome://openpgp/content/modules/armor.jsm"
@@ -335,17 +332,17 @@ var EnigmailKeyRing = {
         )
       );
 
       tryAgain = false;
       let failed = res.exitCode || !res.importedKeys.length;
       if (failed && !permissive) {
         let agreed = getDialog().confirmDlg(
           win,
-          EnigmailLocale.getString("confirmPermissiveImport")
+          l10n.formatValueSync("confirm-permissive-import")
         );
         if (agreed) {
           permissive = true;
           tryAgain = true;
         }
       }
     } while (tryAgain);
 
@@ -639,17 +636,17 @@ var EnigmailKeyRing = {
         ); // public only
       }
 
       tryAgain = false;
       let failed = result.exitCode || !result.importedKeys.length;
       if (failed && isInteractive && !permissive) {
         let agreed = getDialog().confirmDlg(
           parent,
-          EnigmailLocale.getString("confirmPermissiveImport")
+          l10n.formatValueSync("confirm-permissive-import")
         );
         if (agreed) {
           permissive = true;
           tryAgain = true;
         }
       }
     } while (tryAgain);
 
--- a/mail/extensions/openpgp/content/modules/keyUsability.jsm
+++ b/mail/extensions/openpgp/content/modules/keyUsability.jsm
@@ -3,19 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
  */
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["EnigmailKeyUsability"];
 
-const { EnigmailLocale } = ChromeUtils.import(
-  "chrome://openpgp/content/modules/locale.jsm"
-);
 const { EnigmailPrefs } = ChromeUtils.import(
   "chrome://openpgp/content/modules/prefs.jsm"
 );
 const { EnigmailLog } = ChromeUtils.import(
   "chrome://openpgp/content/modules/log.jsm"
 );
 const { EnigmailCore } = ChromeUtils.import(
   "chrome://openpgp/content/modules/core.jsm"
@@ -321,19 +318,19 @@ var EnigmailKeyUsability = {
         actionButtonText = await l10n.formatValue("expiry-open-key-manager");
       }
 
       let checkedObj = {};
       let r = getDialog().msgBox(
         null,
         {
           msgtext: msg,
-          dialogTitle: EnigmailLocale.getString("enigInfo2"),
-          checkboxLabel: EnigmailLocale.getString("dlgNoPrompt"),
-          button1: EnigmailLocale.getString("dlg.button.close"),
+          dialogTitle: await l10n.formatValue("enig-info"),
+          checkboxLabel: await l10n.formatValue("dlg-no-prompt"),
+          button1: await l10n.formatValue("dlg-button-close"),
           button2: actionButtonText,
           iconType: EnigmailConstants.ICONTYPE_INFO,
         },
         checkedObj
       );
       if (r >= 0 && checkedObj.value) {
         // Do not show me this dialog again
         EnigmailPrefs.setPref("warnOnMissingOwnerTrust", false);
--- a/mail/extensions/openpgp/content/modules/mimeDecrypt.jsm
+++ b/mail/extensions/openpgp/content/modules/mimeDecrypt.jsm
@@ -17,19 +17,16 @@ const { EnigmailCore } = ChromeUtils.imp
   "chrome://openpgp/content/modules/core.jsm"
 );
 const { EnigmailVerify } = ChromeUtils.import(
   "chrome://openpgp/content/modules/mimeVerify.jsm"
 );
 const { EnigmailLog } = ChromeUtils.import(
   "chrome://openpgp/content/modules/log.jsm"
 );
-const { EnigmailLocale } = ChromeUtils.import(
-  "chrome://openpgp/content/modules/locale.jsm"
-);
 const { EnigmailData } = ChromeUtils.import(
   "chrome://openpgp/content/modules/data.jsm"
 );
 const { EnigmailPrefs } = ChromeUtils.import(
   "chrome://openpgp/content/modules/prefs.jsm"
 );
 const { EnigmailDecryption } = ChromeUtils.import(
   "chrome://openpgp/content/modules/decryption.jsm"
@@ -846,17 +843,17 @@ MimeDecryptHandler.prototype = {
         headerSink.updateSecurityStatus(
           this.msgUriSpec,
           EnigmailConstants.POSSIBLE_PGPMIME,
           0,
           0,
           "",
           "",
           "",
-          EnigmailLocale.getString("possiblyPgpMime"),
+          l10n.formatValueSync("possibly-pgp-mime"),
           "",
           this.uri,
           null,
           ""
         );
       }
     } catch (ex) {
       console.debug(ex);
--- a/mail/extensions/openpgp/content/modules/persistentCrypto.jsm
+++ b/mail/extensions/openpgp/content/modules/persistentCrypto.jsm
@@ -14,19 +14,16 @@ const { EnigmailLazy } = ChromeUtils.imp
   "chrome://openpgp/content/modules/lazy.jsm"
 );
 const { EnigmailLog } = ChromeUtils.import(
   "chrome://openpgp/content/modules/log.jsm"
 );
 const { EnigmailArmor } = ChromeUtils.import(
   "chrome://openpgp/content/modules/armor.jsm"
 );
-const { EnigmailLocale } = ChromeUtils.import(
-  "chrome://openpgp/content/modules/locale.jsm"
-);
 const { GlodaUtils } = ChromeUtils.import(
   "chrome://openpgp/content/modules/glodaUtils.jsm"
 );
 const { EnigmailCompat } = ChromeUtils.import(
   "chrome://openpgp/content/modules/compat.jsm"
 );
 const { EnigmailCore } = ChromeUtils.import(
   "chrome://openpgp/content/modules/core.jsm"
@@ -663,18 +660,18 @@ CryptMessageIntoFolder.prototype = {
                   subject: this.subject,
                 }
               );
 
               if (
                 !getDialog().confirmDlg(
                   null,
                   msg,
-                  EnigmailLocale.getString("dlg.button.retry"),
-                  EnigmailLocale.getString("dlg.button.skip")
+                  l10n.formatValueSync("dlg-button-retry"),
+                  l10n.formatValueSync("dlg-button-skip")
                 )
               ) {
                 this.messageDecrypted = false;
                 return -1;
               }
             } else if (
               statusFlagsObj.value & EnigmailConstants.DECRYPTION_INCOMPLETE
             ) {
--- a/mail/extensions/openpgp/content/modules/windows.jsm
+++ b/mail/extensions/openpgp/content/modules/windows.jsm
@@ -11,19 +11,16 @@ const EXPORTED_SYMBOLS = ["EnigmailWindo
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 const { EnigmailLog } = ChromeUtils.import(
   "chrome://openpgp/content/modules/log.jsm"
 );
 const { EnigmailCore } = ChromeUtils.import(
   "chrome://openpgp/content/modules/core.jsm"
 );
-const { EnigmailLocale } = ChromeUtils.import(
-  "chrome://openpgp/content/modules/locale.jsm"
-);
 const { EnigmailKeyRing } = ChromeUtils.import(
   "chrome://openpgp/content/modules/keyRing.jsm"
 );
 const { EnigmailStdlib } = ChromeUtils.import(
   "chrome://openpgp/content/modules/stdlib.jsm"
 );
 
 var l10n = new Localization(["messenger/openpgp/enigmail.ftl"], true);
@@ -256,17 +253,17 @@ var EnigmailWindows = {
    * @win       - |object| holding the parent window for the dialog
    *
    * no return value
    */
   openDebugLog(win) {
     EnigmailWindows.openWin(
       "enigmail:logFile",
       "chrome://openpgp/content/ui/enigmailViewFile.xhtml?viewLog=1&title=" +
-        escape(EnigmailLocale.getString("debugLog2.title")),
+        escape(l10n.formatValueSync("debug-log-title")),
       "centerscreen"
     );
   },
 
   /**
    * Display the dialog for changing the expiry date of one or several keys
    *
    * @win        - |object| holding the parent window for the dialog
@@ -359,32 +356,28 @@ var EnigmailWindows = {
   showPhoto(win, keyId, userId, photoNumber) {
     const enigmailSvc = EnigmailCore.getService(win);
     if (enigmailSvc) {
       if (!photoNumber) {
         photoNumber = 0;
       }
       let keyObj = EnigmailKeyRing.getKeyById(keyId);
       if (!keyObj) {
-        EnigmailWindows.alert(
-          win,
-          EnigmailLocale.getString("noPhotoAvailable")
-        );
+        EnigmailWindows.alert(win, l10n.formatValueSync("no-photo-available"));
       }
 
       let photoFile = keyObj.getPhotoFile(photoNumber);
 
       if (photoFile) {
         if (!(photoFile.isFile() && photoFile.isReadable())) {
           EnigmailWindows.alert(
             win,
-            EnigmailLocale.getString(
-              "error.photoPathNotReadable",
-              photoFile.path
-            )
+            l10n.formatValueSync("error-photo-path-not-readable", {
+              photo: photoFile.path,
+            })
           );
         } else {
           const photoUri = Services.io.newFileURI(photoFile).spec;
           const argsObj = {
             photoUri,
             userId,
             keyId,
           };
@@ -396,20 +389,17 @@ var EnigmailWindows = {
             argsObj
           );
           try {
             // delete the photo file
             photoFile.remove(false);
           } catch (ex) {}
         }
       } else {
-        EnigmailWindows.alert(
-          win,
-          EnigmailLocale.getString("noPhotoAvailable")
-        );
+        EnigmailWindows.alert(win, l10n.formatValueSync("no-photo-available"));
       }
     }
   },
 
   /**
    * Display the OpenPGP Key Details window
    *
    * @win        - |object| holding the parent window for the dialog
--- a/mail/extensions/openpgp/content/strings/bond.ftl
+++ b/mail/extensions/openpgp/content/strings/bond.ftl
@@ -15,21 +15,24 @@ openpgp-ctx-decrypt-save =
 openpgp-ctx-import-key =
     .label = Import OpenPGP Key
     .accesskey = I
 openpgp-ctx-verify-att =
     .label = Verify Signature
     .accesskey = V
 
 openpgp-has-sender-key = This message claims to contain the sender's OpenPGP public key.
-openpgp-import-sender-key = Import…
+openpgp-import-sender-key =
+    .label = Import…
 
 openpgp-search-keys-openpgp =
     .label = Discover OpenPGP Key
 
 openpgp-missing-signature-key = This message was signed with a key that you don't yet have.
 
-openpgp-search-signature-key = Discover…
+openpgp-search-signature-key =
+    .label = Discover…
 
 # Don't translate the terms "OpenPGP" and "MS-Exchange"
 openpgp-broken-exchange-info = This is an OpenPGP message that was apparently corrupted by MS-Exchange. If the message contents isn't shown as expected, you can try an automatic repair.
-openpgp-broken-exchange-repair = Repair message
+openpgp-broken-exchange-repair =
+    .label = Repair message
 openpgp-broken-exchange-wait = Please wait ...
--- a/mail/extensions/openpgp/content/strings/enigmail.ftl
+++ b/mail/extensions/openpgp/content/strings/enigmail.ftl
@@ -258,66 +258,87 @@ key-type-primary = primary key
 key-type-subkey = subkey
 key-type-pair = key pair (secret key and public key)
 key-expiry-never = never
 key-usage-encrypt = Encrypt
 key-usage-sign = Sign
 key-usage-certify = Certify
 key-usage-authentication = Authentication
 key-does-not-expire = Key does not expire
-key-expired = Key expired on { $keyExpiry }
+key-expired-date = Key expired on { $keyExpiry }
 key-expired-simple = Key has expired
-key-revoked = Key was revoked
+key-revoked-date = Key was revoked
 key-do-you-accept = Do you accept this key for verifying digital signatures and for encrypting messages?
 key-accept-warning = Avoid accepting a rogue key. Use a communication channel other than email to verify the fingerprint of your correspondent's key.
 
 # Strings enigmailMsgComposeOverlay.js
 cannot-use-own-key-because = Unable to send the message, because there is a problem with your personal key. { $problem }
 cannot-encrypt-because-missing = Unable to send this message with end-to-end encryption, because there are problems with the keys of the following recipients: { $problem }
+window-locked = Compose window is locked; send cancelled
 
 # Strings in mimeDecrypt.jsm
 mime-decrypt-encrypted-part-attachment-label = Encrypted message part
 mime-decrypt-encrypted-part-concealed-data = This is an encrypted message part. You need to open it in a separate window by clicking on the attachment.
 
 # Strings in keyserver.jsm
 keyserver-error-aborted = Aborted
 keyserver-error-unknown = An unknown error occurred
 keyserver-error-server-error = The keyserver reported an error.
 keyserver-error-import-error = Failed to import the downloaded key.
 keyserver-error-unavailable = The keyserver is not available.
 keyserver-error-security-error = The keyserver does not support encrypted access.
 keyserver-error-certificate-error = The keyserver’s certificate is not valid.
 keyserver-error-unsupported = The keyserver is not supported.
 
 # Strings in mimeWkdHandler.jsm
-wkd-message-body-req = Your email provider processed your request to upload your public key to the OpenPGP Web Key Directory.\n\nPlease confirm to complete the publishing of your public key.
-wkd-message-body-process = This is an email related to the automatic processing to upload your public key to the OpenPGP Web Key Directory.\n\nYou do not need to take any manual action at this point.
+wkd-message-body-req =
+    Your email provider processed your request to upload your public key to the OpenPGP Web Key Directory.
+    Please confirm to complete the publishing of your public key.
+wkd-message-body-process =
+    This is an email related to the automatic processing to upload your public key to the OpenPGP Web Key Directory.
+    You do not need to take any manual action at this point.
 
 # Strings in persistentCrypto.jsm
-converter-decrypt-body-failed = Could not decrypt message with subject\n{ $subject }.\nDo you want to retry with a different passphrase or do you want to skip the message?
+converter-decrypt-body-failed =
+    Could not decrypt message with subject
+    { $subject }.
+    Do you want to retry with a different passphrase or do you want to skip the message?
 
 # Strings in gpg.jsm
 unknown-signing-alg = Unknown signing algorithm (ID: { $id })
 unknown-hash-alg = Unknown cryptographic hash (ID: { $id })
 
 # Strings in keyUsability.jsm
-expiry-key-expires-soon = Your key { $desc } will expire in less than { $days } days.\n\nWe recommend that you create a new key pair and configure the corresponding accounts to use it.
-expiry-keys-expire-soon = Your following keys will expire in less than { $days } days:\n{ $desc }. We recommend that you create new keys and configure the corresponding accounts to use them.
-expiry-key-missing-owner-trust = Your secret key { $desc } has missing trust.\n\nWe recommend that you set "You rely on certifications" to "ultimate" in key properties.
-expiry-keys-missing-owner-trust = The following of your secret keys have missing trust.\n{ $desc }.\nWe recommend that you set "You rely on certifications" to "ultimate" in key properties.
+expiry-key-expires-soon =
+    Your key { $desc } will expire in less than { $days } days.
+    We recommend that you create a new key pair and configure the corresponding accounts to use it.
+expiry-keys-expire-soon =
+    Your following keys will expire in less than { $days } days:{ $desc }.
+    We recommend that you create new keys and configure the corresponding accounts to use them.
+expiry-key-missing-owner-trust =
+    Your secret key { $desc } has missing trust.
+    We recommend that you set "You rely on certifications" to "ultimate" in key properties.
+expiry-keys-missing-owner-trust =
+    The following of your secret keys have missing trust.
+    { $desc }.
+    We recommend that you set "You rely on certifications" to "ultimate" in key properties.
 expiry-open-key-manager = Open OpenPGP Key Management
 expiry-open-key-properties = Open Key Properties
 
 # Strings filters.jsm
 filter-folder-required = You must select a target folder.
-filter-decrypt-move-warn-experimental = Warning - the filter action "Decrypt permanently" may lead to destroyed messages.\n\nWe strongly recommend that you first try the "Create decrypted Copy" filter, test the result carefully, and only start using this filter once you are satisified with the result.
+filter-decrypt-move-warn-experimental =
+    Warning - the filter action "Decrypt permanently" may lead to destroyed messages.
+    We strongly recommend that you first try the "Create decrypted Copy" filter, test the result carefully, and only start using this filter once you are satisfied with the result.
 filter-term-pgpencrypted-label = OpenPGP Encrypted
 filter-key-required = You must select a recipient key.
 filter-key-not-found = Could not find an encryption key for '{ $desc }'.
-filter-warn-key-not-secret = Warning - the filter action "Encrypt to key" replaces the recipients.\n\nIf you do not have the secret key for '{ $desc }' you will no longer be able to read the emails.
+filter-warn-key-not-secret =
+    Warning - the filter action "Encrypt to key" replaces the recipients.
+    If you do not have the secret key for '{ $desc }' you will no longer be able to read the emails.
 
 #Strings filtersWrapper.jsm
 filter-decrypt-move-label = Decrypt permanently (OpenPGP)
 filter-decrypt-copy-label = Create decrypted Copy (OpenPGP)
 filter-encrypt-label = Encrypt to key (OpenPGP)
 
 # Strings in enigmailKeyImportInfo.js
 import-info-title =
@@ -328,19 +349,28 @@ import-info-fpr = Fingerprint
 import-info-details = View Details and manage key acceptance
 import-info-no-keys = No keys imported.
 
 # Strings in enigmailKeyManager.js
 import-from-clip = Do you want to import some key(s) from clipboard?
 import-from-url = Download public key from this URL:
 copy-to-clipbrd-failed = Could not copy the selected key(s) to the clipboard.
 copy-to-clipbrd-ok = Key(s) copied to clipboard
-delete-secret-key = WARNING: You are about to delete a secret key!\nIf you delete your secret key, you will no longer be able to decrypt any messages encrypted for that key, nor will you be able to revoke it.\n\nDo you really want to delete BOTH, the secret key and the public key\n'{ $userId }'?
-delete-mix = WARNING: You are about to delete secret keys!\nIf you delete your secret key, you will no longer be able to decrypt any messages encrypted for that key.\n\nDo you really want to delete BOTH, the selected secret and public keys?
-delete-pub-key = Do you want to delete the public key\n'{ $userId }'?
+delete-secret-key =
+    WARNING: You are about to delete a secret key!
+    If you delete your secret key, you will no longer be able to decrypt any messages encrypted for that key, nor will you be able to revoke it.
+    Do you really want to delete BOTH, the secret key and the public key
+    '{ $userId }'?
+delete-mix =
+    WARNING: You are about to delete secret keys!
+    If you delete your secret key, you will no longer be able to decrypt any messages encrypted for that key.
+    Do you really want to delete BOTH, the selected secret and public keys?
+delete-pub-key =
+    Do you want to delete the public key
+    '{ $userId }'?
 delete-selected-pub-key = Do you want to delete the public keys?
 refresh-all-question = You did not select any key. Would you like to refresh ALL keys?
 key-man-button-export-sec-key = Export &Secret Keys
 key-man-button-export-pub-key = Export &Public Keys Only
 key-man-button-refresh-all = &Refresh All Keys
 key-man-loading-keys = Loading keys, please wait…
 ascii-armor-file = ASCII Armored Files (*.asc)
 no-key-selected = You should select at least one key in order to perform the selected operation
@@ -348,16 +378,18 @@ export-to-file = Export Public Key To Fi
 export-keypair-to-file = Export Secret and Public Key To File
 export-secret-key = Do you want to include the secret key in the saved OpenPGP key file?
 save-keys-ok = The keys were successfully saved
 save-keys-failed = Saving the keys failed
 default-pub-key-filename = Exported-public-keys
 default-pub-sec-key-filename = Exported-public-and-secret-keys
 refresh-key-warn = Warning: depending on the number of keys and the connection speed, refreshing all keys could be quite a lengthy process!
 preview-failed = Can't read public key file.
+general-error = Error: { $reason }
+dlg-button-delete = &Delete
 
 # Strings in keyObj.jsm
 key-ring-pub-key-revoked = The key { $userId } (key ID { $keyId }) is revoked.
 key-ring-pub-key-expired = The key { $userId } (key ID { $keyId }) has expired.
 key-ring-key-disabled = The key { $userId } (key ID { $keyId }) is disabled; it cannot be used.
 key-ring-key-invalid = The key { $userId } (key ID { $keyId }) is not valid. Please consider verifying it correctly.
 key-ring-key-not-trusted=The key { $userId } (key ID { $keyId }) is not trusted enough. Please set the trust level of your key to "ultimate" to use it for signing.
 key-ring-no-secret-key = You do not seem to have the secret key for { $userId } (key ID { $keyId }) on your keyring; you cannot use the key for signing.
@@ -370,18 +402,23 @@ key-ring-enc-sub-keys-revoked = All encr
 key-ring-enc-sub-keys-expired = All encryption subkeys of key { $userId } (key ID { $keyId }) have expired.
 key-ring-enc-sub-keys-unusable = All encryption subkeys of key { $userId } (key ID { $keyId }) are revoked, expired or otherwise unusable.
 
 # Strings in gnupg-keylist.jsm
 keyring-photo = Photo
 user-att-photo = User attribute (JPEG image)
 
 # Strings in key.jsm
-revoke-key-question = You are about to revoke the key '{ $userId }'.\n\nYou will no longer be able to sign with this key, and once distributed, others will no longer be able to encrypt with that key. You can still use the key to decrypt old messages.\n\nDo you want to proceed?
-revoke-key-not-present = You have no key (0x{ $keyId }) which matches this revocation certificate!\n\nIf you have lost your key, you must import it (e.g. from a keyserver) before importing the revocation certificate!
+revoke-key-question =
+    You are about to revoke the key '{ $userId }'.
+    You will no longer be able to sign with this key, and once distributed, others will no longer be able to encrypt with that key. You can still use the key to decrypt old messages.
+    Do you want to proceed?
+revoke-key-not-present =
+    You have no key (0x{ $keyId }) which matches this revocation certificate!
+    If you have lost your key, you must import it (e.g. from a keyserver) before importing the revocation certificate!
 revoke-key-already-revoked = The key 0x{ $keyId } has already been revoked.
 key-man-button-revoke-key = &Revoke Key
 
 # Strings in keyRing.jsm & decryption.jsm
 key-man-button-import = &Import
 
 delete-key-title = Delete OpenPGP Key
 
@@ -404,16 +441,17 @@ fail-key-extract = Error - key extractio
 
 # Strings used in keyRing.jsm
 fail-cancel = Error - Key receive cancelled by user
 not-first-block = Error - First OpenPGP block not public key block
 import-key-confirm = Import public key(s) embedded in message?
 fail-key-import = Error - key importing failed
 file-write-failed = Failed to write to file { $output }
 no-pgp-block = Error - No valid armored OpenPGP data block found
+confirm-permissive-import = Import failed. The key you are trying to import might be corrupt or use unknown attributes. Would you like to attempt to import the parts that are correct? This might result in the import of incomplete and unusable keys.
 
 # Strings used in trust.jsm
 key-valid-unknown = unknown
 key-valid-invalid = invalid
 key-valid-disabled = disabled
 key-valid-revoked = revoked
 key-valid-expired = expired
 key-trust-untrusted = untrusted
@@ -422,53 +460,128 @@ key-trust-full = trusted
 key-trust-ultimate = ultimate
 key-trust-group = (group)
 
 # Strings used in commonWorkflows.js
 import-key-file = Import OpenPGP Key File
 gnupg-file = GnuPG Files
 import-keys-failed=Importing the keys failed
 passphrase-prompt = Please enter the passphrase that unlocks the following key: { $key }
+file-to-big-to-import = This file is too big. Please don't import a large set of keys at once.
 
 # Strings used in enigmailKeygen.js
 save-revoke-cert-as = Create & Save Revocation Certificate
 revoke-cert-ok = The revocation certificate has been successfully created. You can use it to invalidate your public key, e.g. in case you would lose your secret key.
 revoke-cert-failed = The revocation certificate could not be created.
+gen-going = Key generation already in progress!
+keygen-missing-user-name = There is no name specified for the selected account/identity. Please enter a value in the field  "Your name" in the account settings.
+expiry-too-short = Your key must be valid for at least one day.
+expiry-too-long = You cannot create a key that expires in more than 100 years.
+key-confirm = Generate public and secret key for '{ $id }'?
+key-man-button-generate-key = &Generate Key
+key-abort = Abort key generation?
+key-man-button-generate-key-abort = &Abort Key Generation
+key-man-button-generate-key-continue = &Continue Key Generation
 
 # Strings used in enigmailMessengerOverlay.js
 failed-decrypt = Error - decryption failed
+fix-broken-exchange-msg-failed = Did not succeed to repair message.
+attachment-no-match-from-signature = Could not match signature file '{ $attachment }' to an attachment
+attachment-no-match-to-signature = Could not match attachment '{ $attachment }' to a signature file
+signature-verified-ok = The signature for attachment { $attachment } was successfully verified
+signature-verify-failed = The signature for attachment { $attachment } could not be verified
+decrypt-ok-no-sig =
+    Warning
+    Decryption was successful, but the signature could not be verified correctly
+msg-ovl-button-cont-anyway = &Continue Anyway
+begin-pgp-part = ********* *BEGIN ENCRYPTED or SIGNED PART* *********
+end-pgp-part = ********** *END ENCRYPTED or SIGNED PART* **********
+enig-content-note = *Attachments to this message have not been signed nor encrypted*
 
 # Strings used in enigmailMsgComposeOverlay.js
 msg-compose-button-send = &Send Message
 msg-compose-details-button-label = Details…
 msg-compose-details-button-access-key = D
-send-aborted = Send operation aborted.\n\n
+send-aborted = Send operation aborted.
 key-not-trusted = Not enough trust for key '{ $key }'
 key-not-found = Key '{ $key }' not found
 key-revoked = Key '{ $key }' revoked
 key-expired = Key '{ $key }' expired
 msg-compose-internal-error = An internal error has occurred.
 keys-to-export = Select OpenPGP Keys to Insert
-msg-compose-partially-encrypted-inlinePGP = The message you are replying to contained both unencrypted and encrypted parts. If the sender was not able to decrypt some message parts originally, you may be leaking confidential information that the sender was not able to originally decrypt themselves.\n\nPlease consider removing all quoted text from your reply to this sender.
+msg-compose-partially-encrypted-inlinePGP =
+    The message you are replying to contained both unencrypted and encrypted parts. If the sender was not able to decrypt some message parts originally, you may be leaking confidential information that the sender was not able to originally decrypt themselves.
+    Please consider removing all quoted text from your reply to this sender.
 msg-compose-cannot-save-draft = Error while saving draft
 msg-compose-partially-encrypted-short = Beware of leaking sensitive information - partially encrypted email.
-quoted-printable-warn = You have enabled 'quoted-printable' encoding for sending messages. This may result in incorrect decryption and/or verification of your message.\nDo you wish to turn off sending 'quoted-printable' messages now?
-minimal-line-wrapping = You have set line wrapping to { $width } characters. For correct encryption and/or signing, this value needs to be at least 68.\nDo you wish to change line wrapping to 68 characters now?
+quoted-printable-warn =
+    You have enabled 'quoted-printable' encoding for sending messages. This may result in incorrect decryption and/or verification of your message.
+    Do you wish to turn off sending 'quoted-printable' messages now?
+minimal-line-wrapping =
+    You have set line wrapping to { $width } characters. For correct encryption and/or signing, this value needs to be at least 68.
+    Do you wish to change line wrapping to 68 characters now?
 sending-hidden-rcpt = This message has BCC (blind copy) recipients. If this message is encrypted, it is possible to hide the BCC recipients but users of some products (e.g. PGP Corp.) will not be able to decrypt the message. Given this, we recommend to avoid BCC-emails with encrypted messages.
 send-with-hidden-bcc = Hide BCC recipients
 send-with-shown-bcc = Encrypt normally
-sending-news = Encrypted send operation aborted.\n\nThis message cannot be encrypted because there are newsgroup recipients. Please re-send the message without encryption.
-send-to-news-warning = Warning: you are about to send an encrypted email to a newsgroup.\n\nThis is discouraged because it only makes sense if all members of the group can decrypt the message, i.e. the message needs to be encrypted with the keys of all group participants. Please send this message only if you know exactly what you are doing.\n\nContinue?
+sending-news =
+    Encrypted send operation aborted.
+    This message cannot be encrypted because there are newsgroup recipients. Please re-send the message without encryption.
+send-to-news-warning =
+    Warning: you are about to send an encrypted email to a newsgroup.
+    This is discouraged because it only makes sense if all members of the group can decrypt the message, i.e. the message needs to be encrypted with the keys of all group participants. Please send this message only if you know exactly what you are doing.
+    Continue?
+save-attachment-header = Save decrypted attachment
+no-temp-dir =
+    Could not find a temporary directory to write to
+    Please set the TEMP environment variable
+possibly-pgp-mime = Possibly PGP/MIME encrypted or signed message; use 'Decrypt/Verify' function to verify
+cannot-send-sig-because-no-own-key = Cannot digitally sign this message, because you haven't yet configured end-to-end encryption for <{ $key }>
+cannot-send-enc-because-no-own-key = Cannot send this message encrypted, because you haven't yet configured end-to-end encryption for <{ $key }>
 
 # Strings used in decryption.jsm
-do-import-multiple = Import the following keys?\n\n{ $key }
+do-import-multiple =
+    Import the following keys?
+    { $key }
 do-import-one = Import { $name } ({ $id })?
-cant-import = Error importing public key\n\n
+cant-import = Error importing public key
 unverified-reply = Indented message part (reply) was probably modified
 key-in-message-body = A key was found in the message body. Click 'Import Key' to import the key
 sig-mismatch = Error - Signature mismatch
 invalid-email = Error - invalid email address(es)
+attachment-pgp-key =
+    The attachment '{ $name }' you are opening appears to be an OpenPGP key file.
+    Click 'Import' to import the keys contained or 'View' to view the file contents in a browser window
+dlg-button-view = &View
 
 # Strings used in enigmailMsgHdrViewOverlay.js
 decrypted-msg-with-format-error = Decrypted message (restored broken PGP email format probably caused by an old Exchange server, so that the result might not be perfect to read)
 
 # Strings used in encryption.jsm
 not-required = Error - no encryption required
+
+# Strings used in windows.jsm
+no-photo-available = No Photo available
+error-photo-path-not-readable = Photo path '{ $photo }' is not readable
+debug-log-title = OpenPGP Debug Log
+
+# Strings used in dialog.jsm
+repeat-prefix = This alert will repeat { $count }
+repeat-suffix-singular = more time.
+repeat-suffix-plural = more times.
+no-repeat = This alert will not be shown again.
+dlg-keep-setting = Remember my answer and do not ask me again
+dlg-button-ok = &OK
+dlg-button-close = &Close
+dlg-button-cancel = &Cancel
+dlg-no-prompt = Do not show me this dialog again
+enig-prompt = OpenPGP Prompt
+enig-confirm = OpenPGP Confirmation
+enig-alert = OpenPGP Alert
+enig-info = OpenPGP Information
+
+# Strings used in persistentCrypto.jsm
+dlg-button-retry = &Retry
+dlg-button-skip = &Skip
+
+# Strings used in enigmailCommon.js
+enig-error = OpenPGP Error
+enig-alert-title =
+    .title = OpenPGP Alert
--- a/mail/extensions/openpgp/content/strings/enigmail.properties
+++ b/mail/extensions/openpgp/content/strings/enigmail.properties
@@ -1,44 +1,17 @@
 #####################################################################
 # Strings used within enigmailCommon.js and enigmailCommon.jsm
 #####################################################################
 
-enigAlert2=OpenPGP Alert
-enigConfirm2=OpenPGP Confirmation
-enigInfo2=OpenPGP Information
-enigError2=OpenPGP Error
-enigPrompt2=OpenPGP Prompt
-
-dlgYes=&Yes
+### dlgYes=&Yes
 ### dlgNo=&No
-dlgKeepSetting=Remember my answer and do not ask me again
-dlgNoPrompt=Do not show me this dialog again
-dlg.button.delete=&Delete
-dlg.button.cancel=&Cancel
-dlg.button.close=&Close
-dlg.button.continue=Con&tinue
-dlg.button.skip=&Skip
 ### dlg.button.overwrite=&Overwrite
-dlg.button.view=&View
-dlg.button.retry=&Retry
 ### dlg.button.ignore=&Ignore
 ### dlg.button.install=&Install
-dlg.button.ok=&OK
-
-repeatPrefix=\n\nThis alert will repeat %S
-repeatSuffixSingular=more time.
-repeatSuffixPlural=more times.
-noRepeat2=\n\nThis alert will not be shown again.
-
-noPhotoAvailable=No Photo available
-debugLog2.title=OpenPGP Debug Log
-error.photoPathNotReadable=Photo path '%S' is not readable
-
-generalError=Error: %S
 
 # Strings in configure.jsm
 ### enigmailCommon.checkPreferences=Check Preferences ...
 
 #####################################################################
 ### Strings in enigmailAbout.js
 #####################################################################
 
@@ -49,68 +22,42 @@ generalError=Error: %S
 #####################################################################
 
 ### onlyGPG=Key generation only works with GnuPG (not with PGP)!
 
 ### keygenComplete=Key generation completed! Identity <%S> will be used for signing.
 ### revokeCertRecommended=We highly recommend to create a revocation certificate for your key. This certificate can be used to invalidate your key, e.g. in case your secret key gets lost or compromised. Do you want to create such a revocation certificate now?
 ### keyMan.button.generateCert=&Generate Certificate
 ### genCompleteNoSign=Key generation completed!
-genGoing=Key generation already in progress!
 
 ### passNoMatch=Passphrase entries do not match; please re-enter
 ### passCheckBox=Please check box if specifying no passphrase for key
 ### passUserName=Please specify user name for this identity
-keygen.missingUserName=There is no name specified for the selected account/identity. Please enter a value in the field  "Your name" in the account settings.
 ### keygen.passCharProblem=You are using special characters in your passphrase. Unfortunately, this can cause troubles for other applications. We recommend you choose a passphrase consisting only of any of these characters:\na-z A-Z 0-9 /.;:-,!?(){}[]%*
 ### passSpaceProblem=Due to technical reasons, your passphrase may not start or end with a space character.
 ### changePassFailed=Changing the passphrase failed.
 
-keyConfirm=Generate public and secret key for '%S'?
-keyMan.button.generateKey=&Generate Key
-keyAbort=Abort key generation?
-keyMan.button.generateKeyAbort=&Abort Key Generation
-keyMan.button.generateKeyContinue=&Continue Key Generation
-expiryTooLong=You cannot create a key that expires in more than 100 years.
 ### expiryTooLongShorter=You cannot create a key that expires in more than 90 years.
-expiryTooShort=Your key must be valid for at least one day.
 ### setKeyExpirationDateFailed=The expiration date could not be changed
 
-enigContentNote2=*Attachments to this message have not been signed nor encrypted*\r\n\r\n
-possiblyPgpMime=Possibly PGP/MIME encrypted or signed message; use 'Decrypt/Verify' function to verify
-
-saveAttachmentHeader2=Save decrypted attachment
-noTempDir=Could not find a temporary directory to write to\nPlease set the TEMP environment variable
-attachmentPgpKey=The attachment '%S' you are opening appears to be an OpenPGP key file.\n\nClick 'Import' to import the keys contained or 'View' to view the file contents in a browser window
+### notePartEncrypted2=*Parts of the message have NOT been signed nor encrypted*
+### noteCutMessage2=*Multiple message blocks found -- decryption/verification aborted*
 
-beginPgpPart=********* *BEGIN ENCRYPTED or SIGNED PART* *********
-endPgpPart=********** *END ENCRYPTED or SIGNED PART* **********
-notePartEncrypted2=*Parts of the message have NOT been signed nor encrypted*
-noteCutMessage2=*Multiple message blocks found -- decryption/verification aborted*
-
-decryptOkNoSig=Warning\n\nDecryption was successful, but the signature could not be verified correctly
-msgOvl.button.contAnyway=&Continue Anyway
-signature.verifiedOK=The signature for attachment %S was successfully verified
-signature.verifyFailed=The signature for attachment %S could not be verified
-attachment.noMatchToSignature=Could not match attachment '%S' to a signature file
-attachment.noMatchFromSignature=Could not match signature file '%S' to an attachment
-fixBrokenExchangeMsg.failed=Did not succeed to repair message.
 ### detailsDlg.importKey=Import key
 ### wksNoIdentity=This key is not linked to any of your email accounts. Please add an account for at least one of the following email addresse(s):\n\n%S
 ### wksConfirmSuccess=Confirmation email sent.
 ### wksConfirmFailure=Sending the confirmation email failed.
 
 #####################################################################
 # Strings in enigmailMsgComposeOverlay.js
 #####################################################################
 
 ### keysToUse=Select OpenPGP Key(s) to use for %S
 ### pubKey=Public key for %S\n
 
-### windowLocked=Compose window is locked; send cancelled
 ### composeSpecifyEmail=Please specify your primary email address, which will be used to choose the signing key for outgoing messages.\n If you leave it blank, the FROM address of the message will be used to choose the signing key.
 ### attachWarning=Attachments to this message are not local, they cannot be encrypted. In order to encrypt the attachments, store them as local files first and attach these files. Do you wish to send the message anyway?
 ### warning=Warning
 ### signIconClicked=You have manually modified signing. Therefore, while you are composing this message, (de)activating signing does not depend anymore on (de)activating encryption.
 
 ### msgCompose.internalEncryptionError=Internal Error: promised encryption disabled
 
 ### msgCompose.protectSubject.tooltip=Protect the message subject
@@ -424,18 +371,8 @@ fixBrokenExchangeMsg.failed=Did not succ
 
 #strings in gnupg-key.jsm
 ### import.secretKeyImportError=An error has occurred in GnuPG while importing secret keys. The import was not successful.
 
 #strings in importSettings.js
 ### importSettings.errorNoFile=The file you specified is not a regular file!
 ### importSettings.cancelWhileInProgress=Restoring is in progress. Do you really want to abort the process?
 ### importSettings.button.abortImport=&Abort process
-
-
-
-
-fileToBigToImport=This file is too big. Please don't import a large set of keys at once.
-cannotSendSigBecauseNoOwnKey=Cannot digitally sign this message, because you haven't yet configured end-to-end encryption for <%S>
-cannotSendEncBecauseNoOwnKey=Cannot send this message encrypted, because you haven't yet configured end-to-end encryption for <%S>
-
-
-confirmPermissiveImport=Import failed. The key you are trying to import might be corrupt or use unknown attributes. Would you like to attempt to import the parts that are correct? This might result in the import of incomplete and unusable keys.
--- a/mail/extensions/openpgp/content/ui/commonWorkflows.js
+++ b/mail/extensions/openpgp/content/ui/commonWorkflows.js
@@ -66,17 +66,19 @@ function EnigmailCommon_importKeysFromFi
   );
   if (!inFile) {
     return false;
   }
 
   // infile type: nsIFile
   // RNP.maxImportKeyBlockSize
   if (inFile.fileSize > 5000000) {
-    EnigmailDialog.alert(window, EnigmailLocale.getString("fileToBigToImport"));
+    document.l10n.formatValue("file-to-big-to-import").then(value => {
+      EnigmailDialog.alert(window, value);
+    });
     return false;
   }
   let errorMsgObj = {};
   // preview
   let preview = EnigmailKey.getKeyListFromKeyFile(
     inFile,
     errorMsgObj,
     !secret,
--- a/mail/extensions/openpgp/content/ui/enigmailCommon.js
+++ b/mail/extensions/openpgp/content/ui/enigmailCommon.js
@@ -313,18 +313,22 @@ function EnigAlertPref(mesg, prefText) {
   return EnigmailDialog.alertPref(window, mesg, prefText);
 }
 
 // Confirmation dialog with OK / Cancel buttons (both customizable)
 function EnigConfirm(mesg, okLabel, cancelLabel) {
   return EnigmailDialog.confirmDlg(window, mesg, okLabel, cancelLabel);
 }
 
-function EnigError(mesg) {
-  return gEnigPromptSvc.alert(window, EnigGetString("enigError2"), mesg);
+async function EnigError(mesg) {
+  return gEnigPromptSvc.alert(
+    window,
+    await document.l10n.formatValue("enig-error"),
+    mesg
+  );
 }
 
 function EnigHelpWindow(source) {
   EnigmailWindows.openHelpWindow(source);
 }
 
 function EnigDisplayRadioPref(prefName, prefValue, optionElementIds) {
   EnigmailLog.DEBUG(
--- a/mail/extensions/openpgp/content/ui/enigmailKeyManager.js
+++ b/mail/extensions/openpgp/content/ui/enigmailKeyManager.js
@@ -307,53 +307,53 @@ function enigmailDeleteKey() {
     // one key selected
     var userId = gKeyList[keyList[0]].userId;
     if (gKeyList[keyList[0]].secretAvailable) {
       if (
         !EnigConfirm(
           l10n.formatValueSync("delete-secret-key", {
             userId,
           }),
-          EnigGetString("dlg.button.delete")
+          l10n.formatValueSync("dlg-button-delete")
         )
       ) {
         return;
       }
       deleteSecret = true;
     } else if (
       !EnigConfirm(
         l10n.formatValueSync("delete-pub-key", {
           userId,
         }),
-        EnigGetString("dlg.button.delete")
+        l10n.formatValueSync("dlg-button-delete")
       )
     ) {
       return;
     }
   } else {
     // several keys selected
     for (var i = 0; i < keyList.length; i++) {
       if (gKeyList[keyList[i]].secretAvailable) {
         deleteSecret = true;
       }
     }
 
     if (deleteSecret) {
       if (
         !EnigConfirm(
           l10n.formatValueSync("delete-mix"),
-          EnigGetString("dlg.button.delete")
+          l10n.formatValueSync("dlg-button-delete")
         )
       ) {
         return;
       }
     } else if (
       !EnigConfirm(
-        l10n.formatValueSync("deleteSelectedPubKey"),
-        EnigGetString("dlg.button.delete")
+        l10n.formatValueSync("delete-selected-pub-key"),
+        l10n.formatValueSync("dlg-button-delete")
       )
     ) {
       return;
     }
   }
 
   const cApi = EnigmailCryptoAPI();
   for (let j in keyList) {
@@ -381,17 +381,19 @@ function enigCreateKeyMsg() {
   var tmpDir = EnigGetTempDir();
   var tmpFile;
   try {
     tmpFile = Cc[ENIG_LOCAL_FILE_CONTRACTID].createInstance(
       EnigGetLocalFileApi()
     );
     tmpFile.initWithPath(tmpDir);
     if (!(tmpFile.isDirectory() && tmpFile.isWritable())) {
-      EnigAlert(EnigGetString("noTempDir"));
+      document.l10n.formatValue("no-temp-dir").then(value => {
+        EnigAlert(value);
+      });
       return;
     }
   } catch (ex) {}
   tmpFile.append("key.asc");
   tmpFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
 
   // save file
   var exitCodeObj = {};
@@ -600,17 +602,17 @@ async function enigmailExportKeys() {
     }
   }
 
   var exportSecretKey = false;
   if (secretFound) {
     // double check that also the pivate keys shall be exported
     var r = EnigmailDialog.msgBox(window, {
       msgtext: await document.l10n.formatValue("export-secret-key"),
-      dialogTitle: EnigGetString("enigConfirm2"),
+      dialogTitle: await document.l10n.formatValue("enig-confirm"),
       button1: await document.l10n.formatValue("key-man-button-export-pub-key"),
       button2: await document.l10n.formatValue("key-man-button-export-sec-key"),
       cancelButton: ":cancel",
       iconType: EnigmailConstants.ICONTYPE_QUESTION,
     });
     switch (r) {
       case 0: // export pub key only
         break;
@@ -935,21 +937,21 @@ function userAcceptsWarning(warningMessa
 
   let checkedObj = {};
 
   let confirm =
     EnigmailDialog.msgBox(
       window,
       {
         msgtext: warningMessage,
-        checkboxLabel: EnigGetString("dlgNoPrompt"),
-        button1: EnigGetString("dlg.button.continue"),
+        checkboxLabel: l10n.formatValueSync("dlg-no-prompt"),
+        button1: l10n.formatValueSync("dlg-button-continue"),
         cancelButton: ":cancel",
         iconType: EnigmailConstants.ICONTYPE_QUESTION,
-        dialogTitle: EnigmailLocale.getString("enigConfirm2"),
+        dialogTitle: l10n.formatValueSync("enig-confirm"),
       },
       checkedObj
     ) === 0;
 
   if (checkedObj.value) {
     EnigSetPref("warnRefreshAll", false);
   }
   return confirm;
@@ -1092,17 +1094,17 @@ function enigmailImportKeysFromUrl() {
   if (
     EnigmailDialog.promptValue(
       window,
       l10n.formatValueSync("import-from-url"),
       value
     )
   ) {
     var p = new Promise(function(resolve, reject) {
-      var cbFunc = function(data) {
+      var cbFunc = async function(data) {
         EnigmailLog.DEBUG("enigmailImportKeysFromUrl: _cbFunc()\n");
         var errorMsgObj = {};
 
         var preview = EnigmailKey.getKeyListFromKeyBlock(
           data,
           errorMsgObj,
           true,
           true,
@@ -1110,25 +1112,25 @@ function enigmailImportKeysFromUrl() {
         );
         // should we allow importing secret keys?
         var exitStatus = -1;
 
         if (preview && preview.length > 0) {
           if (preview.length == 1) {
             exitStatus = EnigmailDialog.confirmDlg(
               window,
-              l10n.formatValueSync("do-import-one", {
+              await document.l10n.formatValue("do-import-one", {
                 name: preview[0].name,
                 id: preview[0].id,
               })
             );
           } else {
             exitStatus = EnigmailDialog.confirmDlg(
               window,
-              l10n.formatValueSync("do-import-multiple", {
+              await document.l10n.formatValue("do-import-multiple", {
                 key: preview
                   .map(function(a) {
                     return "\t" + a.name + " (" + a.id + ")";
                   })
                   .join("\n"),
               })
             );
           }
@@ -1141,19 +1143,20 @@ function enigmailImportKeysFromUrl() {
               false,
               "",
               errorMsgObj
             );
             errorMsgObj.preview = preview;
             resolve(errorMsgObj);
           }
         } else {
-          document.l10n.formatValue("preview-failed").then(value => {
-            EnigmailDialog.alert(window, value);
-          });
+          EnigmailDialog.alert(
+            window,
+            await document.l10n.formatValue("preview-failed")
+          );
         }
       };
 
       try {
         var bufferListener = EnigmailStreams.newStringStreamListener(cbFunc);
         var ioServ = Services.io;
         var msgUri = ioServ.newURI(value.value);
 
@@ -1168,20 +1171,22 @@ function enigmailImportKeysFromUrl() {
     });
 
     p.then(function(errorMsgObj) {
       var keyList = errorMsgObj.preview.map(function(a) {
         return a.id;
       });
       EnigmailDialog.keyImportDlg(window, keyList);
       refreshKeys();
-    }).catch(function(reason) {
+    }).catch(async function(reason) {
       EnigmailDialog.alert(
         window,
-        EnigGetString("generalError", [reason.value])
+        await document.l10n.formatValue("general-error", {
+          reason: reason.value,
+        })
       );
     });
   }
 }
 
 function initiateAcKeyTransfer() {
   EnigmailWindows.inititateAcSetupMessage();
 }
--- a/mail/extensions/openpgp/content/ui/enigmailKeygen.js
+++ b/mail/extensions/openpgp/content/ui/enigmailKeygen.js
@@ -101,19 +101,19 @@ function updateKeySizeSel(selectedObj) {
     document.getElementById("keySize").removeAttribute("disabled");
   }
 }
 
 function enigmailOnClose() {
   var closeWin = true;
   if (gKeygenRequest) {
     closeWin = EnigConfirm(
-      EnigGetString("keyAbort"),
-      EnigGetString("keyMan.button.generateKeyAbort"),
-      EnigGetString("keyMan.button.generateKeyContinue")
+      l10n.formatValueSync("key-abort"),
+      l10n.formatValueSync("key-man-button-generate-key-abort"),
+      l10n.formatValueSync("key-man-button-generate-key-continue")
     );
   }
   if (closeWin) {
     abortKeyGeneration();
   }
   return closeWin;
 }
 
@@ -165,23 +165,23 @@ function enigmailKeygenCloseRequest() {
 
   if (gKeygenRequest) {
     var p = gKeygenRequest;
     gKeygenRequest = null;
     p.kill(false);
   }
 }
 
-function enigmailKeygenStart() {
+async function enigmailKeygenStart() {
   EnigmailLog.DEBUG("enigmailKeygen.js: Start\n");
 
   if (gKeygenRequest) {
     let req = gKeygenRequest.QueryInterface(Ci.nsIRequest);
     if (req.isPending()) {
-      EnigmailDialog.info(window, EnigGetString("genGoing"));
+      EnigmailDialog.info(window, await document.l10n.formatValue("gen-going"));
       return;
     }
   }
 
   gGeneratedKey = null;
   gAllData = "";
 
   var enigmailSvc = GetEnigmailSvc();
@@ -192,45 +192,61 @@ function enigmailKeygenStart() {
   var noExpiry = document.getElementById("noExpiry");
   var expireInput = document.getElementById("expireInput");
   var timeScale = document.getElementById("timeScale");
 
   var expiryTime = 0;
   if (!noExpiry.checked) {
     expiryTime = Number(expireInput.value) * Number(timeScale.value);
     if (expiryTime > 36500) {
-      EnigmailDialog.info(window, EnigGetString("expiryTooLong"));
+      EnigmailDialog.info(
+        window,
+        await document.l10n.formatValue("expiry-too-long")
+      );
       return;
     }
     if (expiryTime <= 0) {
-      EnigmailDialog.info(window, EnigGetString("expiryTooShort"));
+      EnigmailDialog.info(
+        window,
+        await document.l10n.formatValue("expiry-too-short")
+      );
       return;
     }
   }
   var keySize = Number(document.getElementById("keySize").value);
   var keyType = document.getElementById("keyType").value;
 
   var curId = getCurrentIdentity();
   gUsedId = curId;
 
   var userName = curId.fullName;
   var userEmail = curId.email;
 
   if (!userName) {
-    EnigmailDialog.info(window, EnigGetString("keygen.missingUserName"));
+    EnigmailDialog.info(
+      window,
+      await document.l10n.formatValue("keygen-missing-user-name")
+    );
     return;
   }
 
   var idString = userName;
 
   idString += " <" + userEmail + ">";
 
-  var confirmMsg = EnigGetString("keyConfirm", idString);
+  var confirmMsg = await document.l10n.formatValue("key-confirm", {
+    id: idString,
+  });
 
-  if (!EnigConfirm(confirmMsg, EnigGetString("keyMan.button.generateKey"))) {
+  if (
+    !EnigConfirm(
+      confirmMsg,
+      await document.l10n.formatValue("key-man-button-generate-key")
+    )
+  ) {
     return;
   }
 
   var cApi;
   try {
     let newId = null;
     cApi = EnigmailCryptoAPI();
     newId = cApi.sync(
@@ -291,19 +307,19 @@ function abortKeyGeneration() {
 }
 
 function enigmailKeygenCancel() {
   EnigmailLog.DEBUG("enigmailKeygen.js: Cancel\n");
   var closeWin = false;
 
   if (gKeygenRequest) {
     closeWin = EnigConfirm(
-      EnigGetString("keyAbort"),
-      EnigGetString("keyMan.button.generateKeyAbort"),
-      EnigGetString("keyMan.button.generateKeyContinue")
+      l10n.formatValueSync("key-abort"),
+      l10n.formatValueSync("key-man-button-generate-key-abort"),
+      l10n.formatValueSync("key-man-button-generate-key-continue")
     );
     if (closeWin) {
       abortKeyGeneration();
     }
   } else {
     closeWin = true;
   }
 
--- a/mail/extensions/openpgp/content/ui/enigmailMessengerOverlay.js
+++ b/mail/extensions/openpgp/content/ui/enigmailMessengerOverlay.js
@@ -127,16 +127,18 @@ var EnigmailStdlib = ChromeUtils.import(
 var EnigmailConfigure = ChromeUtils.import(
   "chrome://openpgp/content/modules/configure.jsm"
 ).EnigmailConfigure;
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var KeyLookupHelper = ChromeUtils.import(
   "chrome://openpgp/content/modules/keyLookupHelper.jsm"
 ).KeyLookupHelper;
 
+var l10n = new Localization(["messenger/openpgp/enigmail.ftl"], true);
+
 var Enigmail;
 if (!Enigmail) {
   Enigmail = {};
 }
 
 Enigmail.getEnigmailSvc = function() {
   return EnigmailCore.getService(window);
 };
@@ -724,17 +726,17 @@ Enigmail.msg = {
     }
 
     var i;
     for (i in mimePart.subParts) {
       this.enumerateMimeParts(mimePart.subParts[i], resultObj);
     }
   },
 
-  messageDecryptCb(event, isAuto, mimeMsg) {
+  async messageDecryptCb(event, isAuto, mimeMsg) {
     EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageDecryptCb:\n");
 
     this.buggyExchangeEmailContent = null; // reinit HACK for MS-EXCHANGE-Server Problem
 
     let enigmailSvc;
     let contentType = "";
     try {
       if (!mimeMsg) {
@@ -993,17 +995,17 @@ Enigmail.msg = {
             // decryption set to manual
             Enigmail.hdrView.updateHdrIcons(
               EnigmailConstants.POSSIBLE_PGPMIME,
               0, // exitCode, statusFlags
               0,
               "",
               "", // keyId, userId
               "", // sigDetails
-              EnigmailLocale.getString("possiblyPgpMime"), // infoMsg
+              await document.l10n.formatValue("possibly-pgp-mime"), // infoMsg
               null, // blockSeparation
               "", // encToDetails
               null
             ); // xtraStatus
           }
         } else if (!isAuto) {
           Enigmail.msg.messageReload(false);
         }
@@ -1332,17 +1334,17 @@ Enigmail.msg = {
     let bodyElement = null;
 
     // Thunderbird
     let msgFrame = document.getElementById("messagepane");
     bodyElement = msgFrame.contentDocument.getElementsByTagName("body")[0];
     return bodyElement;
   },
 
-  messageParseCallback(
+  async messageParseCallback(
     msgText,
     contentEncoding,
     charset,
     interactive,
     importOnly,
     messageUrl,
     signature,
     retry,
@@ -1645,26 +1647,26 @@ Enigmail.msg = {
         }
       }
     }
 
     var msgRfc822Text = "";
     if (tail) {
       msgRfc822Text +=
         EnigmailData.convertFromUnicode(
-          EnigmailLocale.getString("beginPgpPart"),
+          await document.l10n.formatValue("begin-pgp-part"),
           charset
         ) + "\n\n";
     }
     msgRfc822Text += plainText;
     if (tail) {
       msgRfc822Text +=
         "\n\n" +
         EnigmailData.convertFromUnicode(
-          EnigmailLocale.getString("endPgpPart"),
+          await document.l10n.formatValue("end-pgp-part"),
           charset
         ) +
         "\n\n" +
         tail;
     }
 
     Enigmail.msg.decryptedMessage = {
       url: messageUrl,
@@ -1928,20 +1930,20 @@ Enigmail.msg = {
 
         EnigmailTimer.setTimeout(function() {
           gFolderDisplay.view.dbView.selectMsgByKey(msgKey);
         }, 750);
       }
 
       hideBrokenExchangePane();
     });
-    p.catch(function() {
+    p.catch(async function() {
       EnigmailDialog.alert(
         window,
-        EnigmailLocale.getString("fixBrokenExchangeMsg.failed")
+        await document.l10n.formatValue("fix-broken-exchange-msg-failed")
       );
       hideBrokenExchangePane();
     });
   },
 
   /**
    * Hide attachments containing OpenPGP keys
    */
@@ -2139,17 +2141,17 @@ Enigmail.msg = {
 
       contentData += "\r\n";
 
       if (
         Enigmail.msg.decryptedMessage.hasAttachments &&
         !Enigmail.msg.decryptedMessage.attachmentsEncrypted
       ) {
         contentData += EnigmailData.convertFromUnicode(
-          EnigmailLocale.getString("enigContentNote2"),
+          l10n.formatValueSync("enig-content-note") + "\r\n\r\n",
           Enigmail.msg.decryptedMessage.charset
         );
       }
 
       contentData += Enigmail.msg.decryptedMessage.plainText;
     } else {
       // text/html or text/plain
 
@@ -2498,17 +2500,17 @@ Enigmail.msg = {
         this.verifyDetachedSignature(anAttachment);
         break;
     }
   },
 
   /**
    * save the original file plus the signature file to disk and then verify the signature
    */
-  verifyDetachedSignature(anAttachment) {
+  async verifyDetachedSignature(anAttachment) {
     EnigmailLog.DEBUG(
       "enigmailMessengerOverlay.js: verifyDetachedSignature: url=" +
         anAttachment.url +
         "\n"
     );
 
     var enigmailSvc = Enigmail.getEnigmailSvc();
     if (!enigmailSvc) {
@@ -2582,39 +2584,42 @@ Enigmail.msg = {
           }
         }
       }
     }
 
     if (!signatureAtt) {
       EnigmailDialog.alert(
         window,
-        EnigmailLocale.getString("attachment.noMatchToSignature", [
-          EnigmailMsgRead.getAttachmentName(origAtt),
-        ])
+        await document.l10n.formatValue("attachment-no-match-to-signature", {
+          attachment: EnigmailMsgRead.getAttachmentName(origAtt),
+        })
       );
       return;
     }
     if (!origAtt) {
       EnigmailDialog.alert(
         window,
-        EnigmailLocale.getString("attachment.noMatchFromSignature", [
-          EnigmailMsgRead.getAttachmentName(signatureAtt),
-        ])
+        await document.l10n.formatValue("attachment-no-match-from-signature", {
+          attachment: EnigmailMsgRead.getAttachmentName(signatureAtt),
+        })
       );
       return;
     }
 
     // open
     var tmpDir = EnigmailFiles.getTempDir();
     var outFile1, outFile2;
     outFile1 = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
     outFile1.initWithPath(tmpDir);
     if (!(outFile1.isDirectory() && outFile1.isWritable())) {
-      EnigmailDialog.alert(window, EnigmailLocale.getString("noTempDir"));
+      EnigmailDialog.alert(
+        window,
+        await document.l10n.formatValue("no-temp-dir")
+      );
       return;
     }
     outFile1.append(EnigmailMsgRead.getAttachmentName(origAtt));
     outFile1.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
     EnigmailFiles.writeUrlToFile(origAtt.url, outFile1);
 
     if (isEncrypted) {
       // Try to decrypt message if we suspect the message is encrypted. If it fails we will just verify the encrypted data.
@@ -2631,32 +2636,32 @@ Enigmail.msg = {
 
     outFile2 = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
     outFile2.initWithPath(tmpDir);
     outFile2.append(EnigmailMsgRead.getAttachmentName(signatureAtt));
     outFile2.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
     EnigmailFiles.writeUrlToFile(signatureAtt.url, outFile2);
 
     var promise = EnigmailVerifyAttachment.attachment(outFile1, outFile2);
-    promise.then(function(message) {
+    promise.then(async function(message) {
       EnigmailDialog.info(
         window,
-        EnigmailLocale.getString("signature.verifiedOK", [
-          EnigmailMsgRead.getAttachmentName(origAtt),
-        ]) +
+        (await document.l10n.formatValue("signature-verified-ok", {
+          attachment: EnigmailMsgRead.getAttachmentName(origAtt),
+        })) +
           "\n\n" +
           message
       );
     });
-    promise.catch(function(err) {
+    promise.catch(async function(err) {
       EnigmailDialog.alert(
         window,
-        EnigmailLocale.getString("signature.verifyFailed", [
-          EnigmailMsgRead.getAttachmentName(origAtt),
-        ]) +
+        (await document.l10n.formatValue("signature-verify-failed", {
+          attachment: EnigmailMsgRead.getAttachmentName(origAtt),
+        })) +
           "\n\n" +
           err
       );
     });
 
     outFile1.remove(false);
     outFile2.remove(false);
   },
@@ -2740,17 +2745,17 @@ Enigmail.msg = {
       if (origFilename && origFilename.length > rawFileName.length) {
         rawFileName = origFilename;
       }
     }
 
     if (callbackArg.actionType == "saveAttachment") {
       outFile = EnigmailDialog.filePicker(
         window,
-        EnigmailLocale.getString("saveAttachmentHeader2"),
+        await document.l10n.formatValue("save-attachment-header"),
         Enigmail.msg.lastSaveDir,
         true,
         "",
         rawFileName,
         null
       );
       if (!outFile) {
         return;
@@ -2767,23 +2772,23 @@ Enigmail.msg = {
       return;
     } else {
       // open
       var tmpDir = EnigmailFiles.getTempDir();
       try {
         outFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
         outFile.initWithPath(tmpDir);
         if (!(outFile.isDirectory() && outFile.isWritable())) {
-          errorMsgObj.value = EnigmailLocale.getString("noTempDir");
+          errorMsgObj.value = await document.l10n.formatValue("no-temp-dir");
           return;
         }
         outFile.append(rawFileName);
         outFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
       } catch (ex) {
-        errorMsgObj.value = EnigmailLocale.getString("noTempDir");
+        errorMsgObj.value = await document.l10n.formatValue("no-temp-dir");
         return;
       }
     }
 
     if (callbackArg.actionType == "importKey") {
       var preview = EnigmailKey.getKeyListFromKeyBlock(
         callbackArg.data,
         errorMsgObj,
@@ -2846,23 +2851,23 @@ Enigmail.msg = {
       exitStatus = false;
       if (
         statusFlagsObj.value & EnigmailConstants.DECRYPTION_OKAY &&
         statusFlagsObj.value & EnigmailConstants.UNCERTAIN_SIGNATURE
       ) {
         if (callbackArg.actionType == "openAttachment") {
           exitStatus = EnigmailDialog.confirmDlg(
             window,
-            EnigmailLocale.getString("decryptOkNoSig"),
-            EnigmailLocale.getString("msgOvl.button.contAnyway")
+            await document.l10n.formatValue("decrypt-ok-no-sig"),
+            await document.l10n.formatValue("msg-ovl-button-cont-anyway")
           );
         } else {
           EnigmailDialog.info(
             window,
-            EnigmailLocale.getString("decryptOkNoSig")
+            await document.l10n.formatValue("decrypt-ok-no-sig")
           );
         }
       } else {
         EnigmailDialog.info(
           window,
           (await document.l10n.formatValue("failed-decrypt")) +
             "\n\n" +
             errorMsgObj.value
--- a/mail/extensions/openpgp/content/ui/enigmailMsgBox.js
+++ b/mail/extensions/openpgp/content/ui/enigmailMsgBox.js
@@ -62,17 +62,17 @@ function onLoad() {
     if (EnigmailOS.isMac) {
       let t = document.getElementById("macosDialogTitle");
       t.setAttribute("value", args.dialogTitle);
       t.removeAttribute("collapsed");
     }
 
     dlg.setAttribute("title", args.dialogTitle);
   } else {
-    dlg.setAttribute("title", EnigmailLocale.getString("enigAlert2"));
+    document.l10n.setAttributes(dlg, "enig-alert-title");
   }
 
   if (button1) {
     setButton("accept", button1);
   }
   if (button2) {
     setButton("extra1", button2);
   }
--- a/mail/extensions/openpgp/content/ui/enigmailMsgComposeOverlay.js
+++ b/mail/extensions/openpgp/content/ui/enigmailMsgComposeOverlay.js
@@ -1001,17 +1001,19 @@ Enigmail.msg = {
     }
 
     var tmpDir = EnigmailFiles.getTempDir();
     var tmpFile;
     try {
       tmpFile = Cc[LOCAL_FILE_CONTRACTID].createInstance(Ci.nsIFile);
       tmpFile.initWithPath(tmpDir);
       if (!(tmpFile.isDirectory() && tmpFile.isWritable())) {
-        EnigmailDialog.alert(window, EnigmailLocale.getString("noTempDir"));
+        document.l10n.formatValue("no-temp-dir").then(value => {
+          EnigmailDialog.alert(window, value);
+        });
         return null;
       }
     } catch (ex) {
       EnigmailLog.writeException(
         "enigmailMsgComposeOverlay.js: Enigmail.msg.extractAndAttachKey",
         ex
       );
     }
@@ -2044,17 +2046,17 @@ Enigmail.msg = {
         // BCC and encryption
 
         var dummy = {
           value: null,
         };
 
         var hideBccUsers = promptSvc.confirmEx(
           window,
-          EnigmailLocale.getString("enigConfirm2"),
+          l10n.formatValueSync("enig-confirm"),
           l10n.formatValueSync("sending-hidden-rcpt"),
           promptSvc.BUTTON_TITLE_IS_STRING * promptSvc.BUTTON_POS_0 +
             promptSvc.BUTTON_TITLE_CANCEL * promptSvc.BUTTON_POS_1 +
             promptSvc.BUTTON_TITLE_IS_STRING * promptSvc.BUTTON_POS_2,
           l10n.formatValueSync("send-with-shown-bcc"),
           null,
           l10n.formatValueSync("send-with-hidden-bcc"),
           null,
@@ -2225,19 +2227,21 @@ Enigmail.msg = {
       return false;
     }
 
     this.identity = getCurrentIdentity();
     let senderKeyId = this.identity.getUnicharAttribute("openpgp_key_id");
 
     if ((gSendEncrypted || gSendSigned) && !senderKeyId) {
       let msgId = gSendEncrypted
-        ? "cannotSendEncBecauseNoOwnKey"
-        : "cannotSendSigBecauseNoOwnKey";
-      let fullAlert = EnigmailLocale.getString(msgId, [this.identity.email]);
+        ? "cannot-send-enc-because-no-own-key"
+        : "cannot-send-sig-because-no-own-key";
+      let fullAlert = await document.l10n.formatValue(msgId, {
+        key: this.identity.email,
+      });
       EnigmailDialog.alert(window, fullAlert);
       return false;
     }
 
     if (senderKeyId) {
       let senderKeyUsable = await EnigmailEncryption.determineOwnKeyUsability(
         sendFlags,
         senderKeyId
@@ -2277,17 +2281,20 @@ Enigmail.msg = {
 
         EnigmailDialog.alert(window, fullAlert);
         showMessageComposeSecurityStatus();
         return false;
       }
     }
 
     if (gWindowLocked) {
-      EnigmailDialog.alert(window, EnigmailLocale.getString("windowLocked"));
+      EnigmailDialog.alert(
+        window,
+        await document.l10n.formatValue("window-locked")
+      );
       return false;
     }
 
     let newSecurityInfo = this.resetDirty();
     this.dirty = 1;
 
     try {
       this.modifiedAttach = null;
@@ -2670,17 +2677,17 @@ Enigmail.msg = {
           }
         }
       }
       if (errorMsg !== "") {
         txt = errorMsg + "\n" + txt;
       }
       EnigmailDialog.info(
         window,
-        (await document.l10n.formatValue("send-aborted")) + txt
+        (await document.l10n.formatValue("send-aborted")) + "\n" + txt
       );
     } else {
       EnigmailDialog.info(
         window,
         (await document.l10n.formatValue("send-aborted")) +
           "\n" +
           (await document.l10n.formatValue("msg-compose-internal-error"))
       );
--- a/mail/extensions/openpgp/content/ui/keyDetailsDlg.js
+++ b/mail/extensions/openpgp/content/ui/keyDetailsDlg.js
@@ -131,27 +131,27 @@ async function reloadData(firstLoad) {
 
   let keyIsExpired =
     keyObj.expiryTime && keyObj.expiryTime < Math.floor(Date.now() / 1000);
 
   let expiryInfo;
   let expireArgument = null;
   let expiryInfoKey = "";
   if (keyObj.keyTrust == "r") {
-    expiryInfoKey = "key-revoked";
+    expiryInfoKey = "key-revoked-date";
   } else if (keyObj.keyTrust == "e" || keyIsExpired) {
-    expiryInfoKey = "key-expired";
+    expiryInfoKey = "key-expired-date";
     expireArgument = keyObj.expiry;
   } else if (keyObj.expiry.length === 0) {
     expiryInfoKey = "key-does-not-expire";
   } else {
     expiryInfo = keyObj.expiry;
   }
   if (expiryInfoKey) {
-    expiryInfo = l10n.formatValueSync(expiryInfoKey, {
+    expiryInfo = await document.l10n.formatValue(expiryInfoKey, {
       keyExpiry: expireArgument,
     });
   }
   setLabel("keyExpiry", expiryInfo);
 
   gModePersonal = keyObj.secretAvailable;
   if (gModePersonal) {
     gPersonalRadio.removeAttribute("hidden");
@@ -488,17 +488,17 @@ SigListView.prototype = {
     gTreeFuncs.rowCountChanged(row, this.rowCount - r);
   },
 };
 
 function createSubkeyItem(subkey) {
   // Get expiry state of this subkey
   let expire;
   if (subkey.keyTrust === "r") {
-    expire = EnigmailLocale.getString("keyValid.revoked");
+    expire = l10n.formatValueSync("key-valid-revoked");
   } else if (subkey.expiryTime === 0) {
     expire = l10n.formatValueSync("key-expiry-never");
   } else {
     expire = subkey.expiry;
   }
 
   let subkeyType =
     subkey.type === "pub"