Bug 1498448 - Migrate Certificate Manager Dialog to use fluent for localization r=Gijs,flod,zbraniecki
authorQinghao_Jack_Song <songqing@msu.edu>
Wed, 28 Nov 2018 10:30:06 +0000
changeset 504921 ff378a3336a5704867e20ea5a27893e729aa5f9e
parent 504920 1af50e5a47da5a1c95c7bb915d23704c12846dfc
child 504922 66612048bbdcd6a587c480ede79a5cc53138db7e
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs, flod, zbraniecki
bugs1498448
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1498448 - Migrate Certificate Manager Dialog to use fluent for localization r=Gijs,flod,zbraniecki Differential Revision: https://phabricator.services.mozilla.com/D8499
browser/components/preferences/in-content/preferences.xul
browser/components/preferences/in-content/privacy.xul
python/l10n/fluent_migrations/bug_1498448_certificateManager.py
security/manager/locales/en-US/chrome/pipnss/pipnss.properties
security/manager/locales/en-US/chrome/pippki/certManager.dtd
security/manager/locales/en-US/chrome/pippki/pippki.properties
security/manager/locales/en-US/security/certificates/certManager.ftl
security/manager/locales/jar.mn
security/manager/pki/resources/content/certManager.js
security/manager/pki/resources/content/certManager.xul
security/manager/pki/resources/content/certViewer.js
security/manager/pki/resources/content/certViewer.xul
security/manager/pki/resources/content/deletecert.js
security/manager/pki/resources/content/deletecert.xul
security/manager/pki/resources/content/editcacert.js
security/manager/pki/resources/content/editcacert.xul
security/manager/pki/resources/content/exceptionDialog.js
security/manager/pki/resources/content/exceptionDialog.xul
security/manager/ssl/tests/mochitest/browser/browser_certViewer.js
security/manager/ssl/tests/mochitest/browser/browser_deleteCert_ui.js
toolkit/content/widgets/dialog.xml
--- a/browser/components/preferences/in-content/preferences.xul
+++ b/browser/components/preferences/in-content/preferences.xul
@@ -11,22 +11,17 @@
   href="chrome://browser/skin/preferences/in-content/preferences.css"?>
 <?xml-stylesheet
   href="chrome://browser/content/preferences/handlers.css"?>
 <?xml-stylesheet href="chrome://browser/skin/preferences/applications.css"?>
 <?xml-stylesheet href="chrome://browser/skin/preferences/in-content/search.css"?>
 <?xml-stylesheet href="chrome://browser/skin/preferences/in-content/containers.css"?>
 <?xml-stylesheet href="chrome://browser/skin/preferences/in-content/privacy.css"?>
 
-<!DOCTYPE page [
-<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
-<!ENTITY % certManagerDTD SYSTEM "chrome://pippki/locale/certManager.dtd">
-%brandDTD;
-%certManagerDTD;
-]>
+<!DOCTYPE page>
 
 <page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
       xmlns:html="http://www.w3.org/1999/xhtml"
       role="document"
       data-l10n-id="pref-page"
       data-l10n-attrs="title">
 
   <linkset>
@@ -44,16 +39,17 @@
     <link rel="localization" href="browser/preferences/languages.ftl"/>
     <link rel="localization" href="browser/preferences/permissions.ftl"/>
     <link rel="localization" href="browser/preferences/selectBookmark.ftl"/>
     <link rel="localization" href="browser/preferences/siteDataSettings.ftl"/>
     <link rel="localization" href="browser/aboutDialog.ftl"/>
     <link rel="localization" href="browser/sanitize.ftl"/>
     <link rel="localization" href="toolkit/updates/history.ftl"/>
     <link rel="localization" href="security/certificates/deviceManager.ftl"/>
+    <link rel="localization" href="security/certificates/certManager.ftl"/>
   </linkset>
 
   <html:link rel="shortcut icon"
               href="chrome://browser/skin/settings.svg"/>
 
   <script type="application/javascript"
           src="chrome://browser/content/utilityOverlay.js"/>
   <script type="application/javascript"
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -787,29 +787,31 @@
               flex="1" />
     <vbox>
       <!-- Please don't remove the wrapping hbox/vbox/box for these elements. It's used to properly compute the search tooltip position. -->
       <hbox pack="end">
         <button id="viewCertificatesButton"
                 class="accessory-button"
                 data-l10n-id="certs-view"
                 preference="security.disable_button.openCertManager"
-                searchkeywords="&certmgr.tab.mine;
-                                &certmgr.tab.others2;
-                                &certmgr.tab.websites3;
-                                &certmgr.tab.ca;
-                                &certmgr.mine2;
-                                &certmgr.others2;
-                                &certmgr.websites3;
-                                &certmgr.cas2;
-                                &certmgr.certname;
-                                &certmgr.tokenname;
-                                &certmgr.view2.label;
-                                &certmgr.export.label;
-                                &certmgr.delete2.label;"/>
+                search-l10n-ids="
+                  certmgr-tab-mine.label,
+                  certmgr-tab-people.label,
+                  certmgr-tab-servers.label,
+                  certmgr-tab-ca.label,
+                  certmgr-mine,
+                  certmgr-people,
+                  certmgr-servers,
+                  certmgr-ca,
+                  certmgr-cert-name.label,
+                  certmgr-token-name.label,
+                  certmgr-view.label,
+                  certmgr-export.label,
+                  certmgr-delete.label
+                "/>
       </hbox>
       <!-- Please don't remove the wrapping hbox/vbox/box for these elements. It's used to properly compute the search tooltip position. -->
       <hbox pack="end">
         <button id="viewSecurityDevicesButton"
                 class="accessory-button"
                 data-l10n-id="certs-devices"
                 preference="security.disable_button.openDeviceManager"
                 search-l10n-ids="
new file mode 100644
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1498448_certificateManager.py
@@ -0,0 +1,404 @@
+# coding=utf8
+
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+from __future__ import absolute_import
+import fluent.syntax.ast as FTL
+from fluent.migrate.helpers import transforms_from
+from fluent.migrate import COPY
+from fluent.migrate import REPLACE
+from fluent.migrate import CONCAT
+from fluent.migrate.helpers import VARIABLE_REFERENCE
+from fluent.migrate.helpers import TERM_REFERENCE
+from fluent.migrate.helpers import MESSAGE_REFERENCE
+
+def migrate(ctx):
+    """Bug 1498448 - Migrate Certificate Manager Dialog to use fluent for localization, part {index}."""
+
+    ctx.add_transforms(
+        "security/manager/security/certificates/certManager.ftl",
+        "security/manager/security/certificates/certManager.ftl",
+        transforms_from(
+"""
+certmgr-title =
+    .title = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.title") }
+
+certmgr-tab-mine =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.tab.mine") }
+
+certmgr-tab-people =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.tab.others2") }
+
+certmgr-tab-servers =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.tab.websites3") }
+
+certmgr-tab-ca =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.tab.ca") }
+
+certmgr-mine = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.mine2") }
+certmgr-people = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.others2") }
+certmgr-servers = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.websites3") }
+certmgr-ca = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.cas2") }
+
+certmgr-detail-general-tab-title =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.detail.general_tab.title") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.detail.general_tab.accesskey") }
+
+certmgr-detail-pretty-print-tab-title =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.detail.prettyprint_tab.title") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.detail.prettyprint_tab.accesskey") }
+
+certmgr-pending-label =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.pending.label") }
+
+certmgr-subject-info-label =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.subjectinfo.label") }
+
+certmgr-issuer-info-label =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.issuerinfo.label") }
+
+certmgr-period-of-validity-label =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.periodofvalidity.label") }
+
+certmgr-fingerprints-label =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.fingerprints.label") }
+
+certmgr-cert-detail =
+    .title = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.certdetail.title") }
+    .buttonlabelaccept = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.close.label") }
+    .buttonaccesskeyaccept = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.close.accesskey") }
+
+certmgr-cert-detail-cn =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.certdetail.cn") }
+
+certmgr-cert-detail-o =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.certdetail.o") }
+
+certmgr-cert-detail-ou =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.certdetail.ou") }
+
+certmgr-cert-detail-serialnumber =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.certdetail.serialnumber") }
+
+certmgr-cert-detail-sha256-fingerprint =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.certdetail.sha256fingerprint") }
+
+certmgr-cert-detail-sha1-fingerprint =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.certdetail.sha1fingerprint") }
+
+certmgr-edit-cert-edit-trust = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.editcert.edittrust") }
+
+certmgr-edit-cert-trust-ssl =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.editcert.trustssl") }
+
+certmgr-edit-cert-trust-email =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.editcert.trustemail") }
+
+certmgr-cert-name =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.certname") }
+
+certmgr-cert-server =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.certserver") }
+
+certmgr-override-lifetime
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.override_lifetime") }
+
+certmgr-token-name =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.tokenname") }
+
+certmgr-begins-label =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.begins") }
+
+certmgr-expires-label =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.expires") }
+
+certmgr-email =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.email") }
+
+certmgr-serial =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.serial") }
+
+certmgr-view =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.view2.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.view2.accesskey") }
+
+certmgr-edit =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.edit3.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.edit3.accesskey") }
+
+certmgr-export =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.export.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.export.accesskey") }
+
+certmgr-delete =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.delete2.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.delete2.accesskey") }
+
+certmgr-delete-builtin =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.delete_builtin.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.delete_builtin.accesskey") }
+
+certmgr-backup =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.backup2.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.backup2.accesskey") }
+
+certmgr-backup-all =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.backupall2.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.backupall2.accesskey") }
+
+certmgr-restore =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.restore2.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.restore2.accesskey") }
+
+certmgr-details =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.details.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.details.accesskey") }
+
+certmgr-fields=
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.fields.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.fields.accesskey") }
+
+certmgr-hierarchy =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.hierarchy.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.hierarchy.accesskey2") }
+
+certmgr-add-exception =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.addException.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "certmgr.addException.accesskey") }
+
+exception-mgr =
+    .title = { COPY("security/manager/chrome/pippki/certManager.dtd", "exceptionMgr.title") }
+
+exception-mgr-extra-button =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "exceptionMgr.exceptionButton.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "exceptionMgr.exceptionButton.accesskey") }
+
+exception-mgr-supplemental-warning = { COPY("security/manager/chrome/pippki/certManager.dtd", "exceptionMgr.supplementalWarning") }
+
+exception-mgr-cert-location-url =
+    .value = { COPY("security/manager/chrome/pippki/certManager.dtd", "exceptionMgr.certlocation.url") }
+
+exception-mgr-cert-location-download =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "exceptionMgr.certlocation.download") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "exceptionMgr.certlocation.accesskey") }
+
+exception-mgr-cert-status-view-cert =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "exceptionMgr.certstatus.viewCert") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "exceptionMgr.certstatus.accesskey") }
+
+exception-mgr-permanent =
+    .label = { COPY("security/manager/chrome/pippki/certManager.dtd", "exceptionMgr.permanent.label") }
+    .accesskey = { COPY("security/manager/chrome/pippki/certManager.dtd", "exceptionMgr.permanent.accesskey") }
+
+pk11-bad-password = { COPY("security/manager/chrome/pipnss/pipnss.properties", "PK11BadPassword") }
+pkcs12-decode-err = { COPY("security/manager/chrome/pipnss/pipnss.properties", "PKCS12DecodeErr") }
+pkcs12-unknown-err-restore = { COPY("security/manager/chrome/pipnss/pipnss.properties", "PKCS12UnknownErrRestore") }
+pkcs12-unknown-err-backup = { COPY("security/manager/chrome/pipnss/pipnss.properties", "PKCS12UnknownErrBackup") }
+pkcs12-unknown-err = { COPY("security/manager/chrome/pipnss/pipnss.properties", "PKCS12UnknownErr") }
+pkcs12-info-no-smartcard-backup = { COPY("security/manager/chrome/pipnss/pipnss.properties", "PKCS12InfoNoSmartcardBackup") }
+pkcs12-dup-data = { COPY("security/manager/chrome/pipnss/pipnss.properties", "PKCS12DupData") }
+
+choose-p12-backup-file-dialog = { COPY("security/manager/chrome/pippki/pippki.properties", "chooseP12BackupFileDialog") }
+file-browse-pkcs12-spec = { COPY("security/manager/chrome/pippki/pippki.properties", "file_browse_PKCS12_spec") }
+choose-p12-restore-file-dialog = { COPY("security/manager/chrome/pippki/pippki.properties", "chooseP12RestoreFileDialog2") }
+file-browse-certificate-spec = { COPY("security/manager/chrome/pippki/pippki.properties", "file_browse_Certificate_spec") }
+import-ca-certs-prompt = { COPY("security/manager/chrome/pippki/pippki.properties", "importCACertsPrompt") }
+import-email-cert-prompt = { COPY("security/manager/chrome/pippki/pippki.properties", "importEmailCertPrompt") }
+
+delete-user-cert-title =
+    .title = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteUserCertTitle") }
+
+delete-ssl-cert-title =
+    .title = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteSslCertTitle3") }
+
+delete-ca-cert-title =
+    .title = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteCaCertTitle2") }
+
+delete-email-cert-title =
+    .title = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteEmailCertTitle") }
+
+delete-user-cert-confirm = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteUserCertConfirm") }
+delete-user-cert-impact = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteUserCertImpact") }
+delete-ssl-cert-confirm = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteSslCertConfirm3") }
+delete-ssl-cert-impact = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteSslCertImpact3") }
+delete-ca-cert-confirm = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteCaCertConfirm2") }
+delete-ca-cert-impact = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteCaCertImpactX2") }
+delete-email-cert-confirm = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteEmailCertConfirm") }
+delete-email-cert-impact = { COPY("security/manager/chrome/pippki/pippki.properties", "deleteEmailCertImpactDesc") }
+
+cert-verified = { COPY("security/manager/chrome/pippki/pippki.properties", "certVerified") }
+
+not-present =
+    .value = { COPY("security/manager/chrome/pippki/pippki.properties", "notPresent") }
+
+verify-ssl-client =
+    .value = { COPY("security/manager/chrome/pipnss/pipnss.properties", "VerifySSLClient") }
+
+verify-ssl-server =
+    .value = { COPY("security/manager/chrome/pipnss/pipnss.properties", "VerifySSLServer") }
+
+verify-ssl-ca =
+    .value = { COPY("security/manager/chrome/pipnss/pipnss.properties", "VerifySSLCA") }
+
+verify-email-signer =
+    .value = { COPY("security/manager/chrome/pipnss/pipnss.properties", "VerifyEmailSigner") }
+
+verify-email-recip =
+    .value = { COPY("security/manager/chrome/pipnss/pipnss.properties", "VerifyEmailRecip") }
+
+cert-not-verified-cert-revoked = { COPY("security/manager/chrome/pippki/pippki.properties", "certNotVerified_CertRevoked") }
+cert-not-verified-cert-expired = { COPY("security/manager/chrome/pippki/pippki.properties", "certNotVerified_CertExpired") }
+cert-not-verified-cert-not-trusted = { COPY("security/manager/chrome/pippki/pippki.properties", "certNotVerified_CertNotTrusted") }
+cert-not-verified-issuer-not-trusted = { COPY("security/manager/chrome/pippki/pippki.properties", "certNotVerified_IssuerNotTrusted") }
+cert-not-verified-issuer-unknown = { COPY("security/manager/chrome/pippki/pippki.properties", "certNotVerified_IssuerUnknown") }
+cert-not-verified-ca-invalid = { COPY("security/manager/chrome/pippki/pippki.properties", "certNotVerified_CAInvalid") }
+cert-not-verified_algorithm-disabled = { COPY("security/manager/chrome/pippki/pippki.properties", "certNotVerified_AlgorithmDisabled") }
+cert-not-verified-unknown = { COPY("security/manager/chrome/pippki/pippki.properties", "certNotVerified_Unknown") }
+
+add-exception-invalid-header = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionInvalidHeader") }
+add-exception-domain-mismatch-short = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionDomainMismatchShort") }
+add-exception-domain-mismatch-long = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionDomainMismatchLong2") }
+add-exception-expired-short = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionExpiredShort") }
+add-exception-expired-long = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionExpiredLong2") }
+add-exception-unverified-or-bad-signature-short = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionUnverifiedOrBadSignatureShort") }
+add-exception-unverified-or-bad-signature-long = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionUnverifiedOrBadSignatureLong2") }
+add-exception-valid-short = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionValidShort") }
+add-exception-valid-long = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionValidLong") }
+add-exception-checking-short = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionCheckingShort") }
+add-exception-checking-long = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionCheckingLong2") }
+add-exception-no-cert-short = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionNoCertShort") }
+add-exception-no-cert-long = { COPY("security/manager/chrome/pippki/pippki.properties", "addExceptionNoCertLong2") }
+""")
+)
+
+    ctx.add_transforms(
+    "security/manager/security/certificates/certManager.ftl",
+    "security/manager/security/certificates/certManager.ftl",
+    [
+        FTL.Message(
+            id=FTL.Identifier("edit-trust-ca"),
+            value=REPLACE(
+                "security/manager/chrome/pippki/pippki.properties",
+                "editTrustCA",
+                {
+                    "%S": VARIABLE_REFERENCE("certName")
+                },
+            )
+        ),
+
+            FTL.Message(
+                id=FTL.Identifier("cert-with-serial"),
+                attributes=[
+                    FTL.Attribute(
+                        id=FTL.Identifier("value"),
+                        value=REPLACE(
+                            "security/manager/chrome/pippki/pippki.properties",
+                            "certWithSerial",
+                            {
+                                "%1$S": VARIABLE_REFERENCE("serialNumber")
+                            },
+                        )
+                    )
+                ]
+            ),
+
+            FTL.Message(
+                id=FTL.Identifier("cert-viewer-title"),
+                attributes=[
+                    FTL.Attribute(
+                        id=FTL.Identifier("title"),
+                        value=REPLACE(
+                            "security/manager/chrome/pippki/pippki.properties",
+                            "certViewerTitle",
+                            {
+                                "%1$S": VARIABLE_REFERENCE("certName")
+                            },
+                        )
+                    )
+                ]
+            ),
+
+            FTL.Message(
+                id=FTL.Identifier("add-exception-branded-warning"),
+                value=REPLACE(
+                    "security/manager/chrome/pippki/pippki.properties",
+                    "addExceptionBrandedWarning2",
+                    {
+                        "%S": TERM_REFERENCE("-brand-short-name")
+                    },
+                )
+            ),
+
+            FTL.Message(
+                id=FTL.Identifier("certmgr-edit-ca-cert"),
+                attributes=[
+                    FTL.Attribute(
+                        id=FTL.Identifier("title"),
+                        value=COPY(
+                                "security/manager/chrome/pippki/certManager.dtd",
+                                "certmgr.editcacert.title",
+                            )
+                        ),
+                    FTL.Attribute(
+                        id=FTL.Identifier("style"),
+                        value=CONCAT(
+                            FTL.TextElement("width: 48em;"),
+                        )
+                    )
+                ]
+            ),
+
+            FTL.Message(
+                id=FTL.Identifier("certmgr-delete-cert"),
+                attributes=[
+                    FTL.Attribute(
+                        id=FTL.Identifier("title"),
+                        value=COPY(
+                                "security/manager/chrome/pippki/certManager.dtd",
+                                "certmgr.deletecert.title",
+                            )
+                        ),
+                    FTL.Attribute(
+                        id=FTL.Identifier("style"),
+                        value=CONCAT(
+                            FTL.TextElement("width: 48em; height: 24em;"),
+                        )
+                    )
+                ]
+            ),
+
+            FTL.Message(
+                id=FTL.Identifier("certmgr-begins-value"),
+                attributes=[
+                    FTL.Attribute(
+                        id=FTL.Identifier("value"),
+                        value=FTL.Pattern(
+                            elements=[
+                                FTL.Placeable(
+                                    expression=MESSAGE_REFERENCE("certmgr-begins-label.label")
+                                )
+                            ]
+                        )
+                    )
+                ]
+            ),
+
+            FTL.Message(
+                id=FTL.Identifier("certmgr-expires-value"),
+                attributes=[
+                    FTL.Attribute(
+                        id=FTL.Identifier("value"),
+                        value=FTL.Pattern(
+                            elements=[
+                                FTL.Placeable(
+                                    expression=MESSAGE_REFERENCE("certmgr-expires-label.label")
+                                )
+                            ]
+                        )
+                    )
+                ]
+            ),
+        ]
+    )
+
--- a/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
+++ b/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
@@ -52,21 +52,16 @@ PrivateSlotDescription=PSM Private Keys
 # conversion to UTF-8.
 # length_limit = 32 bytes
 Fips140TokenDescription=Software Security Device (FIPS)
 # LOCALIZATION NOTE (Fips140SlotDescription): string limit is 64 bytes after
 # conversion to UTF-8.
 # length_limit = 64 bytes
 Fips140SlotDescription=FIPS 140 Cryptographic, Key and Certificate Services
 
