Bug 1476034 - about:crashes: switched to fluent. r=flod,Pike
authorAlexis Deschamps <adeschamps@mozilla.com>
Wed, 01 Aug 2018 10:31:14 +0300
changeset 825521 a92a4691c0da85f9141144dee9cbad8c3cf815ad
parent 825335 8ded8bf9b94ca03d8f6ef555af0e9c6c296e1afe
child 825522 019ed2fbfc31ee084b056e4b73a9ac1badec6ef1
push id118129
push userjhofmann@mozilla.com
push dateWed, 01 Aug 2018 22:38:13 +0000
reviewersflod, Pike
bugs1476034, 1463515
milestone63.0a1
Bug 1476034 - about:crashes: switched to fluent. r=flod,Pike Summary: The about:crashes page is being updated (bug 1463515). To facilitate these changes, this patch changes the about:crashes page to use Fluent for localization instead of the old systems. This also includes a script to migrate strings from the old .DTD and .properties files to the new .ftl one. Test Plan: 1. build Firefox with the changes 2. run Firefox 3. go to the about:crashes page 4. expect nothing to be different This extension: https://github.com/rhelmer/webext-experiment-crashme can be used to add local crash reports for verifying the different states of the about:crashes page. Reviewers: flod, Pike, jchen, snorp Reviewed By: flod, Pike, jchen, snorp Subscribers: nalexander, reviewbot Bug #: 1476034 Differential Revision: https://phabricator.services.mozilla.com/D2225
browser/base/content/test/static/browser_all_files_referenced.js
mobile/android/chrome/content/browser.js
mobile/android/chrome/jar.mn
mobile/android/components/geckoview/GeckoViewStartup.js
mobile/android/installer/package-manifest.in
mobile/android/locales/filter.py
mobile/android/locales/jar.mn
mobile/android/locales/l10n.toml
mobile/locales/filter.py
python/l10n/fluent_migrations/bug_1476034_aboutcrashes.py
toolkit/crashreporter/content/crashes.css
toolkit/crashreporter/content/crashes.js
toolkit/crashreporter/content/crashes.xhtml
toolkit/locales/en-US/chrome/global/aboutSupport.dtd
toolkit/locales/en-US/crashreporter/aboutcrashes.ftl
toolkit/locales/en-US/crashreporter/crashes.dtd
toolkit/locales/en-US/crashreporter/crashes.properties
toolkit/locales/jar.mn
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -164,21 +164,16 @@ var whitelist = [
 
 whitelist = new Set(whitelist.filter(item =>
   ("isFromDevTools" in item) == isDevtools &&
   (!item.skipUnofficial || !AppConstants.MOZILLA_OFFICIAL) &&
   (!item.platforms || item.platforms.includes(AppConstants.platform))
 ).map(item => item.file));
 
 const ignorableWhitelist = new Set([
-  // These 2 files are unreferenced only when building without the crash
-  // reporter (eg. Linux x64 asan builds on treeherder)
-  "chrome://global/locale/crashes.dtd",
-  "chrome://global/locale/crashes.properties",
-
   // The following files are outside of the omni.ja file, so we only catch them
   // when testing on a non-packaged build.
 
   // toolkit/mozapps/extensions/nsBlocklistService.js
   "resource://app/blocklist.xml",
 
   // dom/media/gmp/GMPParent.cpp
   "resource://gre/gmp-clearkey/0.1/manifest.json",
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2,16 +2,17 @@
 /* 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/. */
 "use strict";
 
 ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 ChromeUtils.import("resource://gre/modules/DelayedInit.jsm");
+ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm");
 ChromeUtils.import("resource://gre/modules/Messaging.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/TelemetryController.jsm");
 
 if (AppConstants.ACCESSIBILITY) {
   ChromeUtils.defineModuleGetter(this, "AccessFu",
                                  "resource://gre/modules/accessibility/AccessFu.jsm");
@@ -384,16 +385,21 @@ var BrowserApp = {
       "Session:Forward",
       "Session:GetHistory",
       "Session:Navigate",
       "Session:Reload",
       "Session:Stop",
       "Telemetry:CustomTabsPing",
     ]);
 
+    // Initialize the default l10n resource sources for L10nRegistry.
+    let locales = Services.locale.getPackagedLocales();
+    const greSource = new FileSource("toolkit", locales, "resource://gre/localization/{locale}/");
+    L10nRegistry.registerSource(greSource);
+
     // Provide compatibility for add-ons like QuitNow that send "Browser:Quit"
     // as an observer notification.
     Services.obs.addObserver((subject, topic, data) =>
         this.quit(data ? JSON.parse(data) : undefined), "Browser:Quit");
 
     Services.obs.addObserver(this, "android-get-pref");
     Services.obs.addObserver(this, "android-set-pref");
     Services.obs.addObserver(this, "gather-telemetry");
--- a/mobile/android/chrome/jar.mn
+++ b/mobile/android/chrome/jar.mn
@@ -67,18 +67,16 @@ chrome.jar:
 % override chrome://global/locale/charsetMenu.properties chrome://browser/locale/overrides/charsetMenu.properties
 % override chrome://global/locale/commonDialogs.properties chrome://browser/locale/overrides/commonDialogs.properties
 % override chrome://global/locale/intl.properties chrome://browser/locale/overrides/intl.properties
 % override chrome://global/locale/intl.css chrome://browser/locale/overrides/intl.css
 % override chrome://global/locale/search/search.properties chrome://browser/locale/overrides/search/search.properties
 % override chrome://pluginproblem/locale/pluginproblem.dtd chrome://browser/locale/overrides/plugins/pluginproblem.dtd
 % override chrome://global/locale/aboutSupport.dtd chrome://browser/locale/overrides/global/aboutSupport.dtd
 % override chrome://global/locale/aboutSupport.properties chrome://browser/locale/overrides/global/aboutSupport.properties
-% override chrome://global/locale/crashes.dtd chrome://browser/locale/overrides/crashreporter/crashes.dtd
-% override chrome://global/locale/crashes.properties chrome://browser/locale/overrides/crashreporter/crashes.properties
 % override chrome://global/locale/mozilla.dtd chrome://browser/locale/overrides/global/mozilla.dtd
 % override chrome://global/locale/aboutTelemetry.dtd chrome://browser/locale/overrides/global/aboutTelemetry.dtd
 % override chrome://global/locale/aboutTelemetry.properties chrome://browser/locale/overrides/global/aboutTelemetry.properties
 % override chrome://global/locale/aboutWebrtc.properties chrome://browser/locale/overrides/global/aboutWebrtc.properties
 
 # overrides for dom l10n, also for en-US
 # keep this file list in sync with filter.py
 % override chrome://global/locale/global.dtd chrome://browser/locale/overrides/global.dtd
--- a/mobile/android/components/geckoview/GeckoViewStartup.js
+++ b/mobile/android/components/geckoview/GeckoViewStartup.js
@@ -1,17 +1,19 @@
 /* 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/. */
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
+  FileSource: "resource://gre/modules/L10nRegistry.jsm",
   GeckoViewTelemetryController: "resource://gre/modules/GeckoViewTelemetryController.jsm",
   GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm",
+  L10nRegistry: "resource://gre/modules/L10nRegistry.jsm",
   Services: "resource://gre/modules/Services.jsm",
 });
 
 const {debug, warn} = GeckoViewUtils.initLogging("GeckoViewStartup", this);
 
 function GeckoViewStartup() {
 }
 
@@ -106,15 +108,20 @@ GeckoViewStartup.prototype = {
         }, {
           handler: _ => this.GeckoViewRemoteDebugger,
         });
 
         // This initializes Telemetry for GeckoView only in the parent process.
         // The Telemetry initialization for the content process is performed in
         // ContentProcessSingleton.js for consistency with Desktop Telemetry.
         GeckoViewTelemetryController.setup();
