Bug 1615501 - migrate calendar preferences l10n to Fluent. r=mkmelin
authorAlessandro Castellani <alessandro@thunderbird.net>
Sun, 31 May 2020 22:28:54 +0300
changeset 38405 34815bba0c607f411fa8c4cd1bf5829b0c4a182d
parent 38404 8f5971bfa1c6d0713b0e5a45288c595f76abe882
child 38406 56288941d6185b1a281af725996db62324e8c79c
push id2607
push userclokep@gmail.com
push dateMon, 01 Jun 2020 20:50:20 +0000
treeherdercomm-beta@9d45cd34927b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmkmelin
bugs1615501
Bug 1615501 - migrate calendar preferences l10n to Fluent. r=mkmelin
calendar/base/content/preferences/alarms.inc.xhtml
calendar/base/content/preferences/categories.inc.xhtml
calendar/base/content/preferences/categories.js
calendar/base/content/preferences/editCategory.xhtml
calendar/base/content/preferences/general.inc.xhtml
calendar/base/content/preferences/general.js
calendar/base/content/preferences/views.inc.xhtml
calendar/lightning/content/messenger-overlay-preferences.inc.xhtml
calendar/locales/en-US/calendar/category-dialog.ftl
calendar/locales/en-US/calendar/preferences.ftl
calendar/locales/en-US/chrome/calendar/global.dtd
calendar/locales/en-US/chrome/calendar/preferences/alarms.dtd
calendar/locales/en-US/chrome/calendar/preferences/categories.dtd
calendar/locales/en-US/chrome/calendar/preferences/general.dtd
calendar/locales/en-US/chrome/calendar/preferences/preferences.dtd
calendar/locales/en-US/chrome/calendar/preferences/views.dtd
calendar/locales/jar.mn
mail/components/preferences/preferences.xhtml
python/l10n/tb_fluent_migrations/bug_1615501_preferences_calendar.py
--- a/calendar/base/content/preferences/alarms.inc.xhtml
+++ b/calendar/base/content/preferences/alarms.inc.xhtml
@@ -1,134 +1,123 @@
 # 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/.
     <html:fieldset data-category="paneCalendar">
-        <html:legend>&pref.alarmgoesoff.label;</html:legend>
+        <html:legend data-l10n-id="reminder-legend"></html:legend>
         <vbox id="alarm-sound-box">
             <hbox align="center">
                 <checkbox id="alarmSoundCheckbox"
                           preference="calendar.alarms.playsound"
-                          label="&pref.playasound;"
-                          accesskey="&pref.calendar.alarms.playsound.accessKey;"/>
+                          data-l10n-id="play-checkbox"/>
                 <spacer flex="1"/>
                 <button id="calendar.prefs.alarm.sound.play"
-                        label="&pref.calendar.alarms.sound.play.label;"
-                        accesskey="&pref.calendar.alarms.sound.play.accessKey;"
+                        data-l10n-id="play-alarm-button"
                         oncommand="gAlarmsPane.previewAlarm()"/>
             </hbox>
             <radiogroup id="alarmSoundType"
                         class="indent"
                         orient="vertical"
                         preference="calendar.alarms.soundType"
                         aria-labelledby="alarmSoundCheckbox">
                 <hbox>
                     <radio id="alarmSoundSystem"
                            value="0"
-                           label="&pref.calendar.alarms.sound.useDefault.label;"
-                           accesskey="&pref.calendar.alarms.sound.useDefault.accessKey;"/>
+                           data-l10n-id="default-sound-label"/>
                 </hbox>
                 <hbox>
                     <radio id="alarmSoundCustom"
                            value="1"
-                           label="&pref.calendar.alarms.sound.useCustom.label;"
-                           accesskey="&pref.calendar.alarms.sound.useCustom.accessKey;"/>
+                           data-l10n-id="custom-sound-label"/>
                 </hbox>
             </radiogroup>
             <hbox align="center" class="input-container">
                 <html:input id="alarmSoundFileField"
                             type="text"
                             class="input-filefield indent"
                             readonly="readonly"
                             preference="calendar.alarms.soundURL"
                             preference-editable="true"
                             aria-labelledby="alarmSoundCustom"/>
                 <button id="calendar.prefs.alarm.sound.browse"
-                        label="&pref.calendar.alarms.sound.browse.label;"
-                        accesskey="&pref.calendar.alarms.sound.browse.accessKey;"
+                        data-l10n-id="browse-sound-label"
                         oncommand="gAlarmsPane.browseAlarm()"/>
             </hbox>
         </vbox>
         <hbox align="center" flex="1">
             <checkbox id="alarmshow"
                       preference="calendar.alarms.show"
-                      label="&pref.showalarmbox;"
-                      accesskey="&pref.calendar.alarms.showAlarmBox.accessKey;"/>
+                      data-l10n-id="reminder-dialog-label"/>
         </hbox>
         <hbox align="center" flex="1">
             <checkbox id="missedalarms"
                       preference="calendar.alarms.showmissed"
-                      label="&pref.missedalarms2;"
-                      accesskey="&pref.calendar.alarms.missedAlarms.accessKey;"/>
+                      data-l10n-id="missed-reminder-label"/>
         </hbox>
     </html:fieldset>
 
     <html:fieldset data-category="paneCalendar">
-        <html:legend>&pref.calendar.alarms.defaults.label;</html:legend>
+        <html:legend data-l10n-id="reminder-default-legend"></html:legend>
         <hbox align="center">
-            <label value="&pref.defaultsnoozelength.label;"
-                   accesskey="&pref.defaultsnoozelength.accesskey;"
+            <label data-l10n-id="default-snooze-label"
                    control="defaultsnoozelength"/>
             <html:input id="defaultsnoozelength" type="number" class="size3"
                         min="0"
                         preference="calendar.alarms.defaultsnoozelength"
                         onselect="updateUnitLabelPlural('defaultsnoozelength', 'defaultsnoozelengthunit', 'minutes')"
                         oninput="updateUnitLabelPlural('defaultsnoozelength', 'defaultsnoozelengthunit', 'minutes')"/>
             <label id="defaultsnoozelengthunit"/>
         </hbox>
         <hbox>
             <html:table id="alarm-defaults-table">
                 <html:tr>
                     <html:td>
-                        <label value="&pref.defalarm4events.label;"
-                               accesskey="&pref.defalarm4events.accesskey;"
+                        <label data-l10n-id="event-alarm-label"
                                control="eventdefalarm"/>
                     </html:td>
                     <html:td>
                         <menulist id="eventdefalarm"
                                   crop="none"
                                   preference="calendar.alarms.onforevents">
                             <menupopup id="eventdefalarmpopup">
                                 <menuitem id="eventdefalarmon"
-                                          label="&pref.alarm.on;"
+                                          data-l10n-id="alarm-on-label"
                                           value="1"/>
                                 <menuitem id="eventdefalarmoff"
-                                          label="&pref.alarm.off;"
+                                          data-l10n-id="alarm-off-label"
                                           value="0"
                                           selected="true"/>
                             </menupopup>
                         </menulist>
                     </html:td>
                 </html:tr>
                 <html:tr>
                     <html:td>
-                        <label value="&pref.defalarm4todos.label;"
-                               accesskey="&pref.defalarm4todos.accesskey;"
+                        <label data-l10n-id="task-alarm-label"
                                control="tododefalarm"/>
                     </html:td>
                     <html:td>
                         <menulist id="tododefalarm"
                                   crop="none"
                                   preference="calendar.alarms.onfortodos">
                             <menupopup id="tododefalarmpopup">
                                 <menuitem id="tododefalarmon"
-                                          label="&pref.alarm.on;"
+                                          data-l10n-id="alarm-on-label"
                                           value="1"/>
                                 <menuitem id="tododefalarmoff"
-                                          label="&pref.alarm.off;"
+                                          data-l10n-id="alarm-off-label"
                                           value="0"
                                           selected="true"/>
                             </menupopup>
                         </menulist>
                     </html:td>
                 </html:tr>
                 <html:tr>
                     <html:td>
-                        <label value="&pref.defalarmlen4events.label;"
-                               accesskey="&pref.defalarmlen4events.accesskey;"
+                        <label data-l10n-id="event-alarm-time-label"
                                control="eventdefalarmlen"/>
                     </html:td>
                     <html:td>
                         <hbox class="defaultTimeBox"
                               align="center"
                               flex="1">
                             <html:input id="eventdefalarmlen" type="number" class="size3" min="0"
                                         preference="calendar.alarms.eventalarmlen"
@@ -148,18 +137,17 @@
                                               value="days"/>
                                 </menupopup>
                             </menulist>
                         </hbox>
                     </html:td>
                 </html:tr>
                 <html:tr>
                     <html:td>
-                        <label value="&pref.defalarmlen4todos.label;"
-                               accesskey="&pref.defalarmlen4todos.accesskey;"
+                        <label data-l10n-id="task-alarm-time-label"
                                control="tododefalarmlen"/>
                     </html:td>
                     <html:td>
                         <hbox class="defaultTimeBox"
                               align="center"
                               flex="1">
                             <html:input id="tododefalarmlen" type="number" class="size3" min="0"
                                         preference="calendar.alarms.todoalarmlen"
--- a/calendar/base/content/preferences/categories.inc.xhtml
+++ b/calendar/base/content/preferences/categories.inc.xhtml
@@ -4,21 +4,18 @@
     <html:fieldset data-category="paneCalendar">
         <separator class="thin"/>
         <richlistbox id="categorieslist"
                      flex="1"
                      seltype="multiple"
                      onselect="gCategoriesPane.updateButtons()"
                      ondblclick="gCategoriesPane.listOnDblClick(event)"/>
         <hbox pack="end">
-            <button label="&pref.categories.newButton.label;"
-                    accesskey="&pref.categories.newButton.accesskey;"
+            <button data-l10n-id="new-tag-button"
                     oncommand="gCategoriesPane.addCategory()"/>
             <button id="editCButton"
-                    label="&pref.categories.editButton.label;"
-                    accesskey="&pref.categories.editButton.accesskey;"
+                    data-l10n-id="edit-tag-button"
                     oncommand="gCategoriesPane.editCategory()"/>
             <button id="deleteCButton"
