Bug 1622269 - Use fluent to display cert error titles. r=flod,prathiksha,fluent-reviewers
authorsourab <skanthavar@live.com>
Thu, 26 Mar 2020 14:35:50 +0000
changeset 520572 8e6f25128175fceefe4b46f6fb407c2364210b05
parent 520571 e62f3effd132a282c68aac769922710fad287bc5
child 520573 6055f2b2da4460732c2dbad0c53da13db942b80d
push id37253
push usernerli@mozilla.com
push dateThu, 26 Mar 2020 21:36:52 +0000
treeherdermozilla-central@c644dd16e2cc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersflod, prathiksha, fluent-reviewers
bugs1622269
milestone76.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 1622269 - Use fluent to display cert error titles. r=flod,prathiksha,fluent-reviewers Differential Revision: https://phabricator.services.mozilla.com/D66968
browser/base/content/aboutNetError.js
browser/base/content/aboutNetError.xhtml
browser/base/content/test/about/browser_aboutCertError.js
browser/locales/en-US/browser/aboutCertError.ftl
browser/locales/en-US/chrome/overrides/netError.dtd
python/l10n/fluent_migrations/bug_1622269_certError_titles.py
--- a/browser/base/content/aboutNetError.js
+++ b/browser/base/content/aboutNetError.js
@@ -158,16 +158,41 @@ function disallowCertOverridesIfNeeded()
     ).innerHTML;
     // eslint-disable-next-line no-unsanitized/property
     document.getElementById(
       "mitmWhatCanYouDoAboutIt3"
     ).innerHTML = stsMitmWhatCanYouDoAboutIt3;
   }
 }
 