+
+        // Initialize the default l10n resource sources for L10nRegistry.
+        let locales = Services.locale.getPackagedLocales();
+        const greSource = new FileSource("toolkit", locales, "resource://gre/localization/{locale}/");
+        L10nRegistry.registerSource(greSource);
         break;
       }
     }
   },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([GeckoViewStartup]);
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -17,16 +17,17 @@
 [@AB_CD@]
 @BINPATH@/@PREF_DIR@/mobile-l10n.js
 @BINPATH@/update.locale
 #ifdef MOZ_UPDATER
 @BINPATH@/updater.ini
 #endif
 @BINPATH@/dictionaries/*
 @BINPATH@/hyphenation/*
+@BINPATH@/localization/*
 
 [assets destdir="assets/@ANDROID_CPU_ARCH@"]
 #ifndef MOZ_STATIC_JS
 @BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
 #endif
 #ifdef MOZ_DMD
 @BINPATH@/@DLL_PREFIX@dmd@DLL_SUFFIX@
 #endif
--- a/mobile/android/locales/filter.py
+++ b/mobile/android/locales/filter.py
@@ -24,22 +24,24 @@ def test(mod, path, entity=None):
             "chrome/global/charsetMenu.properties",
             "chrome/global/commonDialogs.properties",
             "chrome/global/intl.properties",
             "chrome/global/intl.css",
             "chrome/search/search.properties",
             "chrome/pluginproblem/pluginproblem.dtd",
             "chrome/global/aboutSupport.dtd",
             "chrome/global/aboutSupport.properties",
-            "crashreporter/crashes.dtd",
-            "crashreporter/crashes.properties",
             "chrome/global/mozilla.dtd",
             "chrome/global/aboutTelemetry.dtd",
             "chrome/global/aboutTelemetry.properties",
-            "chrome/global/aboutWebrtc.properties"):
+            "chrome/global/aboutWebrtc.properties",
+        ):
+            return "error"
+        if re.match(r"crashreporter/[^/]*.ftl", path):
+            # error on crashreporter/*.ftl
             return "error"
         return "ignore"
 
     if mod == "dom":
         # keep this file list in sync with jar.mn
         if path in (
             "chrome/global.dtd",
             "chrome/accessibility/AccessFu.properties",
--- a/mobile/android/locales/jar.mn
+++ b/mobile/android/locales/jar.mn
@@ -45,27 +45,37 @@ relativesrcdir toolkit/locales:
   locale/@AB_CD@/browser/overrides/intl.properties                 (%chrome/global/intl.properties)
   locale/@AB_CD@/browser/overrides/intl.css                        (%chrome/global/intl.css)
   locale/@AB_CD@/browser/overrides/search/search.properties        (%chrome/search/search.properties)
 # plugins
   locale/@AB_CD@/browser/overrides/plugins/pluginproblem.dtd       (%chrome/pluginproblem/pluginproblem.dtd)
 # about:support
   locale/@AB_CD@/browser/overrides/global/aboutSupport.dtd         (%chrome/global/aboutSupport.dtd)
   locale/@AB_CD@/browser/overrides/global/aboutSupport.properties  (%chrome/global/aboutSupport.properties)
-#about:crashes
-  locale/@AB_CD@/browser/overrides/crashreporter/crashes.dtd         (%crashreporter/crashes.dtd)
-  locale/@AB_CD@/browser/overrides/crashreporter/crashes.properties  (%crashreporter/crashes.properties)
 #about:mozilla
   locale/@AB_CD@/browser/overrides/global/mozilla.dtd                (%chrome/global/mozilla.dtd)
 #about:telemetry
   locale/@AB_CD@/browser/overrides/global/aboutTelemetry.dtd         (%chrome/global/aboutTelemetry.dtd)
   locale/@AB_CD@/browser/overrides/global/aboutTelemetry.properties  (%chrome/global/aboutTelemetry.properties)
 #about:webrtc
   locale/@AB_CD@/browser/overrides/global/aboutWebrtc.properties  (%chrome/global/aboutWebrtc.properties)
 
 # overrides for dom l10n, also for en-US
 # keep this file list in sync with filter.py
 relativesrcdir dom/locales:
   locale/@AB_CD@/browser/overrides/global.dtd                  (%chrome/global.dtd)
   locale/@AB_CD@/browser/overrides/AccessFu.properties         (%chrome/accessibility/AccessFu.properties)
   locale/@AB_CD@/browser/overrides/dom/dom.properties          (%chrome/dom/dom.properties)
 #about:plugins
   locale/@AB_CD@/browser/overrides/plugins.properties          (%chrome/plugins.properties)
+
+# Fluent files
+# Note: All rules must be wildcards, as localized files are optional
+# Only run this if we're not en-US, as en-US is already built
+# by toolkit/locales/jar.mn.
+
+#define EN_US en-US
+#if AB_CD != EN_US
+[localization] @AB_CD@.jar:
+relativesrcdir toolkit/locales:
+#about:crashes
+  crashreporter                                    (%crashreporter/**/*.ftl)
+#endif
--- a/mobile/android/locales/l10n.toml
+++ b/mobile/android/locales/l10n.toml
@@ -197,16 +197,20 @@ exclude-multi-locale = [
     reference = "toolkit/locales/en-US/chrome/global/aboutSupport.dtd"
     l10n = "{l}toolkit/chrome/global/aboutSupport.dtd"
 
 [[paths]]
     reference = "toolkit/locales/en-US/chrome/global/aboutSupport.properties"
     l10n = "{l}toolkit/chrome/global/aboutSupport.properties"
 
 [[paths]]
+    reference = "toolkit/locales/en-US/crashreporter/*.ftl"
+    l10n = "{l}toolkit/crashreporter/*.ftl"
+
+[[paths]]
     reference = "toolkit/locales/en-US/crashreporter/crashes.dtd"
     l10n = "{l}toolkit/crashreporter/crashes.dtd"
 
 [[paths]]
     reference = "toolkit/locales/en-US/crashreporter/crashes.properties"
     l10n = "{l}toolkit/crashreporter/crashes.properties"
 
 [[paths]]
--- a/mobile/locales/filter.py
+++ b/mobile/locales/filter.py
@@ -24,22 +24,24 @@ def test(mod, path, entity=None):
             "chrome/global/charsetMenu.properties",
             "chrome/global/commonDialogs.properties",
             "chrome/global/intl.properties",
             "chrome/global/intl.css",
             "chrome/search/search.properties",
             "chrome/pluginproblem/pluginproblem.dtd",
             "chrome/global/aboutSupport.dtd",
             "chrome/global/aboutSupport.properties",
-            "crashreporter/crashes.dtd",
-            "crashreporter/crashes.properties",
             "chrome/global/mozilla.dtd",
             "chrome/global/aboutTelemetry.dtd",
             "chrome/global/aboutTelemetry.properties",
-            "chrome/global/aboutWebrtc.properties"):
+            "chrome/global/aboutWebrtc.properties",
+        ):
+            return "error"
+        if re.match(r"crashreporter/[^/]*.ftl", path):
+            # error on crashreporter/*.ftl
             return "error"
         return "ignore"
 
     if mod == "dom":
         # keep this file list in sync with jar.mn
         if path in (
             "chrome/global.dtd",
             "chrome/accessibility/AccessFu.properties",
@@ -47,17 +49,17 @@ def test(mod, path, entity=None):
             "chrome/plugins.properties"):
             return "error"
         return "ignore"
 
     if mod not in ("mobile", "mobile/android"):
         # we only have exceptions for mobile*
         return "error"
     if mod == "mobile/android":