-                    label="&pref.categories.removeButton.label;"
-                    accesskey="&pref.categories.removeButton.accesskey;"
+                    data-l10n-id="delete-tag-button"
                     oncommand="gCategoriesPane.deleteCategory()"/>
         </hbox>
     </html:fieldset>
--- a/calendar/base/content/preferences/categories.js
+++ b/calendar/base/content/preferences/categories.js
@@ -1,17 +1,15 @@
 /* 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/. */
 
 /* exported gCategoriesPane */
 
 /* import-globals-from ../../../lightning/content/messenger-overlay-preferences.js */
-// From categories.xhtml.
-/* globals newTitle, editTitle, overwrite, overwriteTitle, noBlankCategories */
 
 var { cal } = ChromeUtils.import("resource:///modules/calendar/calUtils.jsm");
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { AppConstants } = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 
 Preferences.add({ id: "calendar.categories.names", type: "string" });
 
 var gCategoryList;
@@ -102,38 +100,38 @@ var gCategoriesPane = {
       listbox.appendChild(newListItem);
     }
   },
 
   /**
    * Adds a category, opening the edit category dialog to prompt the user to
    * set up the category.
    */
-  addCategory() {
+  async addCategory() {
     let listbox = document.getElementById("categorieslist");
     listbox.clearSelection();
     this.updateButtons();
     let params = {
-      title: newTitle,
+      title: await document.l10n.formatValue("category-new-label"),
       category: "",
       color: null,
     };
     gSubDialog.open(this.mCategoryDialog, "resizable=no", params);
   },
 
   /**
    * Edits the currently selected category using the edit category dialog.
    */
-  editCategory() {
+  async editCategory() {
     let list = document.getElementById("categorieslist");
     let categoryNameFix = cal.view.formatStringForCSSRule(gCategoryList[list.selectedIndex]);
     let currentColor = categoryPrefBranch.getCharPref(categoryNameFix, "");
 
     let params = {
-      title: editTitle,
+      title: await document.l10n.formatValue("category-edit-label"),
       category: gCategoryList[list.selectedIndex],
       color: currentColor,
     };
     if (list.selectedItem) {
       gSubDialog.open(this.mCategoryDialog, "resizable=no", params);
     }
   },
 
@@ -174,40 +172,43 @@ var gCategoriesPane = {
   },
 
   /**
    * Saves the given category to the preferences.
    *
    * @param categoryName      The name of the category.
    * @param categoryColor     The color of the category
    */
-  saveCategory(categoryName, categoryColor) {
+  async saveCategory(categoryName, categoryColor) {
     let list = document.getElementById("categorieslist");
     // Check to make sure another category doesn't have the same name
     let toBeDeleted = -1;
     for (let i = 0; i < gCategoryList.length; i++) {
       if (i == list.selectedIndex) {
         continue;
       }
 
       if (categoryName.toLowerCase() == gCategoryList[i].toLowerCase()) {
-        if (Services.prompt.confirm(null, overwriteTitle, overwrite)) {
+        let title = await document.l10n.formatValue("category-overwrite-title");
+        let description = await document.l10n.formatValue("category-overwrite");
+        if (Services.prompt.confirm(null, title, description)) {
           if (list.selectedIndex != -1) {
             // Don't delete the old category yet. It will mess up indices.
             toBeDeleted = list.selectedIndex;
           }
           list.selectedIndex = i;
         } else {
           return;
         }
       }
     }
 
     if (categoryName.length == 0) {
-      Services.prompt.alert(null, null, noBlankCategories);
+      let warning = await document.l10n.formatValue("category-blank-warning");
+      Services.prompt.alert(null, null, warning);
       return;
     }
 
     let categoryNameFix = cal.view.formatStringForCSSRule(categoryName);
     if (list.selectedIndex == -1) {
       this.backupData(categoryNameFix);
       gCategoryList.push(categoryName);
       if (categoryColor) {
--- a/calendar/base/content/preferences/editCategory.xhtml
+++ b/calendar/base/content/preferences/editCategory.xhtml
@@ -1,46 +1,45 @@
 <?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/. -->
 
 <?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
 
-<!-- DTD File with all strings specific to the file -->
-<!DOCTYPE window
-[
-  <!ENTITY % dtd1 SYSTEM "chrome://calendar/locale/preferences/categories.dtd" > %dtd1;
-  <!ENTITY % dtd2 SYSTEM "chrome://calendar/locale/global.dtd" > %dtd2;
-]>
+<!DOCTYPE window>
 
 <window id="editCategoryWindow"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         xmlns:html="http://www.w3.org/1999/xhtml"
         onload="editCategoryLoad();">
 
 <dialog id="editCategory"
         buttons="accept,cancel">
 
   <script src="chrome://global/content/globalOverlay.js"/>
   <script src="chrome://global/content/editMenuOverlay.js"/>
   <script src="chrome://calendar/content/preferences/editCategory.js"/>
 
+  <linkset>
+    <html:link rel="localization" href="calendar/category-dialog.ftl"/>
+  </linkset>
+
   <vbox id="dialog-box">
     <label id="categoryNameLabel"
-           value="&pref.categories.name.label;"
+           data-l10n-id="category-name-label"
            control="categoryName"/>
     <html:input id="categoryName"
                 type="text"
                 onchange="categoryNameChanged()"
                 oninput="delay(500, categoryNameChanged)"
                 aria-labelledby="categoryNameLabel"/>
     <hbox id="colorSelectRow">
       <checkbox id="useColor"
-                label="&pref.categories.usecolor.label;"
+                data-l10n-id="category-color-label"
                 oncommand="toggleColor(); categoryNameChanged()"/>
       <html:input id="categoryColor"
                   type="color"
                   style="width: 64px; height: 23px"
                   onclick="clickColor()"
                   onchange="colorPickerChanged()"
                   aria-labelledby="useColor"/>
     </hbox>
--- a/calendar/base/content/preferences/general.inc.xhtml
+++ b/calendar/base/content/preferences/general.inc.xhtml
@@ -1,16 +1,15 @@
 # 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/.
     <html:fieldset data-category="paneCalendar">
-        <html:legend>&pref.calendar.todaypane.agenda.caption;</html:legend>
+        <html:legend data-l10n-id="todaypane-legend"></html:legend>
         <hbox align="center">
-            <label value="&pref.soondays2.label;"
-                   accesskey="&pref.soondays2.accesskey;"
+            <label data-l10n-id="soon-label"
                    control="soondays-menulist"/>
             <menulist id="soondays-menulist"
                       preference="calendar.agendaListbox.soondays">
                 <menupopup id="soondaysdurationpopup">
                     <menuitem value="1"/>
                     <menuitem value="2"/>
                     <menuitem value="3"/>
                     <menuitem value="4"/>
@@ -21,62 +20,61 @@
                     <menuitem value="21"/>
                     <menuitem value="28"/>
                 </menupopup>
             </menulist>
         </hbox>
     </html:fieldset>
 
     <html:fieldset id="defaults-itemtype-groupbox" data-category="paneCalendar">
-        <html:legend>&pref.eventsandtasks.label;</html:legend>
+        <html:legend data-l10n-id="event-task-legend"></html:legend>
         <vbox id="defaults-itemtype-box">
             <hbox id="defaults-event-grid-box" align="center">
                 <label id="default-event-length-label"
-                        value="&pref.default_event_task_length.label;"
-                        accesskey="&pref.default_event_task_length.accesskey;"
-                        control="defaultlength"/>
+                       data-l10n-id="default-length-label"
+                       control="defaultlength"/>
                 <html:input id="defaultlength" type="number"
                             class="size3"
                             min="0"
                             preference="calendar.event.defaultlength"
                             onselect="updateUnitLabelPlural('defaultlength', 'defaultlengthunit', 'minutes')"
                             oninput="updateUnitLabelPlural('defaultlength', 'defaultlengthunit', 'minutes')"/>
                 <label id="defaultlengthunit"/>
             </hbox>
             <html:table id="defaults-task-table">
                 <html:tr id="defaults-task-start-row">
                     <html:td>
                         <label id="default-task-start-label"
-                                value="&read.only.task.start.label;"
-                                control="default_task_start"/>
+                               data-l10n-id="task-start-label"
+                               control="default_task_start"/>
                     </html:td>
                     <html:td>
                         <menulist id="default_task_start"
                                   crop="none"
                                   oncommand="gCalendarGeneralPane.updateDefaultTodoDates()"
                                   preference="calendar.task.defaultstart">
                             <menupopup id="default_task_start_popup">
                                 <menuitem id="default_task_start_none"
-                                          label="&pref.default_task_none.label;"
+                                          data-l10n-id="task-start-1-label"
                                           value="none"
                                           selected="true"/>
                                 <menuitem id="default_task_start_start_of_day"
-                                          label="&pref.default_task_start_of_day.label;"
+                                          data-l10n-id="task-start-2-label"
                                           value="startofday"/>
                                 <menuitem id="default_task_start_tomorrow"
-                                          label="&pref.default_task_tomorrow.label;"
+                                          data-l10n-id="task-start-4-label"
                                           value="tomorrow"/>
                                 <menuitem id="default_task_start_next_week"
-                                          label="&pref.default_task_next_week.label;"
+                                          data-l10n-id="task-start-5-label"
                                           value="nextweek"/>
                                 <menuitem id="default_task_start_offset_current"
-                                          label="&pref.default_task_offset_current.label;"
+                                          data-l10n-id="task-start-6-label"
                                           value="offsetcurrent"/>
                                 <menuitem id="default_task_start_offset_next_hour"
-                                          label="&pref.default_task_offset_next_hour.label;"
+                                          data-l10n-id="task-start-8-label"
                                           value="offsetnexthour"/>
                             </menupopup>
                         </menulist>
                     </html:td>
                     <html:td>
                         <hbox id="default_task_start_offset" align="center">
                             <html:input id="default_task_start_offset_text" type="number"
                                         class="size3"
@@ -98,43 +96,43 @@
                                 </menupopup>
                             </menulist>
                         </hbox>
                     </html:td>
                 </html:tr>
                 <html:tr id="defaults-task-due-row">
                     <html:td>
                         <label id="default-task-due-label"
-                                value="&read.only.task.due.label;"
-                                control="default_task_due"/>
+                               data-l10n-id="task-due-label"
+                               control="default_task_due"/>
                     </html:td>
                     <html:td>
                         <menulist id="default_task_due"
                                   crop="none"
                                   oncommand="gCalendarGeneralPane.updateDefaultTodoDates()"
                                   preference="calendar.task.defaultdue">
                             <menupopup id="default_task_due_popup">
                                 <menuitem id="default_task_due_none"
-                                          label="&pref.default_task_none.label;"
+                                          data-l10n-id="task-start-1-label"
                                           value="none"
                                           selected="true"/>
                                 <menuitem id="default_task_due_end_of_day"
-                                          label="&pref.default_task_end_of_day.label;"
+                                          data-l10n-id="task-start-3-label"
                                           value="endofday"/>
                                 <menuitem id="default_task_due_tomorrow"
-                                          label="&pref.default_task_tomorrow.label;"
+                                          data-l10n-id="task-start-4-label"
                                           value="tomorrow"/>
                                 <menuitem id="default_task_due_next_week"
-                                          label="&pref.default_task_next_week.label;"
+                                          data-l10n-id="task-start-5-label"
                                           value="nextweek"/>
                                 <menuitem id="default_task_due_offset_current"
-                                          label="&pref.default_task_offset_start.label;"
+                                          data-l10n-id="task-start-7-label"
                                           value="offsetcurrent"/>
                                 <menuitem id="default_task_due_offset_next_hour"
-                                          label="&pref.default_task_offset_next_hour.label;"
+                                          data-l10n-id="task-start-8-label"
                                           value="offsetnexthour"/>
                             </menupopup>
                         </menulist>
                     </html:td>
                     <html:td>
                         <hbox id="default_task_due_offset" align="center">
                             <html:input id="default_task_due_offset_text" type="number"
                                         class="size3"
@@ -157,23 +155,21 @@
                             </menulist>
                         </hbox>
                     </html:td>
                 </html:tr>
             </html:table>
         </vbox>
         <hbox align="center">
             <checkbox id="tabedit" pack="end"
-                      label="&pref.editInTab.label;"
-                      accesskey="&pref.editInTab.accesskey;"
+                      data-l10n-id="edit-intab-label"
                       preference="calendar.item.editInTab"/>
         </hbox>
     </html:fieldset>
 
     <html:fieldset id="systemColorsGroupbox" data-category="paneCalendar">
-        <html:legend>&pref.accessibility.label;</html:legend>
+        <html:legend data-l10n-id="accessibility-legend"></html:legend>
         <hbox align="center">
             <checkbox id="systemColors" pack="end"
-                      label="&pref.systemcolors.label;"
-                      accesskey="&pref.systemcolors.accesskey;"
+                      data-l10n-id="accessibility-colors-label"
                       preference="calendar.view.useSystemColors"/>
         </hbox>
     </html:fieldset>
--- a/calendar/base/content/preferences/general.js
+++ b/calendar/base/content/preferences/general.js
@@ -1,16 +1,15 @@
 /* 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/. */
 
 /* exported gCalendarGeneralPane */
 
 /* import-globals-from ../../../lightning/content/messenger-overlay-preferences.js */
-/* globals labelLong, labelShort */ // From general.xhtml.
 
 var { cal } = ChromeUtils.import("resource:///modules/calendar/calUtils.jsm");
 
 Preferences.addAll([
   { id: "calendar.date.format", type: "int" },
   { id: "calendar.event.defaultlength", type: "int" },
   { id: "calendar.timezone.local", type: "string" },
   { id: "calendar.task.defaultstart", type: "string" },
@@ -33,22 +32,27 @@ var gCalendarGeneralPane = {
    * values set in prefs.
    */
   init() {
     let formatter = cal.dtz.formatter;
     let dateFormattedLong = formatter.formatDateLong(cal.dtz.now());
     let dateFormattedShort = formatter.formatDateShort(cal.dtz.now());
 
     // menu items include examples of current date formats.
-    document
-      .getElementById("dateformat-long-menuitem")
-      .setAttribute("label", labelLong + ": " + dateFormattedLong);
-    document
-      .getElementById("dateformat-short-menuitem")
-      .setAttribute("label", labelShort + ": " + dateFormattedShort);
+    document.l10n.setAttributes(
+      document.getElementById("dateformat-long-menuitem"),
+      "dateformat-long",
+      { date: dateFormattedLong }
+    );
+
+    document.l10n.setAttributes(
+      document.getElementById("dateformat-short-menuitem"),
+      "dateformat-short",
+      { date: dateFormattedShort }
+    );
 
     // deselect and reselect to update visible item title
     updateUnitLabelPlural("defaultlength", "defaultlengthunit", "minutes");
     this.updateDefaultTodoDates();
 
     let tzMenuList = document.getElementById("calendar-timezone-menulist");
     let tzMenuPopup = document.getElementById("calendar-timezone-menupopup");
 
--- a/calendar/base/content/preferences/views.inc.xhtml
+++ b/calendar/base/content/preferences/views.inc.xhtml
@@ -1,142 +1,129 @@
 # 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/.
+
     <html:fieldset data-category="paneCalendar">
         <separator/>
         <hbox align="center">
-          <label value="&pref.dateformat.label;"
-                 accesskey="&pref.dateformat.accesskey;"
+          <label data-l10n-id="dateformat-label"
                  control="dateformat"/>
           <menulist id="dateformat" crop="none"
                     preference="calendar.date.format">
               <menupopup id="dateformatpopup">
                   <menuitem id="dateformat-long-menuitem"
-                            label="&pref.dateformat.long;"
                             value="0"/>
                   <menuitem id="dateformat-short-menuitem"
-                            label="&pref.dateformat.short;"
                             value="1"/>
               </menupopup>
           </menulist>
         </hbox>
         <hbox align="center">
-            <label value="&pref.timezones.caption;"
-                   accesskey="&pref.timezones.accesskey;"
+            <label data-l10n-id="timezone-label"
                    control="calendar-timezone-menulist"/>
             <menulist id="calendar-timezone-menulist"
                       preference="calendar.timezone.local">
                 <menupopup id="calendar-timezone-menupopup"/>
             </menulist>
         </hbox>
         <hbox>
             <hbox align="center" flex="1">
-                <label value="&pref.weekstarts.label;"
-                       accesskey="&pref.weekstarts.accesskey;"
+                <label data-l10n-id="weekstart-label"
                        control="weekstarts"/>
                 <menulist id="weekstarts"
                           preference="calendar.week.start"
                           oncommand="gViewsPane.updateViewWorkDayCheckboxes(this.value)">
                     <menupopup id="weekstartspopup">
-                        <menuitem label="&day.1.name;" value="0"/>
-                        <menuitem label="&day.2.name;" value="1"/>
-                        <menuitem label="&day.3.name;" value="2"/>
-                        <menuitem label="&day.4.name;" value="3"/>
-                        <menuitem label="&day.5.name;" value="4"/>
-                        <menuitem label="&day.6.name;" value="5"/>
-                        <menuitem label="&day.7.name;" value="6"/>
+                        <menuitem data-l10n-id="day-1-name" value="0"/>
+                        <menuitem data-l10n-id="day-2-name" value="1"/>
+                        <menuitem data-l10n-id="day-3-name" value="2"/>
+                        <menuitem data-l10n-id="day-4-name" value="3"/>
+                        <menuitem data-l10n-id="day-5-name" value="4"/>
+                        <menuitem data-l10n-id="day-6-name" value="5"/>
+                        <menuitem data-l10n-id="day-7-name" value="6"/>
                     </menupopup>
                 </menulist>
             </hbox>
         </hbox>
         <hbox align="center" flex="1">
             <checkbox id="weekNumber"
                       crop="end"
-                      label="&pref.calendar.view-minimonth.showweeknumber.label;"
-                      accesskey="&pref.calendar.view-minimonth.showweeknumber.accesskey;"
+                      data-l10n-id="show-weeknumber-label"
                       preference="calendar.view-minimonth.showWeekNumber"/>
         </hbox>
         <separator/>
         <hbox>
             <vbox>
-                <label value="&pref.workweekDays.label;"/>
+                <label data-l10n-id="workdays-label"/>
             </vbox>
             <vbox>
                 <hbox>
                     <checkbox id="dayoff0"
                               class="dayOffCheckbox"
-                              label="&day.1.Ddd;"
-                              accesskey="&day.1.Ddd.accesskey;"
+                              data-l10n-id="day-1-checkbox"
                               orient="vertical"
                               preference="calendar.week.d0sundaysoff"/>
                     <checkbox id="dayoff1"
                               class="dayOffCheckbox"
-                              label="&day.2.Ddd;"
-                              accesskey="&day.2.Ddd.accesskey;"
+                              data-l10n-id="day-2-checkbox"
                               orient="vertical"
                               preference="calendar.week.d1mondaysoff"/>
                     <checkbox id="dayoff2"
                               class="dayOffCheckbox"
-                              label="&day.3.Ddd;"
-                              accesskey="&day.3.Ddd.accesskey;"
+                              data-l10n-id="day-3-checkbox"
                               orient="vertical"
                               preference="calendar.week.d2tuesdaysoff"/>
                     <checkbox id="dayoff3"
                               class="dayOffCheckbox"
-                              label="&day.4.Ddd;"
-                              accesskey="&day.4.Ddd.accesskey;"
+                              data-l10n-id="day-4-checkbox"
                               orient="vertical"
                               preference="calendar.week.d3wednesdaysoff"/>
                     <checkbox id="dayoff4"
                               class="dayOffCheckbox"
-                              label="&day.5.Ddd;"
-                              accesskey="&day.5.Ddd.accesskey;"
+                              data-l10n-id="day-5-checkbox"
                               orient="vertical"
                               preference="calendar.week.d4thursdaysoff"/>
                     <checkbox id="dayoff5"
                               class="dayOffCheckbox"
-                              label="&day.6.Ddd;"
-                              accesskey="&day.6.Ddd.accesskey;"
+                              data-l10n-id="day-6-checkbox"
                               orient="vertical"
                               preference="calendar.week.d5fridaysoff"/>
                     <checkbox id="dayoff6"
                               class="dayOffCheckbox"
-                              label="&day.7.Ddd;"
-                              accesskey="&day.7.Ddd.accesskey;"
+                              data-l10n-id="day-7-checkbox"
                               orient="vertical"
                               preference="calendar.week.d6saturdaysoff"/>
                 </hbox>
             </vbox>
         </hbox>
     </html:fieldset>
 
     <html:fieldset data-category="paneCalendar">
-        <html:legend>&pref.calendar.view.dayandweekviews.caption;</html:legend>
+        <html:legend data-l10n-id="dayweek-legend"></html:legend>
         <html:table id="dayAndWeekViewsTable">
             <html:tr>
                 <html:th>
-                   <label value="&pref.calendar.view.visiblehours.label;"
-                           accesskey="&pref.calendar.view.visiblehours.accesskey;"
-                           control="visiblehours"/>
+                   <label data-l10n-id="visible-hours-label"
+                          control="visiblehours"/>
                 </html:th>
                 <html:td>
                     <hbox align="center">
                     <menulist id="visiblehours"
                               preference="calendar.view.visiblehours">
                         <menupopup id="visiblehourspopup">
-                            <menuitem label="1"  value="1"/>
-                            <menuitem label="2"  value="2"/>
-                            <menuitem label="3"  value="3"/>
-                            <menuitem label="4"  value="4"/>
-                            <menuitem label="5"  value="5"/>
-                            <menuitem label="6"  value="6"/>
-                            <menuitem label="7"  value="7"/>
-                            <menuitem label="8"  value="8"/>
-                            <menuitem label="9"  value="9"/>
+                            <menuitem label="1" value="1"/>
+                            <menuitem label="2" value="2"/>
+                            <menuitem label="3" value="3"/>
+                            <menuitem label="4" value="4"/>
+                            <menuitem label="5" value="5"/>
+                            <menuitem label="6" value="6"/>
+                            <menuitem label="7" value="7"/>
+                            <menuitem label="8" value="8"/>
+                            <menuitem label="9" value="9"/>
                             <menuitem label="10" value="10"/>
                             <menuitem label="11" value="11"/>
                             <menuitem label="12" value="12"/>
                             <menuitem label="13" value="13"/>
                             <menuitem label="14" value="14"/>
                             <menuitem label="15" value="15"/>
                             <menuitem label="16" value="16"/>
                             <menuitem label="17" value="17"/>
@@ -144,129 +131,125 @@
                             <menuitem label="19" value="19"/>
                             <menuitem label="20" value="20"/>
                             <menuitem label="21" value="21"/>
                             <menuitem label="22" value="22"/>
                             <menuitem label="23" value="23"/>
                             <menuitem label="24" value="24"/>
                         </menupopup>
                     </menulist>
-                    <label value="&pref.calendar.view.visiblehoursend.label;"/>
+                    <label data-l10n-id="visible-hours-end-label"/>
                     </hbox>
                 </html:td>
             </html:tr>
             <html:tr>
                 <html:th>
-                    <label value="&pref.calendar.view.daystart.label;"
-                           accesskey="&pref.calendar.view.daystart.accesskey;"
+                    <label data-l10n-id="day-start-label"
                            control="daystarthour"/>
                 </html:th>
                 <html:td>
                     <menulist id="daystarthour"
                               oncommand="gViewsPane.updateViewEndMenu(this.value);"
                               preference="calendar.view.daystarthour">
                         <menupopup id="daystarthourpopup">
-                            <menuitem id="timeStart0" label="&time.midnight;" value="0"/>
-                            <menuitem id="timeStart1"                         value="1"/>
-                            <menuitem id="timeStart2"                         value="2"/>
-                            <menuitem id="timeStart3"                         value="3"/>
-                            <menuitem id="timeStart4"                         value="4"/>
-                            <menuitem id="timeStart5"                         value="5"/>
-                            <menuitem id="timeStart6"                         value="6"/>
-                            <menuitem id="timeStart7"                         value="7"/>
-                            <menuitem id="timeStart8"                         value="8"/>
-                            <menuitem id="timeStart9"                         value="9"/>
-                            <menuitem id="timeStart10"                        value="10"/>
-                            <menuitem id="timeStart11"                        value="11"/>
-                            <menuitem id="timeStart12" label="&time.noon;"    value="12"/>
-                            <menuitem id="timeStart13"                        value="13"/>
-                            <menuitem id="timeStart14"                        value="14"/>
-                            <menuitem id="timeStart15"                        value="15"/>
-                            <menuitem id="timeStart16"                        value="16"/>
-                            <menuitem id="timeStart17"                        value="17"/>
-                            <menuitem id="timeStart18"                        value="18"/>
-                            <menuitem id="timeStart19"                        value="19"/>
-                            <menuitem id="timeStart20"                        value="20"/>
-                            <menuitem id="timeStart21"                        value="21"/>
-                            <menuitem id="timeStart22"                        value="22"/>
-                            <menuitem id="timeStart23"                        value="23"/>
+                            <menuitem id="timeStart0" value="0" data-l10n-id="midnight-label"/>
+                            <menuitem id="timeStart1" value="1"/>
+                            <menuitem id="timeStart2" value="2"/>
+                            <menuitem id="timeStart3" value="3"/>
+                            <menuitem id="timeStart4" value="4"/>
+                            <menuitem id="timeStart5" value="5"/>
+                            <menuitem id="timeStart6" value="6"/>
+                            <menuitem id="timeStart7" value="7"/>
+                            <menuitem id="timeStart8" value="8"/>
+                            <menuitem id="timeStart9" value="9"/>
+                            <menuitem id="timeStart10" value="10"/>
+                            <menuitem id="timeStart11" value="11"/>
+                            <menuitem id="timeStart12" value="12" data-l10n-id="noon-label"/>
+                            <menuitem id="timeStart13" value="13"/>
+                            <menuitem id="timeStart14" value="14"/>
+                            <menuitem id="timeStart15" value="15"/>
+                            <menuitem id="timeStart16" value="16"/>
+                            <menuitem id="timeStart17" value="17"/>
+                            <menuitem id="timeStart18" value="18"/>
+                            <menuitem id="timeStart19" value="19"/>
+                            <menuitem id="timeStart20" value="20"/>
+                            <menuitem id="timeStart21" value="21"/>
+                            <menuitem id="timeStart22" value="22"/>
+                            <menuitem id="timeStart23" value="23"/>
                         </menupopup>
                     </menulist>
                 </html:td>
             </html:tr>
             <html:tr>
                 <html:th>
-                    <label value="&pref.calendar.view.dayend.label;"
-                           accesskey="&pref.calendar.view.dayend.accesskey;"
+                    <label data-l10n-id="day-end-label"
                            control="dayendhour"/>
                 </html:th>
                 <html:td>
                     <menulist id="dayendhour"
                               oncommand="gViewsPane.updateViewStartMenu(this.value);"
                               preference="calendar.view.dayendhour">
                         <menupopup id="dayendhourpopup">
-                            <menuitem id="timeEnd1"                          value="1"/>
-                            <menuitem id="timeEnd2"                          value="2"/>
-                            <menuitem id="timeEnd3"                          value="3"/>
-                            <menuitem id="timeEnd4"                          value="4"/>
-                            <menuitem id="timeEnd5"                          value="5"/>
-                            <menuitem id="timeEnd6"                          value="6"/>
-                            <menuitem id="timeEnd7"                          value="7"/>
-                            <menuitem id="timeEnd8"                          value="8"/>
-                            <menuitem id="timeEnd9"                          value="9"/>
-                            <menuitem id="timeEnd10"                         value="10"/>
-                            <menuitem id="timeEnd11"                         value="11"/>
-                            <menuitem id="timeEnd12" label="&time.noon;"     value="12"/>
-                            <menuitem id="timeEnd13"                         value="13"/>
-                            <menuitem id="timeEnd14"                         value="14"/>
-                            <menuitem id="timeEnd15"                         value="15"/>
-                            <menuitem id="timeEnd16"                         value="16"/>
-                            <menuitem id="timeEnd17"                         value="17"/>
-                            <menuitem id="timeEnd18"                         value="18"/>
-                            <menuitem id="timeEnd19"                         value="19"/>
-                            <menuitem id="timeEnd20"                         value="20"/>
-                            <menuitem id="timeEnd21"                         value="21"/>
-                            <menuitem id="timeEnd22"                         value="22"/>
-                            <menuitem id="timeEnd23"                         value="23"/>
-                            <menuitem id="timeEnd24" label="&time.midnight;" value="24"/>
+                            <menuitem id="timeEnd1" value="1"/>
+                            <menuitem id="timeEnd2" value="2"/>
+                            <menuitem id="timeEnd3" value="3"/>
+                            <menuitem id="timeEnd4" value="4"/>
+                            <menuitem id="timeEnd5" value="5"/>
+                            <menuitem id="timeEnd6" value="6"/>
+                            <menuitem id="timeEnd7" value="7"/>
+                            <menuitem id="timeEnd8" value="8"/>
+                            <menuitem id="timeEnd9" value="9"/>
+                            <menuitem id="timeEnd10" value="10"/>
+                            <menuitem id="timeEnd11" value="11"/>
+                            <menuitem id="timeEnd12" value="12" data-l10n-id="noon-label"/>
+                            <menuitem id="timeEnd13" value="13"/>
+                            <menuitem id="timeEnd14" value="14"/>
+                            <menuitem id="timeEnd15" value="15"/>
+                            <menuitem id="timeEnd16" value="16"/>
+                            <menuitem id="timeEnd17" value="17"/>
+                            <menuitem id="timeEnd18" value="18"/>
+                            <menuitem id="timeEnd19" value="19"/>
+                            <menuitem id="timeEnd20" value="20"/>
+                            <menuitem id="timeEnd21" value="21"/>
+                            <menuitem id="timeEnd22" value="22"/>
+                            <menuitem id="timeEnd23" value="23"/>
+                            <menuitem id="timeEnd24" value="24" data-l10n-id="midnight-label"/>
                         </menupopup>
                     </menulist>
                 </html:td>
             </html:tr>
         </html:table>
         <checkbox id="showLocation" pack="end"
-                  label="&pref.showlocation.label;"
+                  data-l10n-id="location-checkbox"
                   preference="calendar.view.showLocation"/>
         <spacer/>
     </html:fieldset>
 
     <html:fieldset id="viewsMultiweekGroupbox" data-category="paneCalendar">
-        <html:legend>&pref.calendar.view.multiweekview.caption;</html:legend>
+        <html:legend data-l10n-id="multiweek-legend"></html:legend>
         <hbox align="center">
-            <label value="&pref.numberofweeks.label;"
-                   accesskey="&pref.numberofweeks.accesskey;"
+            <label data-l10n-id="number-of-weeks-label"
                    control="viewsMultiweekTotalWeeks"/>
             <menulist id="viewsMultiweekTotalWeeks"
                       preference="calendar.weeks.inview">
                 <menupopup>
-                    <menuitem label="&pref.numberofweeks.1;" value="1"/>
-                    <menuitem label="&pref.numberofweeks.2;" value="2"/>
-                    <menuitem label="&pref.numberofweeks.3;" value="3"/>
-                    <menuitem label="&pref.numberofweeks.4;" value="4"/>
-                    <menuitem label="&pref.numberofweeks.5;" value="5"/>
-                    <menuitem label="&pref.numberofweeks.6;" value="6"/>
+                    <menuitem data-l10n-id="week-1-label" value="1"/>
+                    <menuitem data-l10n-id="week-2-label" value="2"/>
+                    <menuitem data-l10n-id="week-3-label" value="3"/>
+                    <menuitem data-l10n-id="week-4-label" value="4"/>
+                    <menuitem data-l10n-id="week-5-label" value="5"/>
+                    <menuitem data-l10n-id="week-6-label" value="6"/>
                 </menupopup>
             </menulist>
         </hbox>
         <hbox align="center" id="previousWeeksBox">
-            <label value="&pref.numberofpreviousweeks.label;"
-                   accesskey="&pref.numberofpreviousweeks.accesskey;"
+            <label data-l10n-id="previous-weeks-label"
                    control="viewsMultiweekPreviousWeeks"/>
             <menulist id="viewsMultiweekPreviousWeeks"
                       preference="calendar.previousweeks.inview">
                 <menupopup>
-                    <menuitem label="&pref.numberofweeks.0;" value="0"/>
-                    <menuitem label="&pref.numberofweeks.1;" value="1"/>
-                    <menuitem label="&pref.numberofweeks.2;" value="2"/>
+                    <menuitem data-l10n-id="week-0-label" value="0"/>
+                    <menuitem data-l10n-id="week-1-label" value="1"/>
+                    <menuitem data-l10n-id="week-2-label" value="2"/>
                 </menupopup>
             </menulist>
         </hbox>
     </html:fieldset>
--- a/calendar/lightning/content/messenger-overlay-preferences.inc.xhtml
+++ b/calendar/lightning/content/messenger-overlay-preferences.inc.xhtml
@@ -1,43 +1,42 @@
 # 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/.
 
 # This file requires the following localization files:
 # chrome://lightning/locale/lightning.dtd
-# chrome://calendar/locale/preferences/preferences.dtd
-# chrome://calendar/locale/preferences/general.dtd
 # chrome://calendar/locale/global.dtd
 # chrome://calendar/locale/calendar-event-dialog.dtd
-# chrome://calendar/locale/preferences/alarms.dtd
-# chrome://calendar/locale/preferences/categories.dtd
-# chrome://calendar/locale/preferences/views.dtd
 
   <prefpane id="paneLightning"
             flex="1"
             insertbefore="paneAdvanced">
 
+    <linkset>
+      <html:link rel="localization" href="calendar/preferences.ftl"/>
+    </linkset>
+
     <hbox id="calendarPaneCategory"
           class="subcategory"
           data-category="paneCalendar">
-      <html:h1>&panelHeader.title;</html:h1>
+      <html:h1 data-l10n-id="calendar-title"></html:h1>
     </hbox>
 
 #include ../../base/content/preferences/views.inc.xhtml
 #include ../../base/content/preferences/general.inc.xhtml
 
     <hbox id="chatPaneCategory"
           class="subcategory"
           data-category="paneCalendar">
-      <html:h1>&panelReminder.title;</html:h1>
+      <html:h1 data-l10n-id="calendar-title-reminder"></html:h1>
     </hbox>
 
 #include ../../base/content/preferences/alarms.inc.xhtml
 
     <hbox id="chatPaneCategory"
           class="subcategory"
           data-category="paneCalendar">
-      <html:h1>&panelCategory.title;</html:h1>
+      <html:h1 data-l10n-id="calendar-title-category"></html:h1>
     </hbox>
 
 #include ../../base/content/preferences/categories.inc.xhtml
   </prefpane>
new file mode 100644
--- /dev/null
+++ b/calendar/locales/en-US/calendar/category-dialog.ftl
@@ -0,0 +1,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/.
+
+category-name-label = Name
+
+category-color-label =
+    .label = Use Color
new file mode 100644
--- /dev/null
+++ b/calendar/locales/en-US/calendar/preferences.ftl
@@ -0,0 +1,230 @@
+# 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/.
+
+calendar-title = Calendar
+calendar-title-reminder = Reminders
+calendar-title-category = Categories
+
+dateformat-label =
+    .value = Date Text Format:
+    .accesskey = D
+
+#   $date (String) - the formatted example date
+dateformat-long =
+    .label = Long: { $date }
+
+#   $date (String) - the formatted example date
+dateformat-short =
+    .label = Short: { $date }
+
+timezone-label =
+    .value = Timezone:
+
+weekstart-label =
+    .value = Start the week on:
+    .accesskey = r
+
+day-1-name =
+    .label = Sunday
+day-2-name =
+    .label = Monday
+day-3-name =
+    .label = Tuesday
+day-4-name =
+    .label = Wednesday
+day-5-name =
+    .label = Thursday
+day-6-name =
+    .label = Friday
+day-7-name =
+    .label = Saturday
+
+show-weeknumber-label =
+    .label = Show week number in views and minimonth
+    .accesskey = n
+
+workdays-label =
+    .value = Workweek days:
+
+day-1-checkbox =
+    .label = Sun
+    .accesskey = S
+day-2-checkbox =
+    .label = Mon
+    .accesskey = M
+day-3-checkbox =
+    .label = Tue
+    .accesskey = T
+day-4-checkbox =
+    .label = Wed
+    .accesskey = W
+day-5-checkbox =
+    .label = Thu
+    .accesskey = h
+day-6-checkbox =
+    .label = Fri
+    .accesskey = F
+day-7-checkbox =
+    .label = Sat
+    .accesskey = a
+
+dayweek-legend = Day and Week Views
+
+visible-hours-label =
+    .value = Show:
+    .accesskey = o
+
+visible-hours-end-label =
+    .value = hours at a time
+
+day-start-label =
+    .value = Day starts at:
+    .accesskey = D
+
+day-end-label =
+    .value = Day ends at:
+    .accesskey = y
+
+midnight-label =
+    .label = Midnight
+noon-label =
+    .label = Noon
+
+location-checkbox =
+    .label = Show location
+    .accesskey = L
+
+multiweek-legend = Multiweek View
+
+number-of-weeks-label =
+    .value = Number of weeks to show (including previous weeks):
+    .accesskey = e
+
+week-0-label =
+    .label = none
+week-1-label =
+    .label = 1 week
+week-2-label =
+    .label = 2 weeks
+week-3-label =
+    .label = 3 weeks
+week-4-label =
+    .label = 4 weeks
+week-5-label =
+    .label = 5 weeks
+week-6-label =
+    .label = 6 weeks
+
+previous-weeks-label =
+    .value = Previous weeks to show:
+    .accesskey = P
+
+todaypane-legend = Today Pane
+
+# Note: "Upcoming" is the name of a section and the translation must match the
+# translation of that section name (calendar.upcoming.button.label). Also,
+# it should be upper case (as a proper name) if the target language permits.
+soon-label =
+    .value = The Upcoming section shows:
+    .accesskey = U
+
+event-task-legend = Events and Tasks
+
+default-length-label =
+    .value = Default Event and Task Length:
+    .accesskey = E
+
+task-start-label =
+    .value = Start Date:
+
+task-start-1-label =
+    .label = None
+task-start-2-label =
+    .label = Start of Day
+task-start-3-label =
+    .label = End of Day
+task-start-4-label =
+    .label = Tomorrow
+task-start-5-label =
+    .label = Next Week
+task-start-6-label =
+    .label = Relative to Current Time
+task-start-7-label =
+    .label = Relative to Start
+task-start-8-label =
+    .label = Relative to Next Hour
+
+task-due-label =
+    .value = Due Date:
+
+edit-intab-label =
+    .label = Edit events and tasks in a tab instead of in a dialog window.
+    .accesskey = t
+
+accessibility-legend = Accessibility
+
+accessibility-colors-label =
+    .label = Optimize colors for accessibility
+    .accesskey = c
+
+reminder-legend = When a Reminder is Due:
+
+play-checkbox =
+    .label = Play a sound
+    .accesskey = s
+
+play-alarm-button =
+    .label = Play
+    .accesskey = P
+
+default-sound-label =
+    .label = Use default sound
+    .accesskey = d
+
+custom-sound-label =
+    .label = Use the following sound file
+    .accesskey = U
+
+reminder-dialog-label =
+    .label = Show the reminder dialog
+    .accesskey = x
+
+missed-reminder-label =
+    .label = Show missed reminders for writable calendars
+    .accesskey = m
+
+reminder-default-legend = Reminder Defaults
+
+default-snooze-label =
+    .value = Default Snooze Length:
+    .accesskey = S
+
+event-alarm-label =
+    .value = Default reminder setting for events:
+    .accesskey = e
+
+alarm-on-label =
+    .label = On
+alarm-off-label =
+    .label = Off
+
+task-alarm-label =
+    .value = Default reminder setting for tasks:
+    .accesskey = a
+
+event-alarm-time-label =
+    .value = Default time a reminder is set before an event:
+    .accesskey = u
+
+task-alarm-time-label =
+    .value = Default time a reminder is set before a task:
+    .accesskey = o
+
+category-new-label = New Category
+
+category-edit-label = Edit Category
+
+category-overwrite-title = Warning: Duplicate name
+category-overwrite = A category already exists with that name. Do you want to overwrite it?
+category-blank-warning = You must enter a category name.
--- a/calendar/locales/en-US/chrome/calendar/global.dtd
+++ b/calendar/locales/en-US/chrome/calendar/global.dtd
@@ -1,41 +1,12 @@
 <!-- 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 time.midnight "Midnight" >
-<!ENTITY time.noon "Noon" >
-
-<!-- Day Names -->
-<!-- LOCALIZATION NOTE : Accesskeys for day.1.Ddd to day.7.Ddd are currently
-     only used in Preferences > Views > Workweek groupbox -->
-<!ENTITY day.1.Ddd "Sun" >
-<!ENTITY day.1.Ddd.accesskey "S">
-<!ENTITY day.2.Ddd "Mon" >
-<!ENTITY day.2.Ddd.accesskey "M">
-<!ENTITY day.3.Ddd "Tue" >
-<!ENTITY day.3.Ddd.accesskey "T">
-<!ENTITY day.4.Ddd "Wed" >
-<!ENTITY day.4.Ddd.accesskey "W">
-<!ENTITY day.5.Ddd "Thu" >
-<!ENTITY day.5.Ddd.accesskey "h">
-<!ENTITY day.6.Ddd "Fri" >
-<!ENTITY day.6.Ddd.accesskey "F">
-<!ENTITY day.7.Ddd "Sat" >
-<!ENTITY day.7.Ddd.accesskey "a">
-
-<!ENTITY day.1.name "Sunday" >
-<!ENTITY day.2.name "Monday" >
-<!ENTITY day.3.name "Tuesday" >
-<!ENTITY day.4.name "Wednesday" >
-<!ENTITY day.5.name "Thursday" >
-<!ENTITY day.6.name "Friday" >
-<!ENTITY day.7.name "Saturday" >
-
 <!ENTITY month.1.name "January" >
 <!ENTITY month.2.name "February" >
 <!ENTITY month.3.name "March" >
 <!ENTITY month.4.name "April" >
 <!ENTITY month.5.name "May" >
 <!ENTITY month.6.name "June" >
 <!ENTITY month.7.name "July" >
 <!ENTITY month.8.name "August" >
deleted file mode 100644
--- a/calendar/locales/en-US/chrome/calendar/preferences/alarms.dtd
+++ /dev/null
@@ -1,38 +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/. -->
-
-<!-- WARNING! This file contains UTF-8 encoded characters!
-   - If this ==> … <== doesn't look like an ellipsis (three dots in a row),
-   - your editor isn't using UTF-8 encoding and may munge up the document!
-  -->
-
-<!ENTITY pref.alarmgoesoff.label "When a Reminder is Due:">
-<!ENTITY pref.playasound "Play a sound">
-<!ENTITY pref.calendar.alarms.playsound.accessKey "s">
-<!ENTITY pref.calendar.alarms.sound.useDefault.label "Use default sound">
-<!ENTITY pref.calendar.alarms.sound.useDefault.accessKey "d">
-<!ENTITY pref.calendar.alarms.sound.useCustom.label "Use the following sound file">
-<!ENTITY pref.calendar.alarms.sound.useCustom.accessKey "U">
-<!ENTITY pref.calendar.alarms.sound.browse.label "Browse…">
-<!ENTITY pref.calendar.alarms.sound.browse.accessKey "B">
-<!ENTITY pref.calendar.alarms.sound.play.label "Play">
-<!ENTITY pref.calendar.alarms.sound.play.accessKey "P">
-<!ENTITY pref.showalarmbox "Show the reminder dialog">
-<!ENTITY pref.calendar.alarms.showAlarmBox.accessKey "x">
-<!ENTITY pref.missedalarms2 "Show missed reminders for writable calendars">
-<!ENTITY pref.calendar.alarms.missedAlarms.accessKey "m">
-<!ENTITY pref.calendar.alarms.defaults.label "Reminder Defaults">
-<!ENTITY pref.defalarm4events.label "Default reminder setting for events:">
-<!ENTITY pref.defalarm4events.accesskey "e">
-<!ENTITY pref.defalarm4todos.label "Default reminder setting for tasks:">
-<!ENTITY pref.defalarm4todos.accesskey "a">
-<!ENTITY pref.alarm.on "On">
-<!ENTITY pref.alarm.off "Off">
-<!ENTITY pref.defalarmlen4events.label "Default time a reminder is set before an event:">
-<!ENTITY pref.defalarmlen4events.accesskey "u">
-<!ENTITY pref.defalarmlen4todos.label "Default time a reminder is set before a task:">
-<!ENTITY pref.defalarmlen4todos.accesskey "o">
-
-<!ENTITY pref.defaultsnoozelength.label "Default Snooze Length:" >
-<!ENTITY pref.defaultsnoozelength.accesskey "S">
deleted file mode 100644
--- a/calendar/locales/en-US/chrome/calendar/preferences/categories.dtd
+++ /dev/null
@@ -1,24 +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/. -->
-
-<!-- WARNING! This file contains UTF-8 encoded characters!
-   - If this ==> … <== doesn't look like an ellipsis (three dots in a row),
-   - your editor isn't using UTF-8 encoding and may munge up the document!
-  -->
-
-<!ENTITY pref.categories.new.title "New Category">
-<!ENTITY pref.categories.newButton.label "New…">
-<!ENTITY pref.categories.newButton.accesskey "N">
-<!ENTITY pref.categories.edit.title "Edit Category">
-<!ENTITY pref.categories.editButton.label "Edit…">
-<!ENTITY pref.categories.editButton.accesskey "E">
-<!ENTITY pref.categories.removeButton.label "Remove">
-<!ENTITY pref.categories.removeButton.accesskey "R">
-<!ENTITY pref.categories.name.label "Name">
-<!ENTITY pref.categories.color.label "Color">
-<!ENTITY pref.categories.usecolor.label "Use Color">
-<!ENTITY pref.categories.none.label "(none)">
-<!ENTITY pref.categories.overwrite "A category already exists with that name. \n Do you want to overwrite it?">
-<!ENTITY pref.categories.overwrite.title "Warning: Duplicate name">
-<!ENTITY pref.categories.noBlankCategories "You must enter a category name.">
deleted file mode 100644
--- a/calendar/locales/en-US/chrome/calendar/preferences/general.dtd
+++ /dev/null
@@ -1,50 +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/. -->
-
-<!-- WARNING! This file contains UTF-8 encoded characters!
-   - If this ==> … <== doesn't look like an ellipsis (three dots in a row),
-   - your editor isn't using UTF-8 encoding and may munge up the document!
-  -->
-
-<!ENTITY pref.dateformat.label "Date Text Format:" >
-<!ENTITY pref.dateformat.accesskey "D">
-<!ENTITY pref.dateformat.long "Long" >
-<!ENTITY pref.dateformat.short "Short"  >
-
-<!ENTITY pref.timezones.caption "Timezone">
-<!ENTITY pref.timezones.label "Select the closest city in your timezone:">
-<!ENTITY pref.timezones.accesskey "S">
-
-<!ENTITY pref.defaults.label "Default Values for New Items">
-<!ENTITY pref.events.label "Events">
-<!ENTITY pref.tasks.label "Tasks">
-
-<!ENTITY pref.default_event_task_length.label "Default Event and Task Length">
-<!ENTITY pref.default_event_task_length.accesskey "E">
-
-<!ENTITY pref.default_task_none.label "None">
-<!ENTITY pref.default_task_start_of_day.label "Start of Day">
-<!ENTITY pref.default_task_end_of_day.label "End of Day">
-<!ENTITY pref.default_task_tomorrow.label "Tomorrow">
-<!ENTITY pref.default_task_next_week.label "Next Week">
-<!ENTITY pref.default_task_offset_current.label "Relative to Current Time">
-<!ENTITY pref.default_task_offset_start.label "Relative to Start">
-<!ENTITY pref.default_task_offset_next_hour.label "Relative to Next Hour">
-
-<!ENTITY pref.calendar.todaypane.agenda.caption "Today Pane">
-<!-- LOCALIZATION NOTE (pref.soondays2.label):
-     "Upcoming" is the name of a section and the translation must match the
-     translation of that section name (calendar.upcoming.button.label). Also,
-     it should be upper case (as a proper name) if the target language permits.
-  -->
-<!ENTITY pref.soondays2.label "The Upcoming section shows:">
-<!ENTITY pref.soondays2.accesskey "U">
-
-<!ENTITY pref.accessibility.label "Accessibility" >
-<!ENTITY pref.systemcolors.label "Optimize colors for accessibility" >
-<!ENTITY pref.systemcolors.accesskey "c">
-
-<!ENTITY pref.eventsandtasks.label "Events and Tasks" >
-<!ENTITY pref.editInTab.label "Edit events and tasks in a tab instead of in a dialog window." >
-<!ENTITY pref.editInTab.accesskey "t">
deleted file mode 100644
--- a/calendar/locales/en-US/chrome/calendar/preferences/preferences.dtd
+++ /dev/null
@@ -1,11 +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  paneGeneral.title       "General">
-<!ENTITY  paneAlarms.title        "Reminders">
-<!ENTITY  paneCategories.title    "Categories">
-<!ENTITY  paneViews.title         "Views">
-<!ENTITY  panelHeader.title       "Calendar">
-<!ENTITY  panelReminder.title     "Reminders">
-<!ENTITY  panelCategory.title     "Categories">
deleted file mode 100644
--- a/calendar/locales/en-US/chrome/calendar/preferences/views.dtd
+++ /dev/null
@@ -1,39 +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/. -->
-
-<!-- WARNING! This file contains UTF-8 encoded characters!
-   - If this ==> … <== doesn't look like an ellipsis (three dots in a row),
-   - your editor isn't using UTF-8 encoding and may munge up the document!
-  -->
-
-<!ENTITY pref.calendar.view.dayandweekviews.caption "Day and Week Views">
-<!ENTITY pref.calendar.view.multiweekview.caption "Multiweek View">
-
-<!ENTITY pref.weekstarts.label "Start the week on:">
-<!ENTITY pref.weekstarts.accesskey "r">
-<!ENTITY pref.calendar.view-minimonth.showweeknumber.label "Show week number in views and minimonth">
-<!ENTITY pref.calendar.view-minimonth.showweeknumber.accesskey "n">
-<!ENTITY pref.workweekDays.label "Workweek days:">
-
-<!ENTITY pref.calendar.view.daystart.label "Day starts at:">
-<!ENTITY pref.calendar.view.daystart.accesskey "D">
-<!ENTITY pref.calendar.view.dayend.label "Day ends at:">
-<!ENTITY pref.calendar.view.dayend.accesskey "y">
-<!ENTITY pref.calendar.view.visiblehours.label "Show:">
-<!ENTITY pref.calendar.view.visiblehours.accesskey "o">
-<!ENTITY pref.calendar.view.visiblehoursend.label "hours at a time">
-
-<!ENTITY pref.numberofweeks.label "Number of weeks to show (including previous weeks):">
-<!ENTITY pref.numberofweeks.accesskey "e">
-<!ENTITY pref.numberofpreviousweeks.label "Previous weeks to show:">
-<!ENTITY pref.numberofpreviousweeks.accesskey "P">
-<!ENTITY pref.numberofweeks.0 "none">
-<!ENTITY pref.numberofweeks.1 "1 week">
-<!ENTITY pref.numberofweeks.2 "2 weeks">
-<!ENTITY pref.numberofweeks.3 "3 weeks">
-<!ENTITY pref.numberofweeks.4 "4 weeks">
-<!ENTITY pref.numberofweeks.5 "5 weeks">
-<!ENTITY pref.numberofweeks.6 "6 weeks">
-<!ENTITY pref.showlocation.label "Show location">
-<!ENTITY pref.showlocation.accesskey "L">
--- a/calendar/locales/jar.mn
+++ b/calendar/locales/jar.mn
@@ -24,21 +24,16 @@
     locale/@AB_CD@/calendar/calendarCreation.properties                  (%chrome/calendar/calendarCreation.properties)
     locale/@AB_CD@/calendar/categories.properties                        (%chrome/calendar/categories.properties)
     locale/@AB_CD@/calendar/dateFormat.properties                        (%chrome/calendar/dateFormat.properties)
     locale/@AB_CD@/calendar/dialogs/calendar-event-dialog-reminder.dtd   (%chrome/calendar/dialogs/calendar-event-dialog-reminder.dtd)
     locale/@AB_CD@/calendar/global.dtd                                   (%chrome/calendar/global.dtd)
     locale/@AB_CD@/calendar/menuOverlay.dtd                              (%chrome/calendar/menuOverlay.dtd)
     locale/@AB_CD@/calendar/migration.dtd                                (%chrome/calendar/migration.dtd)
     locale/@AB_CD@/calendar/migration.properties                         (%chrome/calendar/migration.properties)
-    locale/@AB_CD@/calendar/preferences/alarms.dtd                       (%chrome/calendar/preferences/alarms.dtd)
-    locale/@AB_CD@/calendar/preferences/categories.dtd                   (%chrome/calendar/preferences/categories.dtd)
-    locale/@AB_CD@/calendar/preferences/general.dtd                      (%chrome/calendar/preferences/general.dtd)
-    locale/@AB_CD@/calendar/preferences/preferences.dtd                  (%chrome/calendar/preferences/preferences.dtd)
-    locale/@AB_CD@/calendar/preferences/views.dtd                        (%chrome/calendar/preferences/views.dtd)
     locale/@AB_CD@/calendar/provider-uninstall.dtd                       (%chrome/calendar/provider-uninstall.dtd)
     locale/@AB_CD@/calendar/timezones.properties                         (%chrome/calendar/timezones.properties)
 
 @AB_CD@.jar:
 % locale lightning @AB_CD@ %locale/@AB_CD@/lightning/
     locale/@AB_CD@/lightning/lightning-toolbar.dtd                       (%chrome/lightning/lightning-toolbar.dtd)
     locale/@AB_CD@/lightning/lightning.dtd                               (%chrome/lightning/lightning.dtd)
     locale/@AB_CD@/lightning/lightning.properties                        (%chrome/lightning/lightning.properties)
--- a/mail/components/preferences/preferences.xhtml
+++ b/mail/components/preferences/preferences.xhtml
@@ -35,30 +35,20 @@
 #endif
 #endif
 #ifdef MOZ_UPDATER
 <!ENTITY % aboutDialogDTD SYSTEM "chrome://messenger/locale/aboutDialog.dtd" >
 %aboutDialogDTD;
 #endif
 <!ENTITY % lightningDTD SYSTEM "chrome://lightning/locale/lightning.dtd">
 %lightningDTD;
-<!ENTITY % calendarPreferencesDTD SYSTEM "chrome://calendar/locale/preferences/preferences.dtd">
-%calendarPreferencesDTD;
-<!ENTITY % calendarGeneralDTD SYSTEM "chrome://calendar/locale/preferences/general.dtd">
-%calendarGeneralDTD;
 <!ENTITY % globalDTD SYSTEM "chrome://calendar/locale/global.dtd">
 %globalDTD;
 <!ENTITY % eventDTD SYSTEM "chrome://calendar/locale/calendar-event-dialog.dtd">
 %eventDTD;
-<!ENTITY % alarmsDTD SYSTEM "chrome://calendar/locale/preferences/alarms.dtd">
-%alarmsDTD;
-<!ENTITY % categoriesDTD SYSTEM "chrome://calendar/locale/preferences/categories.dtd">
-%categoriesDTD;
-<!ENTITY % viewsDTD SYSTEM "chrome://calendar/locale/preferences/views.dtd">
-%viewsDTD;
 ]>
 
 <preftab id="MailPreferences" flex="1"
          windowtype="Mail:Preferences"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
          xmlns:xhtml="http://www.w3.org/1999/xhtml"
          xmlns:html="http://www.w3.org/1999/xhtml"
          data-l10n-id="preferences-title">
@@ -181,25 +171,14 @@
 
   <script src="chrome://global/content/globalOverlay.js"/>
   <script src="chrome://communicator/content/contentAreaClick.js"/>
   <script src="chrome://messenger/content/preferences/preferences.js"/>
   <script src="chrome://messenger/content/preferences/subdialogs.js"/>
 
   <script src="chrome://calendar/content/calendar-ui-utils.js"/>
   <script src="chrome://calendar/content/calendar-dialog-utils.js"/>
-  <!-- Get the localized text for use in the JS. -->
-  <script>
-    var labelLong  = "&pref.dateformat.long;";
-    var labelShort = "&pref.dateformat.short;";
-    var noneLabel  = "&pref.categories.none.label;";
-    var newTitle   = "&pref.categories.new.title;";
-    var editTitle  = "&pref.categories.edit.title;";
-    var overwrite  = "&pref.categories.overwrite;";
-    var overwriteTitle = "&pref.categories.overwrite.title;";
-    var noBlankCategories = "&pref.categories.noBlankCategories;";
-  </script>
   <script src="chrome://calendar/content/preferences/general.js"/>
   <script src="chrome://calendar/content/preferences/alarms.js"/>
   <script src="chrome://calendar/content/preferences/categories.js"/>
   <script src="chrome://calendar/content/preferences/views.js"/>
   <script src="chrome://lightning/content/messenger-overlay-preferences.js"/>
 </preftab>
new file mode 100644
--- /dev/null
+++ b/python/l10n/tb_fluent_migrations/bug_1615501_preferences_calendar.py
@@ -0,0 +1,320 @@
+# 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 CONCAT, REPLACE
+from fluent.migrate.helpers import COPY, TERM_REFERENCE
+
+def migrate(ctx):
+    """Bug 1615501 - Fluent migration recipe for Preferences Calendar Tab, part {index}."""
+
+    ctx.add_transforms(
+        "calendar/calendar/preferences.ftl",
+        "calendar/calendar/preferences.ftl",
+        transforms_from(
+"""
+calendar-title = { COPY(from_path, "panelHeader.title") }
+calendar-title-reminder = { COPY(from_path, "panelReminder.title") }
+calendar-title-category = { COPY(from_path, "panelCategory.title") }
+""", from_path="calendar/chrome/calendar/preferences/preferences.dtd"
+        )
+    )
+
+    ctx.add_transforms(
+        "calendar/calendar/preferences.ftl",
+        "calendar/calendar/preferences.ftl",
+        transforms_from(
+"""
+dateformat-label =
+    .value = { COPY(from_path, "pref.dateformat.label") }
+    .accesskey = { COPY(from_path, "pref.dateformat.accesskey") }
+
+#   $date (String) - the formatted example date
+dateformat-long =
+    .label = { COPY(from_path, "pref.dateformat.long") }: { $date }
+
+#   $date (String) - the formatted example date
+dateformat-short =
+    .label = { COPY(from_path, "pref.dateformat.short") }: { $date }
+
+timezone-label =
+    .value = { COPY(from_path, "pref.timezones.caption") }:
+
+todaypane-legend = { COPY(from_path, "pref.calendar.todaypane.agenda.caption") }
+
+soon-label =
+    .value = { COPY(from_path, "pref.soondays2.label") }
+    .accesskey = { COPY(from_path, "pref.soondays2.accesskey") }
+
+event-task-legend = { COPY(from_path, "pref.eventsandtasks.label") }
+
+default-length-label =
+    .value = { COPY(from_path, "pref.default_event_task_length.label") }:
+    .accesskey = { COPY(from_path, "pref.default_event_task_length.accesskey") }
+
+task-start-1-label =
+    .label = { COPY(from_path, "pref.default_task_none.label") }
+task-start-2-label =
+    .label = { COPY(from_path, "pref.default_task_start_of_day.label") }
+task-start-3-label =
+    .label = { COPY(from_path, "pref.default_task_end_of_day.label") }
+task-start-4-label =
+    .label = { COPY(from_path, "pref.default_task_tomorrow.label") }
+task-start-5-label =
+    .label = { COPY(from_path, "pref.default_task_next_week.label") }
+task-start-6-label =
+    .label = { COPY(from_path, "pref.default_task_offset_current.label") }
+task-start-7-label =
+    .label = { COPY(from_path, "pref.default_task_offset_start.label") }
+task-start-8-label =
+    .label = { COPY(from_path, "pref.default_task_offset_next_hour.label") }
+
+edit-intab-label =
+    .label = { COPY(from_path, "pref.editInTab.label") }
+    .accesskey = { COPY(from_path, "pref.editInTab.accesskey") }
+
+accessibility-legend = { COPY(from_path, "pref.accessibility.label") }
+
+accessibility-colors-label =
+    .label = { COPY(from_path, "pref.systemcolors.label") }
+    .accesskey = { COPY(from_path, "pref.systemcolors.accesskey") }
+""", from_path="calendar/chrome/calendar/preferences/general.dtd"
+        )
+    )
+
+    ctx.add_transforms(
+        "calendar/calendar/preferences.ftl",
+        "calendar/calendar/preferences.ftl",
+        transforms_from(
+"""
+weekstart-label =
+    .value = { COPY(from_path, "pref.weekstarts.label") }
+    .accesskey = { COPY(from_path, "pref.weekstarts.accesskey") }
+
+show-weeknumber-label =
+    .label = { COPY(from_path, "pref.calendar.view-minimonth.showweeknumber.label") }
+    .accesskey = { COPY(from_path, "pref.calendar.view-minimonth.showweeknumber.accesskey") }
+
+workdays-label =
+    .value = { COPY(from_path, "pref.workweekDays.label") }
+
+dayweek-legend = { COPY(from_path, "pref.calendar.view.dayandweekviews.caption") }
+
+visible-hours-label =
+    .value = { COPY(from_path, "pref.calendar.view.visiblehours.label") }
+    .accesskey = { COPY(from_path, "pref.calendar.view.visiblehours.accesskey") }
+
+visible-hours-end-label =
+    .value = { COPY(from_path, "pref.calendar.view.visiblehoursend.label") }
+
+day-start-label =
+    .value = { COPY(from_path, "pref.calendar.view.daystart.label") }
+    .accesskey = { COPY(from_path, "pref.calendar.view.daystart.accesskey") }
+
+day-end-label =
+    .value = { COPY(from_path, "pref.calendar.view.dayend.label") }
+    .accesskey = { COPY(from_path, "pref.calendar.view.dayend.accesskey") }
+
+location-checkbox =
+    .label = { COPY(from_path, "pref.showlocation.label") }
+    .accesskey = { COPY(from_path, "pref.showlocation.accesskey") }
+
+multiweek-legend = { COPY(from_path, "pref.calendar.view.multiweekview.caption") }
+
+number-of-weeks-label =
+    .value = { COPY(from_path, "pref.numberofweeks.label") }
+    .accesskey = { COPY(from_path, "pref.numberofweeks.accesskey") }
+
+week-0-label =
+    .label = { COPY(from_path, "pref.numberofweeks.0") }
+week-1-label =
+    .label = { COPY(from_path, "pref.numberofweeks.1") }
+week-2-label =
+    .label = { COPY(from_path, "pref.numberofweeks.2") }
+week-3-label =
+    .label = { COPY(from_path, "pref.numberofweeks.3") }
+week-4-label =
+    .label = { COPY(from_path, "pref.numberofweeks.4") }
+week-5-label =
+    .label = { COPY(from_path, "pref.numberofweeks.5") }
+week-6-label =
+    .label = { COPY(from_path, "pref.numberofweeks.6") }
+
+previous-weeks-label =
+    .value = { COPY(from_path, "pref.numberofpreviousweeks.label") }
+    .accesskey = { COPY(from_path, "pref.numberofpreviousweeks.accesskey") }
+""", from_path="calendar/chrome/calendar/preferences/views.dtd"
+        )
+    )
+
+    ctx.add_transforms(
+        "calendar/calendar/preferences.ftl",
+        "calendar/calendar/preferences.ftl",
+        transforms_from(
+"""
+day-1-name =
+    .label = { COPY(from_path, "day.1.name") }
+day-2-name =
+    .label = { COPY(from_path, "day.2.name") }
+day-3-name =
+    .label = { COPY(from_path, "day.3.name") }
+day-4-name =
+    .label = { COPY(from_path, "day.4.name") }
+day-5-name =
+    .label = { COPY(from_path, "day.5.name") }
+day-6-name =
+    .label = { COPY(from_path, "day.6.name") }
+day-7-name =
+    .label = { COPY(from_path, "day.7.name") }
+
+day-1-checkbox =
+    .label = { COPY(from_path, "day.1.Ddd") }
+    .accesskey = { COPY(from_path, "day.1.Ddd.accesskey") }
+day-2-checkbox =
+    .label = { COPY(from_path, "day.2.Ddd") }
+    .accesskey = { COPY(from_path, "day.2.Ddd.accesskey") }
+day-3-checkbox =
+    .label = { COPY(from_path, "day.3.Ddd") }
+    .accesskey = { COPY(from_path, "day.3.Ddd.accesskey") }
+day-4-checkbox =
+    .label = { COPY(from_path, "day.4.Ddd") }
+    .accesskey = { COPY(from_path, "day.4.Ddd.accesskey") }
+day-5-checkbox =
+    .label = { COPY(from_path, "day.5.Ddd") }
+    .accesskey = { COPY(from_path, "day.5.Ddd.accesskey") }
+day-6-checkbox =
+    .label = { COPY(from_path, "day.6.Ddd") }
+    .accesskey = { COPY(from_path, "day.6.Ddd.accesskey") }
+day-7-checkbox =
+    .label = { COPY(from_path, "day.7.Ddd") }
+    .accesskey = { COPY(from_path, "day.7.Ddd.accesskey") }
+
+midnight-label =
+    .label = { COPY(from_path, "time.midnight") }
+noon-label =
+    .label = { COPY(from_path, "time.noon") }
+""", from_path="calendar/chrome/calendar/global.dtd"
+        )
+    )
+
+    ctx.add_transforms(
+        "calendar/calendar/preferences.ftl",
+        "calendar/calendar/preferences.ftl",
+        transforms_from(
+"""
+task-start-label =
+    .value = { COPY(from_path, "read.only.task.start.label") }
+
+task-due-label =
+    .value = { COPY(from_path, "read.only.task.due.label") }
+""", from_path="calendar/chrome/calendar/calendar-event-dialog.dtd"
+        )
+    )
+
+    ctx.add_transforms(
+        "calendar/calendar/preferences.ftl",
+        "calendar/calendar/preferences.ftl",
+        transforms_from(
+"""
+reminder-legend = { COPY(from_path, "pref.alarmgoesoff.label") }
+
+play-checkbox =
+    .label = { COPY(from_path, "pref.playasound") }
+    .accesskey = { COPY(from_path, "pref.calendar.alarms.playsound.accessKey") }
+
+play-alarm-button =
+    .label = { COPY(from_path, "pref.calendar.alarms.sound.play.label") }
+    .accesskey = { COPY(from_path, "pref.calendar.alarms.sound.play.accessKey") }
+
+default-sound-label =
+    .label = { COPY(from_path, "pref.calendar.alarms.sound.useDefault.label") }
+    .accesskey = { COPY(from_path, "pref.calendar.alarms.sound.useDefault.accessKey") }
+
+custom-sound-label =
+    .label = { COPY(from_path, "pref.calendar.alarms.sound.useCustom.label") }
+    .accesskey = { COPY(from_path, "pref.calendar.alarms.sound.useCustom.accessKey") }
+
+reminder-dialog-label =
+    .label = { COPY(from_path, "pref.showalarmbox") }
+    .accesskey = { COPY(from_path, "pref.calendar.alarms.showAlarmBox.accessKey") }
+
+missed-reminder-label =
+    .label = { COPY(from_path, "pref.missedalarms2") }
+    .accesskey = { COPY(from_path, "pref.calendar.alarms.missedAlarms.accessKey") }
+
+reminder-default-legend = { COPY(from_path, "pref.calendar.alarms.defaults.label") }
+
+default-snooze-label =
+    .value = { COPY(from_path, "pref.defaultsnoozelength.label") }
+    .accesskey = { COPY(from_path, "pref.defaultsnoozelength.accesskey") }
+
+event-alarm-label =
+    .value = { COPY(from_path, "pref.defalarm4events.label") }
+    .accesskey = { COPY(from_path, "pref.defalarm4events.accesskey") }
+
+alarm-on-label =
+    .label = { COPY(from_path, "pref.alarm.on") }
+alarm-off-label =
+    .label = { COPY(from_path, "pref.alarm.off") }
+
+task-alarm-label =
+    .value = { COPY(from_path, "pref.defalarm4todos.label") }
+    .accesskey = { COPY(from_path, "pref.defalarm4todos.accesskey") }
+
+event-alarm-time-label =
+    .value = { COPY(from_path, "pref.defalarmlen4events.label") }
+    .accesskey = { COPY(from_path, "pref.defalarmlen4events.accesskey") }
+
+task-alarm-time-label =
+    .value = { COPY(from_path, "pref.defalarmlen4todos.label") }
+    .accesskey = { COPY(from_path, "pref.defalarmlen4todos.accesskey") }
+""", from_path="calendar/chrome/calendar/preferences/alarms.dtd"
+        )
+    )
+
+    ctx.add_transforms(
+        "calendar/calendar/preferences.ftl",
+        "calendar/calendar/preferences.ftl",
+        transforms_from(
+"""
+category-new-label = { COPY(from_path, "pref.categories.new.title") }
+
+category-edit-label = { COPY(from_path, "pref.categories.edit.title") }
+
+category-overwrite-title = { COPY(from_path, "pref.categories.overwrite.title") }
+category-blank-warning = { COPY(from_path, "pref.categories.noBlankCategories") }
+""", from_path="calendar/chrome/calendar/preferences/categories.dtd"
+        )
+    )
+
+    ctx.add_transforms(
+        "calendar/calendar/preferences.ftl",
+        "calendar/calendar/preferences.ftl",
+        [
+            FTL.Message(
+                id = FTL.Identifier("category-overwrite"),
+                value = REPLACE(
+                    "calendar/chrome/calendar/preferences/categories.dtd",
+                    "pref.categories.overwrite",
+                    {
+                        " \\n": FTL.TextElement("")
+                    },
+                )
+            ),
+        ]
+    )
+
+    ctx.add_transforms(
+        "calendar/calendar/category-dialog.ftl",
+        "calendar/calendar/category-dialog.ftl",
+        transforms_from(
+"""
+category-name-label = { COPY(from_path, "pref.categories.name.label") }
+
+category-color-label =
+    .label = { COPY(from_path, "pref.categories.usecolor.label") }
+""", from_path="calendar/chrome/calendar/preferences/categories.dtd"
+        )
+    )