-VerifySSLClient=SSL Client Certificate
-VerifySSLServer=SSL Server Certificate
-VerifySSLCA=SSL Certificate Authority
-VerifyEmailSigner=Email Signer Certificate
-VerifyEmailRecip=Email Recipient Certificate
 HighGrade=High Grade
 MediumGrade=Medium Grade
 # LOCALIZATION NOTE (nick_template): $1s is the common name from a cert (e.g. "Mozilla"), $2s is the CA name (e.g. VeriSign)
 nick_template=%1$s’s %2$s ID
 #These are the strings set for the ASN1 objects in a certificate.
 CertDumpCertificate=Certificate
 CertDumpVersion=Version
 # LOCALIZATION NOTE (CertDumpVersionValue): %S is a version number (e.g. "3" in "Version 3")
@@ -248,23 +243,16 @@ CertDumpECsect233r1=SECG elliptic curve 
 CertDumpECsect239k1=SECG elliptic curve sect239k1
 CertDumpECsect283k1=SECG elliptic curve sect283k1 (aka NIST K-283)
 CertDumpECsect283r1=SECG elliptic curve sect283r1 (aka NIST B-283)
 CertDumpECsect409k1=SECG elliptic curve sect409k1 (aka NIST K-409)
 CertDumpECsect409r1=SECG elliptic curve sect409r1 (aka NIST B-409)
 CertDumpECsect571k1=SECG elliptic curve sect571k1 (aka NIST K-571)
 CertDumpECsect571r1=SECG elliptic curve sect571r1 (aka NIST B-571)
 CertDumpRawBytesHeader=Size: %S Bytes / %S Bits
-PK11BadPassword=The password entered was incorrect.
-PKCS12DecodeErr=Failed to decode the file.  Either it is not in PKCS #12 format, has been corrupted, or the password you entered was incorrect.
-PKCS12UnknownErrRestore=Failed to restore the PKCS #12 file for unknown reasons.
-PKCS12UnknownErrBackup=Failed to create the PKCS #12 backup file for unknown reasons.
-PKCS12UnknownErr=The PKCS #12 operation failed for unknown reasons.
-PKCS12InfoNoSmartcardBackup=It is not possible to back up certificates from a hardware security device such as a smart card.
-PKCS12DupData=The certificate and private key already exist on the security device.
 AVATemplate=%S = %S
 
 PSMERR_SSL_Disabled=Can’t connect securely because the SSL protocol has been disabled.
 PSMERR_SSL2_Disabled=Can’t connect securely because the site uses an older, insecure version of the SSL protocol.
 PSMERR_HostReusedIssuerSerial=You have received an invalid certificate.  Please contact the server administrator or email correspondent and give them the following information:\n\nYour certificate contains the same serial number as another certificate issued by the certificate authority.  Please get a new certificate containing a unique serial number.
 
 # LOCALIZATION NOTE (SSLConnectionErrorPrefix2): %1$S is the host string, %2$S is more detailed information (localized as well).
 SSLConnectionErrorPrefix2=An error occurred during a connection to %1$S. %2$S\n
deleted file mode 100644
--- a/security/manager/locales/en-US/chrome/pippki/certManager.dtd
+++ /dev/null
@@ -1,88 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!ENTITY certmgr.title                       "Certificate Manager">
-
-<!ENTITY certmgr.tab.mine                     "Your Certificates">
-<!ENTITY certmgr.tab.others2                  "People">
-<!ENTITY certmgr.tab.websites3                "Servers">
-<!ENTITY certmgr.tab.ca                       "Authorities">
-
-<!ENTITY certmgr.mine2                        "You have certificates from these organizations that identify you">
-<!ENTITY certmgr.others2                      "You have certificates on file that identify these people">
-<!ENTITY certmgr.websites3                    "You have certificates on file that identify these servers">
-<!ENTITY certmgr.cas2                         "You have certificates on file that identify these certificate authorities">
-
-<!ENTITY certmgr.detail.general_tab.title     "General">
-<!ENTITY certmgr.detail.general_tab.accesskey "G">
-<!ENTITY certmgr.detail.prettyprint_tab.title "Details">
-<!ENTITY certmgr.detail.prettyprint_tab.accesskey "D">
-
-<!ENTITY certmgr.pending.label                "Currently verifying certificate…">
-<!ENTITY certmgr.subjectinfo.label            "Issued To">
-<!ENTITY certmgr.issuerinfo.label             "Issued By">
-<!ENTITY certmgr.periodofvalidity.label       "Period of Validity" >
-<!ENTITY certmgr.fingerprints.label           "Fingerprints">
-<!ENTITY certmgr.certdetail.title             "Certificate Detail">
-<!ENTITY certmgr.certdetail.cn                "Common Name (CN)">
-<!ENTITY certmgr.certdetail.o                 "Organization (O)">
-<!ENTITY certmgr.certdetail.ou                "Organizational Unit (OU)">
-<!ENTITY certmgr.certdetail.serialnumber      "Serial Number">
-<!ENTITY certmgr.certdetail.sha256fingerprint "SHA-256 Fingerprint">
-<!ENTITY certmgr.certdetail.sha1fingerprint   "SHA1 Fingerprint">
-
-<!ENTITY certmgr.editcacert.title             "Edit CA certificate trust settings">
-<!ENTITY certmgr.editcert.edittrust           "Edit trust settings:">
-<!ENTITY certmgr.editcert.trustssl            "This certificate can identify websites.">
-<!ENTITY certmgr.editcert.trustemail          "This certificate can identify mail users.">
-
-<!ENTITY certmgr.deletecert.title             "Delete Certificate">
-
-<!ENTITY certmgr.certname                     "Certificate Name">
-<!ENTITY certmgr.certserver                   "Server">
-<!ENTITY certmgr.override_lifetime            "Lifetime">
-<!ENTITY certmgr.tokenname                    "Security Device">
-<!ENTITY certmgr.begins                       "Begins On">
-<!ENTITY certmgr.expires                      "Expires On">
-<!ENTITY certmgr.email                        "E-Mail Address">
-<!ENTITY certmgr.serial                       "Serial Number">
-
-<!ENTITY certmgr.close.label                  "Close">
-<!ENTITY certmgr.close.accesskey              "C">
-<!ENTITY certmgr.view2.label                  "View…">
-<!ENTITY certmgr.view2.accesskey              "V">
-<!ENTITY certmgr.edit3.label                  "Edit Trust…">
-<!ENTITY certmgr.edit3.accesskey              "E">
-<!ENTITY certmgr.export.label                 "Export…">
-<!ENTITY certmgr.export.accesskey             "x">
-<!ENTITY certmgr.delete2.label                "Delete…">
-<!ENTITY certmgr.delete2.accesskey            "D">
-<!ENTITY certmgr.delete_builtin.label         "Delete or Distrust…">
-<!ENTITY certmgr.delete_builtin.accesskey     "D">
-<!ENTITY certmgr.backup2.label                "Backup…">
-<!ENTITY certmgr.backup2.accesskey            "B">
-<!ENTITY certmgr.backupall2.label             "Backup All…">
-<!ENTITY certmgr.backupall2.accesskey         "k">
-<!ENTITY certmgr.restore2.label               "Import…">
-<!ENTITY certmgr.restore2.accesskey           "m">
-<!ENTITY certmgr.details.label                "Certificate Fields">
-<!ENTITY certmgr.details.accesskey            "F">
-<!ENTITY certmgr.fields.label                 "Field Value">
-<!ENTITY certmgr.fields.accesskey             "V">
-<!ENTITY certmgr.hierarchy.label              "Certificate Hierarchy">
-<!ENTITY certmgr.hierarchy.accesskey2         "H">
-<!ENTITY certmgr.addException.label           "Add Exception…">
-<!ENTITY certmgr.addException.accesskey       "x">
-
-<!ENTITY exceptionMgr.title                   "Add Security Exception">
-<!ENTITY exceptionMgr.exceptionButton.label   "Confirm Security Exception">
-<!ENTITY exceptionMgr.exceptionButton.accesskey "C">
-<!ENTITY exceptionMgr.supplementalWarning     "Legitimate banks, stores, and other public sites will not ask you to do this.">
-<!ENTITY exceptionMgr.certlocation.url        "Location:">
-<!ENTITY exceptionMgr.certlocation.download   "Get Certificate">
-<!ENTITY exceptionMgr.certlocation.accesskey  "G">
-<!ENTITY exceptionMgr.certstatus.viewCert     "View…">
-<!ENTITY exceptionMgr.certstatus.accesskey    "V">
-<!ENTITY exceptionMgr.permanent.label         "Permanently store this exception">
-<!ENTITY exceptionMgr.permanent.accesskey     "P">
--- a/security/manager/locales/en-US/chrome/pippki/pippki.properties
+++ b/security/manager/locales/en-US/chrome/pippki/pippki.properties
@@ -1,59 +1,21 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-# LOCALIZATION NOTE(certWithSerial): Used for semi-uniquely representing a cert.
-# %1$S is the serial number of the cert in AA:BB:CC hex format.
-certWithSerial=Certificate with serial number: %1$S
-
 # Download Cert dialog
 # LOCALIZATION NOTE(newCAMessage1):
 # %S is a string representative of the certificate being downloaded/imported.
 newCAMessage1=Do you want to trust “%S” for the following purposes?
 unnamedCA=Certificate Authority (unnamed)
 
-# For editing cert trust
-editTrustCA=The certificate “%S” represents a Certificate Authority.
-
-# For Deleting Certificates
-deleteSslCertConfirm3=Are you sure you want to delete these server exceptions?
-deleteSslCertImpact3=If you delete a server exception, you restore the usual security checks for that server and require it uses a valid certificate.
-deleteSslCertTitle3=Delete Server Certificate Exceptions
-
-deleteUserCertConfirm=Are you sure you want to delete these certificates?
-deleteUserCertImpact=If you delete one of your own certificates, you can no longer use it to identify yourself.
-deleteUserCertTitle=Delete your Certificates
-
-deleteCaCertConfirm2=You have requested to delete these CA certificates. For built-in certificates all trust will be removed, which has the same effect. Are you sure you want to delete or distrust?
-deleteCaCertImpactX2=If you delete or distrust a certificate authority (CA) certificate, this application will no longer trust any certificates issued by that CA.
-deleteCaCertTitle2=Delete or Distrust CA Certificates
-
-deleteEmailCertConfirm=Are you sure you want to delete these people’s e-mail certificates?
-deleteEmailCertImpactDesc=If you delete a person’s e-mail certificate, you will no longer be able to send encrypted e-mail to that person.
-deleteEmailCertTitle=Delete E-Mail Certificates
-
 # PKCS#12 file dialogs