-        if not entity:
+        if entity is None:
             if (re.match(r"mobile-l10n.js", path) or
                 re.match(r"defines.inc", path)):
                 return "ignore"
         if path == "defines.inc":
             if entity == "MOZ_LANGPACK_CONTRIBUTORS":
                 return "ignore"
         return "error"
 
new file mode 100644
--- /dev/null
+++ b/python/l10n/fluent_migrations/bug_1476034_aboutcrashes.py
@@ -0,0 +1,35 @@
+# 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
+
+
+def migrate(ctx):
+    """Bug 1476034 - about:crashes localization migration from DTD to Fluent"""
+
+    ctx.add_transforms(
+        "toolkit/crashreporter/aboutcrashes.ftl",
+        "toolkit/crashreporter/aboutcrashes.ftl",
+        transforms_from(
+"""
+crash-reports-title = { COPY("toolkit/crashreporter/crashes.dtd", "crashReports.title") }
+
+clear-all-reports-label = { COPY("toolkit/crashreporter/crashes.dtd", "clearAllReports.label") }
+delete-confirm-title = { COPY("toolkit/crashreporter/crashes.properties", "deleteconfirm.title") }
+delete-confirm-description = { COPY("toolkit/crashreporter/crashes.properties", "deleteconfirm.description") }
+
+crashes-unsubmitted-label = { COPY("toolkit/crashreporter/crashes.dtd", "crashesUnsubmitted.label") }
+id-heading = { COPY("toolkit/crashreporter/crashes.dtd", "id.heading") }
+date-crashed-heading = { COPY("toolkit/crashreporter/crashes.dtd", "dateCrashed.heading") }
+
+crashes-submitted-label = { COPY("toolkit/crashreporter/crashes.dtd", "crashesSubmitted.label") }
+date-submitted-heading = { COPY("toolkit/crashreporter/crashes.dtd", "dateSubmitted.heading") }
+
+no-reports-label = { COPY("toolkit/crashreporter/crashes.dtd", "noReports.label") }
+no-config-label = { COPY("toolkit/crashreporter/crashes.dtd", "noConfig.label") }
+""")
+    )
--- a/toolkit/crashreporter/content/crashes.css
+++ b/toolkit/crashreporter/content/crashes.css
@@ -14,17 +14,17 @@ table {
   margin: 0 auto;
   padding-bottom: 2em;
 }
 th {
   font-size: 130%;
   text-align: left;
   white-space: nowrap;
 }