+async function setErrorPageStrings(err) {
+  let title = err + "-title";
+
+  let isCertError = err == "nssBadCert";
+  let className = getCSSClass();
+  if (isCertError && (window !== window.top || className == "badStsCert")) {
+    title = err + "-sts-title";
+  }
+
+  let [errorCodeTitle] = await document.l10n.formatValues([
+    {
+      id: title,
+    },
+  ]);
+
+  let titleElement = document.querySelector(".title-text");
+  if (!errorCodeTitle) {
+    console.error("No strings exist for this error type");
+    document.l10n.setAttributes(titleElement, "generic-title");
+    return;
+  }
+
+  document.l10n.setAttributes(titleElement, title);
+}
+
 function initPage() {
   var err = getErrorCode();
   // List of error pages with an illustration.
   let illustratedErrors = [
     "malformedURI",
     "dnsNotFound",
     "connectionFailure",
     "netInterrupt",
@@ -201,25 +226,22 @@ function initPage() {
 
   let pageTitle = document.getElementById("ept_" + l10nErrId);
   if (pageTitle) {
     document.title = pageTitle.textContent;
   }
 
   // if it's an unknown error or there's no title or description
   // defined, get the generic message
-  var errTitle = document.getElementById("et_" + l10nErrId);
   var errDesc = document.getElementById("ed_" + l10nErrId);
-  if (!errTitle || !errDesc) {
-    errTitle = document.getElementById("et_generic");
+  if (!errDesc) {
     errDesc = document.getElementById("ed_generic");
   }
 
-  // eslint-disable-next-line no-unsanitized/property
-  document.querySelector(".title-text").innerHTML = errTitle.innerHTML;
+  setErrorPageStrings(err);
 
   var sd = document.getElementById("errorShortDescText");
   if (sd) {
     if (gIsCertError) {
       // eslint-disable-next-line no-unsanitized/property
       sd.innerHTML = errDesc.innerHTML;
     } else {
       sd.textContent = getDescription();
@@ -616,16 +638,17 @@ function setCertErrorDetails(event) {
       );
     }
   }
 
   // This is set to true later if the user's system clock is at fault for this error.
   let clockSkew = false;
   document.body.setAttribute("code", failedCertInfo.errorCodeString);
 
+  let titleElement = document.querySelector(".title-text");
   let desc;
   switch (failedCertInfo.errorCodeString) {
     case "SSL_ERROR_BAD_CERT_DOMAIN":
     case "SEC_ERROR_OCSP_INVALID_SIGNING_CERT":
     case "SEC_ERROR_UNKNOWN_ISSUER":
       if (es) {
         // eslint-disable-next-line no-unsanitized/property
         es.innerHTML = errWhatToDo.innerHTML;
@@ -679,19 +702,18 @@ function setCertErrorDetails(event) {
       // This may be revised in the future.
       let names = document.querySelectorAll(".mitm-name");
       for (let span of names) {
         span.textContent = failedCertInfo.issuerCommonName;
       }
 
       learnMoreLink.href = baseURL + "security-error";
 
-      let title = document.getElementById("et_mitm");
+      document.l10n.setAttributes(titleElement, "certerror-mitm-title");
       desc = document.getElementById("ed_mitm");
-      document.querySelector(".title-text").textContent = title.textContent;
       // eslint-disable-next-line no-unsanitized/property
       document.getElementById("errorShortDescText").innerHTML = desc.innerHTML;
 
       // eslint-disable-next-line no-unsanitized/property
       es.innerHTML = errWhatToDo.innerHTML;
       // eslint-disable-next-line no-unsanitized/property
       est.innerHTML = errWhatToDoTitle.innerHTML;
 
@@ -755,21 +777,18 @@ function setCertErrorDetails(event) {
       }
 
       let systemDate = formatter.format(new Date());
       document.getElementById(
         "wrongSystemTime_systemDate1"
       ).textContent = systemDate;
       if (clockSkew) {
         document.body.classList.add("illustrated", "clockSkewError");
-        let clockErrTitle = document.getElementById("et_clockSkewError");
+        document.l10n.setAttributes(titleElement, "clockSkewError-title");
         let clockErrDesc = document.getElementById("ed_clockSkewError");
-        // eslint-disable-next-line no-unsanitized/property
-        document.querySelector(".title-text").textContent =
-          clockErrTitle.textContent;
         desc = document.getElementById("errorShortDescText");
         document.getElementById("errorShortDesc").style.display = "block";
         document.getElementById("certificateErrorReporting").style.display =
           "none";
         if (desc) {
           // eslint-disable-next-line no-unsanitized/property
           desc.innerHTML = clockErrDesc.innerHTML;
         }
--- a/browser/base/content/aboutNetError.xhtml
+++ b/browser/base/content/aboutNetError.xhtml
@@ -36,51 +36,16 @@
       <div id="errorPageTitlesContainer">
         <span id="ept_nssBadCert">&certerror.pagetitle2;</span>
         <span id="ept_nssBadCert_sts">&certerror.sts.pagetitle;</span>
         <span id="ept_captivePortal">&captivePortal.title;</span>
         <span id="ept_dnsNotFound">&dnsNotFound.pageTitle;</span>
         <span id="ept_malformedURI">&malformedURI.pageTitle;</span>
         <span id="ept_blockedByPolicy">&blockedByPolicy.title;</span>
       </div>
-      <div id="errorTitlesContainer">
-        <h1 id="et_generic">&generic.title;</h1>
-        <h1 id="et_captivePortal">&captivePortal.title;</h1>
-        <h1 id="et_dnsNotFound">&dnsNotFound.title1;</h1>
-        <h1 id="et_fileNotFound">&fileNotFound.title;</h1>
-        <h1 id="et_fileAccessDenied">&fileAccessDenied.title;</h1>
-        <h1 id="et_malformedURI">&malformedURI.title1;</h1>
-        <h1 id="et_unknownProtocolFound">&unknownProtocolFound.title;</h1>
-        <h1 id="et_connectionFailure">&connectionFailure.title;</h1>
-        <h1 id="et_netTimeout">&netTimeout.title;</h1>
-        <h1 id="et_redirectLoop">&redirectLoop.title;</h1>
-        <h1 id="et_unknownSocketType">&unknownSocketType.title;</h1>
-        <h1 id="et_netReset">&netReset.title;</h1>
-        <h1 id="et_notCached">&notCached.title;</h1>
-        <h1 id="et_netOffline">&netOffline.title;</h1>
-        <h1 id="et_netInterrupt">&netInterrupt.title;</h1>
-        <h1 id="et_deniedPortAccess">&deniedPortAccess.title;</h1>
-        <h1 id="et_proxyResolveFailure">&proxyResolveFailure.title;</h1>
-        <h1 id="et_proxyConnectFailure">&proxyConnectFailure.title;</h1>
-        <h1 id="et_contentEncodingError">&contentEncodingError.title;</h1>
-        <h1 id="et_unsafeContentType">&unsafeContentType.title;</h1>
-        <h1 id="et_nssFailure2">&nssFailure2.title;</h1>
-        <h1 id="et_nssBadCert">&certerror.longpagetitle2;</h1>
-        <h1 id="et_nssBadCert_sts">&certerror.sts.longpagetitle;</h1>
-        <h1 id="et_cspBlocked">&cspBlocked.title;</h1>
-        <h1 id="et_xfoBlocked">&xfoBlocked.title;</h1>
-        <h1 id="et_remoteXUL">&remoteXUL.title;</h1>
-        <h1 id="et_corruptedContentErrorv2">&corruptedContentErrorv2.title;</h1>
-        <h1 id="et_sslv3Used">&sslv3Used.title;</h1>
-        <h1 id="et_inadequateSecurityError">&inadequateSecurityError.title;</h1>
-        <h1 id="et_blockedByPolicy">&blockedByPolicy.title;</h1>
-        <h1 id="et_mitm">&certerror.mitm.title;</h1>
-        <h1 id="et_clockSkewError">&clockSkewError.title;</h1>
-        <h1 id="et_networkProtocolError">&networkProtocolError.title;</h1>
-      </div>
       <div id="errorDescriptionsContainer">
         <div id="ed_generic">&generic.longDesc;</div>
         <div id="ed_captivePortal">&captivePortal.longDesc2;</div>
         <div id="ed_dnsNotFound">&dnsNotFound.longDesc1;</div>
         <div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
         <div id="ed_fileAccessDenied">&fileAccessDenied.longDesc;</div>
         <div id="ed_malformedURI"></div>
         <div id="ed_unknownProtocolFound">&unknownProtocolFound.longDesc;</div>
--- a/browser/base/content/test/about/browser_aboutCertError.js
+++ b/browser/base/content/test/about/browser_aboutCertError.js
@@ -460,31 +460,35 @@ add_task(async function checkBadStsCertH
     let tab = await openErrorPage(BAD_CERT, useFrame);
     let browser = tab.linkedBrowser;
 
     let bc = browser.browsingContext;
     if (useFrame) {
       bc = bc.children[0];
     }
 
-    let titleContent = await SpecialPowers.spawn(bc, [], async function() {
+    await SpecialPowers.spawn(bc, [useFrame], async _useFrame => {
       let titleText = content.document.querySelector(".title-text");
-      return titleText.textContent;
+      await ContentTaskUtils.waitForCondition(
+        () => titleText.textContent,
+        "Error page title is initialized"
+      );
+      let titleContent = titleText.textContent;
+      if (_useFrame) {
+        ok(
+          titleContent.endsWith("Security Issue"),
+          "Did Not Connect: Potential Security Issue"
+        );
+      } else {
+        ok(
+          titleContent.endsWith("Risk Ahead"),
+          "Warning: Potential Security Risk Ahead"
+        );
+      }
     });
-    if (useFrame) {
-      ok(
-        titleContent.endsWith("Security Issue"),
-        "Did Not Connect: Potential Security Issue"
-      );
-    } else {
-      ok(
-        titleContent.endsWith("Risk Ahead"),
-        "Warning: Potential Security Risk Ahead"
-      );
-    }
     BrowserTestUtils.removeTab(gBrowser.selectedTab);
   }
 });
 
 add_task(async function checkSandboxedIframe() {
   info(
     "Loading a bad sts cert error in a sandboxed iframe and check that the correct headline is shown"
   );
--- a/browser/locales/en-US/browser/aboutCertError.ftl
+++ b/browser/locales/en-US/browser/aboutCertError.ftl
@@ -74,8 +74,48 @@ cert-error-symantec-distrust-admin = You may notify the website’s administrator about this problem.
 # $hasHSTS (Boolean) - Indicates whether HSTS header is present.
 cert-error-details-hsts-label = HTTP Strict Transport Security: { $hasHSTS }
 
 # Variables:
 # $hasHPKP (Boolean) - Indicates whether HPKP header is present.
 cert-error-details-key-pinning-label = HTTP Public Key Pinning: { $hasHPKP }
 
 cert-error-details-cert-chain-label = Certificate chain:
+
+## Messages used for certificate error titles
+
+connectionFailure-title = Unable to connect
+deniedPortAccess-title = This address is restricted
+# "Hmm" is a sound made when considering or puzzling over something.
+# You don't have to include it in your translation if your language does not have a written word like this.
+dnsNotFound-title = Hmm. We’re having trouble finding that site.
+fileNotFound-title = File not found
+fileAccessDenied-title = Access to the file was denied
+generic-title = Oops.
+captivePortal-title = Log in to network
+# "Hmm" is a sound made when considering or puzzling over something.
+# You don't have to include it in your translation if your language does not have a written word like this.
+malformedURI-title = Hmm. That address doesn’t look right.
+netInterrupt-title = The connection was interrupted
+notCached-title = Document Expired
+netOffline-title = Offline mode
+contentEncodingError-title = Content Encoding Error
+unsafeContentType-title = Unsafe File Type
+netReset-title = The connection was reset
+netTimeout-title = The connection has timed out
+unknownProtocolFound-title = The address wasn’t understood
+proxyConnectFailure-title = The proxy server is refusing connections
+proxyResolveFailure-title = Unable to find the proxy server
+redirectLoop-title = The page isn’t redirecting properly
+unknownSocketType-title = Unexpected response from server
+nssFailure2-title = Secure Connection Failed
+cspBlocked-title = Blocked by Content Security Policy
+xfoBlocked-title = Blocked by X-Frame-Options Policy
+corruptedContentError-title = Corrupted Content Error
+remoteXUL-title = Remote XUL
+sslv3Used-title = Unable to Connect Securely
+inadequateSecurityError-title = Your connection is not secure
+blockedByPolicy-title = Blocked Page
+clockSkewError-title = Your Computer Clock is Wrong
+networkProtocolError-title = Network Protocol Error
+nssBadCert-title = Warning: Potential Security Risk Ahead
+nssBadCert-sts-title = Did Not Connect: Potential Security Issue
+certerror-mitm-title = Software is Preventing { -brand-short-name } From Safely Connecting to This Site
--- a/browser/locales/en-US/chrome/overrides/netError.dtd
+++ b/browser/locales/en-US/chrome/overrides/netError.dtd
@@ -9,151 +9,127 @@
 <!ENTITY retry.label "Try Again">
 <!ENTITY returnToPreviousPage.label "Go Back">
 <!ENTITY returnToPreviousPage1.label "Go Back (Recommended)">
 <!ENTITY advanced2.label "Advanced…">
 <!ENTITY viewCertificate.label "View Certificate">
 
 <!-- Specific error messages -->
 
-<!ENTITY connectionFailure.title "Unable to connect">
 <!ENTITY connectionFailure.longDesc "&sharedLongDesc;">
 
-<!ENTITY deniedPortAccess.title "This address is restricted">
 <!ENTITY deniedPortAccess.longDesc "">
 
 <!ENTITY dnsNotFound.pageTitle "Server Not Found">
-<!-- Localization note (dnsNotFound.title1) - "Hmm" is a sound made when considering or puzzling over something. You don't have to include it in your translation if your language does not have a written word like this. -->
-<!ENTITY dnsNotFound.title1 "Hmm. We’re having trouble finding that site.">
 <!ENTITY dnsNotFound.longDesc1 "
 <strong>If that address is correct, here are three other things you can try:</strong>
 <ul>
   <li>Try again later.</li>
   <li>Check your network connection.</li>
   <li>If you are connected but behind a firewall, check that &brandShortName; has permission to access the Web.</li>
 </ul>
 ">
 
-<!ENTITY fileNotFound.title "File not found">
 <!ENTITY fileNotFound.longDesc "
 <ul>
   <li>Check the file name for capitalization or other typing errors.</li>
   <li>Check to see if the file was moved, renamed or deleted.</li>
 </ul>
 ">
 
-<!ENTITY fileAccessDenied.title "Access to the file was denied">
 <!ENTITY fileAccessDenied.longDesc "
 <ul>
   <li>It may have been removed, moved, or file permissions may be preventing access.</li>
 </ul>
 ">
 
-<!ENTITY generic.title "Oops.">
 <!ENTITY generic.longDesc "
 <p>&brandShortName; can’t load this page for some reason.</p>
 ">
 
 <!ENTITY captivePortal.title "Log in to network">
 <!ENTITY captivePortal.longDesc2 "
 <p>You must log in to this network before you can access the Internet.</p>
 ">
 
 <!ENTITY openPortalLoginPage.label2 "Open Network Login Page">
 
 <!ENTITY malformedURI.pageTitle "Invalid URL">
-<!-- Localization note (malformedURI.title1) - "Hmm" is a sound made when considering or puzzling over something. You don't have to include it in your translation if your language does not have a written word like this. -->
-<!ENTITY malformedURI.title1 "Hmm. That address doesn’t look right.">
 
-<!ENTITY netInterrupt.title "The connection was interrupted">
 <!ENTITY netInterrupt.longDesc "&sharedLongDesc;">
 
-<!ENTITY notCached.title "Document Expired">
 <!ENTITY notCached.longDesc "<p>The requested document is not available in &brandShortName;’s cache.</p><ul><li>As a security precaution, &brandShortName; does not automatically re-request sensitive documents.</li><li>Click Try Again to re-request the document from the website.</li></ul>">
 
-<!ENTITY netOffline.title "Offline mode">
 <!ENTITY netOffline.longDesc2 "
 <ul>
   <li>Press &quot;Try Again&quot; to switch to online mode and reload the page.</li>
 </ul>
 ">
 
-<!ENTITY contentEncodingError.title "Content Encoding Error">
 <!ENTITY contentEncodingError.longDesc "
 <ul>
   <li>Please contact the website owners to inform them of this problem.</li>
 </ul>
 ">
 
-<!ENTITY unsafeContentType.title "Unsafe File Type">
 <!ENTITY unsafeContentType.longDesc "
 <ul>
   <li>Please contact the website owners to inform them of this problem.</li>
 </ul>
 ">
 
-<!ENTITY netReset.title "The connection was reset">
 <!ENTITY netReset.longDesc "&sharedLongDesc;">
 
-<!ENTITY netTimeout.title "The connection has timed out">
 <!ENTITY netTimeout.longDesc "&sharedLongDesc;">
 
-<!ENTITY unknownProtocolFound.title "The address wasn’t understood">
 <!ENTITY unknownProtocolFound.longDesc "
 <ul>
   <li>You might need to install other software to open this address.</li>
 </ul>
 ">
 
-<!ENTITY proxyConnectFailure.title "The proxy server is refusing connections">
 <!ENTITY proxyConnectFailure.longDesc "
 <ul>
   <li>Check the proxy settings to make sure that they are correct.</li>
   <li>Contact your network administrator to make sure the proxy server is
     working.</li>
 </ul>
 ">
 
-<!ENTITY proxyResolveFailure.title "Unable to find the proxy server">
 <!ENTITY proxyResolveFailure.longDesc "
 <ul>
   <li>Check the proxy settings to make sure that they are correct.</li>
   <li>Check to make sure your computer has a working network connection.</li>
   <li>If your computer or network is protected by a firewall or proxy, make sure
     that &brandShortName; is permitted to access the Web.</li>
 </ul>
 ">
 
-<!ENTITY redirectLoop.title "The page isn’t redirecting properly">
 <!ENTITY redirectLoop.longDesc "
 <ul>
   <li>This problem can sometimes be caused by disabling or refusing to accept
     cookies.</li>
 </ul>
 ">
 
-<!ENTITY unknownSocketType.title "Unexpected response from server">
 <!ENTITY unknownSocketType.longDesc "
 <ul>
   <li>Check to make sure your system has the Personal Security Manager
     installed.</li>
   <li>This might be due to a non-standard configuration on the server.</li>
 </ul>
 ">
 
-<!ENTITY nssFailure2.title "Secure Connection Failed">
 <!ENTITY nssFailure2.longDesc2 "
 <ul>
   <li>The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.</li>
   <li>Please contact the website owners to inform them of this problem.</li>
 </ul>
 ">
 
-<!ENTITY certerror.longpagetitle2 "Warning: Potential Security Risk Ahead">
-<!ENTITY certerror.sts.longpagetitle  "Did Not Connect: Potential Security Issue">
 <!-- Localization note (certerror.introPara2) - The text content of the span tag
 will be replaced at runtime with the name of the server to which the user
 was trying to connect. -->
 <!ENTITY certerror.introPara2 "&brandShortName; detected a potential security threat and did not continue to <span class='hostname'/>. If you visit this site, attackers could try to steal information like your passwords, emails, or credit card details.">
 <!ENTITY certerror.sts.introPara "&brandShortName; detected a potential security threat and did not continue to <span class='hostname'/> because this website requires a secure connection.">
 
 <!ENTITY certerror.expiredCert.introPara "&brandShortName; detected an issue and did not continue to <span class='hostname'/>. The website is either misconfigured or your computer clock is set to the wrong time.">
 <!ENTITY certerror.expiredCert.secondPara2 "It’s likely the website’s certificate is expired, which prevents &brandShortName; from connecting securely. If you visit this site, attackers could try to steal information like your passwords, emails, or credit card details.">
@@ -181,61 +157,52 @@ was trying to connect. -->
     moments.</li>
   <li>If you are unable to load any pages, check your computer’s network
     connection.</li>
   <li>If your computer or network is protected by a firewall or proxy, make sure
     that &brandShortName; is permitted to access the Web.</li>
 </ul>
 ">
 
-<!ENTITY cspBlocked.title "Blocked by Content Security Policy">
 <!ENTITY cspBlocked.longDesc "<p>&brandShortName; prevented this page from loading in this way because the page has a content security policy that disallows it.</p>">
 
-<!ENTITY xfoBlocked.title "Blocked by X-Frame-Options Policy">
 <!ENTITY xfoBlocked.longDesc "<p>&brandShortName; prevented this page from loading in this context because the page has an X-Frame-Options policy that disallows it.</p>">
 
-<!ENTITY corruptedContentErrorv2.title "Corrupted Content Error">
 <!ENTITY corruptedContentErrorv2.longDesc "<p>The page you are trying to view cannot be shown because an error in the data transmission was detected.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
 
 <!ENTITY securityOverride.exceptionButton1Label "Accept the Risk and Continue">
 
 <!ENTITY errorReporting.automatic2 "Report errors like this to help Mozilla identify and block malicious sites">
 <!ENTITY errorReporting.learnMore "Learn more…">
 
-<!ENTITY remoteXUL.title "Remote XUL">
 <!ENTITY remoteXUL.longDesc "<p><ul><li>Please contact the website owners to inform them of this problem.</li></ul></p>">
 
-<!ENTITY sslv3Used.title "Unable to Connect Securely">
 <!-- LOCALIZATION NOTE (sslv3Used.longDesc2) - Do not translate
      "SSL_ERROR_UNSUPPORTED_VERSION". -->
 <!ENTITY sslv3Used.longDesc2 "Advanced info: SSL_ERROR_UNSUPPORTED_VERSION">
 
 <!ENTITY certerror.pagetitle2  "Warning: Potential Security Risk Ahead">
 <!ENTITY certerror.sts.pagetitle  "Did Not Connect: Potential Security Issue">
 <!ENTITY certerror.whatShouldIDo.badStsCertExplanation1 "<span class='hostname'></span> has a security policy called HTTP Strict Transport Security (HSTS), which means that &brandShortName; can only connect to it securely. You can’t add an exception to visit this site.">
 <!ENTITY certerror.copyToClipboard.label "Copy text to clipboard">
 
-<!ENTITY inadequateSecurityError.title "Your connection is not secure">
 <!-- LOCALIZATION NOTE (inadequateSecurityError.longDesc) - Do not translate
      "NS_ERROR_NET_INADEQUATE_SECURITY". -->
 <!ENTITY inadequateSecurityError.longDesc "<p><span class='hostname'></span> uses security technology that is outdated and vulnerable to attack. An attacker could easily reveal information which you thought to be safe. The website administrator will need to fix the server first before you can visit the site.</p><p>Error code: NS_ERROR_NET_INADEQUATE_SECURITY</p>">
 
 <!ENTITY blockedByPolicy.title "Blocked Page">
 
-<!ENTITY certerror.mitm.title "Software is Preventing &brandShortName; From Safely Connecting to This Site">
 <!ENTITY certerror.mitm.longDesc "<span class='hostname'></span> is most likely a safe site, but a secure connection could not be established. This issue is caused by <span class='mitm-name'/>, which is either software on your computer or your network.">
 <!ENTITY certerror.mitm.whatCanYouDoAboutIt1 "If your antivirus software includes a feature that scans encrypted connections (often called “web scanning” or “https scanning”), you can disable that feature. If that doesn’t work, you can remove and reinstall the antivirus software.">
 <!ENTITY certerror.mitm.whatCanYouDoAboutIt2 "If you are on a corporate network, you can contact your IT department.">
 <!ENTITY certerror.mitm.whatCanYouDoAboutIt3 "If you are not familiar with <span class='mitm-name'/>, then this could be an attack and you should not continue to the site.">
 <!ENTITY certerror.mitm.sts.whatCanYouDoAboutIt3 "If you are not familiar with <span class='mitm-name'/>, then this could be an attack, and there is nothing you can do to access the site.">
 
-<!ENTITY clockSkewError.title "Your Computer Clock is Wrong">
 <!ENTITY clockSkewError.longDesc "Your computer thinks it is <span id='wrongSystemTime_systemDate1'/>, which prevents &brandShortName; from connecting securely. To visit <span class='hostname'></span>, update your computer clock in your system settings to the current date, time, and time zone, and then refresh <span class='hostname'></span>.">
 
 <!ENTITY prefReset.longDesc "It looks like your network security settings might be causing this. Do you want the default settings to be restored?">
 <!ENTITY prefReset.label "Restore default settings">
 
 <!ENTITY enableTls10.longDesc "This website might not support the TLS 1.2 protocol, which is the minimum version supported by &brandShortName;. Enabling TLS 1.0 and TLS 1.1 might allow this connection to succeed.">
 <!ENTITY enableTls10.note "TLS 1.0 and TLS 1.1 will be permanently disabled in a future release.">
 <!ENTITY enableTls10.label "Enable TLS 1.0 and 1.1">
 
-<!ENTITY networkProtocolError.title "Network Protocol Error">
 <!ENTITY networkProtocolError.longDesc "<p>The page you are trying to view cannot be shown because an error in the network protocol was detected.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
new file mode 100644
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1622269_certError_titles.py
@@ -0,0 +1,67 @@
+# 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, TERM_REFERENCE
+from fluent.migrate import COPY, REPLACE
+
+
+def migrate(ctx):
+    """Bug 1622269 - Migrate cert error titles from netError.dtd to aboutCertError.ftl, part {index}"""
+    ctx.add_transforms(
+        "browser/browser/aboutCertError.ftl",
+        "browser/browser/aboutCertError.ftl",
+            transforms_from(
+"""
+generic-title = { COPY(from_path, "generic.title") }
+captivePortal-title = { COPY(from_path, "captivePortal.title") }
+dnsNotFound-title = { COPY(from_path, "dnsNotFound.title1") }
+fileNotFound-title = { COPY(from_path, "fileNotFound.title") }
+fileAccessDenied-title = { COPY(from_path, "fileAccessDenied.title") }
+malformedURI-title = { COPY(from_path, "malformedURI.title1") }
+unknownProtocolFound-title = { COPY(from_path, "unknownProtocolFound.title") }
+connectionFailure-title = { COPY(from_path, "connectionFailure.title") }
+netTimeout-title = { COPY(from_path, "netTimeout.title") }
+redirectLoop-title = { COPY(from_path, "redirectLoop.title") }
+unknownSocketType-title = { COPY(from_path, "unknownSocketType.title") }
+netReset-title = { COPY(from_path, "netReset.title") }
+notCached-title = { COPY(from_path, "notCached.title") }
+netOffline-title = { COPY(from_path, "netOffline.title") }
+netInterrupt-title = { COPY(from_path, "netInterrupt.title") }
+deniedPortAccess-title = { COPY(from_path, "deniedPortAccess.title") }
+proxyResolveFailure-title = { COPY(from_path, "proxyResolveFailure.title") }
+proxyConnectFailure-title = { COPY(from_path, "proxyConnectFailure.title") }
+contentEncodingError-title = { COPY(from_path, "contentEncodingError.title") }
+unsafeContentType-title = { COPY(from_path, "unsafeContentType.title") }
+nssFailure2-title = { COPY(from_path, "nssFailure2.title") }
+nssBadCert-title = { COPY(from_path, "certerror.longpagetitle2") }
+nssBadCert-sts-title = { COPY(from_path, "certerror.sts.longpagetitle") }
+cspBlocked-title = { COPY(from_path, "cspBlocked.title") }
+xfoBlocked-title = { COPY(from_path, "xfoBlocked.title") }
+remoteXUL-title = { COPY(from_path, "remoteXUL.title") }
+corruptedContentError-title = { COPY(from_path, "corruptedContentErrorv2.title") }
+sslv3Used-title = { COPY(from_path, "sslv3Used.title") }
+inadequateSecurityError-title = { COPY(from_path, "inadequateSecurityError.title") }
+blockedByPolicy-title = { COPY(from_path, "blockedByPolicy.title") }
+clockSkewError-title = { COPY(from_path, "clockSkewError.title") }
+networkProtocolError-title = { COPY(from_path, "networkProtocolError.title") }
+""", from_path="browser/chrome/overrides/netError.dtd"))
+    ctx.add_transforms(
+        "browser/browser/aboutCertError.ftl",
+                        "browser/browser/aboutCertError.ftl",
+        [
+            FTL.Message(
+                id=FTL.Identifier("certerror-mitm-title"),
+                value=REPLACE(
+                    "browser/chrome/overrides/netError.dtd",
+                    "certerror.mitm.title",
+                    {
+                        "&brandShortName;": TERM_REFERENCE("brand-short-name"),
+                    },
+                ),
+            ),
+        ]
+    )