Bug 1259859 - Add a test that looks for misused characters in user-facing strings. r?dolske,jryans draft
authorJared Wein <jwein@mozilla.com>
Mon, 28 Mar 2016 20:35:21 -0400
changeset 345356 d9877895c3c919e846775bb3d4f4f556447e19f2
parent 344963 678ddeb8eb8483540c58ce4ad54248a2429cb6b7
child 517166 8e47e577a532b923a6d31c923c139dbfe5c9ec06
push id14060
push userjwein@mozilla.com
push dateTue, 29 Mar 2016 00:35:37 +0000
reviewersdolske, jryans
bugs1259859
milestone48.0a1
Bug 1259859 - Add a test that looks for misused characters in user-facing strings. r?dolske,jryans MozReview-Commit-ID: IBHYB76bvsk
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_misused_characters_in_strings.js
browser/components/search/test/browser_contextmenu.js
browser/extensions/loop/chrome/locale/en-US/loop.properties
browser/locales/en-US/chrome/browser/browser.properties
browser/locales/en-US/chrome/browser/downloads/downloads.properties
browser/locales/en-US/chrome/browser/engineManager.properties
browser/locales/en-US/chrome/browser/feeds/subscribe.properties
browser/locales/en-US/chrome/browser/places/bookmarkProperties.properties
browser/locales/en-US/chrome/browser/places/places.properties
browser/locales/en-US/chrome/browser/search.properties
browser/locales/en-US/chrome/browser/webrtcIndicator.properties
browser/locales/en-US/pdfviewer/viewer.properties
devtools/client/commandline/test/browser_cmd_appcache_invalid.js
devtools/client/commandline/test/browser_cmd_highlight_01.js
devtools/client/commandline/test/browser_cmd_pref1.js
devtools/client/commandline/test/browser_gcli_cli1.js
devtools/client/commandline/test/browser_gcli_cli2.js
devtools/client/commandline/test/browser_gcli_union.js
devtools/client/debugger/test/mochitest/browser_dbg_cmd-break.js
devtools/client/inspector/test/browser_inspector_gcli-inspect-command.js
devtools/client/locales/en-US/app-manager.properties
devtools/client/locales/en-US/appcacheutils.properties
devtools/client/locales/en-US/canvasdebugger.dtd
devtools/client/locales/en-US/connection-screen.dtd
devtools/client/locales/en-US/filterwidget.properties
devtools/client/locales/en-US/jsonview.properties
devtools/client/locales/en-US/memory.properties
devtools/client/locales/en-US/scratchpad.properties
devtools/client/locales/en-US/styleeditor.properties
devtools/client/locales/en-US/webconsole.properties
devtools/client/locales/en-US/webide.dtd
devtools/client/locales/en-US/webide.properties
devtools/client/styleeditor/test/browser_styleeditor_cmd_edit.js
devtools/shared/locales/en-US/csscoverage.dtd
devtools/shared/locales/en-US/csscoverage.properties
devtools/shared/locales/en-US/gcli.properties
devtools/shared/locales/en-US/gclicommands.properties
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -342,16 +342,17 @@ skip-if = buildapp == 'mulet'
 skip-if = toolkit == "windows" # Disabled on Windows due to frequent failures (bug 969405)
 [browser_locationBarCommand.js]
 skip-if = os == "linux" # Linux: Intermittent failures, bug 917535
 [browser_locationBarExternalLoad.js]
 [browser_menuButtonFitts.js]
 skip-if = os != "win" # The Fitts Law menu button is only supported on Windows (bug 969376)
 [browser_middleMouse_noJSPaste.js]
 [browser_minimize.js]