-th[chromedir="rtl"] {
+th:-moz-locale-dir(rtl) {
   text-align: right;
 }
 /* name */
 th:first-child {
   padding-inline-end: 2em;
 }
 /* submitted */
 th:last-child {
@@ -46,17 +46,17 @@ td:last-child {
   width: 0;
   padding-inline-start: .5em;
   white-space: nowrap;
 }
 
 #clear-reports {
   float: right;
 }
-#clear-reports[chromedir="rtl"] {
+#clear-reports:-moz-locale-dir(rtl) {
   float: left;
 }
 
 .submitting {
   background-image: url(chrome://global/skin/icons/loading.png);
   background-repeat: no-repeat;
   background-position: right;
   background-size: 16px;
--- a/toolkit/crashreporter/content/crashes.js
+++ b/toolkit/crashreporter/content/crashes.js
@@ -125,22 +125,21 @@ function populateReportList() {
       document.getElementById("unsubmitted").appendChild(row);
     } else {
       document.getElementById("submitted").appendChild(row);
     }
   }
 }
 
 var clearReports = async function() {
-  let bundle = Services.strings.createBundle("chrome://global/locale/crashes.properties");
-
-  if (!Services.
-         prompt.confirm(window,
-                        bundle.GetStringFromName("deleteconfirm.title"),
-                        bundle.GetStringFromName("deleteconfirm.description"))) {
+  const [title, description] = await document.l10n.formatValues([
+    {id: "delete-confirm-title"},
+    {id: "delete-confirm-description"},
+  ]);
+  if (!Services.prompt.confirm(window, title, description)) {
     return;
   }
 
   let cleanupFolder = async function(path, filter) {
     let iterator = new OS.File.DirectoryIterator(path);
     try {
       await iterator.forEach(async function(aEntry) {
         if (!filter || (await filter(aEntry))) {
--- a/toolkit/crashreporter/content/crashes.xhtml
+++ b/toolkit/crashreporter/content/crashes.xhtml
@@ -1,56 +1,51 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- 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/. -->
 
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
-    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
-[
-  <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
-  <!ENTITY % crashesDTD SYSTEM "chrome://global/locale/crashes.dtd">
-  %globalDTD;
-  %crashesDTD;
-]>
+<!DOCTYPE html>
 
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
+<link rel="localization" href="crashreporter/aboutcrashes.ftl"/>
 <link rel="stylesheet" type="text/css" href="chrome://global/content/crashes.css"/>
 <link rel="stylesheet" media="screen, projection" type="text/css"
       href="chrome://global/skin/in-content/common.css"/>
 <script type="application/javascript" src="chrome://global/content/crashes.js"/>
+<script type="text/javascript" src="chrome://global/content/l10n.js"/>
 
-<title>&crashReports.title;</title>
-</head><body dir="&locale.dir;">
-<button chromedir="&locale.dir;" id="clear-reports">&clearAllReports.label;</button>
+<title data-l10n-id="crash-reports-title"></title>
+</head><body>
+<button id="clear-reports" data-l10n-id="clear-all-reports-label"></button>
 <div id="reportList">
   <div id="reportListUnsubmitted">
-    <h1>&crashesUnsubmitted.label;</h1>
+    <h1 data-l10n-id="crashes-unsubmitted-label"></h1>
     <table>
       <thead>
         <tr>
-          <th chromedir="&locale.dir;">&id.heading;</th>
-          <th chromedir="&locale.dir;" colspan="2">&dateCrashed.heading;</th>
+          <th data-l10n-id="id-heading"></th>
+          <th colspan="2" data-l10n-id="date-crashed-heading"></th>
         </tr>
       </thead>
       <tbody id="unsubmitted">
       </tbody>
     </table>
   </div>
   <div id="reportListSubmitted">
-    <h1>&crashesSubmitted.label;</h1>
+    <h1 data-l10n-id="crashes-submitted-label"></h1>
     <table>
       <thead>
         <tr>
-          <th chromedir="&locale.dir;">&id.heading;</th>
-          <th chromedir="&locale.dir;" colspan="2">&dateSubmitted.heading;</th>
+          <th data-l10n-id="id-heading"></th>
+          <th colspan="2" data-l10n-id="date-submitted-heading"></th>
         </tr>
       </thead>
       <tbody id="submitted">
       </tbody>
     </table>
   </div>
 </div>
-<p id="noReports" style="display: none">&noReports.label;</p>
-<p id="noConfig" style="display: none">&noConfig.label;</p>
+<p id="noReports" style="display: none" data-l10n-id="no-reports-label"></p>
+<p id="noConfig" style="display: none" data-l10n-id="no-config-label"></p>
 </body>
 </html>
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
@@ -8,17 +8,17 @@
 <!ENTITY aboutSupport.pageSubtitle "
   This page contains technical information that might be useful when you’re
   trying to solve a problem. If you are looking for answers to common questions
   about &brandShortName;, check out our <a id='supportLink'>support website</a>.
 ">
 
 <!ENTITY aboutSupport.crashes.title "Crash Reports">
 <!-- LOCALIZATION NOTE (aboutSupport.crashes.id):
-This is likely the same like id.heading in crashes.dtd. -->
+This is likely the same like id.heading in aboutcrashes.ftl. -->
 <!ENTITY aboutSupport.crashes.id "Report ID">
 <!ENTITY aboutSupport.crashes.sendDate "Submitted">
 <!ENTITY aboutSupport.crashes.allReports "All Crash Reports">
 <!ENTITY aboutSupport.crashes.noConfig "This application has not been configured to display crash reports.">
 
 <!ENTITY aboutSupport.extensionsTitle "Extensions">
 <!ENTITY aboutSupport.extensionName "Name">
 <!ENTITY aboutSupport.extensionEnabled "Enabled">
new file mode 100644
--- /dev/null
+++ b/toolkit/locales/en-US/crashreporter/aboutcrashes.ftl
@@ -0,0 +1,19 @@
+# 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/-
+
+crash-reports-title = Crash Reports
+
+clear-all-reports-label = Remove All Reports
+delete-confirm-title = Are you sure?
+delete-confirm-description = This will delete all reports and cannot be undone.
+
+crashes-unsubmitted-label = Unsubmitted Crash Reports
+id-heading = Report ID
+date-crashed-heading = Date Crashed
+
+crashes-submitted-label = Submitted Crash Reports
+date-submitted-heading = Date Submitted
+
+no-reports-label = No crash reports have been submitted.
+no-config-label = This application has not been configured to display crash reports. The preference <code>breakpad.reportURL</code> must be set.
deleted file mode 100644
--- a/toolkit/locales/en-US/crashreporter/crashes.dtd
+++ /dev/null
@@ -1,13 +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 crashReports.title         "Crash Reports">
-<!ENTITY crashesUnsubmitted.label   "Unsubmitted Crash Reports">
-<!ENTITY crashesSubmitted.label     "Submitted Crash Reports">
-<!ENTITY id.heading                 "Report ID">
-<!ENTITY dateCrashed.heading        "Date Crashed">
-<!ENTITY dateSubmitted.heading      "Date Submitted">
-<!ENTITY noReports.label            "No crash reports have been submitted.">
-<!ENTITY noConfig.label             "This application has not been configured to display crash reports. The preference <code>breakpad.reportURL</code> must be set.">
-<!ENTITY clearAllReports.label      "Remove All Reports">
deleted file mode 100644
--- a/toolkit/locales/en-US/crashreporter/crashes.properties
+++ /dev/null
@@ -1,7 +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/.
-
-deleteconfirm.title=Are you sure?
-deleteconfirm.description=This will delete all reports and cannot be undone.
-
--- a/toolkit/locales/jar.mn
+++ b/toolkit/locales/jar.mn
@@ -1,14 +1,15 @@
 #filter substitution
 # 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] @AB_CD@.jar:
+  crashreporter                                    (%crashreporter/**/*.ftl)
   toolkit                                          (%toolkit/**/*.ftl)
 
 @AB_CD@.jar:
 % locale global @AB_CD@ %locale/@AB_CD@/global/
   locale/@AB_CD@/global/aboutAbout.dtd                  (%chrome/global/aboutAbout.dtd)
   locale/@AB_CD@/global/aboutReader.properties          (%chrome/global/aboutReader.properties)
   locale/@AB_CD@/global/aboutRights.dtd                 (%chrome/global/aboutRights.dtd)
   locale/@AB_CD@/global/aboutNetworking.dtd             (%chrome/global/aboutNetworking.dtd)
@@ -71,18 +72,16 @@
   locale/@AB_CD@/global/resetProfile.properties         (%chrome/global/resetProfile.properties)
   locale/@AB_CD@/global/dialog.properties               (%chrome/global/dialog.properties)
   locale/@AB_CD@/global/tree.dtd                        (%chrome/global/tree.dtd)
   locale/@AB_CD@/global/textcontext.dtd                 (%chrome/global/textcontext.dtd)
   locale/@AB_CD@/global/videocontrols.dtd               (%chrome/global/videocontrols.dtd)
   locale/@AB_CD@/global/viewSource.properties           (%chrome/global/viewSource.properties)
   locale/@AB_CD@/global/wizard.dtd                      (%chrome/global/wizard.dtd)
   locale/@AB_CD@/global/wizard.properties               (%chrome/global/wizard.properties)
-  locale/@AB_CD@/global/crashes.dtd                     (%crashreporter/crashes.dtd)
-  locale/@AB_CD@/global/crashes.properties              (%crashreporter/crashes.properties)
 % locale global-platform @AB_CD@ %locale/@AB_CD@/global-platform/unix/ os=LikeUnix os=Android
 % locale global-platform @AB_CD@ %locale/@AB_CD@/global-platform/mac/ os=Darwin
 % locale global-platform @AB_CD@ %locale/@AB_CD@/global-platform/win/ os=WINNT
   locale/@AB_CD@/global-platform/mac/platformKeys.properties  (%chrome/global-platform/mac/platformKeys.properties)
   locale/@AB_CD@/global-platform/unix/platformKeys.properties (%chrome/global-platform/unix/platformKeys.properties)
   locale/@AB_CD@/global-platform/win/platformKeys.properties  (%chrome/global-platform/win/platformKeys.properties)
   locale/@AB_CD@/global-platform/mac/intl.properties          (%chrome/global-platform/mac/intl.properties)
   locale/@AB_CD@/global-platform/unix/intl.properties         (%chrome/global-platform/unix/intl.properties)