-chooseP12RestoreFileDialog2=Certificate File to Import
-chooseP12BackupFileDialog=File Name to Backup
-file_browse_PKCS12_spec=PKCS12 Files
 getPKCS12FilePasswordMessage=Please enter the password that was used to encrypt this certificate backup:
 
-# Cert verification
-certVerified=This certificate has been verified for the following uses:
-certNotVerified_CertRevoked=Could not verify this certificate because it has been revoked.
-certNotVerified_CertExpired=Could not verify this certificate because it has expired.
-certNotVerified_CertNotTrusted=Could not verify this certificate because it is not trusted.
-certNotVerified_IssuerNotTrusted=Could not verify this certificate because the issuer is not trusted.
-certNotVerified_IssuerUnknown=Could not verify this certificate because the issuer is unknown.
-certNotVerified_CAInvalid=Could not verify this certificate because the CA certificate is invalid.
-certNotVerified_AlgorithmDisabled=Could not verify this certificate because it was signed using a signature algorithm that was disabled because that algorithm is not secure.
-certNotVerified_Unknown=Could not verify this certificate for unknown reasons.
-
 # Client auth
 clientAuthRemember=Remember this decision
 # LOCALIZATION NOTE(clientAuthNickAndSerial): Represents a single cert when the
 # user is choosing from a list of certificates.
 # %1$S is the nickname of the cert.
 # %2$S is the serial number of the cert in AA:BB:CC hex format.
 clientAuthNickAndSerial=%1$S [%2$S]
 # LOCALIZATION NOTE(clientAuthHostnameAndPort):
@@ -103,63 +65,36 @@ pageInfo_EncryptionWithBitsAndProtocol=C
 pageInfo_BrokenEncryption=Broken Encryption (%1$S, %2$S bit keys, %3$S)
 pageInfo_Privacy_Encrypted1=The page you are viewing was encrypted before being transmitted over the Internet.
 pageInfo_Privacy_Encrypted2=Encryption makes it difficult for unauthorized people to view information traveling between computers. It is therefore unlikely that anyone read this page as it traveled across the network.
 pageInfo_MixedContent=Connection Partially Encrypted
 pageInfo_MixedContent2=Parts of the page you are viewing were not encrypted before being transmitted over the Internet.
 pageInfo_WeakCipher=Your connection to this website uses weak encryption and is not private. Other people can view your information or modify the website’s behavior.
 pageInfo_CertificateTransparency_Compliant=This website complies with the Certificate Transparency policy.
 
-# Cert Viewer
-# LOCALIZATION NOTE(certViewerTitle): Title used for the Certificate Viewer.
-# %1$S is a string representative of the certificate being viewed.
-certViewerTitle=Certificate Viewer: “%1$S”
-notPresent=<Not Part Of Certificate>
-
 # Token Manager
 password_not_set=(not set)
 failed_pw_change=Unable to change Master Password.
 incorrect_pw=You did not enter the correct current Master Password. Please try again.
 pw_change_ok=Master Password successfully changed.
 pw_erased_ok=Warning! You have deleted your Master Password. 
 pw_not_wanted=Warning! You have decided not to use a Master Password.
 pw_empty_warning=Your stored web and email passwords, form data, and private keys will not be protected.
 pw_change2empty_in_fips_mode=You are currently in FIPS mode. FIPS requires a non-empty Master Password.
 enable_fips=Enable FIPS
 disable_fips=Disable FIPS
 
 resetPasswordConfirmationTitle=Reset Master Password
 resetPasswordConfirmationMessage=Your password has been reset.
 
-# Import certificate(s) file dialog
-importEmailCertPrompt=Select File containing somebody’s Email certificate to import
-importCACertsPrompt=Select File containing CA certificate(s) to import
-file_browse_Certificate_spec=Certificate Files
-
 # Cert export
 SaveCertAs=Save Certificate To File
 CertFormatBase64=X.509 Certificate (PEM)
 CertFormatBase64Chain=X.509 Certificate with chain (PEM)
 CertFormatDER=X.509 Certificate (DER)
 CertFormatPKCS7=X.509 Certificate (PKCS#7)
 CertFormatPKCS7Chain=X.509 Certificate with chain (PKCS#7)
 writeFileFailure=File Error
 writeFileFailed=Can’t write to file %S:\n%S.
 writeFileAccessDenied=Access denied
 writeFileIsLocked=File is locked
 writeFileNoDeviceSpace=No space left on device
 writeFileUnknownError=Unknown error
-
-# Add Security Exception dialog
-addExceptionBrandedWarning2=You are about to override how %S identifies this site.
-addExceptionInvalidHeader=This site attempts to identify itself with invalid information.
-addExceptionDomainMismatchShort=Wrong Site
-addExceptionDomainMismatchLong2=The certificate belongs to a different site, which could mean that someone is trying to impersonate this site.
-addExceptionExpiredShort=Outdated Information
-addExceptionExpiredLong2=The certificate is not currently valid. It may have been stolen or lost, and could be used by someone to impersonate this site.
-addExceptionUnverifiedOrBadSignatureShort=Unknown Identity
-addExceptionUnverifiedOrBadSignatureLong2=The certificate is not trusted because it hasn’t been verified as issued by a trusted authority using a secure signature.
-addExceptionValidShort=Valid Certificate
-addExceptionValidLong=This site provides valid, verified identification.  There is no need to add an exception.
-addExceptionCheckingShort=Checking Information
-addExceptionCheckingLong2=Attempting to identify this site…
-addExceptionNoCertShort=No Information Available
-addExceptionNoCertLong2=Unable to obtain identification status for this site.
new file mode 100644
--- /dev/null
+++ b/security/manager/locales/en-US/security/certificates/certManager.ftl
@@ -0,0 +1,300 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+certmgr-title =
+    .title = Certificate Manager
+
+certmgr-tab-mine =
+    .label = Your Certificates
+
+certmgr-tab-people =
+    .label = People
+
+certmgr-tab-servers =
+    .label = Servers
+
+certmgr-tab-ca =
+    .label = Authorities
+
+certmgr-mine = You have certificates from these organizations that identify you
+certmgr-people = You have certificates on file that identify these people
+certmgr-servers = You have certificates on file that identify these servers
+certmgr-ca = You have certificates on file that identify these certificate authorities
+
+certmgr-detail-general-tab-title =
+    .label = General
+    .accesskey = G
+
+certmgr-detail-pretty-print-tab-title =
+    .label = Details
+    .accesskey = D
+
+certmgr-pending-label =
+    .value = Currently verifying certificate…
+
+certmgr-subject-info-label =
+    .value = Issued To
+
+certmgr-issuer-info-label =
+    .value = Issued By
+
+certmgr-period-of-validity-label =
+    .value = Period of Validity
+
+certmgr-fingerprints-label =
+    .value = Fingerprints
+
+certmgr-cert-detail =
+    .title = Certificate Detail
+    .buttonlabelaccept = Close
+    .buttonaccesskeyaccept = C
+
+certmgr-cert-detail-cn =
+    .value = Common Name (CN)
+
+certmgr-cert-detail-o =
+    .value = Organization (O)
+
+certmgr-cert-detail-ou =
+    .value = Organizational Unit (OU)
+
+certmgr-cert-detail-serialnumber =
+    .value = Serial Number
+
+certmgr-cert-detail-sha256-fingerprint =
+    .value = SHA-256 Fingerprint
+
+certmgr-cert-detail-sha1-fingerprint =
+    .value = SHA1 Fingerprint
+
+certmgr-edit-ca-cert =
+    .title = Edit CA certificate trust settings
+    .style = width: 48em;
+
+certmgr-edit-cert-edit-trust = Edit trust settings:
+
+certmgr-edit-cert-trust-ssl =
+    .label = This certificate can identify websites.
+
+certmgr-edit-cert-trust-email =
+    .label = This certificate can identify mail users.
+
+certmgr-delete-cert =
+    .title = Delete Certificate
+    .style = width: 48em; height: 24em;
+
+certmgr-cert-name =
+    .label = Certificate Name
+
+certmgr-cert-server =
+    .label = Server
+
+certmgr-override-lifetime =
+    .label = Lifetime
+
+certmgr-token-name =
+    .label = Security Device
+
+certmgr-begins-label =
+    .label = Begins On
+
+certmgr-begins-value =
+    .value = { certmgr-begins-label.label }
+
+certmgr-expires-label =
+    .label = Expires On
+
+certmgr-expires-value =
+    .value = { certmgr-expires-label.label }
+
+certmgr-email =
+    .label = E-Mail Address
+
+certmgr-serial =
+    .label = Serial Number
+
+certmgr-view =
+    .label = View…
+    .accesskey = V
+
+certmgr-edit =
+    .label = Edit Trust…
+    .accesskey = E
+
+certmgr-export =
+    .label = Export…
+    .accesskey = x
+
+certmgr-delete =
+    .label = Delete…
+    .accesskey = D
+
+certmgr-delete-builtin =
+    .label = Delete or Distrust…
+    .accesskey = D
+
+certmgr-backup =
+    .label = Backup…
+    .accesskey = B
+
+certmgr-backup-all =
+    .label = Backup All…
+    .accesskey = k
+
+certmgr-restore =
+    .label = Import…
+    .accesskey = m
+
+certmgr-details =
+    .value = Certificate Fields
+    .accesskey = F
+
+certmgr-fields =
+    .value = Field Value
+    .accesskey = V
+
+certmgr-hierarchy =
+    .value = Certificate Hierarchy
+    .accesskey = H
+
+certmgr-add-exception =
+    .label = Add Exception…
+    .accesskey = x
+
+exception-mgr =
+    .title = Add Security Exception
+
+exception-mgr-extra-button =
+    .label = Confirm Security Exception
+    .accesskey = C
+
+exception-mgr-supplemental-warning = Legitimate banks, stores, and other public sites will not ask you to do this.
+
+exception-mgr-cert-location-url =
+    .value = Location:
+
+exception-mgr-cert-location-download =
+    .label = Get Certificate
+    .accesskey = G
+
+exception-mgr-cert-status-view-cert =
+    .label = View…
+    .accesskey = V
+
+exception-mgr-permanent =
+    .label = Permanently store this exception
+    .accesskey = P
+
+pk11-bad-password = The password entered was incorrect.
+pkcs12-decode-err = Failed to decode the file. Either it is not in PKCS #12 format, has been corrupted, or the password you entered was incorrect.
+pkcs12-unknown-err-restore = Failed to restore the PKCS #12 file for unknown reasons.
+pkcs12-unknown-err-backup = Failed to create the PKCS #12 backup file for unknown reasons.
+pkcs12-unknown-err = The PKCS #12 operation failed for unknown reasons.
+pkcs12-info-no-smartcard-backup = It is not possible to back up certificates from a hardware security device such as a smart card.
+pkcs12-dup-data = The certificate and private key already exist on the security device.
+
+## PKCS#12 file dialogs
+choose-p12-backup-file-dialog = File Name to Backup
+file-browse-pkcs12-spec = PKCS12 Files
+choose-p12-restore-file-dialog = Certificate File to Import
+
+## Import certificate(s) file dialog
+file-browse-certificate-spec = Certificate Files
+import-ca-certs-prompt = Select File containing CA certificate(s) to import
+import-email-cert-prompt = Select File containing somebody’s Email certificate to import
+
+## For editing certificates trust
+
+# Variables:
+#   $certName: the name of certificate
+edit-trust-ca = The certificate “{ $certName }” represents a Certificate Authority.
+
+## For Deleting Certificates
+
+delete-user-cert-title =
+    .title = Delete your Certificates
+delete-user-cert-confirm = Are you sure you want to delete these certificates?
+delete-user-cert-impact = If you delete one of your own certificates, you can no longer use it to identify yourself.
+
+
+delete-ssl-cert-title =
+    .title = Delete Server Certificate Exceptions
+delete-ssl-cert-confirm = Are you sure you want to delete these server exceptions?
+delete-ssl-cert-impact = If you delete a server exception, you restore the usual security checks for that server and require it uses a valid certificate.
+
+delete-ca-cert-title =
+    .title = Delete or Distrust CA Certificates
+delete-ca-cert-confirm = You have requested to delete these CA certificates. For built-in certificates all trust will be removed, which has the same effect. Are you sure you want to delete or distrust?
+delete-ca-cert-impact = If you delete or distrust a certificate authority (CA) certificate, this application will no longer trust any certificates issued by that CA.
+
+
+delete-email-cert-title =
+    .title = Delete E-Mail Certificates
+delete-email-cert-confirm = Are you sure you want to delete these people’s e-mail certificates?
+delete-email-cert-impact = If you delete a person’s e-mail certificate, you will no longer be able to send encrypted e-mail to that person.
+
+# Used for semi-uniquely representing a cert.
+#
+# Variables:
+#   $serialNumber : the serial number of the cert in AA:BB:CC hex format.
+cert-with-serial =
+    .value = Certificate with serial number: { $serialNumber }
+
+## Cert Viewer
+
+# Title used for the Certificate Viewer.
+#
+# Variables:
+#   $certificate : a string representative of the certificate being viewed.
+cert-viewer-title =
+    .title = Certificate Viewer: “{ $certName }”
+
+not-present =
+    .value = <Not Part Of Certificate>
+
+# Cert verification
+cert-verified = This certificate has been verified for the following uses:
+
+# Add usage
+verify-ssl-client =
+    .value = SSL Client Certificate
+
+verify-ssl-server =
+    .value = SSL Server Certificate
+
+verify-ssl-ca =
+    .value = SSL Certificate Authority
+
+verify-email-signer =
+    .value = Email Signer Certificate
+
+verify-email-recip =
+    .value = Email Recipient Certificate
+
+# Cert verification
+cert-not-verified-cert-revoked = Could not verify this certificate because it has been revoked.
+cert-not-verified-cert-expired = Could not verify this certificate because it has expired.
+cert-not-verified-cert-not-trusted = Could not verify this certificate because it is not trusted.
+cert-not-verified-issuer-not-trusted = Could not verify this certificate because the issuer is not trusted.
+cert-not-verified-issuer-unknown = Could not verify this certificate because the issuer is unknown.
+cert-not-verified-ca-invalid = Could not verify this certificate because the CA certificate is invalid.
+cert-not-verified_algorithm-disabled = Could not verify this certificate because it was signed using a signature algorithm that was disabled because that algorithm is not secure.
+cert-not-verified-unknown = Could not verify this certificate for unknown reasons.
+
+## Add Security Exception dialog
+add-exception-branded-warning = You are about to override how { -brand-short-name } identifies this site.
+add-exception-invalid-header = This site attempts to identify itself with invalid information.
+add-exception-domain-mismatch-short = Wrong Site
+add-exception-domain-mismatch-long = The certificate belongs to a different site, which could mean that someone is trying to impersonate this site.
+add-exception-expired-short = Outdated Information
+add-exception-expired-long = The certificate is not currently valid. It may have been stolen or lost, and could be used by someone to impersonate this site.
+add-exception-unverified-or-bad-signature-short = Unknown Identity
+add-exception-unverified-or-bad-signature-long = The certificate is not trusted because it hasn’t been verified as issued by a trusted authority using a secure signature.
+add-exception-valid-short = Valid Certificate
+add-exception-valid-long = This site provides valid, verified identification.  There is no need to add an exception.
+add-exception-checking-short = Checking Information
+add-exception-checking-long = Attempting to identify this site…
+add-exception-no-cert-short = No Information Available
+add-exception-no-cert-long = Unable to obtain identification status for this site.
+
--- a/security/manager/locales/jar.mn
+++ b/security/manager/locales/jar.mn
@@ -8,9 +8,8 @@
 
 @AB_CD@.jar:
 % locale pipnss @AB_CD@ %locale/@AB_CD@/pipnss/
 % locale pippki @AB_CD@ %locale/@AB_CD@/pippki/
   locale/@AB_CD@/pipnss/pipnss.properties     (%chrome/pipnss/pipnss.properties)
   locale/@AB_CD@/pipnss/nsserrors.properties  (%chrome/pipnss/nsserrors.properties)
   locale/@AB_CD@/pippki/pippki.dtd            (%chrome/pippki/pippki.dtd)
   locale/@AB_CD@/pippki/pippki.properties     (%chrome/pippki/pippki.properties)
-  locale/@AB_CD@/pippki/certManager.dtd       (%chrome/pippki/certManager.dtd)
--- a/security/manager/pki/resources/content/certManager.js
+++ b/security/manager/pki/resources/content/certManager.js
@@ -16,18 +16,16 @@ const nsCertTree = "@mozilla.org/securit
 
 const gCertFileTypes = "*.p7b; *.crt; *.cert; *.cer; *.pem; *.der";
 
 var { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm", {});
 
 var key;
 
 var certdialogs = Cc[nsCertificateDialogs].getService(nsICertificateDialogs);
-var strbundle = Cc[nsStringBundle].getService(nsIStringBundleService)
-                  .createBundle("chrome://pipnss/locale/pipnss.properties");
 
 /**
  * List of certs currently selected in the active tab.
  * @type nsIX509Cert[]
  */
 var selected_certs = [];
 var selected_tree_items = [];
 var selected_index = [];
@@ -206,43 +204,43 @@ function nothingOrContainerSelected(cert
         return true;
       }
     }
   }
 
   return false;
 }
 