+[browser_misused_characters_in_strings.js]
 [browser_mixedcontent_securityflags.js]
 tags = mcb
 [browser_offlineQuotaNotification.js]
 skip-if = buildapp == 'mulet'
 [browser_gZipOfflineChild.js]
 skip-if = buildapp == 'mulet' # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
 support-files = test_offline_gzip.html gZipOfflineChild.cacheManifest gZipOfflineChild.cacheManifest^headers^ gZipOfflineChild.html gZipOfflineChild.html^headers^
 [browser_openPromptInBackgroundTab.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_misused_characters_in_strings.js
@@ -0,0 +1,140 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* This list allows pre-existing or 'unfixable' issues to remain, while we
+ * detect newly occurring issues in shipping files. It is a list of objects
+ * specifying conditions under which an error should be ignored. */
+const kWhitelist = [{
+    file: "gclicommands.properties",
+    entity: "cmdSetdirManual2",
+    type: "double-quote"
+  }, {
+    file: "search.properties",
+    entity: "searchForSomethingWith",
+    type: "single-quote"
+  }, {
+    file: "aboutCertError.dtd",
+    entity: "certerror.introPara",
+    type: "single-quote"
+  }, {
+    file: "browser.dtd",
+    entity: "social.activated.description",
+    type: "single-quote"
+  }, {
+    file: "netError.dtd",
+    entity: "weakCryptoAdvanced.longDesc",
+    type: "single-quote"
+  }, {
+    file: "netError.dtd",
+    entity: "weakCryptoAdvanced.override",
+    type: "single-quote"
+  }, {
+    file: "phishing-afterload-warning-message.dtd",
+    entity: "safeb.blocked.malwarePage.shortDesc",
+    type: "single-quote"
+  }, {
+    file: "phishing-afterload-warning-message.dtd",
+    entity: "safeb.blocked.unwantedPage.shortDesc",
+    type: "single-quote"
+  }, {
+    file: "phishing-afterload-warning-message.dtd",
+    entity: "safeb.blocked.phishingPage.shortDesc2",
+    type: "single-quote"
+  }, {
+    file: "phishing-afterload-warning-message.dtd",
+    entity: "safeb.blocked.forbiddenPage.shortDesc2",
+    type: "single-quote"
+  }
+];
+
+var moduleLocation = gTestPath.replace(/\/[^\/]*$/i, "/parsingTestHelpers.jsm");
+var {generateURIsFromDirTree} = Cu.import(moduleLocation, {});
+
+/**
+ * Check if an error should be ignored due to matching one of the whitelist
+ * objects defined in kWhitelist
+ *
+ * @param spec The URI spec of the locale file
+ * @param entity The name of the entity that is being checked
+ * @param type The type of error that has been found
+ * @return true if the error should be ignored, false otherwise.
+ */
+function ignoredError(spec, entity, type) {
+  for (let whitelistItem of kWhitelist) {
+    if (spec.endsWith(whitelistItem.file) &&
+        entity == whitelistItem.entity &&
+        type == whitelistItem.type) {
+      return true;
+    }
+  }
+  return false;
+}
+
+function fetchFile(uri) {
+  return new Promise((resolve, reject) => {
+    let xhr = new XMLHttpRequest();
+    xhr.open("GET", uri, true);
+    xhr.onreadystatechange = function() {
+      if (this.readyState != this.DONE) {
+        return;
+      }
+      try {
+        resolve(this.responseText);
+      } catch (ex) {
+        ok(false, `Script error reading ${uri}: ${ex}`);
+        resolve("");
+      }
+    };
+    xhr.onerror = error => {
+      ok(false, `XHR error reading ${uri}: ${error}`);
+      resolve("");
+    };
+    xhr.send(null);
+  });
+}
+
+function testForError(spec, entity, str, pattern, type, expected) {
+  if (str.match(pattern) &&
+      !ignoredError(spec, entity, type)) {
+    ok(false, `${spec} with key=${entity} has a misused ${type}. Expected ${expected} instead.`);
+  }
+}
+
+function testForErrors(spec, entity, str) {
+  testForError(spec, entity, str, /\w'\w/, "single-quote", "\u2018\u2019");
+  testForError(spec, entity, str, /'.+'/, "single-quote", "\u2018\u2019");
+  testForError(spec, entity, str, /"/, "double-quote", "\u201c\u201d");
+  testForError(spec, entity, str, /\.\.\./, "ellipsis", "\u2026");
+}
+
+add_task(function* checkAllTheProperties() {
+  let appDir = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
+  // This asynchronously produces a list of URLs (sadly, mostly sync on our
+  // test infrastructure because it runs against jarfiles there, and
+  // our zipreader APIs are all sync)
+  let uris = yield generateURIsFromDirTree(appDir, [".properties"]);
+  ok(uris.length, `Found ${uris.length} .properties files to scan for misused characters`);
+
+  for (let uri of uris) {
+    let bundle = new StringBundle(uri.spec);
+    let entities = bundle.getAll();
+    for (let entity of entities) {
+      testForErrors(uri.spec, entity.key, entity.value);
+    }
+  }
+});
+
+add_task(function* checkAllTheDTDs() {
+  let appDir = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
+  let uris = yield generateURIsFromDirTree(appDir, [".dtd"]);
+  ok(uris.length, `Found ${uris.length} .dtd files to scan for misused characters`);
+
+  for (let uri of uris) {
+    let rawContents = yield fetchFile(uri.spec);
+    let entities = rawContents.match(/ENTITY\s+([\w\.]*)\s+["'](.*)["']/g);
+    for (let entity of entities) {
+      let [, key, str] = entity.match(/ENTITY\s+([\w\.]*)\s+["'](.*)["']/);
+      testForErrors(uri.spec, key, str);
+    }
+  }
+});
--- a/browser/components/search/test/browser_contextmenu.js
+++ b/browser/components/search/test/browser_contextmenu.js
@@ -71,17 +71,17 @@ add_task(function* () {
 
   let popupPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
   BrowserTestUtils.synthesizeMouseAtCenter("body", eventDetails, gBrowser.selectedBrowser);
   yield popupPromise;
 
   info("checkContextMenu");
   var searchItem = contextMenu.getElementsByAttribute("id", "context-searchselect")[0];
   ok(searchItem, "Got search context menu item");
-  is(searchItem.label, 'Search ' + ENGINE_NAME + ' for "test search"', "Check context menu label");
+  is(searchItem.label, 'Search ' + ENGINE_NAME + ' for \u201ctest search\u201d', "Check context menu label");
   is(searchItem.disabled, false, "Check that search context menu item is enabled");
 
   yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
     searchItem.click();
   });
 
   is(gBrowser.currentURI.spec,
      "http://mochi.test:8888/browser/browser/components/search/test/?test=test+search&ie=utf-8&channel=contextsearch",
--- a/browser/extensions/loop/chrome/locale/en-US/loop.properties
+++ b/browser/extensions/loop/chrome/locale/en-US/loop.properties
@@ -151,17 +151,17 @@ contact_offline_title=This person is not
 ## when the call didn't go through.
 call_timeout_notification_text=Your call did not go through.
 
 ## LOCALIZATION NOTE (cancel_button):
 ## This button is displayed when a call has failed.
 cancel_button=Cancel
 rejoin_button=Rejoin Conversation
 
-cannot_start_call_session_not_ready=Can't start call, session is not ready.
+cannot_start_call_session_not_ready=Can’t start call, session is not ready.
 network_disconnected=The network connection terminated abruptly.
 connection_error_see_console_notification=Call failed; see console for details.
 no_media_failure_message=No camera or microphone found.
 ice_failure_message=Connection failed. Your firewall may be blocking calls.
 
 ## LOCALIZATION NOTE (legal_text_and_links3): In this item, don't translate the
 ## parts between {{..}} because these will be replaced with links with the labels
 ## from legal_text_tos and legal_text_privacy. clientShortname will be replaced
@@ -189,17 +189,17 @@ tour_label=Tour
 
 rooms_list_recently_browsed2=Recently browsed
 rooms_list_currently_browsing2=Currently browsing
 rooms_signout_alert=Open conversations will be closed
 room_name_untitled_page=Untitled Page
 
 ## LOCALIZATION NOTE (door_hanger_return, door_hanger_prompt_name, door_hanger_button): Dialog message on leaving conversation
 door_hanger_return=See you later! You can return to this shared session at any time through the Hello panel.
-door_hanger_prompt_name=Would you like to give it a name that's easier to remember? Current name:
+door_hanger_prompt_name=Would you like to give it a name that’s easier to remember? Current name:
 door_hanger_button=OK
 
 # Infobar strings
 
 infobar_screenshare_no_guest_message=As soon as your friend joins, they will be able to see any tab you click on.
 infobar_screenshare_browser_message2=You are sharing your tabs. Any tab you click on can be seen by your friends
 infobar_screenshare_browser_message3=You are now sharing your tabs. Your friend will see any tab you click on.
 infobar_screenshare_stop_sharing_message=You are no longer sharing your tabs
@@ -208,32 +208,32 @@ infobar_button_restart_accesskey=R
 infobar_button_stop_label2=Stop sharing
 infobar_button_stop_accesskey=S
 infobar_button_disconnect_label=Disconnect
 infobar_button_disconnect_accesskey=D
 
 # E10s not supported strings
 
 e10s_not_supported_button_label=Launch New Window
-e10s_not_supported_subheading={{brandShortname}} doesn't work in a multi-process window.
+e10s_not_supported_subheading={{brandShortname}} doesn’t work in a multi-process window.
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 ## LOCALIZATION NOTE: In this file, don't translate the part between {{..}}
 
 # Text chat strings
 chat_textbox_placeholder=Type here…
 
 ## LOCALIZATION NOTE(clientShortname2): This should not be localized and
 ## should remain "Firefox Hello" for all locales.
 clientShortname2=Firefox Hello
 
 conversation_has_ended=Your conversation has ended.
-generic_failure_message=We're having technical difficulties…
+generic_failure_message=We’re having technical difficulties…
 
 generic_failure_no_reason2=Would you like to try again?
 
 help_label=Help
 
 mute_local_audio_button_title=Mute your audio
 unmute_local_audio_button_title=Unmute your audio
 mute_local_video_button_title2=Disable video
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -7,17 +7,17 @@ openFile=Open File
 
 droponhometitle=Set Home Page
 droponhomemsg=Do you want this document to be your new home page?
 
 # context menu strings
 
 # LOCALIZATION NOTE (contextMenuSearch): %1$S is the search engine,
 # %2$S is the selection string.
-contextMenuSearch=Search %1$S for "%2$S"
+contextMenuSearch=Search %1$S for “%2$S”
 contextMenuSearch.accesskey=S
 
 # bookmark dialog strings
 
 bookmarkAllTabsDefault=[Folder Name]
 
 xpinstallPromptMessage=%S prevented this site from asking you to install software on your computer.
 xpinstallPromptAllowButton=Allow
@@ -130,17 +130,17 @@ popupWarning.message=#1 prevented this s
 popupWarningButton=Options
 popupWarningButton.accesskey=O
 popupWarningButtonUnix=Preferences
 popupWarningButtonUnix.accesskey=P
 popupAllow=Allow pop-ups for %S
 popupBlock=Block pop-ups for %S
 popupWarningDontShowFromMessage=Don’t show this message when pop-ups are blocked
 popupWarningDontShowFromLocationbar=Don’t show info bar when pop-ups are blocked
-popupShowPopupPrefix=Show '%S'
+popupShowPopupPrefix=Show ‘%S’
 
 # Bad Content Blocker Doorhanger Notification
 # %S is brandShortName
 badContentBlocked.blocked.message=%S is blocking content on this page.
 badContentBlocked.notblocked.message=%S is not blocking any content on this page.
 
 crashedpluginsMessage.title=The %S plugin has crashed.
 crashedpluginsMessage.reloadButton.label=Reload page
@@ -159,40 +159,40 @@ keywordURIFixup.goTo=Yes, take me to %S
 keywordURIFixup.goTo.accesskey=Y
 keywordURIFixup.dismiss=No thanks
 keywordURIFixup.dismiss.accesskey=N
 
 ## Plugin doorhanger strings
 # LOCALIZATION NOTE (pluginActivateNew.message): Used for newly-installed
 # plugins which are not known to be unsafe. %1$S is the plugin name and %2$S
 # is the site domain.
-pluginActivateNew.message=Allow %2$S to run "%1$S"?
+pluginActivateNew.message=Allow %2$S to run “%1$S”?
 pluginActivateMultiple.message=Allow %S to run plugins?
 pluginActivate.learnMore=Learn More…
 # LOCALIZATION NOTE (pluginActivateOutdated.message, pluginActivateOutdated.label):
 # These strings are used when an unsafe plugin has an update available.
 # %1$S is the plugin name, %2$S is the domain, and %3$S is brandShortName.
-pluginActivateOutdated.message=%3$S has prevented the outdated plugin "%1$S" from running on %2$S.
+pluginActivateOutdated.message=%3$S has prevented the outdated plugin “%1$S” from running on %2$S.
 pluginActivateOutdated.label=Outdated plugin
 pluginActivate.updateLabel=Update now…
 # LOCALIZATION NOTE (pluginActivateVulnerable.message, pluginActivateVulnerable.label):
 # These strings are used when an unsafe plugin has no update available.
 # %1$S is the plugin name, %2$S is the domain, and %3$S is brandShortName.
-pluginActivateVulnerable.message=%3$S has prevented the unsafe plugin "%1$S" from running on %2$S.
+pluginActivateVulnerable.message=%3$S has prevented the unsafe plugin “%1$S” from running on %2$S.
 pluginActivateVulnerable.label=Vulnerable plugin!
 pluginActivate.riskLabel=What’s the risk?
 # LOCALIZATION NOTE (pluginActivateBlocked.message): %1$S is the plugin name, %2$S is brandShortName
-pluginActivateBlocked.message=%2$S has blocked "%1$S" for your protection.
+pluginActivateBlocked.message=%2$S has blocked “%1$S” for your protection.
 pluginActivateBlocked.label=Blocked for your protection
-pluginActivateDisabled.message="%S" is disabled.
+pluginActivateDisabled.message=“%S” is disabled.
 pluginActivateDisabled.label=Disabled
 pluginActivateDisabled.manage=Manage plugins…
-pluginEnabled.message="%S" is enabled on %S.
-pluginEnabledOutdated.message=Outdated plugin "%S" is enabled on %S.
-pluginEnabledVulnerable.message=Insecure plugin "%S" is enabled on %S.
+pluginEnabled.message=“%S” is enabled on %S.
+pluginEnabledOutdated.message=Outdated plugin “%S” is enabled on %S.
+pluginEnabledVulnerable.message=Insecure plugin “%S” is enabled on %S.
 pluginInfo.unknownPlugin=Unknown
 
 # LOCALIZATION NOTE (pluginActivateNow.label, pluginActivateAlways.label, pluginBlockNow.label): These should be the same as the matching strings in browser.dtd
 # LOCALIZATION NOTE (pluginActivateNow.label): This button will enable the
 # plugin in the current session for an short time (about an hour), auto-renewed
 # if the site keeps using the plugin.
 pluginActivateNow.label=Allow Now
 pluginActivateNow.accesskey=N
--- a/browser/locales/en-US/chrome/browser/downloads/downloads.properties
+++ b/browser/locales/en-US/chrome/browser/downloads/downloads.properties
@@ -89,17 +89,17 @@ shortTimeLeftDays=%1$Sd
 # that we use a wider space after the separator when it is followed by a number,
 # just to avoid visually confusing it with with a minus sign with some fonts.
 # If you use a different separator, this might not be necessary.  However, there
 # is usually no need to change the separator or the order of the substitutions,
 # even for right-to-left languages, unless the defaults are not suitable.
 statusSeparator=%1$S \u2014 %2$S
 statusSeparatorBeforeNumber=%1$S \u2014  %2$S
 
-fileExecutableSecurityWarning="%S" is an executable file. Executable files may contain viruses or other malicious code that could harm your computer. Use caution when opening this file. Are you sure you want to launch "%S"?
+fileExecutableSecurityWarning=“%S” is an executable file. Executable files may contain viruses or other malicious code that could harm your computer. Use caution when opening this file. Are you sure you want to launch “%S”?
 fileExecutableSecurityWarningTitle=Open Executable File?
 fileExecutableSecurityWarningDontAsk=Don’t ask me this again
 
 # LOCALIZATION NOTE (otherDownloads2):
 # This is displayed in an item at the bottom of the Downloads Panel when
 # there are more downloads than can fit in the list in the panel. Use a
 # semi-colon list of plural forms.
 # See: http://developer.mozilla.org/en/Localization_and_Plurals
--- a/browser/locales/en-US/chrome/browser/engineManager.properties
+++ b/browser/locales/en-US/chrome/browser/engineManager.properties
@@ -1,7 +1,7 @@
 # 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/.
 
 duplicateTitle=Duplicate Keyword
-duplicateEngineMsg=You have chosen a keyword that is currently in use by "%S". Please select another.
+duplicateEngineMsg=You have chosen a keyword that is currently in use by “%S”. Please select another.
 duplicateBookmarkMsg=You have chosen a keyword that is currently in use by a bookmark. Please select another.
--- a/browser/locales/en-US/chrome/browser/feeds/subscribe.properties
+++ b/browser/locales/en-US/chrome/browser/feeds/subscribe.properties
@@ -1,17 +1,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/.
 
 linkTitleTextFormat=Go to %S
-addHandler=Add "%S" (%S) as a Feed Reader?
+addHandler=Add “%S” (%S) as a Feed Reader?
 addHandlerAddButton=Add Feed Reader
 addHandlerAddButtonAccesskey=A
-handlerRegistered="%S" is already registered as a Feed Reader
+handlerRegistered=“%S” is already registered as a Feed Reader
 liveBookmarks=Live Bookmarks
 subscribeNow=Subscribe Now
 chooseApplicationMenuItem=Choose Application…
 chooseApplicationDialogTitle=Choose Application
 alwaysUse=Always use %S to subscribe to feeds
 mediaLabel=Media files
 
 # LOCALIZATION NOTE: The next string is for the size of the enclosed media.
@@ -32,19 +32,19 @@ gigabyte=GB
 alwaysUseForFeeds=Always use %S to subscribe to feeds.
 alwaysUseForAudioPodcasts=Always use %S to subscribe to podcasts.
 alwaysUseForVideoPodcasts=Always use %S to subscribe to video podcasts.
 
 subscribeFeedUsing=Subscribe to this feed using 
 subscribeAudioPodcastUsing=Subscribe to this podcast using 
 subscribeVideoPodcastUsing=Subscribe to this video podcast using 
 
-feedSubscriptionFeed1=This is a "feed" of frequently changing content on this site.
-feedSubscriptionAudioPodcast1=This is a "podcast" of frequently changing content on this site.
-feedSubscriptionVideoPodcast1=This is a "video podcast" of frequently changing content on this site.
+feedSubscriptionFeed1=This is a “feed” of frequently changing content on this site.
+feedSubscriptionAudioPodcast1=This is a “podcast” of frequently changing content on this site.
+feedSubscriptionVideoPodcast1=This is a “video podcast” of frequently changing content on this site.
 
 feedSubscriptionFeed2=You can subscribe to this feed to receive updates when this content changes.
 feedSubscriptionAudioPodcast2=You can subscribe to this podcast to receive updates when this content changes.
 feedSubscriptionVideoPodcast2=You can subscribe to this video podcast to receive updates when this content changes.
 
 # Protocol Handling
 # "Add %appName (%appDomain) as an application for %protocolType links?"
 addProtocolHandler=Add %S (%S) as an application for %S links?
--- a/browser/locales/en-US/chrome/browser/places/bookmarkProperties.properties
+++ b/browser/locales/en-US/chrome/browser/places/bookmarkProperties.properties
@@ -6,14 +6,14 @@ dialogAcceptLabelAddItem=Add
 dialogAcceptLabelSaveItem=Save
 dialogAcceptLabelAddLivemark=Subscribe
 dialogAcceptLabelAddMulti=Add Bookmarks
 dialogAcceptLabelEdit=Save
 dialogTitleAddBookmark=New Bookmark
 dialogTitleAddLivemark=Subscribe with Live Bookmark
 dialogTitleAddFolder=New Folder
 dialogTitleAddMulti=New Bookmarks
-dialogTitleEdit=Properties for "%S"
+dialogTitleEdit=Properties for “%S”
 
 bookmarkAllTabsDefault=[Folder Name]
 newFolderDefault=New Folder
 newBookmarkDefault=New Bookmark
 newLivemarkDefault=New Live Bookmark
--- a/browser/locales/en-US/chrome/browser/places/places.properties
+++ b/browser/locales/en-US/chrome/browser/places/places.properties
@@ -15,19 +15,19 @@ bookmarksRestoreTitle=Select a bookmarks
 bookmarksRestoreFilterName=JSON
 
 bookmarksRestoreFormatError=Unsupported file type.
 bookmarksRestoreParseError=Unable to process the backup file.
 
 bookmarksLivemarkLoading=Live Bookmark loading…
 bookmarksLivemarkFailed=Live Bookmark feed failed to load.
 
-menuOpenLivemarkOrigin.label=Open "%S"
+menuOpenLivemarkOrigin.label=Open “%S”
 
-sortByName=Sort '%S' by Name
+sortByName=Sort ‘%S’ by Name
 sortByNameGeneric=Sort by Name
 # LOCALIZATION NOTE (view.sortBy.1.name.label): sortBy properties are versioned.
 # When any of these changes, all of the properties must be bumped, and the
 # change must be annotated here.  Both label and accesskey must be updated.
 # - version 1: changed view.sortBy.1.date.
 view.sortBy.1.name.label=Sort by Name
 view.sortBy.1.name.accesskey=N
 view.sortBy.1.url.label=Sort by Location
--- a/browser/locales/en-US/chrome/browser/search.properties
+++ b/browser/locales/en-US/chrome/browser/search.properties
@@ -21,17 +21,17 @@ cmd_clearHistory=Clear Search History
 cmd_clearHistory_accesskey=H
 
 cmd_showSuggestions=Show Suggestions
 cmd_showSuggestions_accesskey=S
 
 # LOCALIZATION NOTE (cmd_addFoundEngine): %S is replaced by the name of
 # a search engine offered by a web page. Each engine is displayed as a
 # menuitem at the bottom of the search panel.
-cmd_addFoundEngine=Add "%S"
+cmd_addFoundEngine=Add “%S”
 # LOCALIZATION NOTE (cmd_addFoundEngineMenu): When more than 5 engines
 # are offered by a web page, instead of listing all of them in the
 # search panel using the cmd_addFoundEngine string, they will be
 # grouped in a submenu using cmd_addFoundEngineMenu as a label.
 cmd_addFoundEngineMenu=Add search engine
 
 # LOCALIZATION NOTE (searchForSomethingWith):
 # This string is used to build the header above the list of one-click
--- a/browser/locales/en-US/chrome/browser/webrtcIndicator.properties
+++ b/browser/locales/en-US/chrome/browser/webrtcIndicator.properties
@@ -18,22 +18,22 @@ webrtcIndicator.sharingWindow.tooltip = 
 webrtcIndicator.sharingBrowser.tooltip = A tab is being shared. Click to control sharing.
 
 
 # LOCALIZATION NOTE : The following strings are only used on Mac for
 # menus attached to icons near the clock on the mac menubar.
 
 # LOCALIZATION NOTE (webrtcIndicator.sharing*With.menuitem):
 # %S is the title of the tab using the share.
-webrtcIndicator.sharingCameraWith.menuitem = Sharing Camera with "%S"
-webrtcIndicator.sharingMicrophoneWith.menuitem = Sharing Microphone with "%S"
-webrtcIndicator.sharingApplicationWith.menuitem = Sharing an Application with "%S"
-webrtcIndicator.sharingScreenWith.menuitem = Sharing Screen with "%S"
-webrtcIndicator.sharingWindowWith.menuitem = Sharing a Window with "%S"
-webrtcIndicator.sharingBrowserWith.menuitem = Sharing a Tab with "%S"
+webrtcIndicator.sharingCameraWith.menuitem = Sharing Camera with “%S”
+webrtcIndicator.sharingMicrophoneWith.menuitem = Sharing Microphone with “%S”
+webrtcIndicator.sharingApplicationWith.menuitem = Sharing an Application with “%S”
+webrtcIndicator.sharingScreenWith.menuitem = Sharing Screen with “%S”
+webrtcIndicator.sharingWindowWith.menuitem = Sharing a Window with “%S”
+webrtcIndicator.sharingBrowserWith.menuitem = Sharing a Tab with “%S”
 webrtcIndicator.controlSharing.menuitem = Control Sharing
 # LOCALIZATION NOTE (webrtcIndicator.sharingCameraWithNTabs.menuitem):
 # Semicolon-separated list of plural forms. See:
 # http://developer.mozilla.org/en/docs/Localization_and_Plurals
 webrtcIndicator.sharingCameraWithNTabs.menuitem = Sharing Camera with #1 tab;Sharing Camera with #1 tabs
 # LOCALIZATION NOTE (webrtcIndicator.sharingMicrophoneWithNTabs.menuitem):
 # Semicolon-separated list of plural forms. See:
 # http://developer.mozilla.org/en/docs/Localization_and_Plurals
@@ -53,9 +53,9 @@ webrtcIndicator.sharingWindowWithNTabs.m
 # LOCALIZATION NOTE (webrtcIndicator.sharingBrowserWithNTabs.menuitem):
 # Semicolon-separated list of plural forms. See:
 # http://developer.mozilla.org/en/docs/Localization_and_Plurals
 # This message is shown when the contents of a tab is shared during a WebRTC
 # session, which currently is only possible with Loop/Hello.
 webrtcIndicator.sharingBrowserWithNTabs.menuitem = Sharing a Tab with #1 tab;Sharing Tabs with #1 tabs
 # LOCALIZATION NOTE (webrtcIndicator.controlSharingOn.menuitem):
 # %S is the title of the tab using the share.
-webrtcIndicator.controlSharingOn.menuitem = Control Sharing on "%S"
+webrtcIndicator.controlSharingOn.menuitem = Control Sharing on “%S”
--- a/browser/locales/en-US/pdfviewer/viewer.properties
+++ b/browser/locales/en-US/pdfviewer/viewer.properties
@@ -165,9 +165,9 @@ text_annotation_type.alt=[{{type}} Annot
 password_label=Enter the password to open this PDF file.
 password_invalid=Invalid password. Please try again.
 password_ok=OK
 password_cancel=Cancel
 
 printing_not_supported=Warning: Printing is not fully supported by this browser.
 printing_not_ready=Warning: The PDF is not fully loaded for printing.
 web_fonts_disabled=Web fonts are disabled: unable to use embedded PDF fonts.
-document_colors_not_allowed=PDF documents are not allowed to use their own colors: 'Allow pages to choose their own colors' is deactivated in the browser.
+document_colors_not_allowed=PDF documents are not allowed to use their own colors: “Allow pages to choose their own colors” is deactivated in the browser.
--- a/devtools/client/commandline/test/browser_cmd_appcache_invalid.js
+++ b/devtools/client/commandline/test/browser_cmd_appcache_invalid.js
@@ -10,18 +10,18 @@ const TEST_URI = "http://sub1.test1.exam
 function test() {
   return Task.spawn(spawnTest).then(finish, helpers.handleError);
 }
 
 function* spawnTest() {
   let lines = [
     'Manifest has a character encoding of ISO-8859-1. Manifests must have the ' +
       'utf-8 character encoding.',
-    'The first line of the manifest must be "CACHE MANIFEST" at line 1.',
-    '"CACHE MANIFEST" is only valid on the first line but was found at line 3.',
+    'The first line of the manifest must be \u201cCACHE MANIFEST\u201d at line 1.',
+    '\u201cCACHE MANIFEST\u201d is only valid on the first line but was found at line 3.',
     'images/sound-icon.png points to a resource that is not available at line 9.',
     'images/background.png points to a resource that is not available at line 10.',
     '/checking.cgi points to a resource that is not available at line 13.',
     'Asterisk (*) incorrectly used in the NETWORK section at line 14. If a line ' +
       'in the NETWORK section contains only a single asterisk character, then any ' +
       'URI not listed in the manifest will be treated as if the URI was listed in ' +
       'the NETWORK section. Otherwise such URIs will be treated as unavailable. ' +
     'Other uses of the * character are prohibited',
@@ -56,17 +56,17 @@ function* spawnTest() {
     'http://example.com/check.png points to a resource that is not available at line 41.',
     'Spaces in URIs need to be replaced with % at line 42.',
     'http://example.com/cr oss.png points to a resource that is not available at line 42.',
     'Asterisk (*) incorrectly used in the CACHE section at line 43. If a line ' +
       'in the NETWORK section contains only a single asterisk character, then ' +
       'any URI not listed in the manifest will be treated as if the URI was ' +
       'listed in the NETWORK section. Otherwise such URIs will be treated as ' +
       'unavailable. Other uses of the * character are prohibited',
-    'The SETTINGS section may only contain a single value, "prefer-online" or "fast" at line 47.',
+    'The SETTINGS section may only contain a single value, \u201cprefer-online\u201d or \u201cfast\u201d at line 47.',
     'FALLBACK section line 50 (/section1/ /offline1.html) prevents caching of ' +
       'line 30 (/section1/blockedbyfallback.html) in the CACHE section.',
     '/offline1.html points to a resource that is not available at line 50.',
     'FALLBACK section line 51 (/section2/ offline2.html) prevents caching of ' +
       'line 32 (/section2/blockedbyfallback.html) in the CACHE section.',
     'offline2.html points to a resource that is not available at line 51.',
     'Only two URIs separated by spaces are allowed in the FALLBACK section at line 52.',
     'Asterisk (*) incorrectly used in the FALLBACK section at line 53. URIs ' +
--- a/devtools/client/commandline/test/browser_cmd_highlight_01.js
+++ b/devtools/client/commandline/test/browser_cmd_highlight_01.js
@@ -145,17 +145,17 @@ function* spawnTest() {
       setup: 'highlight body --region',
       check: {
         input:  'highlight body --region',
         hints:                         ' <selection> [options]',
         markup: 'VVVVVVVVVVVVVVVIIIIIIII',
         status: 'ERROR'
       },
       exec: {
-        output: 'Error: Value required for \'region\'.'
+        output: 'Error: Value required for \u2018region\u2019.'
       }
     },
     {
       setup: 'highlight body --fi',
       check: {
         input:  'highlight body --fi',
         hints:                     'll [options]',
         markup: 'VVVVVVVVVVVVVVVIIII',
@@ -169,17 +169,17 @@ function* spawnTest() {
       setup: 'highlight body --fill',
       check: {
         input:  'highlight body --fill',
         hints:                       ' <string> [options]',
         markup: 'VVVVVVVVVVVVVVVIIIIII',
         status: 'ERROR'
       },
       exec: {
-        output: 'Error: Value required for \'fill\'.'
+        output: 'Error: Value required for \u2018fill\u2019.'
       }
     },
     {
       setup: 'highlight body --ke',
       check: {
         input:  'highlight body --ke',
         hints:                     'ep [options]',
         markup: 'VVVVVVVVVVVVVVVIIII',
@@ -221,17 +221,17 @@ function* spawnTest() {
       check: {
         input:  'highlight .item',
         hints:                 ' [options]',
         markup: 'VVVVVVVVVVVVVVV',
         status: 'VALID'
       },
       exec: {
         output: '200 nodes matched, but only 100 nodes highlighted. Use ' +
-          '\'--showall\' to show all'
+          '\u2018--showall\u2019 to show all'
       }
     },
     {
       setup: 'highlight .item --showall',
       check: {
         input:  'highlight .item --showall',
         hints:                           ' [options]',
         markup: 'VVVVVVVVVVVVVVVVVVVVVVVVV',
--- a/devtools/client/commandline/test/browser_cmd_pref1.js
+++ b/devtools/client/commandline/test/browser_cmd_pref1.js
@@ -100,17 +100,17 @@ function* spawnTest() {
       setup: 'pref set devtools.netmonitor.enabled 4',
       check: {
         input:  'pref set devtools.netmonitor.enabled 4',
         hints:                                  '',
         markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE',
         status: 'ERROR',
         args: {
           setting: { arg: ' devtools.netmonitor.enabled' },
-          value: { status: 'ERROR', message: 'Can\'t use \'4\'.' },
+          value: { status: 'ERROR', message: 'Can\u2019t use \u20184\u2019.' },
         }
       },
     },
     {
       setup: 'pref set devtools.editor.tabsize 4',
       check: {
         input:  'pref set devtools.editor.tabsize 4',
         hints:                                    '',
--- a/devtools/client/commandline/test/browser_gcli_cli1.js
+++ b/devtools/client/commandline/test/browser_gcli_cli1.js
@@ -207,23 +207,23 @@ exports.testTsv = function(options) {
         unassigned: [ ],
         tooltipState: 'true:importantFieldFlag',
         args: {
           command: { name: 'tsv' },
           optionType: {
             value: undefined,
             arg: ' o',
             status: 'INCOMPLETE',
-            message: 'Value required for \'optionType\'.'
+            message: 'Value required for \u2018optionType\u2019.'
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'optionValue\'.'
+            message: 'Value required for \u2018optionValue\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsv option',
       check: {
         input:  'tsv option',
@@ -236,23 +236,23 @@ exports.testTsv = function(options) {
         unassigned: [ ],
         tooltipState: 'true:importantFieldFlag',
         args: {
           command: { name: 'tsv' },
           optionType: {
             value: undefined,
             arg: ' option',
             status: 'INCOMPLETE',
-            message: 'Value required for \'optionType\'.'
+            message: 'Value required for \u2018optionType\u2019.'
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'optionValue\'.'
+            message: 'Value required for \u2018optionValue\u2019.'
           }
         }
       }
     },
     {
       name: '|tsv option',
       setup: function() {
         return helpers.setInput(options, 'tsv option', 0);
@@ -267,23 +267,23 @@ exports.testTsv = function(options) {
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsv' },
           optionType: {
             value: undefined,
             arg: ' option',
             status: 'INCOMPLETE',
-            message: 'Value required for \'optionType\'.'
+            message: 'Value required for \u2018optionType\u2019.'
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'optionValue\'.'
+            message: 'Value required for \u2018optionValue\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsv option ',
       check: {
         input:  'tsv option ',
@@ -296,23 +296,23 @@ exports.testTsv = function(options) {
         unassigned: [ ],
         tooltipState: 'false:default',
         args: {
           command: { name: 'tsv' },
           optionType: {
             value: undefined,
             arg: ' option ',
             status: 'ERROR',
-            message: 'Can\'t use \'option\'.'
+            message: 'Can\u2019t use \u2018option\u2019.'
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'optionValue\'.'
+            message: 'Value required for \u2018optionValue\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsv option1',
       check: {
         input:  'tsv option1',
@@ -331,17 +331,17 @@ exports.testTsv = function(options) {
             arg: ' option1',
             status: 'VALID',
             message: ''
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'optionValue\'.'
+            message: 'Value required for \u2018optionValue\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsv option1 ',
       check: {
         input:  'tsv option1 ',
@@ -359,17 +359,17 @@ exports.testTsv = function(options) {
             arg: ' option1 ',
             status: 'VALID',
             message: ''
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'optionValue\'.'
+            message: 'Value required for \u2018optionValue\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsv option2',
       check: {
         input:  'tsv option2',
@@ -388,17 +388,17 @@ exports.testTsv = function(options) {
             arg: ' option2',
             status: 'VALID',
             message: ''
           },
           optionValue: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'optionValue\'.'
+            message: 'Value required for \u2018optionValue\u2019.'
           }
         }
       }
     }
   ]);
 };
 
 exports.testTsvValues = function(options) {
--- a/devtools/client/commandline/test/browser_gcli_cli2.js
+++ b/devtools/client/commandline/test/browser_gcli_cli2.js
@@ -40,17 +40,17 @@ exports.testSingleString = function(opti
         status: 'ERROR',
         unassigned: [ ],
         args: {
           command: { name: 'tsr' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'text\'.'
+            message: 'Value required for \u2018text\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsr ',
       check: {
         input:  'tsr ',
@@ -62,17 +62,17 @@ exports.testSingleString = function(opti
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsr' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'text\'.'
+            message: 'Value required for \u2018text\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsr h',
       check: {
         input:  'tsr h',
@@ -155,17 +155,17 @@ exports.testSingleNumber = function(opti
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsu' },
           num: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'num\'.'
+            message: 'Value required for \u2018num\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsu ',
       check: {
         input:  'tsu ',
@@ -177,17 +177,17 @@ exports.testSingleNumber = function(opti
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsu' },
           num: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'num\'.'
+            message: 'Value required for \u2018num\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsu 1',
       check: {
         input:  'tsu 1',
@@ -217,17 +217,17 @@ exports.testSingleNumber = function(opti
         unassigned: [ ],
         tooltipState: 'true:isError',
         args: {
           command: { name: 'tsu' },
           num: {
             value: undefined,
             arg: ' x',
             status: 'ERROR',
-            message: 'Can\'t convert "x" to a number.'
+            message: 'Can\u2019t convert \u201cx\u201d to a number.'
           }
         }
       }
     },
     {
       setup:    'tsu 1.5',
       check: {
         input:  'tsu 1.5',
@@ -239,17 +239,17 @@ exports.testSingleNumber = function(opti
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsu' },
           num: {
             value: undefined,
             arg: ' 1.5',
             status: 'ERROR',
-            message: 'Can\'t convert "1.5" to an integer.'
+            message: 'Can\u2019t convert \u201c1.5\u201d to an integer.'
           }
         }
       }
     }
   ]);
 };
 
 exports.testSingleFloat = function(options) {
@@ -266,17 +266,17 @@ exports.testSingleFloat = function(optio
         error: '',
         unassigned: [ ],
         args: {
           command: { name: 'tsf' },
           num: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'num\'.'
+            message: 'Value required for \u2018num\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsf 1',
       check: {
         input:  'tsf 1',
@@ -355,26 +355,26 @@ exports.testSingleFloat = function(optio
       },
       check: {
         input:  'tsf x',
         hints:       '',
         markup: 'VVVVE',
         cursor: 4,
         current: 'num',
         status: 'ERROR',
-        error: 'Can\'t convert "x" to a number.',
+        error: 'Can\u2019t convert \u201cx\u201d to a number.',
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsf' },
           num: {
             value: undefined,
             arg: ' x',
             status: 'ERROR',
-            message: 'Can\'t convert "x" to a number.'
+            message: 'Can\u2019t convert \u201cx\u201d to a number.'
           }
         }
       }
     }
   ]);
 };
 
 exports.testElementWeb = function(options) {
@@ -593,17 +593,17 @@ exports.testNestedCommand = function(opt
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn dif' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'text\'.'
+            message: 'Value required for \u2018text\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsn dif ',
       check: {
         input:  'tsn dif ',
@@ -615,17 +615,17 @@ exports.testNestedCommand = function(opt
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn dif' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'text\'.'
+            message: 'Value required for \u2018text\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsn dif x',
       check: {
         input:  'tsn dif x',
@@ -654,17 +654,17 @@ exports.testNestedCommand = function(opt
         predictions: [ 'tsn ext', 'tsn exte', 'tsn exten', 'tsn extend' ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn ext' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'text\'.'
+            message: 'Value required for \u2018text\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsn exte',
       check: {
         input:  'tsn exte',
@@ -676,17 +676,17 @@ exports.testNestedCommand = function(opt
         predictions: [ 'tsn exte', 'tsn exten', 'tsn extend' ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn exte' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'text\'.'
+            message: 'Value required for \u2018text\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsn exten',
       check: {
         input:  'tsn exten',
@@ -698,17 +698,17 @@ exports.testNestedCommand = function(opt
         predictions: [ 'tsn exten', 'tsn extend' ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn exten' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'text\'.'
+            message: 'Value required for \u2018text\u2019.'
           }
         }
       }
     },
     {
       setup:    'tsn extend',
       check: {
         input:  'tsn extend',
@@ -720,17 +720,17 @@ exports.testNestedCommand = function(opt
         predictions: [ ],
         unassigned: [ ],
         args: {
           command: { name: 'tsn extend' },
           text: {
             value: undefined,
             arg: '',
             status: 'INCOMPLETE',
-            message: 'Value required for \'text\'.'
+            message: 'Value required for \u2018text\u2019.'
           }
         }
       }
     },
     {
       setup:    'ts ',
       check: {
         input:  'ts ',
--- a/devtools/client/commandline/test/browser_gcli_union.js
+++ b/devtools/client/commandline/test/browser_gcli_union.js
@@ -159,15 +159,15 @@ exports.testDefault = function(options) 
           'https://on/'
         ],
         args: {
           command: { name: 'unionc2' },
           first: {
             value: undefined,
             arg: ' on',
             status: 'INCOMPLETE',
-            message: 'Can\'t use \'on\'.'
+            message: 'Can\u2019t use \u2018on\u2019.'
           },
         }
       }
     }
   ]);
 };
--- a/devtools/client/debugger/test/mochitest/browser_dbg_cmd-break.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_cmd-break.js
@@ -144,17 +144,17 @@ function test() {
         check: {
           input:  'break del 14',
           hints:              ' -> doc_cmd-break.html:14',
           markup: 'VVVVVVVVVVII',
           status: 'ERROR',
           args: {
             breakpoint: {
               status: 'INCOMPLETE',
-              message: 'Value required for \'breakpoint\'.'
+              message: 'Value required for \u2018breakpoint\u2019.'
             }
           }
         }
       }]);
 
       yield helpers.audit(aOptions, [{
         setup: 'break del doc_cmd-break.html:14',
         check: {
--- a/devtools/client/inspector/test/browser_inspector_gcli-inspect-command.js
+++ b/devtools/client/inspector/test/browser_inspector_gcli-inspect-command.js
@@ -14,17 +14,17 @@ add_task(function* () {
         setup: "inspect",
         check: {
           input:  'inspect',
           hints:         ' <selector>',
           markup: 'VVVVVVV',
           status: 'ERROR',
           args: {
             selector: {
-              message: 'Value required for \'selector\'.'
+              message: 'Value required for \u2018selector\u2019.'
             },
           }
         },
       },
       {
         setup: "inspect h1",
         check: {
           input:  'inspect h1',
--- a/devtools/client/locales/en-US/app-manager.properties
+++ b/devtools/client/locales/en-US/app-manager.properties
@@ -1,29 +1,29 @@
 # 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/.
 
-validator.nonExistingFolder=The project folder doesn't exists
+validator.nonExistingFolder=The project folder doesn’t exists
 validator.expectProjectFolder=The project folder ends up being a file
-validator.noManifestFile=A manifest file is required at project root folder, named either 'manifest.webapp' for packaged apps or 'manifest.json' for add-ons.
-validator.invalidManifestURL=Invalid manifest URL '%S'
+validator.noManifestFile=A manifest file is required at project root folder, named either ‘manifest.webapp’ for packaged apps or ‘manifest.json’ for add-ons.
+validator.invalidManifestURL=Invalid manifest URL ‘%S’
 # LOCALIZATION NOTE (validator.invalidManifestJSON, validator.noAccessManifestURL):
 # %1$S is the error message, %2$S is the URI of the manifest.
-validator.invalidManifestJSON=The webapp manifest isn't a valid JSON file: %1$S at: %2$S
+validator.invalidManifestJSON=The webapp manifest isn’t a valid JSON file: %1$S at: %2$S
 validator.noAccessManifestURL=Unable to read manifest file: %1$S at: %2$S
 # LOCALIZATION NOTE (validator.invalidHostedManifestURL): %1$S is the URI of
 # the manifest, %2$S is the error message.
-validator.invalidHostedManifestURL=Invalid hosted manifest URL '%1$S': %2$S
-validator.invalidProjectType=Unknown project type '%S'
+validator.invalidHostedManifestURL=Invalid hosted manifest URL ‘%1$S’: %2$S
+validator.invalidProjectType=Unknown project type ‘%S’
 # LOCALIZATION NOTE (validator.missNameManifestProperty, validator.missIconsManifestProperty):
 # don't translate 'icons' and 'name'.
-validator.missNameManifestProperty=Missing mandatory 'name' in Manifest.
-validator.missIconsManifestProperty=Missing 'icons' in Manifest.
+validator.missNameManifestProperty=Missing mandatory ‘name’ in Manifest.
+validator.missIconsManifestProperty=Missing ‘icons’ in Manifest.
 validator.missIconMarketplace2=app submission to the Marketplace requires a 128px icon
-validator.invalidAppType=Unknown app type: '%S'.
-validator.invalidHostedPriviledges=Hosted App can't be type '%S'.
-validator.noCertifiedSupport='certified' apps are not fully supported on the App manager.
-validator.nonAbsoluteLaunchPath=Launch path has to be an absolute path starting with '/': '%S'
-validator.accessFailedLaunchPath=Unable to access the app starting document '%S'
+validator.invalidAppType=Unknown app type: ‘%S’.
+validator.invalidHostedPriviledges=Hosted App can’t be type ‘%S’.
+validator.noCertifiedSupport=‘certified’ apps are not fully supported on the App manager.
+validator.nonAbsoluteLaunchPath=Launch path has to be an absolute path starting with ‘/’: ‘%S’
+validator.accessFailedLaunchPath=Unable to access the app starting document ‘%S’
 # LOCALIZATION NOTE (validator.accessFailedLaunchPathBadHttpCode): %1$S is the URI of
 # the launch document, %2$S is the http error code.
-validator.accessFailedLaunchPathBadHttpCode=Unable to access the app starting document '%1$S', got HTTP code %2$S
+validator.accessFailedLaunchPathBadHttpCode=Unable to access the app starting document ‘%1$S’, got HTTP code %2$S
--- a/devtools/client/locales/en-US/appcacheutils.properties
+++ b/devtools/client/locales/en-US/appcacheutils.properties
@@ -63,22 +63,22 @@ noResults=Your search returned no result
 
 # LOCALIZATION NOTE (cacheDisabled): it's used when the cache is disabled and
 # an attempt is made to view offline data.
 cacheDisabled=Your disk cache is disabled. Please set browser.cache.disk.enable to true in about:config and try again.
 
 # LOCALIZATION NOTE (firstLineMustBeCacheManifest): the associated cache
 # manifest has a first line that is not "CACHE MANIFEST". Parameters: %S is
 # the line number.
-firstLineMustBeCacheManifest=The first line of the manifest must be "CACHE MANIFEST" at line %S.
+firstLineMustBeCacheManifest=The first line of the manifest must be “CACHE MANIFEST” at line %S.
 
 # LOCALIZATION NOTE (cacheManifestOnlyFirstLine2): the associated cache
 # manifest has "CACHE MANIFEST" on a line other than the first line.
 # Parameters: %S is the line number where "CACHE MANIFEST" appears.
-cacheManifestOnlyFirstLine2="CACHE MANIFEST" is only valid on the first line but was found at line %S.
+cacheManifestOnlyFirstLine2=“CACHE MANIFEST” is only valid on the first line but was found at line %S.
 
 # LOCALIZATION NOTE (asteriskInWrongSection2): the associated cache manifest
 # has an asterisk (*) in a section other than the NETWORK section. Parameters:
 # %1$S is the section name, %2$S is the line number.
 asteriskInWrongSection2=Asterisk (*) incorrectly used in the %1$S section at line %2$S. If a line in the NETWORK section contains only a single asterisk character, then any URI not listed in the manifest will be treated as if the URI was listed in the NETWORK section. Otherwise such URIs will be treated as unavailable. Other uses of the * character are prohibited.
 
 # LOCALIZATION NOTE (escapeSpaces): the associated cache manifest has a space
 # in a URI. Spaces must be replaced with %20. Parameters: %S is the line
@@ -106,17 +106,17 @@ fallbackUseSpaces=Only two URIs separate
 # FALLBACK section that attempts to use an asterisk (*) as a wildcard. In this
 # section the URI is simply a path prefix. Parameters: %S is the line number
 # where this error occurs.
 fallbackAsterisk2=Asterisk (*) incorrectly used in the FALLBACK section at line %S. URIs in the FALLBACK section simply need to match a prefix of the request URI.
 
 # LOCALIZATION NOTE (settingsBadValue): the associated cache manifest has a
 # SETTINGS section containing something other than the valid "prefer-online"
 # or "fast". Parameters: %S is the line number where this error occurs.
-settingsBadValue=The SETTINGS section may only contain a single value, "prefer-online" or "fast" at line %S.
+settingsBadValue=The SETTINGS section may only contain a single value, “prefer-online” or “fast” at line %S.
 
 # LOCALIZATION NOTE (invalidSectionName): the associated cache manifest
 # contains an invalid section name. Parameters: %1$S is the section name, %2$S
 # is the line number.
 invalidSectionName=Invalid section name (%1$S) at line %2$S.
 
 # LOCALIZATION NOTE (entryNotFound): the requested cache entry that does not
 # exist.
--- a/devtools/client/locales/en-US/canvasdebugger.dtd
+++ b/devtools/client/locales/en-US/canvasdebugger.dtd
@@ -17,17 +17,17 @@
 
 <!-- LOCALIZATION NOTE (canvasDebuggerUI.reloadNotice2): This is the label shown
   -  along with the button that triggers a page refresh. -->
 <!ENTITY canvasDebuggerUI.reloadNotice2   "the page to be able to debug &lt;canvas&gt; contexts.">
 
 <!-- LOCALIZATION NOTE (canvasDebuggerUI.emptyNotice1/2): This is the label shown
   -  in the call list view when empty. -->
 <!ENTITY canvasDebuggerUI.emptyNotice1    "Click on the">
-<!ENTITY canvasDebuggerUI.emptyNotice2    "button to record an animation frame's call stack.">
+<!ENTITY canvasDebuggerUI.emptyNotice2    "button to record an animation frame’s call stack.">
 
 <!-- LOCALIZATION NOTE (canvasDebuggerUI.waitingNotice): This is the label shown
   -  in the call list view while recording a snapshot. -->
 <!ENTITY canvasDebuggerUI.waitingNotice   "Recording an animation cycle…">
 
 <!-- LOCALIZATION NOTE (canvasDebuggerUI.recordSnapshot): This string is displayed
   -  on a button that starts a new snapshot. -->
 <!ENTITY canvasDebuggerUI.recordSnapshot.tooltip "Record the next frame in the animation loop.">
--- a/devtools/client/locales/en-US/connection-screen.dtd
+++ b/devtools/client/locales/en-US/connection-screen.dtd
@@ -19,12 +19,12 @@
 <!ENTITY connectionError "Error:">
 <!ENTITY errorTimeout "Error: connection timeout.">
 <!ENTITY errorRefused "Error: connection refused.">
 <!ENTITY errorUnexpected "Unexpected error.">
 
 <!-- LOCALIZATION NOTE (remoteHelp, remoteDocumentation, remoteHelpSuffix):
 these strings will be concatenated in a single label, remoteDocumentation will
 be used as text for a link to MDN. -->
-<!ENTITY remoteHelp "Firefox Developer Tools can debug remote devices (Firefox for Android and Firefox OS, for example). Make sure that you have turned on the 'Remote debugging' option in the remote device. For more, see the ">
+<!ENTITY remoteHelp "Firefox Developer Tools can debug remote devices (Firefox for Android and Firefox OS, for example). Make sure that you have turned on the ‘Remote debugging’ option in the remote device. For more, see the ">
 <!ENTITY remoteDocumentation "documentation">
 <!ENTITY remoteHelpSuffix ".">
 
--- a/devtools/client/locales/en-US/filterwidget.properties
+++ b/devtools/client/locales/en-US/filterwidget.properties
@@ -8,17 +8,17 @@
 
 # LOCALIZATION NOTE (emptyFilterList):
 # This string is displayed when filter's list is empty
 # (no filter specified / all removed)
 emptyFilterList=No filter specified
 
 # LOCALIZATION NOTE (emptyPresetList):
 # This string is displayed when preset's list is empty
-emptyPresetList=You don't have any saved presets. \
+emptyPresetList=You don’t have any saved presets. \
 You can store filter presets by choosing a name and saving them. \
 Presets are quickly accessible and you can re-use them with ease.
 
 # LOCALIZATION NOTE (addUsingList):
 # This string is displayed under [emptyFilterList] when filter's
 # list is empty, guiding user to add a filter using the list below it
 addUsingList=Add a filter using the list below
 
--- a/devtools/client/locales/en-US/jsonview.properties
+++ b/devtools/client/locales/en-US/jsonview.properties
@@ -30,17 +30,17 @@ jsonViewer.Save=Save
 jsonViewer.Copy=Copy
 
 # LOCALIZATION NOTE (jsonViewer.PrettyPrint): Label for JSON
 # pretty print action button.
 jsonViewer.PrettyPrint=Pretty Print
 
 # LOCALIZATION NOTE (jsonViewer.reps.more): Label used in arrays
 # that have more items than displayed.
-jsonViewer.reps.more=more...
+jsonViewer.reps.more=more…
 
 # LOCALIZATION NOTE (jsonViewer.filterJSON): Label used in search box
 # at the top right cornder of the JSON Viewer.
 jsonViewer.filterJSON=Filter JSON
 
 # LOCALIZATION NOTE (jsonViewer.reps.reference): Label used for cycle
 # references in an array.
 jsonViewer.reps.reference=Cycle Reference
--- a/devtools/client/locales/en-US/memory.properties
+++ b/devtools/client/locales/en-US/memory.properties
@@ -114,17 +114,17 @@ toolbar.view=View:
 toolbar.view.tooltip=Change the view of the heap snapshot
 
 # LOCALIZATION NOTE (toolbar.view.census): The label for the census view option
 # in the toolbar.
 toolbar.view.census=Aggregate
 
 # LOCALIZATION NOTE (toolbar.view.census.tooltip): The tooltip for the label for
 # the census view option in the toolbar.
-toolbar.view.census.tooltip=View a summary of the heap snapshot's contents by aggregating objects into groups
+toolbar.view.census.tooltip=View a summary of the heap snapshot’s contents by aggregating objects into groups
 
 # LOCALIZATION NOTE (toolbar.view.dominators): The label for the dominators view
 # option in the toolbar.
 toolbar.view.dominators=Dominators
 
 # LOCALIZATION NOTE (toolbar.view.dominators.tooltip): The tooltip for the label
 # for the dominators view option in the toolbar.
 toolbar.view.dominators.tooltip=View the dominator tree and surface the largest structures in the heap snapshot
--- a/devtools/client/locales/en-US/scratchpad.properties
+++ b/devtools/client/locales/en-US/scratchpad.properties
@@ -112,14 +112,14 @@ scratchpad.panelLabel=Scratchpad Panel
 # LOCALIZATION NOTE (scratchpad.tooltip):  This string is displayed in the
 # tooltip of the tab when the Scratchpad is displayed inside the developer tools
 # window.
 scratchpad.tooltip=Scratchpad
 
 # LOCALIZATION NOTE (selfxss.msg): the text that is displayed when
 # a new user of the developer tools pastes code into the console
 # %1 is the text of selfxss.okstring
-selfxss.msg=Scam Warning: Take care when pasting things you don't understand. This could allow attackers to steal your identity or take control of your computer. Please type '%S' in the scratchpad below to allow pasting.
+selfxss.msg=Scam Warning: Take care when pasting things you don’t understand. This could allow attackers to steal your identity or take control of your computer. Please type ‘%S’ in the scratchpad below to allow pasting.
 
 # LOCALIZATION NOTE (selfxss.msg): the string to be typed
 # in by a new user of the developer tools when they receive the sefxss.msg prompt.
 # Please avoid using non-keyboard characters here
 selfxss.okstring=allow pasting
--- a/devtools/client/locales/en-US/styleeditor.properties
+++ b/devtools/client/locales/en-US/styleeditor.properties
@@ -35,17 +35,17 @@ ruleCount.label=#1 rule.;#1 rules.
 # LOCALIZATION NOTE  (error-load): This is shown when loading fails.
 error-load=Style sheet could not be loaded.
 
 # LOCALIZATION NOTE  (error-save): This is shown when saving fails.
 error-save=Style sheet could not be saved.
 
 # LOCALIZATION NOTE  (error-compressed): This is shown when we can't show
 # coverage information because the css source is compressed.
-error-compressed=Can't show coverage information for compressed stylesheets
+error-compressed=Can’t show coverage information for compressed stylesheets
 
 # LOCALIZATION NOTE  (importStyleSheet.title): This is the file picker title,
 # when you import a style sheet into the Style Editor.
 importStyleSheet.title=Import style sheet
 
 # LOCALIZATION NOTE  (importStyleSheet.filter): This is the *.css filter title
 importStyleSheet.filter=CSS files
 
--- a/devtools/client/locales/en-US/webconsole.properties
+++ b/devtools/client/locales/en-US/webconsole.properties
@@ -34,17 +34,17 @@ update.button=Update
 update.accesskey=U
 cmd.commandkey=K
 webConsoleCmd.accesskey=W
 
 # LOCALIZATION NOTE (timestampFormat): %1$02S = hours (24-hour clock),
 # %2$02S = minutes, %3$02S = seconds, %4$03S = milliseconds.
 timestampFormat=%02S:%02S:%02S.%03S
 
-helperFuncUnsupportedTypeError=Can't call pprint on this type of object.
+helperFuncUnsupportedTypeError=Can’t call pprint on this type of object.
 
 # LOCALIZATION NOTE (NetworkPanel.deltaDurationMS): this string is used to
 # show the duration between two network events (e.g request and response
 # header or response header and response body). Parameters: %S is the duration.
 NetworkPanel.durationMS=%Sms
 
 ConsoleAPIDisabled=The Web Console logging API (console.log, console.info, console.warn, console.error) has been disabled by a script on this page.
 
@@ -214,17 +214,17 @@ openNodeInInspector=Click to select the 
 
 # LOCALIZATION NOTE (cdFunctionInvalidArgument): the text that is displayed when
 # cd() is invoked with an invalid argument.
 cdFunctionInvalidArgument=Cannot cd() to the given window. Invalid argument.
 
 # LOCALIZATION NOTE (selfxss.msg): the text that is displayed when
 # a new user of the developer tools pastes code into the console
 # %1 is the text of selfxss.okstring
-selfxss.msg=Scam Warning: Take care when pasting things you don't understand. This could allow attackers to steal your identity or take control of your computer. Please type '%S' below (no need to press enter) to allow pasting.
+selfxss.msg=Scam Warning: Take care when pasting things you don’t understand. This could allow attackers to steal your identity or take control of your computer. Please type ‘%S’ below (no need to press enter) to allow pasting.
 
 # LOCALIZATION NOTE (selfxss.msg): the string to be typed
 # in by a new user of the developer tools when they receive the sefxss.msg prompt.
 # Please avoid using non-keyboard characters here
 selfxss.okstring=allow pasting
 
 # LOCALIZATION NOTE (messageToggleDetails): the text that is displayed when
 # you hover the arrow for expanding/collapsing the message details. For
--- a/devtools/client/locales/en-US/webide.dtd
+++ b/devtools/client/locales/en-US/webide.dtd
@@ -80,17 +80,17 @@
 <!ENTITY projectPanel_runtimeApps "Runtime Apps">
 <!ENTITY projectPanel_tabs "Tabs">
 <!ENTITY runtimePanel_usb "USB Devices">
 <!ENTITY runtimePanel_wifi "Wi-Fi Devices">
 <!ENTITY runtimePanel_simulator "Simulators">
 <!ENTITY runtimePanel_other "Other">
 <!ENTITY runtimePanel_installsimulator "Install Simulator">
 <!ENTITY runtimePanel_noadbhelper "Install ADB Helper">
-<!ENTITY runtimePanel_nousbdevice "Can't see your device?">
+<!ENTITY runtimePanel_nousbdevice "Can’t see your device?">
 <!ENTITY runtimePanel_refreshDevices_label "Refresh Devices">
 
 <!-- Lense -->
 <!ENTITY details_valid_header "valid">
 <!ENTITY details_warning_header "warnings">
 <!ENTITY details_error_header "errors">
 <!ENTITY details_description "Description">
 <!ENTITY details_location "Location">
--- a/devtools/client/locales/en-US/webide.properties
+++ b/devtools/client/locales/en-US/webide.properties
@@ -26,48 +26,48 @@ notification_showTroubleShooting_label=T
 notification_showTroubleShooting_accesskey=T
 
 # LOCALIZATION NOTE (project_tab_loading): This is shown as a temporary tab
 # title for browser tab projects when the tab is still loading.
 project_tab_loading=Loading…
 
 # These messages appear in a notification box when an error occur.
 
-error_cantInstallNotFullyConnected=Can't install project. Not fully connected.
-error_cantInstallValidationErrors=Can't install project. Validation errors.
-error_listRunningApps=Can't get app list from device
+error_cantInstallNotFullyConnected=Can’t install project. Not fully connected.
+error_cantInstallValidationErrors=Can’t install project. Validation errors.
+error_listRunningApps=Can’t get app list from device
 
 # Variable: name of the operation (in english)
 error_operationTimeout=Operation timed out: %1$S
 error_operationFail=Operation failed: %1$S
 
 # Variable: app name
-error_cantConnectToApp=Can't connect to app: %1$S
+error_cantConnectToApp=Can’t connect to app: %1$S
 
 # Variable: error message (in english)
-error_cantFetchAddonsJSON=Can't fetch the add-on list: %S
+error_cantFetchAddonsJSON=Can’t fetch the add-on list: %S
 
-error_appProjectsLoadFailed=Unable to load project list. This can occur if you've used this profile with a newer version of Firefox.
+error_appProjectsLoadFailed=Unable to load project list. This can occur if you’ve used this profile with a newer version of Firefox.
 error_folderCreationFailed=Unable to create project folder in the selected directory.
 
 # Variable: runtime app build ID (looks like this %Y%M%D format) and firefox build ID (same format)
 error_runtimeVersionTooRecent=The connected runtime has a more recent build date (%1$S) than your desktop Firefox (%2$S) does. This is an unsupported setup and may cause DevTools to fail. Please update Firefox.
 
 addons_stable=stable
 addons_unstable=unstable
 # LOCALIZATION NOTE (addons_simulator_label): This label is shown as the name of
 # a given simulator version in the "Manage Simulators" pane.  %1$S: Firefox OS
 # version in the simulator, ex. 1.3.  %2$S: Simulator stability label, ex.
 # "stable" or "unstable".
 addons_simulator_label=Firefox OS %1$S Simulator (%2$S)
 addons_install_button=install
 addons_uninstall_button=uninstall
 addons_adb_label=ADB Helper Add-on
 addons_adapters_label=Tools Adapters Add-on
-addons_adb_warning=USB devices won't be detected without this add-on
+addons_adb_warning=USB devices won’t be detected without this add-on
 addons_status_unknown=?
 addons_status_installed=Installed
 addons_status_uninstalled=Not Installed
 addons_status_preparing=preparing
 addons_status_downloading=downloading
 addons_status_installing=installing
 
 runtimedetails_checkno=no
--- a/devtools/client/styleeditor/test/browser_styleeditor_cmd_edit.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_cmd_edit.js
@@ -65,17 +65,17 @@ add_task(function* () {
         hints: "://example.com/browser/devtools/client/styleeditor/test/" +
                "resources_inpage1.css [line]",
         markup: "VVVVVIIII",
         status: "ERROR",
         args: {
           resource: {
             arg: " http",
             status: "INCOMPLETE",
-            message: "Value required for \'resource\'."
+            message: "Value required for \u2018resource\u2019."
           },
           line: { status: "VALID" },
         }
       },
     },
     {
       setup: "edit page1",
       check: {
@@ -83,17 +83,17 @@ add_task(function* () {
         hints: " [line] -> http://example.com/browser/devtools/client/" +
                "styleeditor/test/resources_inpage1.css",
         markup: "VVVVVIIIII",
         status: "ERROR",
         args: {
           resource: {
             arg: " page1",
             status: "INCOMPLETE",
-            message: "Value required for \'resource\'."
+            message: "Value required for \u2018resource\u2019."
           },
           line: { status: "VALID" },
         }
       },
     },
     {
       setup: "edit page2",
       check: {
@@ -101,33 +101,33 @@ add_task(function* () {
         hints: " [line] -> http://example.com/browser/devtools/client/" +
                "styleeditor/test/resources_inpage2.css",
         markup: "VVVVVIIIII",
         status: "ERROR",
         args: {
           resource: {
             arg: " page2",
             status: "INCOMPLETE",
-            message: "Value required for \'resource\'."
+            message: "Value required for \u2018resource\u2019."
           },
           line: { status: "VALID" },
         }
       },
     },
     {
       setup: "edit stylez",
       check: {
         input: "edit stylez",
         hints: " [line]",
         markup: "VVVVVEEEEEE",
         status: "ERROR",
         args: {
           resource: {
             arg: " stylez",
-            status: "ERROR", message: "Can\'t use \'stylez\'." },
+            status: "ERROR", message: "Can\u2019t use \u2018stylez\u2019." },
           line: { status: "VALID" },
         }
       },
     },
     {
       setup: "edit css#style2",
       check: {
         input: "edit css#style2",
--- a/devtools/shared/locales/en-US/csscoverage.dtd
+++ b/devtools/shared/locales/en-US/csscoverage.dtd
@@ -26,17 +26,17 @@
 <!ENTITY csscoverage.optimize.header "Optimizable Pages">
 
 <!-- LOCALIZATION NOTE (csscoverage.preload1, csscoverage.preload2,
   -  csscoverage.preload3): These 3 are part of a paragraph with 1 and 2
   -  separated by a styled <link> tag and 2 and 3 separated by a styled
   -  <style> tag -->
 <!ENTITY csscoverage.optimize.body1 "You can sometimes speed up loading by moving">
 <!ENTITY csscoverage.optimize.body2 "tags to the bottom of the page and creating a new inline">
-<!ENTITY csscoverage.optimize.body3 "element with the styles needed before the 'load' event to the top. Here are the style blocks you need:">
+<!ENTITY csscoverage.optimize.body3 "element with the styles needed before the ‘load’ event to the top. Here are the style blocks you need:">
 
 <!-- LOCALIZATION NOTE (csscoverage.optimize.bodyX):
   -  This is what we say when we have no optimization suggestions -->
 <!ENTITY csscoverage.optimize.bodyX "All rules are inlined.">
 
 <!-- LOCALIZATION NOTE (csscoverage.footer1, csscoverage.footer2a,
   -  csscoverage.footer3, csscoverage.footer4): The text displayed at the
   -  bottom of the page, with 2a being the URL opened when the link text in 3
--- a/devtools/shared/locales/en-US/csscoverage.properties
+++ b/devtools/shared/locales/en-US/csscoverage.properties
@@ -9,24 +9,24 @@
 # csscoverageStopDesc2, csscoverageOneShotDesc2, csscoverageToggleDesc2,
 # csscoverageReportDesc2): Short descriptions of the csscoverage commands
 csscoverageDesc=Control CSS coverage analysis
 csscoverageStartDesc2=Begin collecting CSS coverage data
 csscoverageStopDesc2=Stop collecting CSS coverage data
 csscoverageOneShotDesc2=Collect instantaneous CSS coverage data
 csscoverageToggleDesc2=Toggle collecting CSS coverage data
 csscoverageReportDesc2=Show CSS coverage report
-csscoverageStartNoReloadDesc=Don't start with a page reload
-csscoverageStartNoReloadManual=It's best if we start by reloading the current page because that starts the test at a known point, but there could be reasons why we don't want to do that (e.g. the page contains state that will be lost across a reload)
+csscoverageStartNoReloadDesc=Don’t start with a page reload
+csscoverageStartNoReloadManual=It’s best if we start by reloading the current page because that starts the test at a known point, but there could be reasons why we don’t want to do that (e.g. the page contains state that will be lost across a reload)
 
 # LOCALIZATION NOTE (csscoverageRunningReply, csscoverageDoneReply): Text that
 # describes the current state of the css coverage system
 csscoverageRunningReply=Running CSS coverage analysis
 csscoverageDoneReply=CSS Coverage analysis completed
 
 # LOCALIZATION NOTE (csscoverageRunningError, csscoverageNotRunningError,
 # csscoverageNotRunError): Error message that describe things that can go wrong
 # with the css coverage system
 csscoverageRunningError=CSS coverage analysis already running
 csscoverageNotRunningError=CSS coverage analysis not running
 csscoverageNotRunError=CSS coverage analysis has not been run
 csscoverageNoRemoteError=Target does not support CSS Coverage
-csscoverageOneShotReportError=CSS coverage report is not available for 'oneshot' data. Please use start/stop.
+csscoverageOneShotReportError=CSS coverage report is not available for ‘oneshot’ data. Please use start/stop.
--- a/devtools/shared/locales/en-US/gcli.properties
+++ b/devtools/shared/locales/en-US/gcli.properties
@@ -30,103 +30,103 @@ canonDefaultGroupName=Options
 # LOCALIZATION NOTE (canonProxyDesc, canonProxyManual): These commands are
 # used to execute commands on a remote system (using a proxy). Parameters: %S
 # is the name of the remote system.
 canonProxyDesc=Execute a command on %S
 canonProxyManual=A set of commands that are executed on a remote system. The remote system is reached via %S
 
 # LOCALIZATION NOTE: This error message is displayed when we try to add a new
 # command (using a proxy) where one already exists with the same name.
-canonProxyExists=There is already a command called '%S'
+canonProxyExists=There is already a command called ‘%S’
 
 # LOCALIZATION NOTE: This message describes the '{' command, which allows
 # entry of JavaScript like traditional developer tool command lines.
 cliEvalJavascript=Enter JavaScript directly
 
 # LOCALIZATION NOTE: This message is displayed when the command line has more
 # arguments than the current command can understand.
 cliUnusedArg=Too many arguments
 
 # LOCALIZATION NOTE: The title of the dialog which displays the options that
 # are available to the current command.
 cliOptions=Available Options
 
 # LOCALIZATION NOTE: The error message when the user types a command that
 # isn't registered
-cliUnknownCommand2=Invalid Command: '%1$S'.
+cliUnknownCommand2=Invalid Command: ‘%1$S’.
 
 # LOCALIZATION NOTE: A parameter should have a value, but doesn't
-cliIncompleteParam=Value required for '%1$S'.
+cliIncompleteParam=Value required for ‘%1$S’.
 
 # LOCALIZATION NOTE: Error message given when a file argument points to a file
 # that does not exist, but should (e.g. for use with File->Open) %1$S is a
 # filename
-fileErrNotExists='%1$S' doesn't exist
+fileErrNotExists=‘%1$S’ doesn’t exist
 
 # LOCALIZATION NOTE: Error message given when a file argument points to a file
 # that exists, but should not (e.g. for use with File->Save As) %1$S is a
 # filename
-fileErrExists='%1$S' already exists
+fileErrExists=‘%1$S’ already exists
 
 # LOCALIZATION NOTE: Error message given when a file argument points to a
 # non-file, when a file is needed. %1$S is a filename
-fileErrIsNotFile='%1$S' is not a file
+fileErrIsNotFile=‘%1$S’ is not a file
 
 # LOCALIZATION NOTE: Error message given when a file argument points to a
 # non-directory, when a directory is needed (e.g. for use with 'cd') %1$S is a
 # filename
-fileErrIsNotDirectory='%1$S' is not a directory
+fileErrIsNotDirectory=‘%1$S’ is not a directory
 
 # LOCALIZATION NOTE: Error message given when a file argument does not match
 # the specified regular expression %1$S is a filename %2$S is a regular
 # expression
-fileErrDoesntMatch='%1$S' does not match '%2$S'
+fileErrDoesntMatch=‘%1$S’ does not match ‘%2$S’
 
 # LOCALIZATION NOTE: When the menu has displayed all the matches that it
 # should (i.e. about 10 items) then we display this to alert the user that
 # more matches are available.
 fieldMenuMore=More matches, keep typing
 
 # LOCALIZATION NOTE: The command line provides completion for JavaScript
 # commands, however there are times when the scope of what we're completing
 # against can't be used. This error message is displayed when this happens.
 jstypeParseScope=Scope lost
 
 # LOCALIZATION NOTE (jstypeParseMissing, jstypeBeginSyntax,
 # jstypeBeginUnterm): These error messages are displayed when the command line
 # is doing JavaScript completion and encounters errors.
-jstypeParseMissing=Can't find property '%S'
+jstypeParseMissing=Can’t find property ‘%S’
 jstypeBeginSyntax=Syntax error
 jstypeBeginUnterm=Unterminated string literal
 
 # LOCALIZATION NOTE: This message is displayed if the system for providing
 # JavaScript completions encounters and error it displays this.
 jstypeParseError=Error
 
 # LOCALIZATION NOTE (typesNumberNan, typesNumberNotInt2, typesDateNan): These
 # error messages are displayed when the command line is passed a variable
 # which has the wrong format and can't be converted. Parameters: %S is the
 # passed variable.
-typesNumberNan=Can't convert "%S" to a number.
-typesNumberNotInt2=Can't convert "%S" to an integer.
-typesDateNan=Can't convert "%S" to a date.
+typesNumberNan=Can’t convert “%S” to a number.
+typesNumberNotInt2=Can’t convert “%S” to an integer.
+typesDateNan=Can’t convert “%S” to a date.
 
 # LOCALIZATION NOTE (typesNumberMax, typesNumberMin, typesDateMax,
 # typesDateMin): These error messages are displayed when the command line is
 # passed a variable which has a value out of range (number or date).
 # Parameters: %1$S is the passed variable, %2$S is the limit value.
 typesNumberMax=%1$S is greater than maximum allowed: %2$S.
 typesNumberMin=%1$S is smaller than minimum allowed: %2$S.
 typesDateMax=%1$S is later than maximum allowed: %2$S.
 typesDateMin=%1$S is earlier than minimum allowed: %2$S.
 
 # LOCALIZATION NOTE: This error message is displayed when the command line is
 # passed an option with a limited number of correct values, but the passed
 # value is not one of them.
-typesSelectionNomatch=Can't use '%S'.
+typesSelectionNomatch=Can’t use ‘%S’.
 
 # LOCALIZATION NOTE: This error message is displayed when the command line is
 # expecting a CSS query string, however the passed string is not valid.
 nodeParseSyntax=Syntax error in CSS query
 
 # LOCALIZATION NOTE (nodeParseMultiple, nodeParseNone): These error messages
 # are displayed when the command line is expecting a CSS string that matches a
 # single node, but more nodes (or none) match.
@@ -152,18 +152,18 @@ helpManNone=None
 # LOCALIZATION NOTE: This message is displayed in response to the 'help'
 # command when used without a filter, just above the list of known commands.
 helpListAll=Available Commands:
 
 # LOCALIZATION NOTE (helpListPrefix, helpListNone): These messages are
 # displayed in response to the 'help <search>' command (i.e. with a search
 # string), just above the list of matching commands. Parameters: %S is the
 # search string.
-helpListPrefix=Commands starting with '%S':
-helpListNone=No commands starting with '%S'
+helpListPrefix=Commands starting with ‘%S’:
+helpListNone=No commands starting with ‘%S’
 
 # LOCALIZATION NOTE (helpManRequired, helpManOptional, helpManDefault): When
 # the 'help x' command wants to show the manual for the 'x' command, it needs
 # to be able to describe the parameters as either required or optional, or if
 # they have a default value.
 helpManRequired=required
 helpManOptional=optional
 helpManDefault=optional, default=%S
@@ -181,22 +181,22 @@ subCommands=Sub-Commands
 # cannot find a match for the parse types.
 commandParseError=Command line parsing error
 
 # LOCALIZATION NOTE (contextDesc, contextManual, contextPrefixDesc): These
 # strings are used to describe the 'context' command and its 'prefix'
 # parameter. See localization comment for 'connect' for an explanation about
 # 'prefix'.
 contextDesc=Concentrate on a group of commands
-contextManual=Setup a default prefix to future commands. For example 'context git' would allow you to type 'commit' rather than 'git commit'.
+contextManual=Setup a default prefix to future commands. For example ‘context git’ would allow you to type ‘commit’ rather than ‘git commit’.
 contextPrefixDesc=The command prefix
 
 # LOCALIZATION NOTE: This message message displayed during the processing of
 # the 'context' command, when the found command is not a parent command.
-contextNotParentError=Can't use '%S' as a prefix because it is not a parent command.
+contextNotParentError=Can’t use ‘%S’ as a prefix because it is not a parent command.
 
 # LOCALIZATION NOTE (contextReply, contextEmptyReply): These messages are
 # displayed during the processing of the 'context' command, to indicate
 # success or that there is no command prefix.
 contextReply=Using %S as a command prefix
 contextEmptyReply=Command prefix is unset
 
 # LOCALIZATION NOTE (connectDesc, connectManual, connectPrefixDesc,
@@ -246,17 +246,17 @@ langOutput=You are now using %S
 
 # LOCALIZATION NOTE (prefDesc, prefManual, prefListDesc, prefListManual,
 # prefListSearchDesc, prefListSearchManual, prefShowDesc, prefShowManual,
 # prefShowSettingDesc, prefShowSettingManual): These strings describe the
 # 'pref' command and all its available sub-commands and parameters.
 prefDesc=Commands to control settings
 prefManual=Commands to display and alter preferences both for GCLI and the surrounding environment
 prefListDesc=Display available settings
-prefListManual=Display a list of preferences, optionally filtered when using the 'search' parameter
+prefListManual=Display a list of preferences, optionally filtered when using the ‘search’ parameter
 prefListSearchDesc=Filter the list of settings displayed
 prefListSearchManual=Search for the given string in the list of available preferences
 prefShowDesc=Display setting value
 prefShowManual=Display the value of a given preference
 prefShowSettingDesc=Setting to display
 prefShowSettingManual=The name of the setting to display
 
 # LOCALIZATION NOTE: This message is used to show the preference name and the
@@ -291,17 +291,17 @@ prefOutputFilter=Filter
 # displayed in the output from the 'pref list' command as table headings.
 prefOutputName=Name
 prefOutputValue=Value
 
 # LOCALIZATION NOTE (introDesc, introManual): These strings describe the
 # 'intro' command. The localization of 'Got it!' should be the same used in
 # introTextGo.
 introDesc=Show the opening message
-introManual=Redisplay the message that is shown to new users until they click the 'Got it!' button
+introManual=Redisplay the message that is shown to new users until they click the ‘Got it!’ button
 
 # LOCALIZATION NOTE (introTextOpening3, introTextCommands, introTextKeys2,
 # introTextF1Escape, introTextGo): These strings are displayed when the user
 # first opens the developer toolbar to explain the command line, and is shown
 # each time it is opened until the user clicks the 'Got it!' button.
 introTextOpening3=GCLI is an experiment to create a highly usable command line for web developers.
 introTextCommands=For a list of commands type
 introTextKeys2=, or to show/hide command hints press
--- a/devtools/shared/locales/en-US/gclicommands.properties
+++ b/devtools/shared/locales/en-US/gclicommands.properties
@@ -17,17 +17,17 @@
 helpDesc=Get help on the available commands
 
 # LOCALIZATION NOTE (helpAvailable) Used in the output of the help command to
 # explain the contents of the command help table.
 helpAvailable=Available Commands
 
 # LOCALIZATION NOTE (notAvailableInE10S) Used in the output of any command that
 # is not compatible with multiprocess mode (E10S).
-notAvailableInE10S=The command '%1$S' is not available in multiprocess mode (E10S)
+notAvailableInE10S=The command ‘%1$S’ is not available in multiprocess mode (E10S)
 
 # LOCALIZATION NOTE (consoleDesc) A very short string used to describe the
 # function of the console command.
 consoleDesc=Commands to control the console
 
 # LOCALIZATION NOTE (consoleManual) A longer description describing the
 # set of commands that control the console.
 consoleManual=Filter, clear and close the web console
@@ -49,17 +49,17 @@ screenshotManual=Save a PNG image of the
 # LOCALIZATION NOTE (screenshotFilenameDesc) A very short string to describe
 # the 'filename' parameter to the 'screenshot' command, which is displayed in
 # a dialog when the user is using this command.
 screenshotFilenameDesc=Destination filename
 
 # LOCALIZATION NOTE (screenshotFilenameManual) A fuller description of the
 # 'filename' parameter to the 'screenshot' command, displayed when the user
 # asks for help on what it does.
-screenshotFilenameManual=The name of the file (should have a '.png' extension) to which we write the screenshot.
+screenshotFilenameManual=The name of the file (should have a ‘.png’ extension) to which we write the screenshot.
 
 # LOCALIZATION NOTE (screenshotClipboardDesc) A very short string to describe
 # the 'clipboard' parameter to the 'screenshot' command, which is displayed in
 # a dialog when the user is using this command.
 screenshotClipboardDesc=Copy screenshot to clipboard? (true/false)
 
 # LOCALIZATION NOTE (screenshotClipboardManual) A fuller description of the
 # 'clipboard' parameter to the 'screenshot' command, displayed when the user
@@ -71,17 +71,17 @@ screenshotClipboardManual=True if you wa
 # a dialog when the user is using this command.
 # The argument (%1$S) is the browser name.
 screenshotChromeDesc2=Capture %1$S chrome window? (true/false)
 
 # LOCALIZATION NOTE (screenshotChromeManual) A fuller description of the
 # 'chrome' parameter to the 'screenshot' command, displayed when the user
 # asks for help on what it does.
 # The argument (%1$S) is the browser name.
-screenshotChromeManual2=True if you want to take the screenshot of the %1$S window rather than the web page's content window.
+screenshotChromeManual2=True if you want to take the screenshot of the %1$S window rather than the web page’s content window.
 
 # LOCALIZATION NOTE (screenshotGroupOptions) A label for the optional options of
 # the screenshot command.
 screenshotGroupOptions=Options
 
 # LOCALIZATION NOTE (screenshotGroupOptions) A label for the advanced options of
 # the screenshot command.
 screenshotAdvancedOptions=Advanced Options
@@ -222,17 +222,17 @@ highlightShowAllManual=If too many nodes
 # LOCALIZATION NOTE (highlightRegionDesc) A very short string to describe the
 # 'region' option parameter to the 'highlight' command, which is displayed in a
 # dialog when the user is using this command.
 highlightRegionDesc=Box model region
 
 # LOCALIZATION NOTE (highlightRegionManual) A fuller description of the 'region'
 # option parameter to the 'highlight' command, displayed when the user asks for
 # help on what it does.
-highlightRegionManual=Which box model region should be highlighted: 'content', 'padding', 'border' or 'margin'
+highlightRegionManual=Which box model region should be highlighted: ‘content’, ‘padding’, ‘border’ or ‘margin’
 
 # LOCALIZATION NOTE (highlightFillDesc) A very short string to describe the
 # 'fill' option parameter to the 'highlight' command, which is displayed in a
 # dialog when the user is using this command.
 highlightFillDesc=Fill style
 
 # LOCALIZATION NOTE (highlightFillManual) A fuller description of the 'fill'
 # option parameter to the 'highlight' command, displayed when the user asks for
@@ -255,27 +255,27 @@ highlightKeepManual=By default, existing
 # to turn highlighting off
 highlightOutputConfirm2=%1$S node highlighted;%1$S nodes highlighted
 
 # LOCALIZATION NOTE (highlightOutputMaxReached) A confirmation message for the
 # 'highlight' command, displayed to the user once the command has been entered,
 # informing the user how many nodes have been highlighted successfully and that
 # some nodes could not be highlighted due to the maximum number of nodes being
 # reached, and how to turn highlighting off
-highlightOutputMaxReached=%1$S nodes matched, but only %2$S nodes highlighted. Use '--showall' to show all
+highlightOutputMaxReached=%1$S nodes matched, but only %2$S nodes highlighted. Use ‘--showall’ to show all
 
 # LOCALIZATION NOTE (unhighlightDesc) A very short description of the
 # 'unhighlight' command. See unhighlightManual for a fuller description of what
 # it does. This string is designed to be shown in a menu alongside the
 # command name, which is why it should be as short as possible.
 unhighlightDesc=Unhighlight all nodes
 
 # LOCALIZATION NOTE (unhighlightManual) A fuller description of the 'unhighlight'
 # command, displayed when the user asks for help on what it does.
-unhighlightManual=Unhighlight all nodes previously highlighted with the 'highlight' command
+unhighlightManual=Unhighlight all nodes previously highlighted with the ‘highlight’ command
 
 # LOCALIZATION NOTE (restartBrowserDesc) A very short description of the
 # 'restart' command. This string is designed to be shown in a menu alongside the
 # command name, which is why it should be as short as possible.
 # The argument (%1$S) is the browser name.
 restartBrowserDesc=Restart %1$S
 
 # LOCALIZATION NOTE (restartBrowserNocacheDesc) A very short string to
@@ -456,17 +456,17 @@ dbgListSourcesDesc=List the source URLs 
 dbgBlackBoxDesc=Black box sources in the debugger
 
 # LOCALIZATION NOTE (dbgBlackBoxSourceDesc) A very short string used to describe the
 # 'source' parameter to the 'dbg blackbox' command.
 dbgBlackBoxSourceDesc=A specific source to black box
 
 # LOCALIZATION NOTE (dbgBlackBoxGlobDesc) A very short string used to describe the
 # 'glob' parameter to the 'dbg blackbox' command.
-dbgBlackBoxGlobDesc=Black box all sources that match this glob (for example: "*.min.js")
+dbgBlackBoxGlobDesc=Black box all sources that match this glob (for example: “*.min.js”)
 
 # LOCALIZATION NOTE (dbgBlackBoxInvertDesc) A very short string used to describe the
 # 'invert' parameter to the 'dbg blackbox' command.
 dbgBlackBoxInvertDesc=Invert matching, so that we black box every source that is not the source provided or does not match the provided glob pattern.
 
 # LOCALIZATION NOTE (dbgBlackBoxEmptyDesc) A very short string used to let the
 # user know that no sources were black boxed.
 dbgBlackBoxEmptyDesc=(No sources black boxed)
@@ -485,17 +485,17 @@ dbgBlackBoxErrorDesc=Error black boxing:
 dbgUnBlackBoxDesc=Stop black boxing sources in the debugger
 
 # LOCALIZATION NOTE (dbgUnBlackBoxSourceDesc) A very short string used to describe the
 # 'source' parameter to the 'dbg unblackbox' command.
 dbgUnBlackBoxSourceDesc=A specific source to stop black boxing
 
 # LOCALIZATION NOTE (dbgUnBlackBoxGlobDesc) A very short string used to describe the
 # 'glob' parameter to the 'dbg blackbox' command.
-dbgUnBlackBoxGlobDesc=Stop black boxing all sources that match this glob (for example: "*.min.js")
+dbgUnBlackBoxGlobDesc=Stop black boxing all sources that match this glob (for example: “*.min.js”)
 
 # LOCALIZATION NOTE (dbgUnBlackBoxEmptyDesc) A very short string used to let the
 # user know that we did not stop black boxing any sources.
 dbgUnBlackBoxEmptyDesc=(Did not stop black boxing any sources)
 
 # LOCALIZATION NOTE (dbgUnBlackBoxNonEmptyDesc) A very short string used to let the
 # user know which sources we stopped black boxing.
 dbgUnBlackBoxNonEmptyDesc=Stopped black boxing the following sources:
@@ -595,26 +595,26 @@ cmdDesc=Manipulate the commands
 
 # LOCALIZATION NOTE (cmdRefreshDesc) A very short description of the 'cmd refresh'
 # command. This string is designed to be shown in a menu alongside the command
 # name, which is why it should be as short as possible.
 cmdRefreshDesc=Re-read mozcmd directory
 
 # LOCALIZATION NOTE (cmdStatus3) When the we load new commands from mozcmd
 # directory, we report where we loaded from using %1$S.
-cmdStatus3=Loaded commands from '%1$S'
+cmdStatus3=Loaded commands from ‘%1$S’
 
 # LOCALIZATION NOTE (cmdSetdirDesc)  A very short description of the 'cmd setdir'
 # command. This string is designed to be shown in a menu alongside the command
 # name, which is why it should be as short as possible.
 cmdSetdirDesc=Setup a mozcmd directory
 
 # LOCALIZATION NOTE (cmdSetdirManual2) A fuller description of the 'cmd setdir'
 # command, displayed when the user asks for help on what it does.
-cmdSetdirManual2=A 'mozcmd' directory is an easy way to create new custom commands. For more information see the <a href="https://developer.mozilla.org/docs/Tools/GCLI/Customization">MDN documentation</a>.
+cmdSetdirManual2=A ‘mozcmd’ directory is an easy way to create new custom commands. For more information see the <a href="https://developer.mozilla.org/docs/Tools/GCLI/Customization">MDN documentation</a>.
 
 # LOCALIZATION NOTE (cmdSetdirDirectoryDesc) The description of the directory
 # parameter to the 'cmd setdir' command.
 cmdSetdirDirectoryDesc=Directory containing .mozcmd files
 
 # LOCALIZATION NOTE (addonDesc) A very short description of the 'addon'
 # command. This string is designed to be shown in a menu alongside the command
 # name, which is why it should be as short as possible.
@@ -1214,17 +1214,17 @@ callLogChromeVarNotFoundChrome=Variable 
 # LOCALIZATION NOTE (callLogChromeEvalException) A string displayed as the
 # result of the 'calllog chromestart' command with a source type of JavaScript
 # and invalid JavaScript code.
 callLogChromeEvalException=Evaluated JavaScript threw the following exception
 
 # LOCALIZATION NOTE (callLogChromeEvalNeedsObject) A string displayed as the
 # result of passing a non-JavaScript object creating source via the
 # 'calllog chromestart javascript' command.
-callLogChromeEvalNeedsObject=The JavaScript source must evaluate to an object whose method calls are to be logged e.g. "({a1: function() {this.a2()},a2: function() {}});"
+callLogChromeEvalNeedsObject=The JavaScript source must evaluate to an object whose method calls are to be logged e.g. “({a1: function() {this.a2()},a2: function() {}});”
 
 # LOCALIZATION NOTE (scratchpadOpenTooltip) A string displayed as the
 # tooltip of button in devtools toolbox which opens Scratchpad.
 scratchpadOpenTooltip=Scratchpad
 
 # LOCALIZATION NOTE (paintflashingDesc) A very short string used to describe the
 # function of the "paintflashing" command
 paintflashingDesc=Highlight painted area
@@ -1383,17 +1383,17 @@ profilerAlreadyStarted2=Profile has alre
 # an operation cannot be completed because the profile in question could not be
 # found.
 profilerNotFound=Profile not found
 
 # LOCALIZATION NOTE (profilerNotStarted) A message that is displayed whenever
 # an operation cannot be completed because the profile in question has not been
 # started yet. It also contains a hint to use the 'profile start' command to
 # start the profiler.
-profilerNotStarted3=Profiler has not been started yet. Use 'profile start' to start profiling
+profilerNotStarted3=Profiler has not been started yet. Use ‘profile start’ to start profiling
 
 # LOCALIZATION NOTE (profilerStarted2) A very short string that indicates that
 # we have started recording.
 profilerStarted2=Recording…
 
 # LOCALIZATION NOTE (profilerStopped) A very short string that indicates that
 # we have stopped recording.
 profilerStopped=Stopped…
@@ -1486,17 +1486,17 @@ mdnDesc=Retrieve documentation from MDN
 mdnCssDesc=Retrieve documentation about a given CSS property name from MDN
 # LOCALIZATION NOTE (mdnCssProp) String used to describe the 'property name'
 # parameter used in the 'mdn css' command.
 mdnCssProp=Property name
 # LOCALIZATION NOTE (mdnCssPropertyNotFound) String used to display an error in
 # the result of the 'mdn css' command. Errors occur when a given CSS property
 # wasn't found on MDN. The %1$S parameter will be replaced with the name of the
 # CSS property.
-mdnCssPropertyNotFound=MDN documentation for the CSS property '%1$S' was not found.
+mdnCssPropertyNotFound=MDN documentation for the CSS property ‘%1$S’ was not found.
 # LOCALIZATION NOTE (mdnCssVisitPage) String used as the label of a link to the
 # MDN page for a given CSS property.
 mdnCssVisitPage=Visit MDN page
 
 # LOCALIZATION NOTE (security)
 securityPrivacyDesc=Display supported security and privacy features
 securityManual=Commands to list and get suggestions about security features for the current domain.
 securityListDesc=Display security features