-function promptError(aErrorCode) {
+async function promptError(aErrorCode) {
   if (aErrorCode != Ci.nsIX509CertDB.Success) {
-    let msgName = "PKCS12UnknownErr";
+    let msgName = "pkcs12-unknown-err";
     switch (aErrorCode) {
       case Ci.nsIX509CertDB.ERROR_PKCS12_NOSMARTCARD_EXPORT:
-        msgName = "PKCS12InfoNoSmartcardBackup";
+        msgName = "pkcs12-info-no-smartcard-backup";
         break;
       case Ci.nsIX509CertDB.ERROR_PKCS12_RESTORE_FAILED:
-        msgName = "PKCS12UnknownErrRestore";
+        msgName = "pkcs12-unknown-err-restore";
         break;
       case Ci.nsIX509CertDB.ERROR_PKCS12_BACKUP_FAILED:
-        msgName = "PKCS12UnknownErrBackup";
+        msgName = "pkcs12-unknown-err-backup";
         break;
       case Ci.nsIX509CertDB.ERROR_PKCS12_CERT_COLLISION:
       case Ci.nsIX509CertDB.ERROR_PKCS12_DUPLICATE_DATA:
-        msgName = "PKCS12DupData";
+        msgName = "pkcs12-dup-data";
         break;
       case Ci.nsIX509CertDB.ERROR_BAD_PASSWORD:
-        msgName = "PK11BadPassword";
+        msgName = "pk11-bad-password";
         break;
       case Ci.nsIX509CertDB.ERROR_DECODE_ERROR:
-        msgName = "PKCS12DecodeErr";
+        msgName = "pkcs12-decode-err";
         break;
       default:
         break;
     }
-    let message = strbundle.GetStringFromName(msgName);
+    let [message] = await document.l10n.formatValues([{id: msgName}]);
     let prompter = Services.ww.getNewPrompter(window);
     prompter.alert(null, message);
   }
 }
 
 /**
  * Enables or disables buttons corresponding to a cert tree depending on what
  * is selected in the cert tree.
@@ -291,30 +289,30 @@ function email_enableButtons() {
   let idList = [
     "email_viewButton",
     "email_exportButton",
     "email_deleteButton",
   ];
   enableButtonsForCertTree(emailTreeView, idList);
 }
 
-function backupCerts() {
+async function backupCerts() {
   getSelectedCerts();
   var numcerts = selected_certs.length;
   if (numcerts == 0) {
     return;
   }
 
-  var bundle = document.getElementById("pippki_bundle");
   var fp = Cc[nsFilePicker].createInstance(nsIFilePicker);
-  fp.init(window,
-          bundle.getString("chooseP12BackupFileDialog"),
-          nsIFilePicker.modeSave);
-  fp.appendFilter(bundle.getString("file_browse_PKCS12_spec"),
-                  "*.p12");
+  let [backupFileDialog, filePkcs12Spec] = await document.l10n.formatValues([
+    {id: "choose-p12-backup-file-dialog"},
+    {id: "file-browse-pkcs12-spec"},
+  ]);
+  fp.init(window, backupFileDialog, nsIFilePicker.modeSave);
+  fp.appendFilter(filePkcs12Spec, "*.p12");
   fp.appendFilters(nsIFilePicker.filterAll);
   fp.defaultExtension = "p12";
   fp.open(rv => {
     if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
       let password = {};
       if (certdialogs.setPKCS12FilePassword(window, password)) {
         let errorCode = certdb.exportPKCS12File(fp.file, selected_certs.length,
                                                 selected_certs, password.value);
@@ -334,26 +332,26 @@ function editCerts() {
   getSelectedCerts();
 
   for (let cert of selected_certs) {
     window.openDialog("chrome://pippki/content/editcacert.xul", "",
                       "chrome,centerscreen,modal", cert);
   }
 }
 
-function restoreCerts() {
-  var bundle = document.getElementById("pippki_bundle");
+async function restoreCerts() {
   var fp = Cc[nsFilePicker].createInstance(nsIFilePicker);
-  fp.init(window,
-          bundle.getString("chooseP12RestoreFileDialog2"),
-          nsIFilePicker.modeOpen);
-  fp.appendFilter(bundle.getString("file_browse_PKCS12_spec"),
-                  "*.p12; *.pfx");
-  fp.appendFilter(bundle.getString("file_browse_Certificate_spec"),
-                  gCertFileTypes);
+  let [restoreFileDialog, filePkcs12Spec, fileCertSpec] = await document.l10n.formatValues([
+    {id: "choose-p12-restore-file-dialog"},
+    {id: "file-browse-pkcs12-spec"},
+    {id: "file-browse-certificate-spec"},
+  ]);
+  fp.init(window, restoreFileDialog, nsIFilePicker.modeOpen);
+  fp.appendFilter(filePkcs12Spec, "*.p12; *.pfx");
+  fp.appendFilter(fileCertSpec, gCertFileTypes);
   fp.appendFilters(nsIFilePicker.filterAll);
   fp.open(rv => {
     if (rv != nsIFilePicker.returnOK) {
       return;
     }
 
     // If this is an X509 user certificate, import it as one.
 
@@ -465,42 +463,42 @@ function deleteCerts() {
 function viewCerts() {
   getSelectedCerts();
 
   for (let cert of selected_certs) {
     viewCertHelper(window, cert);
   }
 }
 
-function addCACerts() {
-  var bundle = document.getElementById("pippki_bundle");
+async function addCACerts() {
   var fp = Cc[nsFilePicker].createInstance(nsIFilePicker);
-  fp.init(window,
-          bundle.getString("importCACertsPrompt"),
-          nsIFilePicker.modeOpen);
-  fp.appendFilter(bundle.getString("file_browse_Certificate_spec"),
-                  gCertFileTypes);
+  let [importCa, fileCertSpec] = await document.l10n.formatValues([
+    {id: "import-ca-certs-prompt"},
+    {id: "file-browse-certificate-spec"},
+  ]);
+  fp.init(window, importCa, nsIFilePicker.modeOpen);
+  fp.appendFilter(fileCertSpec, gCertFileTypes);
   fp.appendFilters(nsIFilePicker.filterAll);
   fp.open(rv => {
     if (rv == nsIFilePicker.returnOK) {
       certdb.importCertsFromFile(fp.file, nsIX509Cert.CA_CERT);
       caTreeView.loadCerts(nsIX509Cert.CA_CERT);
       caTreeView.selection.clearSelection();
     }
   });
 }
 
-function addEmailCert() {
-  var bundle = document.getElementById("pippki_bundle");
+async function addEmailCert() {
   var fp = Cc[nsFilePicker].createInstance(nsIFilePicker);
-  fp.init(window,
-          bundle.getString("importEmailCertPrompt"),
-          nsIFilePicker.modeOpen);
-  fp.appendFilter(bundle.getString("file_browse_Certificate_spec"),
-                  gCertFileTypes);
+  let [importEmail, fileCertSpec] = await document.l10n.formatValues([
+    {id: "import-email-cert-prompt"},
+    {id: "file-browse-certificate-spec"},
+  ]);
+  fp.init(window, importEmail, nsIFilePicker.modeOpen);
+  fp.appendFilter(fileCertSpec, gCertFileTypes);
   fp.appendFilters(nsIFilePicker.filterAll);
   fp.open(rv => {
     if (rv == nsIFilePicker.returnOK) {
       certdb.importCertsFromFile(fp.file, nsIX509Cert.EMAIL_CERT);
       var certcache = certdb.getCerts();
       emailTreeView.loadCertsFromCache(certcache, nsIX509Cert.EMAIL_CERT);
       emailTreeView.selection.clearSelection();
       caTreeView.loadCertsFromCache(certcache, nsIX509Cert.CA_CERT);
--- a/security/manager/pki/resources/content/certManager.xul
+++ b/security/manager/pki/resources/content/certManager.xul
@@ -1,207 +1,191 @@
 <?xml version="1.0"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 
-<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/certManager.dtd">
+<!DOCTYPE dialog>
 
 <dialog id="certmanager"
 	windowtype="mozilla:certmanager"
 	xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="&certmgr.title;"
+        data-l10n-id="certmgr-title"
         onload="LoadCerts();"
         buttons="accept"
         style="width: 63em; height: 32em;"
         persist="screenX screenY width height">
 
-  <stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
+  <linkset>
+    <link rel="localization" href="security/certificates/certManager.ftl"/>
+  </linkset>
 
   <script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
   <script type="application/javascript" src="chrome://pippki/content/certManager.js"/>
 
   <vbox flex="1">
     <tabbox id="certmanagertabs" flex="1" style="margin:5px" persist="selectedIndex">
       <tabs id="certMgrTabbox">
-        <tab id="mine_tab" label="&certmgr.tab.mine;"/>
-        <tab id="others_tab" label="&certmgr.tab.others2;"/>
-        <tab id="websites_tab" label="&certmgr.tab.websites3;"/>
-        <tab id="ca_tab" label="&certmgr.tab.ca;" selected="true"/>
+        <tab id="mine_tab" data-l10n-id="certmgr-tab-mine"/>
+        <tab id="others_tab" data-l10n-id="certmgr-tab-people"/>
+        <tab id="websites_tab" data-l10n-id="certmgr-tab-servers"/>
+        <tab id="ca_tab" data-l10n-id="certmgr-tab-ca" selected="true"/>
       </tabs>
       <tabpanels flex="1">
         <vbox id="myCerts" flex="1">
-          <description>&certmgr.mine2;</description>
+          <description data-l10n-id="certmgr-mine"></description>
           <separator class="thin"/>
           <tree id="user-tree" flex="1" enableColumnDrag="true"
                     onselect="mine_enableButtons()">
             <treecols>
-              <treecol id="certcol" label="&certmgr.certname;" primary="true"
+              <treecol id="certcol" data-l10n-id="certmgr-cert-name" primary="true"
                            persist="hidden width ordinal" flex="1"/>
               <splitter class="tree-splitter"/>
-              <treecol id="tokencol" label="&certmgr.tokenname;"
+              <treecol id="tokencol" data-l10n-id="certmgr-token-name"
                            persist="hidden width ordinal" flex="1"/>
               <splitter class="tree-splitter"/>
-              <treecol id="serialnumcol" label="&certmgr.serial;"
+              <treecol id="serialnumcol" data-l10n-id="certmgr-serial"
                            persist="hidden width ordinal" flex="1"/>
               <splitter class="tree-splitter"/>
-              <treecol id="issuedcol" label="&certmgr.begins;"
+              <treecol id="issuedcol" data-l10n-id="certmgr-begins-label"
                            hidden="true" persist="hidden width ordinal" flex="1"/>
               <splitter class="tree-splitter"/>
-              <treecol id="expiredcol" label="&certmgr.expires;"
+              <treecol id="expiredcol" data-l10n-id="certmgr-expires-label"
                            persist="hidden width ordinal" flex="1"/>
             </treecols>
             <treechildren ondblclick="viewCerts();"/>
           </tree>
 
           <separator class="thin"/>
 
           <hbox>
              <button id="mine_viewButton" class="normal"
-                     label="&certmgr.view2.label;"
-                     accesskey="&certmgr.view2.accesskey;"
+                     data-l10n-id="certmgr-view"
                      disabled="true" oncommand="viewCerts();"/>
              <button id="mine_backupButton" class="normal"
-                     label="&certmgr.backup2.label;"
-                     accesskey="&certmgr.backup2.accesskey;"
+                     data-l10n-id="certmgr-backup"
                      disabled="true" oncommand="backupCerts();"/>
              <button id="mine_backupAllButton" class="normal"
-                     label="&certmgr.backupall2.label;"
-                     accesskey="&certmgr.backupall2.accesskey;"
+                     data-l10n-id="certmgr-backup-all"
                      oncommand="backupAllCerts();"/>
              <button id="mine_restoreButton" class="normal"
-                     label="&certmgr.restore2.label;"
-                     accesskey="&certmgr.restore2.accesskey;"
+                     data-l10n-id="certmgr-restore"
                      oncommand="restoreCerts();"/>
              <button id="mine_deleteButton" class="normal"
-                     label="&certmgr.delete2.label;"
-                     accesskey="&certmgr.delete2.accesskey;"
+                     data-l10n-id="certmgr-delete"
                      disabled="true" oncommand="deleteCerts();"/>
           </hbox>
         </vbox>
         <vbox id="othersCerts" flex="1">
-          <description>&certmgr.others2;</description>
+          <description data-l10n-id="certmgr-people"></description>
           <separator class="thin"/>
           <tree id="email-tree" flex="1"
                     onselect="email_enableButtons()">
             <treecols>
-              <treecol id="certcol" label="&certmgr.certname;" primary="true"
+              <treecol id="certcol" data-l10n-id="certmgr-cert-name" primary="true"
                            flex="1"/>
               <splitter class="tree-splitter"/>
-              <treecol id="emailcol" label="&certmgr.email;"
+              <treecol id="emailcol" data-l10n-id="certmgr-email"
                            flex="1"/>
               <splitter class="tree-splitter"/>
-              <treecol id="expiredcol" label="&certmgr.expires;"
+              <treecol id="expiredcol" data-l10n-id="certmgr-expires-label"
                        flex="1"/>
             </treecols>
             <treechildren flex="1" ondblclick="viewCerts();"/>
           </tree>
 
           <separator class="thin"/>
 
           <hbox>
             <button id="email_viewButton"
-                    label="&certmgr.view2.label;"
-                    accesskey="&certmgr.view2.accesskey;"
+                    data-l10n-id="certmgr-view"
                     disabled="true" oncommand="viewCerts();"/>
             <button id="email_addButton"
-                    label="&certmgr.restore2.label;"
-                    accesskey="&certmgr.restore2.accesskey;"
+                    data-l10n-id="certmgr-restore"
                     oncommand="addEmailCert();"/>
             <button id="email_exportButton"
-                    label="&certmgr.export.label;"
-                    accesskey="&certmgr.export.accesskey;"
+                    data-l10n-id="certmgr-export"
                     disabled="true" oncommand="exportCerts();"/>
             <button id="email_deleteButton"
-                    label="&certmgr.delete2.label;"
-                    accesskey="&certmgr.delete2.accesskey;"
+                    data-l10n-id="certmgr-delete"
                     disabled="true" oncommand="deleteCerts();"/>
           </hbox>
         </vbox>
         <vbox id="webCerts" flex="1">
-          <description>&certmgr.websites3;</description>
+          <description data-l10n-id="certmgr-servers"></description>
           <separator class="thin"/>
           <tree id="server-tree" flex="1" enableColumnDrag="true"
                     onselect="websites_enableButtons()">
             <treecols>
-              <treecol id="certcol" label="&certmgr.certname;" primary="true"
+              <treecol id="certcol" data-l10n-id="certmgr-cert-name" primary="true"
                            persist="hidden width ordinal" flex="1"/>
               <splitter class="tree-splitter"/>
-              <treecol id="sitecol" label="&certmgr.certserver;"
+              <treecol id="sitecol" data-l10n-id="certmgr-cert-server"
                        persist="hidden width ordinal" flex="1"/>
               <splitter class="tree-splitter"/>
-              <treecol id="lifetimecol" label="&certmgr.override_lifetime;"
+              <treecol id="lifetimecol" data-l10n-id="certmgr-override-lifetime"
                        persist="hidden width ordinal" flex="1"/>
               <splitter class="tree-splitter"/>
-              <treecol id="expiredcol" label="&certmgr.expires;"
+              <treecol id="expiredcol" data-l10n-id="certmgr-expires-label"
                        persist="hidden width ordinal" flex="1"/>
             </treecols>
             <treechildren ondblclick="viewCerts();"/>
           </tree>
 
           <separator class="thin"/>
 
           <hbox>
             <button id="websites_viewButton"
-                    label="&certmgr.view2.label;"
-                    accesskey="&certmgr.view2.accesskey;"
+                    data-l10n-id="certmgr-view"
                     disabled="true" oncommand="viewCerts();"/>
             <button id="websites_exportButton"
-                    label="&certmgr.export.label;"
-                    accesskey="&certmgr.export.accesskey;"
+                    data-l10n-id="certmgr-export"
                     disabled="true" oncommand="exportCerts();"/>
             <button id="websites_deleteButton"
-                    label="&certmgr.delete2.label;"
-                    accesskey="&certmgr.delete2.accesskey;"
+                    data-l10n-id="certmgr-delete"
                     disabled="true" oncommand="deleteCerts();"/>
             <button id="websites_exceptionButton"
-                    label="&certmgr.addException.label;"
-                    accesskey="&certmgr.addException.accesskey;"
+                    data-l10n-id="certmgr-add-exception"
                     oncommand="addException();"/>
           </hbox>
         </vbox>
         <vbox id="CACerts" flex="1">
-          <description>&certmgr.cas2;</description>
+          <description data-l10n-id="certmgr-ca"></description>
           <separator class="thin"/>
           <tree id="ca-tree" flex="1" enableColumnDrag="true"
                     onselect="ca_enableButtons()">
             <treecols>
-              <treecol id="certcol" label="&certmgr.certname;" primary="true"
+              <treecol id="certcol" data-l10n-id="certmgr-cert-name" primary="true"
                            persist="hidden width ordinal" flex="1"/>
               <splitter class="tree-splitter"/>
-              <treecol id="tokencol" label="&certmgr.tokenname;"
+              <treecol id="tokencol" data-l10n-id="certmgr-token-name"
                            persist="hidden width ordinal" flex="1"/>
             </treecols>
             <treechildren ondblclick="viewCerts();"/>
           </tree>
 
           <separator class="thin"/>
 
           <hbox>
             <button id="ca_viewButton"
-                    label="&certmgr.view2.label;"
-                    accesskey="&certmgr.view2.accesskey;"
+                    data-l10n-id="certmgr-view"
                     disabled="true" oncommand="viewCerts();"/>
             <button id="ca_editButton"
-                    label="&certmgr.edit3.label;"
-                    accesskey="&certmgr.edit3.accesskey;"
+                    data-l10n-id="certmgr-edit"
                     disabled="true" oncommand="editCerts();"/>
             <button id="ca_addButton"
-                    label="&certmgr.restore2.label;"
-                    accesskey="&certmgr.restore2.accesskey;"
+                    data-l10n-id="certmgr-restore"
                     oncommand="addCACerts();"/>
             <button id="ca_exportButton"
-                    label="&certmgr.export.label;"
-                    accesskey="&certmgr.export.accesskey;"
+                    data-l10n-id="certmgr-export"
                     disabled="true" oncommand="exportCerts();"/>
             <button id="ca_deleteButton"
-                    label="&certmgr.delete_builtin.label;"
-                    accesskey="&certmgr.delete_builtin.accesskey;"
+                    data-l10n-id="certmgr-delete-builtin"
                     disabled="true" oncommand="deleteCerts();"/>
           </hbox>
         </vbox>
       </tabpanels>
     </tabbox>
 
   </vbox>
 
--- a/security/manager/pki/resources/content/certViewer.js
+++ b/security/manager/pki/resources/content/certViewer.js
@@ -18,18 +18,16 @@ const nsIX509CertDB = Ci.nsIX509CertDB;
 const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
 const nsIPK11TokenDB = Ci.nsIPK11TokenDB;
 const nsIASN1Object = Ci.nsIASN1Object;
 const nsIASN1Sequence = Ci.nsIASN1Sequence;
 const nsIASN1PrintableItem = Ci.nsIASN1PrintableItem;
 const nsIASN1Tree = Ci.nsIASN1Tree;
 const nsASN1Tree = "@mozilla.org/security/nsASN1Tree;1";
 
-var bundle;
-
 /**
  * Fills out the "Certificate Hierarchy" tree of the cert viewer "Details" tab.
  *
  * @param {tree} node
  *        Parent tree node to append to.
  * @param {Array} chain
  *        An array of nsIX509Cert where cert n is issued by cert n + 1.
  */
@@ -49,35 +47,33 @@ function AddCertChain(node, chain) {
     let addTwistie = i != 0;
     child = addChildrenToTree(child, displayValue, currCert.dbKey, addTwistie);
   }
 }
 
 /**
  * Adds a "verified usage" of a cert to the "General" tab of the cert viewer.
  *
- * @param {String} usage
- *        Verified usage to add.
+ * @param {String} l10nId
+ *        l10nId of verified usage to add.
  */
-function AddUsage(usage) {
+function AddUsage(l10nId) {
   let verifyInfoBox = document.getElementById("verify_info_box");
   let text = document.createXULElement("textbox");
-  text.setAttribute("value", usage);
+  document.l10n.setAttributes(text, l10nId);
+  text.setAttribute("data-l10n-attrs", "value");
   text.setAttribute("style", "margin: 2px 5px");
   text.setAttribute("readonly", "true");
   text.setAttribute("class", "scrollfield");
   verifyInfoBox.appendChild(text);
 }
 
 function setWindowName() {
-  bundle = document.getElementById("pippki_bundle");
-
   let cert = window.arguments[0].QueryInterface(Ci.nsIX509Cert);
-  document.title = bundle.getFormattedString("certViewerTitle",
-                                             [cert.displayName]);
+  window.document.l10n.setAttributes(window.document.documentElement, "cert-viewer-title", {certName: cert.displayName});
 
   //
   //  Set the cert attributes for viewing
   //
 
   // Set initial dummy chain of just the cert itself. A more complete chain (if
   // one can be found), will be set when the promise chain beginning at
   // asyncDetermineUsages finishes.
@@ -85,21 +81,21 @@ function setWindowName() {
   DisplayGeneralDataFromCert(cert);
   BuildPrettyPrint(cert);
 
   asyncDetermineUsages(cert).then(displayUsages);
 }
 
 // Map of certificate usage name to localization identifier.
 const certificateUsageToStringBundleName = {
-  certificateUsageSSLClient: "VerifySSLClient",
-  certificateUsageSSLServer: "VerifySSLServer",
-  certificateUsageSSLCA: "VerifySSLCA",
-  certificateUsageEmailSigner: "VerifyEmailSigner",
-  certificateUsageEmailRecipient: "VerifyEmailRecip",
+  certificateUsageSSLClient: "verify-ssl-client",
+  certificateUsageSSLServer: "verify-ssl-server",
+  certificateUsageSSLCA: "verify-ssl-ca",
+  certificateUsageEmailSigner: "verify-email-signer",
+  certificateUsageEmailRecipient: "verify-email-recip",
 };
 
 const SEC_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE;
 const SEC_ERROR_EXPIRED_CERTIFICATE                     = SEC_ERROR_BASE + 11;
 const SEC_ERROR_REVOKED_CERTIFICATE                     = SEC_ERROR_BASE + 12;
 const SEC_ERROR_UNKNOWN_ISSUER                          = SEC_ERROR_BASE + 13;
 const SEC_ERROR_UNTRUSTED_ISSUER                        = SEC_ERROR_BASE + 20;
 const SEC_ERROR_UNTRUSTED_CERT                          = SEC_ERROR_BASE + 21;
@@ -120,60 +116,56 @@ const SEC_ERROR_CERT_SIGNATURE_ALGORITHM
  */
 function displayUsages(results) {
   document.getElementById("verify_pending").setAttribute("hidden", "true");
   let verified = document.getElementById("verified");
   let someSuccess = results.some(result =>
     result.errorCode == PRErrorCodeSuccess
   );
   if (someSuccess) {
-    let verifystr = bundle.getString("certVerified");
-    verified.textContent = verifystr;
-    let pipnssBundle = Services.strings.createBundle(
-      "chrome://pipnss/locale/pipnss.properties");
+    document.l10n.setAttributes(verified, "cert-verified");
     results.forEach(result => {
       if (result.errorCode != PRErrorCodeSuccess) {
         return;
       }
-      let bundleName = certificateUsageToStringBundleName[result.usageString];
-      let usage = pipnssBundle.GetStringFromName(bundleName);
-      AddUsage(usage);
+      let usageL10nId = certificateUsageToStringBundleName[result.usageString];
+      AddUsage(usageL10nId);
     });
     AddCertChain("treesetDump", getBestChain(results));
   } else {
     const errorRankings = [
       { error: SEC_ERROR_REVOKED_CERTIFICATE,
-        bundleString: "certNotVerified_CertRevoked" },
+        bundleString: "cert-not-verified-cert-revoked" },
       { error: SEC_ERROR_UNTRUSTED_CERT,
-        bundleString: "certNotVerified_CertNotTrusted" },
+        bundleString: "cert-not-verified-cert-not-trusted" },
       { error: SEC_ERROR_UNTRUSTED_ISSUER,
-        bundleString: "certNotVerified_IssuerNotTrusted" },
+        bundleString: "cert-not-verified-issuer-not-trusted" },
       { error: SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED,
-        bundleString: "certNotVerified_AlgorithmDisabled" },
+        bundleString: "cert-not-verified_algorithm-disabled" },
       { error: SEC_ERROR_EXPIRED_CERTIFICATE,
-        bundleString: "certNotVerified_CertExpired" },
+        bundleString: "cert-not-verified-cert-expired" },
       { error: SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE,
-        bundleString: "certNotVerified_CAInvalid" },
+        bundleString: "cert-not-verified-ca-invalid" },
       { error: SEC_ERROR_UNKNOWN_ISSUER,
-        bundleString: "certNotVerified_IssuerUnknown" },
+        bundleString: "cert-not-verified-issuer-unknown" },
     ];
-    let verifystr;
+    let errorPresentFlag = false;
     for (let errorRanking of errorRankings) {
       let errorPresent = results.some(result =>
         result.errorCode == errorRanking.error
       );
       if (errorPresent) {
-        verifystr = bundle.getString(errorRanking.bundleString);
+        document.l10n.setAttributes(verified, errorRanking.bundleString);
+        errorPresentFlag = true;
         break;
       }
     }
-    if (!verifystr) {
-      verifystr = bundle.getString("certNotVerified_Unknown");
+    if (!errorPresentFlag) {
+      document.l10n.setAttributes(verified, "cert-not-verified-unknown");
     }
-    verified.textContent = verifystr;
   }
   // Notify that we are done determining the certificate's valid usages (this
   // should be treated as an implementation detail that enables tests to run
   // efficiently - other code in the browser probably shouldn't rely on this).
   Services.obs.notifyObservers(window, "ViewCertDetails:CertUsagesDone");
 }
 
 function addChildrenToTree(parentTree, label, value, addTwistie) {
@@ -220,17 +212,18 @@ function BuildPrettyPrint(cert) {
                           createInstance(nsIASN1Tree);
   certDumpTree.loadASN1Structure(cert.ASN1Structure);
   document.getElementById("prettyDumpTree").view = certDumpTree;
 }
 
 function addAttributeFromCert(nodeName, value) {
   var node = document.getElementById(nodeName);
   if (!value) {
-    value = bundle.getString("notPresent");
+    document.l10n.setAttributes(node, "not-present");
+    return;
   }
   node.setAttribute("value", value);
 }
 
 /**
  * Displays information about a cert in the "General" tab of the cert viewer.
  *
  * @param {nsIX509Cert} cert
--- a/security/manager/pki/resources/content/certViewer.xul
+++ b/security/manager/pki/resources/content/certViewer.xul
@@ -1,160 +1,156 @@
 <?xml version="1.0"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 
-<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/certManager.dtd">
+<!DOCTYPE dialog>
 
 <dialog id="certDetails"
-  title="&certmgr.certdetail.title;"
+  data-l10n-id="certmgr-cert-detail"
+  data-l10n-attrs="buttonlabelaccept, buttonaccesskeyaccept"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   buttons="accept"
-  buttonlabelaccept="&certmgr.close.label;"
-  buttonaccesskeyaccept="&certmgr.close.accesskey;"
   onload="setWindowName();">
 
-<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
+
+<linkset>
+  <link rel="localization" href="security/certificates/certManager.ftl"/>
+</linkset>
 
 <script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
 <script type="application/javascript"
         src="chrome://pippki/content/certViewer.js"/>
 
   <tabbox flex="1">
     <tabs>
-      <tab id="general_tab" label="&certmgr.detail.general_tab.title;"
-           accesskey="&certmgr.detail.general_tab.accesskey;"/>
-      <tab id="prettyprint_tab" label="&certmgr.detail.prettyprint_tab.title;"
-           accesskey="&certmgr.detail.prettyprint_tab.accesskey;"/>
+      <tab id="general_tab" data-l10n-id="certmgr-detail-general-tab-title"/>
+      <tab id="prettyprint_tab" data-l10n-id="certmgr-detail-pretty-print-tab-title"/>
     </tabs>
     <tabpanels flex="1">
       <vbox class="box-padded" id="general_info">
         <vbox id="verify_info_box">
-          <label id="verify_pending" value="&certmgr.pending.label;"/>
+          <label id="verify_pending" data-l10n-id="certmgr-pending-label"/>
           <label class="header" id="verified"/>
         </vbox>
         <separator class="groove"/>
         <vbox flex="1">
           <grid>
             <columns>
               <column/>
               <column flex="1"/>
             </columns>
             <rows>
               <row>
-                <label class="header" value="&certmgr.subjectinfo.label;"/>
+                <label class="header" data-l10n-id="certmgr-subject-info-label"/>
                 <spacer/>
                 <spacer/>
               </row>
               <row>
-                <label value="&certmgr.certdetail.cn;"/>
+                <label data-l10n-id="certmgr-cert-detail-cn"/>
                 <textbox id="commonname" class="plain" readonly="true"/>
               </row>
               <row>
-                <label value="&certmgr.certdetail.o;"/>
+                <label data-l10n-id="certmgr-cert-detail-o"/>
                 <textbox id="organization" class="plain" readonly="true"/>
               </row>
               <row>
-                <label value="&certmgr.certdetail.ou;"/>
+                <label data-l10n-id="certmgr-cert-detail-ou"/>
                 <textbox id="orgunit" class="plain" readonly="true"/>
               </row>
               <row>
-                <label value="&certmgr.certdetail.serialnumber;"/>
+                <label data-l10n-id="certmgr-cert-detail-serialnumber"/>
                 <textbox id="serialnumber" class="plain" readonly="true"/>
               </row>
               <row>
                 <separator class="thin"/>
                 <spacer/>
               </row>
               <row>
-                <label class="header" value="&certmgr.issuerinfo.label;"/>
+                <label class="header" data-l10n-id="certmgr-issuer-info-label"/>
                 <spacer/>
               </row>
               <row>
-                <label value="&certmgr.certdetail.cn;"/>
+                <label data-l10n-id="certmgr-cert-detail-cn"/>
                 <textbox id="issuercommonname" class="plain" readonly="true"/>
               </row>
               <row>
-                <label value="&certmgr.certdetail.o;"/>
+                <label data-l10n-id="certmgr-cert-detail-o"/>
                 <textbox id="issuerorganization" class="plain" readonly="true"/>
               </row>
               <row>
-                <label value="&certmgr.certdetail.ou;"/>
+                <label data-l10n-id="certmgr-cert-detail-ou"/>
                 <textbox id="issuerorgunit" class="plain" readonly="true"/>
               </row>
               <row>
                 <separator class="thin"/>
                 <spacer/>
               </row>
               <row>
-                <label class ="header" value="&certmgr.periodofvalidity.label;"/>
+                <label class ="header" data-l10n-id="certmgr-period-of-validity-label"/>
                 <spacer/>
               </row>
               <row>
-                <label value="&certmgr.begins;"/>
+                <label data-l10n-id="certmgr-begins-value"/>
                 <textbox id="validitystart" class="plain" readonly="true"/>
               </row>
               <row>
-                <label value="&certmgr.expires;"/>
+                <label data-l10n-id="certmgr-expires-value"/>
                 <textbox id="validityend" class="plain" readonly="true"/>
               </row>
               <row>
                 <separator class="thin"/>
                 <spacer/>
               </row>
               <row>
-                <label class="header" value="&certmgr.fingerprints.label;"/>
+                <label class="header" data-l10n-id="certmgr-fingerprints-label"/>
                 <spacer/>
               </row>
               <row>
-                <label value="&certmgr.certdetail.sha256fingerprint;"/>
+                <label data-l10n-id="certmgr-cert-detail-sha256-fingerprint"/>
                 <hbox>
                   <textbox id="sha256fingerprint" class="plain" readonly="true" multiline="true"
                            style="height: 6ex; width: 48ch; font-family: monospace;"/>
                 </hbox>
               </row>
               <row>
-                <label value="&certmgr.certdetail.sha1fingerprint;"/>
+                <label data-l10n-id="certmgr-cert-detail-sha1-fingerprint"/>
                 <textbox id="sha1fingerprint" class="plain" readonly="true" style="min-width:34em;"/>
               </row>
             </rows>
           </grid>
         </vbox>
       </vbox>
       <vbox class="box-padded" id="certPrettyPrint" flex="1">
-        <label class="header" value="&certmgr.hierarchy.label;"
-               control="treesetDump" accesskey="&certmgr.hierarchy.accesskey2;"/>
+        <label class="header" data-l10n-id="certmgr-hierarchy" control="treesetDump"/>
         <tree id="treesetDump" onselect="updateCertDump();" flex="1"
               hidecolumnpicker="true" style="height: 8em;">
           <treecols>
             <treecol id="dumpCol" flex="1" primary="true" hideheader="true"/>
           </treecols>
         </tree>
 
-        <label class="header" value="&certmgr.details.label;"
-               control="prettyDumpTree" accesskey="&certmgr.details.accesskey;"/>
+        <label class="header" data-l10n-id="certmgr-details" control="prettyDumpTree"/>
         <tree id="prettyDumpTree" style="height: 15em" treelines="true" flex="1"
                   onselect="displaySelected();" hidecolumnpicker="true">
           <treecols>
             <treecol flex="1" id="certDataCol" primary="true" hideheader="true"/>
           </treecols>
           <treechildren/>
         </tree>
 
-        <label class="header" value="&certmgr.fields.label;"
-               control="certDumpVal" accesskey="&certmgr.fields.accesskey;"/>
+        <label class="header" data-l10n-id="certmgr-fields" control="certDumpVal"/>
         <textbox id="certDumpVal" multiline="true" flex="1"
                  readonly="true" style="height: 11em; font-family: -moz-fixed;"/>
 
         <separator class="thin"/>
         <hbox>
-          <button id="export_cert" class="normal" label="&certmgr.export.label;"
-                  accesskey="&certmgr.export.accesskey;"
+          <button id="export_cert" class="normal" data-l10n-id="certmgr-export"
                   oncommand="exportToFile(window, getCurrentCert());"/>
         </hbox>
       </vbox>
     </tabpanels>
   </tabbox>
 
 </dialog>
--- a/security/manager/pki/resources/content/deletecert.js
+++ b/security/manager/pki/resources/content/deletecert.js
@@ -19,94 +19,84 @@
  * @typedef DeleteCertReturnValues
  * @type Object
  * @property {Boolean} deleteConfirmed
  *           Set to true if the user confirmed deletion of the given certs,
  *           false otherwise.
  */
 
 /**
- * Returns the most appropriate string to represent the given nsICertTreeItem.
+ * Returns the element to represent the given nsICertTreeItem.
  * @param {nsICertTreeItem} certTreeItem
  *        The item to represent.
- * @returns {String}
- *          A representative string.
+ * @returns {Element}
+ *          A element of each cert tree item.
  */
-function certTreeItemToString(certTreeItem) {
+function getLabelForCertTreeItem(certTreeItem) {
+  let element = document.createXULElement("label");
   let cert = certTreeItem.cert;
   if (!cert) {
-    return certTreeItem.hostPort;
+    element.setAttribute("value", certTreeItem.hostPort);
+    return element;
   }
 
   const attributes = [
     cert.commonName,
     cert.organizationalUnit,
     cert.organization,
     cert.subjectName,
   ];
   for (let attribute of attributes) {
     if (attribute) {
-      return attribute;
+      element.setAttribute("value", attribute);
+      return element;
     }
   }
 
-  let bundle = document.getElementById("pippki_bundle");
-  return bundle.getFormattedString("certWithSerial", [cert.serialNumber]);
+  document.l10n.setAttributes(element, "cert-with-serial", { serialNumber: cert.serialNumber});
+  return element;
 }
 
 /**
  * onload() handler.
  */
 function onLoad() {
   let typeFlag = window.arguments[0];
-  let bundle = document.getElementById("pippki_bundle");
-  let title;
-  let confirm;
-  let impact;
-
+  let confirm = document.getElementById("confirm");
+  let impact = document.getElementById("impact");
+  let prefixForType;
   switch (typeFlag) {
     case "mine_tab":
-      title = bundle.getString("deleteUserCertTitle");
-      confirm = bundle.getString("deleteUserCertConfirm");
-      impact = bundle.getString("deleteUserCertImpact");
+      prefixForType = "delete-user-cert-";
       break;
     case "websites_tab":
-      title = bundle.getString("deleteSslCertTitle3");
-      confirm = bundle.getString("deleteSslCertConfirm3");
-      impact = bundle.getString("deleteSslCertImpact3");
+      prefixForType = "delete-ssl-cert-";
       break;
     case "ca_tab":
-      title = bundle.getString("deleteCaCertTitle2");
-      confirm = bundle.getString("deleteCaCertConfirm2");
-      impact = bundle.getString("deleteCaCertImpactX2");
+      prefixForType = "delete-ca-cert-";
       break;
     case "others_tab":
-      title = bundle.getString("deleteEmailCertTitle");
-      confirm = bundle.getString("deleteEmailCertConfirm");
-      impact = bundle.getString("deleteEmailCertImpactDesc");
+      prefixForType = "delete-email-cert-";
       break;
     default:
       return;
   }
 
-  document.title = title;
-
-  setText("confirm", confirm);
+  document.l10n.setAttributes(document.documentElement, prefixForType + "title");
+  document.l10n.setAttributes(confirm, prefixForType + "confirm");
+  document.l10n.setAttributes(impact, prefixForType + "impact");
 
   let box = document.getElementById("certlist");
   let certTreeItems = window.arguments[1];
   for (let certTreeItem of certTreeItems) {
     let listItem = document.createXULElement("richlistitem");
-    let label = document.createXULElement("label");
-    label.setAttribute("value", certTreeItemToString(certTreeItem));
+    let label = getLabelForCertTreeItem(certTreeItem);
     listItem.appendChild(label);
     box.appendChild(listItem);
   }
-
-  setText("impact", impact);
 }
 
 /**
  * ondialogaccept() handler.
  *
  * @returns {Boolean} true to make the dialog close, false otherwise.
  */
 function onDialogAccept() {
--- a/security/manager/pki/resources/content/deletecert.xul
+++ b/security/manager/pki/resources/content/deletecert.xul
@@ -1,26 +1,29 @@
 <?xml version="1.0"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 
-<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/certManager.dtd">
+<!DOCTYPE dialog>
 
 <dialog id="deleteCertificate"
-  title="&certmgr.deletecert.title;"
+  data-l10n-id="certmgr-delete-cert"
+  data-l10n-attrs="style"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   onload="onLoad();"
   buttons="accept,cancel"
   ondialogaccept="return onDialogAccept();"
   ondialogcancel="return onDialogCancel();">
 
-  <stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
+  <linkset>
+    <link rel="localization" href="security/certificates/certManager.ftl"/>
+  </linkset>
 
   <script type="application/javascript" src="pippki.js" />
   <script type="application/javascript" src="chrome://pippki/content/deletecert.js"/>
 
   <description id="confirm" style="width: 400px;"/>
   <richlistbox id="certlist" class="box-padded" flex="1"
                style="min-height: 8em; height: 8em; min-width: 35em;"/>
   <description id="impact" style="width: 400px;"/>
--- a/security/manager/pki/resources/content/editcacert.js
+++ b/security/manager/pki/resources/content/editcacert.js
@@ -13,19 +13,18 @@ var gCertDB = Cc["@mozilla.org/security/
 var gCert;
 
 /**
  * onload() handler.
  */
 function onLoad() {
   gCert = window.arguments[0];
 
-  let bundle = document.getElementById("pippki_bundle");
-  setText("certmsg",
-          bundle.getFormattedString("editTrustCA", [gCert.commonName]));
+  let certMsg = document.getElementById("certmsg");
+  document.l10n.setAttributes(certMsg, "edit-trust-ca", { certName: gCert.commonName});
 
   let sslCheckbox = document.getElementById("trustSSL");
   sslCheckbox.checked = gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
                                               Ci.nsIX509CertDB.TRUSTED_SSL);
 
   let emailCheckbox = document.getElementById("trustEmail");
   emailCheckbox.checked = gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
                                                 Ci.nsIX509CertDB.TRUSTED_EMAIL);
--- a/security/manager/pki/resources/content/editcacert.xul
+++ b/security/manager/pki/resources/content/editcacert.xul
@@ -1,34 +1,36 @@
 <?xml version="1.0"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 
-<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/certManager.dtd">
+<!DOCTYPE dialog>
 
 <dialog id="editCaCert"
-        title="&certmgr.editcacert.title;"
+        data-l10n-id="certmgr-edit-ca-cert"
+        data-l10n-attrs="style"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         buttons="accept,cancel"
         ondialogaccept="return onDialogAccept();"
-        onload="onLoad();"
->
+        onload="onLoad();">
 
-  <stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
+  <linkset>
+    <link rel="localization" href="security/certificates/certManager.ftl"/>
+  </linkset>
 
   <script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
   <script type="application/javascript"
           src="chrome://pippki/content/editcacert.js"/>
 
   <description id="certmsg"/>
   <separator/>
-  <description>&certmgr.editcert.edittrust;</description>
+  <description data-l10n-id="certmgr-edit-cert-edit-trust"></description>
   <vbox align="start">
-    <checkbox label="&certmgr.editcert.trustssl;"
+    <checkbox data-l10n-id="certmgr-edit-cert-trust-ssl"
               id="trustSSL"/>
-    <checkbox label="&certmgr.editcert.trustemail;"
+    <checkbox data-l10n-id="certmgr-edit-cert-trust-email"
               id="trustEmail"/>
   </vbox>
 
 </dialog>
--- a/security/manager/pki/resources/content/exceptionDialog.js
+++ b/security/manager/pki/resources/content/exceptionDialog.js
@@ -1,39 +1,32 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 /* import-globals-from pippki.js */
 "use strict";
 
 var gDialog;
-var gBundleBrand;
-var gPKIBundle;
 var gSecInfo;
 var gCert;
 var gChecking;
 var gBroken;
 var gNeedReset;
 var gSecHistogram;
 var gNsISecTel;
 
 ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 function initExceptionDialog() {
   gNeedReset = false;
   gDialog = document.documentElement;
-  gBundleBrand = document.getElementById("brand_bundle");
-  gPKIBundle = document.getElementById("pippki_bundle");
   gSecHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
   gNsISecTel = Ci.nsISecurityUITelemetry;
-
-  var brandName = gBundleBrand.getString("brandShortName");
-  setText("warningText",
-          gPKIBundle.getFormattedString("addExceptionBrandedWarning2",
-                                        [brandName]));
+  let warningText = document.getElementById("warningText");
+  document.l10n.setAttributes(warningText, "add-exception-branded-warning");
   gDialog.getButton("extra1").disabled = true;
 
   var args = window.arguments;
   if (args && args[0]) {
     if (args[0].location) {
       // We were pre-seeded with a location.
       document.getElementById("locationTextBox").value = args[0].location;
       document.getElementById("checkCertButton").disabled = false;
@@ -172,22 +165,22 @@ function updateCertStatus() {
   var shortDesc, longDesc;
   var shortDesc2, longDesc2;
   var shortDesc3, longDesc3;
   var use2 = false;
   var use3 = false;
   let bucketId = gNsISecTel.WARNING_BAD_CERT_TOP_ADD_EXCEPTION_BASE;
   if (gCert) {
     if (gBroken) {
-      var mms = "addExceptionDomainMismatchShort";
-      var mml = "addExceptionDomainMismatchLong2";
-      var exs = "addExceptionExpiredShort";
-      var exl = "addExceptionExpiredLong2";
-      var uts = "addExceptionUnverifiedOrBadSignatureShort";
-      var utl = "addExceptionUnverifiedOrBadSignatureLong2";
+      var mms = "add-exception-domain-mismatch-short";
+      var mml = "add-exception-domain-mismatch-long";
+      var exs = "add-exception-expired-short";
+      var exl = "add-exception-expired-long";
+      var uts = "add-exception-unverified-or-bad-signature-short";
+      var utl = "add-exception-unverified-or-bad-signature-long";
       var use1 = false;
       if (gSecInfo.isDomainMismatch) {
         bucketId += gNsISecTel.WARNING_BAD_CERT_TOP_ADD_EXCEPTION_FLAG_DOMAIN;
         use1 = true;
         shortDesc = mms;
         longDesc  = mml;
       }
       if (gSecInfo.isNotValidAtThisTime) {
@@ -227,62 +220,67 @@ function updateCertStatus() {
       // If the Private Browsing service is available and the mode is active,
       // don't store permanent exceptions, since they would persist after
       // private browsing mode was disabled.
       var inPrivateBrowsing = inPrivateBrowsingMode();
       var pe = document.getElementById("permanent");
       pe.disabled = inPrivateBrowsing;
       pe.checked = !inPrivateBrowsing;
 
-      setText("headerDescription",
-              gPKIBundle.getString("addExceptionInvalidHeader"));
+      let headerDescription = document.getElementById("headerDescription");
+      document.l10n.setAttributes(headerDescription, "add-exception-invalid-header");
     } else {
-      shortDesc = "addExceptionValidShort";
-      longDesc  = "addExceptionValidLong";
+      shortDesc = "add-exception-valid-short";
+      longDesc  = "add-exception-valid-long";
       gDialog.getButton("extra1").disabled = true;
       document.getElementById("permanent").disabled = true;
     }
 
     // We're done checking the certificate, so allow the user to check it again.
     document.getElementById("checkCertButton").disabled = false;
     document.getElementById("viewCertButton").disabled = false;
 
     // Notify observers about the availability of the certificate
     Services.obs.notifyObservers(null, "cert-exception-ui-ready");
   } else if (gChecking) {
-    shortDesc = "addExceptionCheckingShort";
-    longDesc  = "addExceptionCheckingLong2";
+    shortDesc = "add-exception-checking-short";
+    longDesc  = "add-exception-checking-long";
     // We're checking the certificate, so we disable the Get Certificate
     // button to make sure that the user can't interrupt the process and
     // trigger another certificate fetch.
     document.getElementById("checkCertButton").disabled = true;
     document.getElementById("viewCertButton").disabled = true;
     gDialog.getButton("extra1").disabled = true;
     document.getElementById("permanent").disabled = true;
   } else {
-    shortDesc = "addExceptionNoCertShort";
-    longDesc  = "addExceptionNoCertLong2";
+    shortDesc = "add-exception-no-cert-short";
+    longDesc  = "add-exception-no-cert-long";
     // We're done checking the certificate, so allow the user to check it again.
     document.getElementById("checkCertButton").disabled = false;
     document.getElementById("viewCertButton").disabled = true;
     gDialog.getButton("extra1").disabled = true;
     document.getElementById("permanent").disabled = true;
   }
-
-  setText("statusDescription", gPKIBundle.getString(shortDesc));
-  setText("statusLongDescription", gPKIBundle.getString(longDesc));
+  let statusDescription = document.getElementById("statusDescription");
+  let statusLongDescription = document.getElementById("statusLongDescription");
+  document.l10n.setAttributes(statusDescription, shortDesc);
+  document.l10n.setAttributes(statusLongDescription, longDesc);
 
   if (use2) {
-    setText("status2Description", gPKIBundle.getString(shortDesc2));
-    setText("status2LongDescription", gPKIBundle.getString(longDesc2));
+    let status2Description = document.getElementById("status2Description");
+    let status2LongDescription = document.getElementById("status2LongDescription");
+    document.l10n.setAttributes(status2Description, shortDesc2);
+    document.l10n.setAttributes(status2LongDescription, longDesc2);
   }
 
   if (use3) {
-    setText("status3Description", gPKIBundle.getString(shortDesc3));
-    setText("status3LongDescription", gPKIBundle.getString(longDesc3));
+    let status3Description = document.getElementById("status3Description");
+    let status3LongDescription = document.getElementById("status3LongDescription");
+    document.l10n.setAttributes(status3Description, shortDesc3);
+    document.l10n.setAttributes(status3LongDescription, longDesc3);
   }
 
   window.sizeToContent();
   gNeedReset = true;
 }
 
 /**
  * Handle user request to display certificate details
--- a/security/manager/pki/resources/content/exceptionDialog.xul
+++ b/security/manager/pki/resources/content/exceptionDialog.xul
@@ -1,33 +1,32 @@
 <?xml version="1.0"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 
-<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/certManager.dtd">
+<!DOCTYPE dialog>
 
 <dialog id="exceptiondialog"
         windowtype="mozilla:exceptiondialog"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="&exceptionMgr.title;"
+        data-l10n-id="exception-mgr"
+        buttonidextra1="exception-mgr-extra-button"
         buttons="cancel,extra1,extra2"
-        buttonlabelextra1="&exceptionMgr.exceptionButton.label;"
-        buttonaccesskeyextra1="&exceptionMgr.exceptionButton.accesskey;"
         onload="initExceptionDialog();"
         ondialogextra1="addException();"
         ondialogextra2="checkCert();"
         defaultButton="extra2">
 
-  <stringbundleset id="stringbundleset">
-    <stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
-    <stringbundle id="brand_bundle" src="chrome://branding/locale/brand.properties"/>
-  </stringbundleset>
+  <linkset>
+    <link rel="localization" href="security/certificates/certManager.ftl"/>
+    <link rel="localization" href="branding/brand.ftl"/>
+  </linkset>
 
   <script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
   <script type="application/javascript" src="chrome://pippki/content/exceptionDialog.js"/>
 
   <hbox>
     <vbox>
 #ifdef MOZ_WIDGET_GTK
       <image src="moz-icon://stock/gtk-dialog-warning?size=dialog"/>
@@ -38,42 +37,39 @@
     </vbox>
     <vbox flex="1">
       <!-- Note that because of the styling, there must be no whitespace within
       the description tags -->
       <description id="warningText"
                    style="white-space: pre-wrap"/>
       <description id="warningSupplemental"
                    style="font-weight: bold; white-space: pre-wrap;"
-                   >&exceptionMgr.supplementalWarning;</description>
+                   data-l10n-id="exception-mgr-supplemental-warning"></description>
     </vbox>
   </hbox>
 
   <hbox align="center">
-    <label control="locationTextBox" value="&exceptionMgr.certlocation.url;"/>
+    <label control="locationTextBox" data-l10n-id="exception-mgr-cert-location-url"/>
     <textbox id="locationTextBox" flex="1" oninput="handleTextChange();"
              value="https://" class="uri-element"/>
     <button id="checkCertButton" disabled="true" dlgtype="extra2"
-            accesskey="&exceptionMgr.certlocation.accesskey;"
-            label="&exceptionMgr.certlocation.download;"/>
+            data-l10n-id="exception-mgr-cert-location-download"/>
   </hbox>
 
   <hbox align="center">
     <description id="headerDescription" style="white-space: pre-wrap;"
                  flex="1"/>
-    <button id="viewCertButton" label="&exceptionMgr.certstatus.viewCert;"
-            accesskey="&exceptionMgr.certstatus.accesskey;"
+    <button id="viewCertButton" data-l10n-id="exception-mgr-cert-status-view-cert"
             disabled="true" oncommand="viewCertButtonClick();"/>
   </hbox>
   <description id="statusDescription"
                style="font-weight: bold; padding-bottom: 1em;"/>
   <description id="statusLongDescription" style="white-space: pre-wrap;"/>
   <description id="status2Description"
                style="font-weight: bold; padding-bottom: 1em;"/>
   <description id="status2LongDescription" style="white-space: pre-wrap;"/>
   <description id="status3Description"
                style="font-weight: bold; padding-bottom: 1em;"/>
   <description id="status3LongDescription" style="white-space: pre-wrap;"/>
   <spacer flex="1"/>
   <checkbox id="permanent" disabled="true"
-            label="&exceptionMgr.permanent.label;"
-            accesskey="&exceptionMgr.permanent.accesskey;"/>
+            data-l10n-id="exception-mgr-permanent"/>
 </dialog>
--- a/security/manager/ssl/tests/mochitest/browser/browser_certViewer.js
+++ b/security/manager/ssl/tests/mochitest/browser/browser_certViewer.js
@@ -8,104 +8,95 @@
 // certificates are valid for or what errors prevented the certificates from
 // being verified.
 
 var { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm", {});
 
 add_task(async function testCAandTitle() {
   let cert = await readCertificate("ca.pem", "CTu,CTu,CTu");
   let win = await displayCertificate(cert);
-  checkUsages(win, ["SSL Certificate Authority"]);
+  checkUsages(win, [{id: "verify-ssl-ca"}]);
   checkDetailsPane(win, ["ca"]);
 
   // There's no real need to test the title for every cert, so we just test it
   // once here.
-  Assert.equal(win.document.title, "Certificate Viewer: \u201Cca\u201D",
+  Assert.deepEqual(win.document.l10n.getAttributes(win.document.documentElement),
+                {args: { certName: "ca"}, id: "cert-viewer-title"},
                "Actual and expected title should match");
   await BrowserTestUtils.closeWindow(win);
 });
 
 add_task(async function testSSLEndEntity() {
   let cert = await readCertificate("ssl-ee.pem", ",,");
   let win = await displayCertificate(cert);
-  checkUsages(win, ["SSL Server Certificate", "SSL Client Certificate"]);
+  checkUsages(win, [{id: "verify-ssl-server"}, {id: "verify-ssl-client"}]);
   checkDetailsPane(win, ["ca", "ssl-ee"]);
   await BrowserTestUtils.closeWindow(win);
 });
 
 add_task(async function testEmailEndEntity() {
   let cert = await readCertificate("email-ee.pem", ",,");
   let win = await displayCertificate(cert);
-  checkUsages(win, ["Email Recipient Certificate", "Email Signer Certificate"]);
+  checkUsages(win, [{id: "verify-email-recip"}, {id: "verify-email-signer"}]);
   checkDetailsPane(win, ["ca", "email-ee"]);
   await BrowserTestUtils.closeWindow(win);
 });
 
 add_task(async function testCodeSignEndEntity() {
   let cert = await readCertificate("code-ee.pem", ",,");
   let win = await displayCertificate(cert);
-  checkError(win, "Could not verify this certificate for unknown reasons.");
+  checkError(win, {id: "cert-not-verified-unknown"});
   checkDetailsPane(win, ["code-ee"]);
   await BrowserTestUtils.closeWindow(win);
 });
 
 add_task(async function testExpired() {
   let cert = await readCertificate("expired-ca.pem", ",,");
   let win = await displayCertificate(cert);
-  checkError(win, "Could not verify this certificate because it has expired.");
+  checkError(win, {id: "cert-not-verified-cert-expired"});
   checkDetailsPane(win, ["expired-ca"]);
   await BrowserTestUtils.closeWindow(win);
 
   // These tasks may run in any order, so we run this additional testcase in the
   // same task.
   let eeCert = await readCertificate("ee-from-expired-ca.pem", ",,");
   let eeWin = await displayCertificate(eeCert);
-  checkError(eeWin,
-             "Could not verify this certificate because the CA certificate " +
-             "is invalid.");
+  checkError(eeWin, {id: "cert-not-verified-ca-invalid"});
   checkDetailsPane(eeWin, ["ee-from-expired-ca"]);
   await BrowserTestUtils.closeWindow(eeWin);
 });
 
 add_task(async function testUnknownIssuer() {
   let cert = await readCertificate("unknown-issuer.pem", ",,");
   let win = await displayCertificate(cert);
-  checkError(win,
-             "Could not verify this certificate because the issuer is " +
-             "unknown.");
+  checkError(win, {id: "cert-not-verified-issuer-unknown"});
   checkDetailsPane(win, ["unknown-issuer"]);
   await BrowserTestUtils.closeWindow(win);
 });
 
 add_task(async function testInsecureAlgo() {
   let cert = await readCertificate("md5-ee.pem", ",,");
   let win = await displayCertificate(cert);
-  checkError(win,
-             "Could not verify this certificate because it was signed using " +
-             "a signature algorithm that was disabled because that algorithm " +
-             "is not secure.");
+  checkError(win, {id: "cert-not-verified_algorithm-disabled"});
   checkDetailsPane(win, ["md5-ee"]);
   await BrowserTestUtils.closeWindow(win);
 });
 
 add_task(async function testUntrusted() {
   let cert = await readCertificate("untrusted-ca.pem", "p,p,p");
   let win = await displayCertificate(cert);
-  checkError(win,
-             "Could not verify this certificate because it is not trusted.");
+  checkError(win, {id: "cert-not-verified-cert-not-trusted"});
   checkDetailsPane(win, ["untrusted-ca"]);
   await BrowserTestUtils.closeWindow(win);
 
   // These tasks may run in any order, so we run this additional testcase in the
   // same task.
   let eeCert = await readCertificate("ee-from-untrusted-ca.pem", ",,");
   let eeWin = await displayCertificate(eeCert);
-  checkError(eeWin,
-             "Could not verify this certificate because the issuer is not " +
-             "trusted.");
+  checkError(eeWin, {id: "cert-not-verified-issuer-not-trusted"});
   checkDetailsPane(eeWin, ["ee-from-untrusted-ca"]);
   await BrowserTestUtils.closeWindow(eeWin);
 });
 
 add_task(async function testRevoked() {
   // Note that there's currently no way to un-do this. This should only be a
   // problem if another test re-uses a certificate with this same key (perhaps
   // likely) and subject (less likely).
@@ -114,30 +105,29 @@ add_task(async function testRevoked() {
   certBlocklist.revokeCertBySubjectAndPubKey(
     "MBIxEDAOBgNVBAMMB3Jldm9rZWQ=", // CN=revoked
     "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8="); // hash of the shared key
   let cert = await readCertificate("revoked.pem", ",,");
   let win = await displayCertificate(cert);
   // As of bug 1312827, OneCRL only applies to TLS web server certificates, so
   // this certificate will actually verify successfully for every end-entity
   // usage except TLS web server.
-  checkUsages(win, ["Email Recipient Certificate", "Email Signer Certificate",
-                    "SSL Client Certificate"]);
+  checkUsages(win, [{id: "verify-email-recip"}, {id: "verify-email-signer"}, {id: "verify-ssl-client"}]);
   checkDetailsPane(win, ["ca", "revoked"]);
   await BrowserTestUtils.closeWindow(win);
 });
 
 add_task(async function testInvalid() {
   // This certificate has a keyUsage extension asserting cRLSign and
   // keyCertSign, but it doesn't have a basicConstraints extension. This
   // shouldn't be valid for any usage. Sadly, we give a pretty lame error
   // message in this case.
   let cert = await readCertificate("invalid.pem", ",,");
   let win = await displayCertificate(cert);
-  checkError(win, "Could not verify this certificate for unknown reasons.");
+  checkError(win, {id: "cert-not-verified-unknown"});
   checkDetailsPane(win, ["invalid"]);
   await BrowserTestUtils.closeWindow(win);
 });
 
 add_task(async function testLongOID() {
   // This certificate has a certificatePolicies extension with a policy with a
   // very long OID. This tests that we don't crash when looking at it.
   let cert = await readCertificate("longOID.pem", ",,");
@@ -166,86 +156,87 @@ function displayCertificate(certificate)
 }
 
 /**
  * Given a certificate viewer window, finds the usages the certificate is valid
  * for.
  *
  * @param {window} win
  *        The certificate viewer window.
- * @return {String[]}
- *         An array of strings describing the usages the certificate is valid
- *         for.
+ * @return {Object[]}
+ *         An array of objects including the L10n Ids of strings describing
+ *         the usages the certificate is valid for.
  */
 function getUsages(win) {
   let determinedUsages = [];
   let verifyInfoBox = win.document.getElementById("verify_info_box");
   Array.from(verifyInfoBox.children).forEach(child => {
     if (child.getAttribute("hidden") != "true" &&
         child.getAttribute("id") != "verified") {
-      determinedUsages.push(child.getAttribute("value"));
+      determinedUsages.push(win.document.l10n.getAttributes(child));
     }
   });
-  return determinedUsages.sort();
+  return determinedUsages.sort(compareL10Ids);
 }
 
 /**
  * Given a certificate viewer window, returns the error string describing a
  * failure encountered when determining the certificate's usages. It will be
  * "This certificate has been verified for the following uses:" when the
  * certificate has successfully verified for at least one usage.
  *
  * @param {window} win
  *        The certificate viewer window.
- * @return {String}
- *         A string describing the error encountered, or the success message if
- *         the certificate is valid for at least one usage.
+ * @return {Object}
+ *         A object with L10n id of the string describing the error encountered,
+ *        or the success message if the certificate is valid for at least one usage.
  */
 function getError(win) {
-  return win.document.getElementById("verified").textContent;
+  let verified = win.document.getElementById("verified");
+  return win.document.l10n.getAttributes(verified);
 }
 
 /**
- * Given a certificate viewer window and an array of expected usage
+ * Given a certificate viewer window and an array of l10n ids of expected usage
  * descriptions, verifies that the window is actually showing that the
  * certificate has validated for those usages.
  *
  * @param {window} win
  *        The certificate viewer window.
- * @param {String[]} usages
- *        An array of expected usage descriptions.
+ * @param {Object[]} usagesL10nIds
+ *        An array of object with l10n ids of expected usage descriptions.
  */
-function checkUsages(win, usages) {
-  Assert.equal(getError(win),
-               "This certificate has been verified for the following uses:",
+function checkUsages(win, usagesL10nIds) {
+  Assert.deepEqual(getError(win),
+               { id: "cert-verified" },
                "should have successful verification message");
   let determinedUsages = getUsages(win);
-  usages.sort();
-  Assert.equal(determinedUsages.length, usages.length,
+  usagesL10nIds.sort(compareL10Ids);
+  Assert.deepEqual(determinedUsages.length, usagesL10nIds.length,
                "number of usages as determined by cert viewer should be equal");
-  while (usages.length > 0) {
-    Assert.equal(determinedUsages.pop(), usages.pop(),
+  while (usagesL10nIds.length > 0) {
+    Assert.deepEqual(determinedUsages.pop(), usagesL10nIds.pop(),
                  "usages as determined by cert viewer should be equal");
   }
 }
 
 /**
- * Given a certificate viewer window and an expected error, verifies that the
+ * Given a certificate viewer window and l10n id of an expected error, verifies that the
  * window is actually showing that error.
  *
  * @param {window} win
  *        The certificate viewer window.
- * @param {String} error
- *        The expected error message.
+ * @param {Object} errorL10nId
+ *        The object with l10n id of expected error message.
  */
-function checkError(win, error) {
+function checkError(win, errorL10nId) {
   let determinedUsages = getUsages(win);
   Assert.equal(determinedUsages.length, 0,
                "should not have any successful usages in error case");
-  Assert.equal(getError(win), error,
+  Assert.deepEqual(getError(win), errorL10nId,
                "determined error should be the same as expected error");
 }
 
 /**
  * Given a certificate viewer window and an expected list of certificate names,
  * verifies that the certificate details pane of the viewer shows the expected
  * certificates in the expected order.
  *
@@ -259,8 +250,27 @@ function checkDetailsPane(win, names) {
   let nodes = tree.querySelectorAll("treecell");
   Assert.equal(nodes.length, names.length,
                "details pane: should have the expected number of cert names");
   for (let i = 0; i < names.length; i++) {
     Assert.equal(nodes[i].getAttribute("label"), names[i],
                  "details pain: should have expected cert name");
   }
 }
+
+/**
+ * Given two objects with l10n id, compare them by l10n id for sorting.
+ *
+ * @param {Objects} ida,idb
+ *        The objects with l10n id.
+ * @param {integer}
+ *        An integer representing true of false.
+ */
+
+function compareL10Ids(ida, idb) {
+  if (ida.id < idb.id) {
+    return -1;
+  } else if (ida.id > idb.id) {
+    return 1;
+  }
+  return 0;
+}
+
--- a/security/manager/ssl/tests/mochitest/browser/browser_deleteCert_ui.js
+++ b/security/manager/ssl/tests/mochitest/browser/browser_deleteCert_ui.js
@@ -21,35 +21,43 @@ const FAKE_HOST_PORT = "Fake host and po
  * @typedef {TestCase}
  * @type Object
  * @property {String} certFilename
  *           Filename of the cert, or null if we don't want to import a cert for
  *           this test case (i.e. we expect the hostPort attribute of
  *           nsICertTreeItem to be used).
  * @property {String} expectedDisplayString
  *           The string we expect the UI to display to represent the given cert.
+ * @property {String} expectedSerialNumber
+ *           The serial number we expect the UI to display if it exists.
  */
 
 /**
  * A list of test cases representing certs that get "deleted".
  * @type TestCase[]
  */
 const TEST_CASES = [
   { certFilename: null,
-    expectedDisplayString: FAKE_HOST_PORT },
+    expectedDisplayString: FAKE_HOST_PORT,
+    expectedSerialNumber: null},
   { certFilename: "has-cn.pem",
-    expectedDisplayString: "Foo" },
+    expectedDisplayString: "Foo",
+    expectedSerialNumber: null},
   { certFilename: "has-ou.pem",
-    expectedDisplayString: "Bar" },
+    expectedDisplayString: "Bar",
+    expectedSerialNumber: null},
   { certFilename: "has-o.pem",
-    expectedDisplayString: "Baz" },
+    expectedDisplayString: "Baz",
+    expectedSerialNumber: null},
   { certFilename: "has-non-empty-subject.pem",
-    expectedDisplayString: "C=US" },
+    expectedDisplayString: "C=US",
+    expectedSerialNumber: null},
   { certFilename: "has-empty-subject.pem",
-    expectedDisplayString: "Certificate with serial number: 0A" },
+    expectedDisplayString: "Certificate with serial number: 0A",
+    expectedSerialNumber: "0A"},
 ];
 
 /**
  * Opens the cert delete confirmation dialog.
  *
  * @param {String} tabID
  *        The ID of the cert category tab the certs to delete belong to.
  * @returns {Promise}
@@ -86,98 +94,94 @@ add_task(async function setup() {
   }
 });
 
 /**
  * Test helper for the below test cases.
  *
  * @param {String} tabID
  *        ID of the cert category tab the certs to delete belong to.
- * @param {String} expectedTitle
- *        Title the dialog is expected to have.
- * @param {String} expectedConfirmMsg
- *        Confirmation message the dialog is expected to show.
- * @param {String} expectedImpact
- *        Impact the dialog is expected to show.
+ * @param {String} expectedTitleL10nId
+ *        The L10nId of title the dialog is expected to have.
+ * @param {String} expectedConfirmL10nId
+ *        The l10n id of confirmation message the dialog expected to show.
+ * @param {String} expectedImpactL10nId
+ *        The l10n id of impact the dialog expected to show.
  */
-async function testHelper(tabID, expectedTitle, expectedConfirmMsg, expectedImpact) {
+async function testHelper(tabID, expectedTitleL10nId, expectedConfirmL10nId, expectedImpactL10nId) {
   let [win] = await openDeleteCertConfirmDialog(tabID);
   let certList = win.document.getElementById("certlist");
 
-  Assert.equal(win.document.title, expectedTitle,
+  Assert.deepEqual(win.document.l10n.getAttributes(win.document.documentElement), expectedTitleL10nId,
                `Actual and expected titles should match for ${tabID}`);
-  Assert.equal(win.document.getElementById("confirm").textContent,
-               expectedConfirmMsg,
+  let confirm = win.document.getElementById("confirm");
+  Assert.deepEqual(win.document.l10n.getAttributes(confirm),
+               expectedConfirmL10nId,
                `Actual and expected confirm message should match for ${tabID}`);
-  Assert.equal(win.document.getElementById("impact").textContent,
-               expectedImpact,
+  let impact = win.document.getElementById("impact");
+  Assert.deepEqual(win.document.l10n.getAttributes(impact),
+               expectedImpactL10nId,
                `Actual and expected impact should match for ${tabID}`);
 
   Assert.equal(certList.itemCount, TEST_CASES.length,
                `No. of certs displayed should match for ${tabID}`);
   for (let i = 0; i < certList.itemCount; i++) {
-    Assert.equal(certList.getItemAtIndex(i).label,
+    let item = certList.getItemAtIndex(i);
+    if (TEST_CASES[i].expectedSerialNumber == null) {
+      Assert.equal(item.label,
                  TEST_CASES[i].expectedDisplayString,
                  "Actual and expected display string should match for " +
                  `index ${i} for ${tabID}`);
+    } else {
+    Assert.deepEqual(win.document.l10n.getAttributes(item.children[0]),
+                 {id: "cert-with-serial", args: { serialNumber: TEST_CASES[i].expectedSerialNumber }},
+                 "Actual and expected display string should match for " +
+                 `index ${i} for ${tabID}`);
+    }
   }
 
   await BrowserTestUtils.closeWindow(win);
 }
 
 // Test deleting certs from the "Your Certificates" tab.
 add_task(async function testDeletePersonalCerts() {
-  const expectedTitle = "Delete your Certificates";
-  const expectedConfirmMsg =
-    "Are you sure you want to delete these certificates?";
-  const expectedImpact =
-    "If you delete one of your own certificates, you can no longer use it to " +
-    "identify yourself.";
-  await testHelper("mine_tab", expectedTitle, expectedConfirmMsg,
-                    expectedImpact);
+  const expectedTitleL10nId = {id: "delete-user-cert-title"};
+  const expectedConfirmL10nId = {id: "delete-user-cert-confirm"};
+  const expectedImpactL10nId = {id: "delete-user-cert-impact"};
+  await testHelper("mine_tab", expectedTitleL10nId, expectedConfirmL10nId,
+                    expectedImpactL10nId);
 });
 
 // Test deleting certs from the "People" tab.
 add_task(async function testDeleteOtherPeopleCerts() {
-  const expectedTitle = "Delete E-Mail Certificates";
+  const expectedTitleL10nId = {id: "delete-email-cert-title"};
   // ’ doesn't seem to work when embedded in the following literals, which is
   // why escape codes are used instead.
-  const expectedConfirmMsg =
-    "Are you sure you want to delete these people\u2019s e-mail certificates?";
-  const expectedImpact =
-    "If you delete a person\u2019s e-mail certificate, you will no longer be " +
-    "able to send encrypted e-mail to that person.";
-  await testHelper("others_tab", expectedTitle, expectedConfirmMsg,
-                    expectedImpact);
+  const expectedConfirmL10nId = {id: "delete-email-cert-confirm"};
+  const expectedImpactL10nId = {id: "delete-email-cert-impact"};
+  await testHelper("others_tab", expectedTitleL10nId, expectedConfirmL10nId,
+                    expectedImpactL10nId);
 });
 
 // Test deleting certs from the "Servers" tab.
 add_task(async function testDeleteServerCerts() {
-  const expectedTitle = "Delete Server Certificate Exceptions";
-  const expectedConfirmMsg =
-    "Are you sure you want to delete these server exceptions?";
-  const expectedImpact =
-    "If you delete a server exception, you restore the usual security checks " +
-    "for that server and require it uses a valid certificate.";
-  await testHelper("websites_tab", expectedTitle, expectedConfirmMsg,
-                    expectedImpact);
+  const expectedTitleL10nId = {id: "delete-ssl-cert-title"};
+  const expectedConfirmL10nId = {id: "delete-ssl-cert-confirm"};
+  const expectedImpactL10nId = {id: "delete-ssl-cert-impact"};
+  await testHelper("websites_tab", expectedTitleL10nId, expectedConfirmL10nId,
+                    expectedImpactL10nId);
 });
 
 // Test deleting certs from the "Authorities" tab.
 add_task(async function testDeleteCACerts() {
-  const expectedTitle = "Delete or Distrust CA Certificates";
-  const expectedConfirmMsg =
-    "You have requested to delete these CA certificates. For built-in " +
-    "certificates all trust will be removed, which has the same effect. Are " +
-    "you sure you want to delete or distrust?";
-  const expectedImpact =
-    "If you delete or distrust a certificate authority (CA) certificate, " +
-    "this application will no longer trust any certificates issued by that CA.";
-  await testHelper("ca_tab", expectedTitle, expectedConfirmMsg,
-                    expectedImpact);
+  const expectedTitleL10nId = {id: "delete-ca-cert-title"};
+  const expectedConfirmL10nId = {id: "delete-ca-cert-confirm"};
+  const expectedImpactL10nId = {id: "delete-ca-cert-impact"};
+  await testHelper("ca_tab", expectedTitleL10nId, expectedConfirmL10nId,
+                    expectedImpactL10nId);
 });
 
 // Test that the right values are returned when the dialog is accepted.
 add_task(async function testAcceptDialogReturnValues() {
   let [win, retVals] = await openDeleteCertConfirmDialog("ca_tab" /* arbitrary */);
   info("Accepting dialog");
   win.document.getElementById("deleteCertificate").acceptDialog();
   await BrowserTestUtils.windowClosed(win);
--- a/toolkit/content/widgets/dialog.xml
+++ b/toolkit/content/widgets/dialog.xml
@@ -284,16 +284,18 @@
                 button.setAttribute("label", this.getAttribute("buttonlabel" + dlgtype));
                 if (this.hasAttribute("buttonaccesskey" + dlgtype))
                   button.setAttribute("accesskey", this.getAttribute("buttonaccesskey" + dlgtype));
               } else if (dlgtype != "extra1" && dlgtype != "extra2") {
                 button.setAttribute("label", this.mStrBundle.GetStringFromName("button-" + dlgtype));
                 var accessKey = this.mStrBundle.GetStringFromName("accesskey-" + dlgtype);
                 if (accessKey)
                   button.setAttribute("accesskey", accessKey);
+              } else if (this.hasAttribute("buttonid" + dlgtype)) {
+                document.l10n.setAttributes(button, this.getAttribute("buttonid" + dlgtype));
               }
             }
             // allow specifying alternate icons in the dialog header
             if (!button.hasAttribute("icon")) {
               // if there's an icon specified, use that
               if (this.hasAttribute("buttonicon" + dlgtype))
                 button.setAttribute("icon", this.getAttribute("buttonicon" + dlgtype));
               // otherwise set defaults