Bug 1319629 - Move components/translation from browser to toolkit. draft
authorEitan Isaacson <eitan@monotonous.org>
Tue, 22 Nov 2016 18:17:19 -0800
changeset 447134 b8f069974ac024f254c13d7ed5093b0b9c89e5e9
parent 447133 d6d2b6f795a0bc68345389c114f96aa61d3f16b7
child 447135 4b7faf401053e396a4fbbbd23c4c0a2877467605
push id37997
push userbmo:eitan@monotonous.org
push dateFri, 02 Dec 2016 18:58:57 +0000
bugs1319629
milestone53.0a1
Bug 1319629 - Move components/translation from browser to toolkit. MozReview-Commit-ID: 53fUAA08Ski
browser/base/content/browser.css
browser/components/moz.build
browser/components/preferences/in-content/content.xul
browser/components/translation/BingTranslator.jsm
browser/components/translation/LanguageDetector.jsm
browser/components/translation/Translation.jsm
browser/components/translation/TranslationContentHandler.jsm
browser/components/translation/TranslationDocument.jsm
browser/components/translation/YandexTranslator.jsm
browser/components/translation/cld2/Makefile
browser/components/translation/cld2/cld-worker.js
browser/components/translation/cld2/cld-worker.js.mem
browser/components/translation/cld2/cld.idl
browser/components/translation/cld2/cldapp.cc
browser/components/translation/cld2/internal/LICENSE
browser/components/translation/cld2/internal/cld2_dynamic_data.h
browser/components/translation/cld2/internal/cld2_dynamic_data_loader.h
browser/components/translation/cld2/internal/cld2_generated_cjk_compatible.cc
browser/components/translation/cld2/internal/cld2_generated_deltaoctachrome0122.cc
browser/components/translation/cld2/internal/cld2_generated_distinctoctachrome0122.cc
browser/components/translation/cld2/internal/cld2_generated_quadchrome0122_16.cc
browser/components/translation/cld2/internal/cld2tablesummary.h
browser/components/translation/cld2/internal/cld_generated_cjk_delta_bi_4.cc
browser/components/translation/cld2/internal/cld_generated_cjk_uni_prop_80.cc
browser/components/translation/cld2/internal/cld_generated_score_quad_octa_0122_2.cc
browser/components/translation/cld2/internal/cldutil.cc
browser/components/translation/cld2/internal/cldutil.h
browser/components/translation/cld2/internal/cldutil_shared.cc
browser/components/translation/cld2/internal/cldutil_shared.h
browser/components/translation/cld2/internal/compact_lang_det.cc
browser/components/translation/cld2/internal/compact_lang_det_hint_code.cc
browser/components/translation/cld2/internal/compact_lang_det_hint_code.h
browser/components/translation/cld2/internal/compact_lang_det_impl.cc
browser/components/translation/cld2/internal/compact_lang_det_impl.h
browser/components/translation/cld2/internal/debug.h
browser/components/translation/cld2/internal/debug_empty.cc
browser/components/translation/cld2/internal/fixunicodevalue.cc
browser/components/translation/cld2/internal/fixunicodevalue.h
browser/components/translation/cld2/internal/generated_distinct_bi_0.cc
browser/components/translation/cld2/internal/generated_entities.cc
browser/components/translation/cld2/internal/generated_language.cc
browser/components/translation/cld2/internal/generated_language.h
browser/components/translation/cld2/internal/generated_ulscript.cc
browser/components/translation/cld2/internal/generated_ulscript.h
browser/components/translation/cld2/internal/getonescriptspan.cc
browser/components/translation/cld2/internal/getonescriptspan.h
browser/components/translation/cld2/internal/integral_types.h
browser/components/translation/cld2/internal/lang_script.cc
browser/components/translation/cld2/internal/lang_script.h
browser/components/translation/cld2/internal/langspan.h
browser/components/translation/cld2/internal/offsetmap.cc
browser/components/translation/cld2/internal/offsetmap.h
browser/components/translation/cld2/internal/port.h
browser/components/translation/cld2/internal/scoreonescriptspan.cc
browser/components/translation/cld2/internal/scoreonescriptspan.h
browser/components/translation/cld2/internal/stringpiece.h
browser/components/translation/cld2/internal/tote.cc
browser/components/translation/cld2/internal/tote.h
browser/components/translation/cld2/internal/utf8prop_lettermarkscriptnum.h
browser/components/translation/cld2/internal/utf8repl_lettermarklower.h
browser/components/translation/cld2/internal/utf8scannot_lettermarkspecial.h
browser/components/translation/cld2/internal/utf8statetable.cc
browser/components/translation/cld2/internal/utf8statetable.h
browser/components/translation/cld2/post.js
browser/components/translation/cld2/public/compact_lang_det.h
browser/components/translation/cld2/public/encodings.h
browser/components/translation/jar.mn
browser/components/translation/microsoft-translator-attribution.png
browser/components/translation/moz.build
browser/components/translation/test/.eslintrc.js
browser/components/translation/test/bing.sjs
browser/components/translation/test/browser.ini
browser/components/translation/test/browser_translation_bing.js
browser/components/translation/test/browser_translation_exceptions.js
browser/components/translation/test/browser_translation_infobar.js
browser/components/translation/test/browser_translation_telemetry.js
browser/components/translation/test/browser_translation_yandex.js
browser/components/translation/test/fixtures/bug1022725-fr.html
browser/components/translation/test/fixtures/result-da39a3ee5e.txt
browser/components/translation/test/fixtures/result-yandex-d448894848.json
browser/components/translation/test/unit/.eslintrc.js
browser/components/translation/test/unit/test_cld2.js
browser/components/translation/test/unit/xpcshell.ini
browser/components/translation/test/yandex.sjs
browser/components/translation/translation-infobar.xml
toolkit/components/moz.build
toolkit/components/translation/BingTranslator.jsm
toolkit/components/translation/LanguageDetector.jsm
toolkit/components/translation/Translation.jsm
toolkit/components/translation/TranslationContentHandler.jsm
toolkit/components/translation/TranslationDocument.jsm
toolkit/components/translation/YandexTranslator.jsm
toolkit/components/translation/cld2/Makefile
toolkit/components/translation/cld2/cld-worker.js
toolkit/components/translation/cld2/cld-worker.js.mem
toolkit/components/translation/cld2/cld.idl
toolkit/components/translation/cld2/cldapp.cc
toolkit/components/translation/cld2/internal/LICENSE
toolkit/components/translation/cld2/internal/cld2_dynamic_data.h
toolkit/components/translation/cld2/internal/cld2_dynamic_data_loader.h
toolkit/components/translation/cld2/internal/cld2_generated_cjk_compatible.cc
toolkit/components/translation/cld2/internal/cld2_generated_deltaoctachrome0122.cc
toolkit/components/translation/cld2/internal/cld2_generated_distinctoctachrome0122.cc
toolkit/components/translation/cld2/internal/cld2_generated_quadchrome0122_16.cc
toolkit/components/translation/cld2/internal/cld2tablesummary.h
toolkit/components/translation/cld2/internal/cld_generated_cjk_delta_bi_4.cc
toolkit/components/translation/cld2/internal/cld_generated_cjk_uni_prop_80.cc
toolkit/components/translation/cld2/internal/cld_generated_score_quad_octa_0122_2.cc
toolkit/components/translation/cld2/internal/cldutil.cc
toolkit/components/translation/cld2/internal/cldutil.h
toolkit/components/translation/cld2/internal/cldutil_shared.cc
toolkit/components/translation/cld2/internal/cldutil_shared.h
toolkit/components/translation/cld2/internal/compact_lang_det.cc
toolkit/components/translation/cld2/internal/compact_lang_det_hint_code.cc
toolkit/components/translation/cld2/internal/compact_lang_det_hint_code.h
toolkit/components/translation/cld2/internal/compact_lang_det_impl.cc
toolkit/components/translation/cld2/internal/compact_lang_det_impl.h
toolkit/components/translation/cld2/internal/debug.h
toolkit/components/translation/cld2/internal/debug_empty.cc
toolkit/components/translation/cld2/internal/fixunicodevalue.cc
toolkit/components/translation/cld2/internal/fixunicodevalue.h
toolkit/components/translation/cld2/internal/generated_distinct_bi_0.cc
toolkit/components/translation/cld2/internal/generated_entities.cc
toolkit/components/translation/cld2/internal/generated_language.cc
toolkit/components/translation/cld2/internal/generated_language.h
toolkit/components/translation/cld2/internal/generated_ulscript.cc
toolkit/components/translation/cld2/internal/generated_ulscript.h
toolkit/components/translation/cld2/internal/getonescriptspan.cc
toolkit/components/translation/cld2/internal/getonescriptspan.h
toolkit/components/translation/cld2/internal/integral_types.h
toolkit/components/translation/cld2/internal/lang_script.cc
toolkit/components/translation/cld2/internal/lang_script.h
toolkit/components/translation/cld2/internal/langspan.h
toolkit/components/translation/cld2/internal/offsetmap.cc
toolkit/components/translation/cld2/internal/offsetmap.h
toolkit/components/translation/cld2/internal/port.h
toolkit/components/translation/cld2/internal/scoreonescriptspan.cc
toolkit/components/translation/cld2/internal/scoreonescriptspan.h
toolkit/components/translation/cld2/internal/stringpiece.h
toolkit/components/translation/cld2/internal/tote.cc
toolkit/components/translation/cld2/internal/tote.h
toolkit/components/translation/cld2/internal/utf8prop_lettermarkscriptnum.h
toolkit/components/translation/cld2/internal/utf8repl_lettermarklower.h
toolkit/components/translation/cld2/internal/utf8scannot_lettermarkspecial.h
toolkit/components/translation/cld2/internal/utf8statetable.cc
toolkit/components/translation/cld2/internal/utf8statetable.h
toolkit/components/translation/cld2/post.js
toolkit/components/translation/cld2/public/compact_lang_det.h
toolkit/components/translation/cld2/public/encodings.h
toolkit/components/translation/jar.mn
toolkit/components/translation/microsoft-translator-attribution.png
toolkit/components/translation/moz.build
toolkit/components/translation/test/.eslintrc.js
toolkit/components/translation/test/bing.sjs
toolkit/components/translation/test/browser.ini
toolkit/components/translation/test/browser_translation_bing.js
toolkit/components/translation/test/browser_translation_exceptions.js
toolkit/components/translation/test/browser_translation_infobar.js
toolkit/components/translation/test/browser_translation_telemetry.js
toolkit/components/translation/test/browser_translation_yandex.js
toolkit/components/translation/test/fixtures/bug1022725-fr.html
toolkit/components/translation/test/fixtures/result-da39a3ee5e.txt
toolkit/components/translation/test/fixtures/result-yandex-d448894848.json
toolkit/components/translation/test/unit/.eslintrc.js
toolkit/components/translation/test/unit/test_cld2.js
toolkit/components/translation/test/unit/xpcshell.ini
toolkit/components/translation/test/yandex.sjs
toolkit/components/translation/translation-infobar.xml
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -936,17 +936,17 @@ html|*#gcli-output-frame,
 
 panelview > .social-panel-frame {
   width: auto;
   height: auto;
 }
 
 /* Translation */
 notification[value="translation"] {
-  -moz-binding: url("chrome://browser/content/translation-infobar.xml#translationbar");
+  -moz-binding: url("chrome://global/content/translation-infobar.xml#translationbar");
 }
 
 /** See bug 872317 for why the following rule is necessary. */
 
 #downloads-button {
   -moz-binding: url("chrome://browser/content/downloads/download.xml#download-toolbarbutton");
 }
 
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -19,17 +19,16 @@ DIRS += [
     'preferences',
     'privatebrowsing',
     'search',
     'sessionstore',
     'shell',
     'selfsupport',
     'syncedtabs',
     'uitour',
-    'translation',
 ]
 
 DIRS += ['build']
 
 XPIDL_SOURCES += [
     'nsIBrowserGlue.idl',
     'nsIBrowserHandler.idl',
 ]
--- a/browser/components/preferences/in-content/content.xul
+++ b/browser/components/preferences/in-content/content.xul
@@ -193,17 +193,17 @@
       <checkbox id="translate" preference="browser.translation.detectLanguage"
                 label="&translateWebPages.label;." accesskey="&translateWebPages.accesskey;"
                 onsyncfrompreference="return gContentPane.updateButtons('translateButton',
                                               'browser.translation.detectLanguage');"/>
       <hbox id="bingAttribution" hidden="true">
         <label>&translation.options.attribution.beforeLogo;</label>
         <separator orient="vertical" class="thin"/>
         <image id="translationAttributionImage" aria-label="Microsoft Translator"
-               src="chrome://browser/content/microsoft-translator-attribution.png"/>
+               src="chrome://global/content/microsoft-translator-attribution.png"/>
         <separator orient="vertical" class="thin"/>
         <label>&translation.options.attribution.afterLogo;</label>
       </hbox>
     </hbox>
     <button id="translateButton" label="&translateExceptions.label;"
             accesskey="&translateExceptions.accesskey;"/>
   </hbox>
 </groupbox>
deleted file mode 100644
--- a/browser/components/translation/jar.mn
+++ /dev/null
@@ -1,6 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-browser.jar:
-       content/browser/translation-infobar.xml
-       content/browser/microsoft-translator-attribution.png
deleted file mode 100644
--- a/browser/components/translation/translation-infobar.xml
+++ /dev/null
@@ -1,441 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE bindings [
-<!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd">
-%notificationDTD;
-<!ENTITY % translationDTD SYSTEM "chrome://browser/locale/translation.dtd" >
-%translationDTD;
-]>
-
-<bindings id="translationBindings"
-          xmlns="http://www.mozilla.org/xbl"
-          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-          xmlns:xbl="http://www.mozilla.org/xbl">
-  <binding id="translationbar" extends="chrome://global/content/bindings/notification.xml#notification" role="xul:alert">
-    <resources>
-      <stylesheet src="chrome://global/skin/notification.css"/>
-    </resources>
-    <content>
-      <xul:hbox class="notification-inner" flex="1" xbl:inherits="type">
-        <xul:hbox anonid="details" align="center" flex="1">
-          <xul:image class="translate-infobar-element messageImage"
-                     anonid="messageImage"/>
-          <xul:panel anonid="welcomePanel" class="translation-welcome-panel"
-                     type="arrow" align="start">
-            <xul:image class="translation-welcome-logo"/>
-            <xul:vbox flex="1" class="translation-welcome-content">
-              <xul:description class="translation-welcome-headline"
-                               anonid="welcomeHeadline"/>
-              <xul:description class="translation-welcome-body" anonid="welcomeBody"/>
-              <xul:hbox align="center">
-                <xul:label anonid="learnMore" class="plain text-link"
-                           onclick="openUILinkIn('https://support.mozilla.org/kb/automatic-translation', 'tab'); this.parentNode.parentNode.parentNode.hidePopup();"/>
-                <xul:spacer flex="1"/>
-                <xul:button class="translate-infobar-element" anonid="thanksButton"
-                            onclick="this.parentNode.parentNode.parentNode.hidePopup();"/>
-              </xul:hbox>
-            </xul:vbox>
-          </xul:panel>
-          <xul:deck anonid="translationStates" selectedIndex="0">
-
-            <!-- offer to translate -->
-            <xul:hbox class="translate-offer-box" align="center">
-              <xul:label class="translate-infobar-element" value="&translation.thisPageIsIn.label;"/>
-              <xul:menulist class="translate-infobar-element" anonid="detectedLanguage">
-                <xul:menupopup/>
-              </xul:menulist>
-              <xul:label class="translate-infobar-element" value="&translation.translateThisPage.label;"/>
-              <xul:button class="translate-infobar-element"
-                          label="&translation.translate.button;"
-                          anonid="translate"
-                          oncommand="document.getBindingParent(this).translate();"/>
-              <xul:button class="translate-infobar-element"
-                          label="&translation.notNow.button;" anonid="notNow"
-                          oncommand="document.getBindingParent(this).closeCommand();"/>
-            </xul:hbox>
-
-            <!-- translating -->
-            <xul:vbox class="translating-box" pack="center">
-              <xul:label class="translate-infobar-element"
-                         value="&translation.translatingContent.label;"/>
-            </xul:vbox>
-
-            <!-- translated -->
-            <xul:hbox class="translated-box" align="center">
-              <xul:label class="translate-infobar-element"
-                         value="&translation.translatedFrom.label;"/>
-              <xul:menulist class="translate-infobar-element"
-                            anonid="fromLanguage"
-                            oncommand="document.getBindingParent(this).translate()">
-                <xul:menupopup/>
-              </xul:menulist>
-              <xul:label class="translate-infobar-element"
-                         value="&translation.translatedTo.label;"/>
-              <xul:menulist class="translate-infobar-element"
-                            anonid="toLanguage"
-                            oncommand="document.getBindingParent(this).translate()">
-                <xul:menupopup/>
-              </xul:menulist>
-              <xul:label class="translate-infobar-element"
-                         value="&translation.translatedToSuffix.label;"/>
-              <xul:button anonid="showOriginal"
-                          class="translate-infobar-element"
-                          label="&translation.showOriginal.button;"
-                          oncommand="document.getBindingParent(this).showOriginal();"/>
-              <xul:button anonid="showTranslation"
-                          class="translate-infobar-element"
-                          label="&translation.showTranslation.button;"
-                          oncommand="document.getBindingParent(this).showTranslation();"/>
-            </xul:hbox>
-
-            <!-- error -->
-            <xul:hbox class="translation-error" align="center">
-              <xul:label class="translate-infobar-element"
-                         value="&translation.errorTranslating.label;"/>
-              <xul:button class="translate-infobar-element"
-                          label="&translation.tryAgain.button;"
-                          anonid="tryAgain"
-                          oncommand="document.getBindingParent(this).translate();"/>
-            </xul:hbox>
-
-            <!-- unavailable -->
-            <xul:vbox class="translation-unavailable" pack="center">
-              <xul:label class="translate-infobar-element"
-                         value="&translation.serviceUnavailable.label;"/>
-            </xul:vbox>
-
-          </xul:deck>
-          <xul:spacer flex="1"/>
-
-          <xul:button type="menu"
-                      class="translate-infobar-element options-menu-button"
-                      anonid="options"
-                      label="&translation.options.menu;">
-            <xul:menupopup class="translation-menupopup cui-widget-panel cui-widget-panelview
-                                  cui-widget-panelWithFooter PanelUI-subView"
-                           onpopupshowing="document.getBindingParent(this).optionsShowing();">
-              <xul:menuitem anonid="neverForLanguage"
-                            oncommand="document.getBindingParent(this).neverForLanguage();"/>
-              <xul:menuitem anonid="neverForSite"
-                            oncommand="document.getBindingParent(this).neverForSite();"
-                            label="&translation.options.neverForSite.label;"
-                            accesskey="&translation.options.neverForSite.accesskey;"/>
-              <xul:menuseparator/>
-              <xul:menuitem oncommand="openPreferences('paneContent');"
-                            label="&translation.options.preferences.label;"
-                            accesskey="&translation.options.preferences.accesskey;"/>
-              <xul:menuitem class="subviewbutton panel-subview-footer"
-                            oncommand="document.getBindingParent(this).openProviderAttribution();">
-                <xul:deck anonid="translationEngine" selectedIndex="0">
-                  <xul:hbox class="translation-attribution">
-                    <xul:label>&translation.options.attribution.beforeLogo;</xul:label>
-                    <xul:image src="chrome://browser/content/microsoft-translator-attribution.png"
-                               aria-label="Microsoft Translator"/>
-                    <xul:label>&translation.options.attribution.afterLogo;</xul:label>
-                  </xul:hbox>
-                  <xul:label class="translation-attribution">&translation.options.attribution.yandexTranslate;</xul:label>
-                </xul:deck>
-              </xul:menuitem>
-            </xul:menupopup>
-          </xul:button>
-
-        </xul:hbox>
-        <xul:toolbarbutton ondblclick="event.stopPropagation();"
-                           anonid="closeButton"
-                           class="messageCloseButton close-icon tabbable"
-                           xbl:inherits="hidden=hideclose"
-                           tooltiptext="&closeNotification.tooltip;"
-                           oncommand="document.getBindingParent(this).closeCommand();"/>
-      </xul:hbox>
-    </content>
-    <implementation>
-      <property name="state"
-                onget="return this._getAnonElt('translationStates').selectedIndex;">
-        <setter>
-          <![CDATA[
-          let deck = this._getAnonElt('translationStates');
-
-          let activeElt = document.activeElement;
-          if (activeElt && deck.contains(activeElt))
-            activeElt.blur();
-
-          let stateName;
-          for (let name of ["OFFER", "TRANSLATING", "TRANSLATED", "ERROR"]) {
-            if (Translation["STATE_" + name] == val) {
-              stateName = name.toLowerCase();
-              break;
-            }
-          }
-          this.setAttribute("state", stateName);
-
-          if (val == Translation.STATE_TRANSLATED)
-            this._handleButtonHiding();
-
-          deck.selectedIndex = val;
-          ]]>
-        </setter>
-      </property>
-
-      <method name="init">
-        <parameter name="aTranslation"/>
-        <body>
-          <![CDATA[
-            this.translation = aTranslation;
-            let bundle = Cc["@mozilla.org/intl/stringbundle;1"]
-                           .getService(Ci.nsIStringBundleService)
-                           .createBundle("chrome://global/locale/languageNames.properties");
-            let sortByLocalizedName = function(aList) {
-              return aList.map(code => [code, bundle.GetStringFromName(code)])
-                          .sort((a, b) => a[1].localeCompare(b[1]));
-            };
-
-            // Fill the lists of supported source languages.
-            let detectedLanguage = this._getAnonElt("detectedLanguage");
-            let fromLanguage = this._getAnonElt("fromLanguage");
-            let sourceLanguages =
-              sortByLocalizedName(Translation.supportedSourceLanguages);
-            for (let [code, name] of sourceLanguages) {
-              detectedLanguage.appendItem(name, code);
-              fromLanguage.appendItem(name, code);
-            }
-            detectedLanguage.value = this.translation.detectedLanguage;
-
-            // translatedFrom is only set if we have already translated this page.
-            if (aTranslation.translatedFrom)
-              fromLanguage.value = aTranslation.translatedFrom;
-
-            // Fill the list of supported target languages.
-            let toLanguage = this._getAnonElt("toLanguage");
-            let targetLanguages =
-              sortByLocalizedName(Translation.supportedTargetLanguages);
-            for (let [code, name] of targetLanguages)
-              toLanguage.appendItem(name, code);
-
-            if (aTranslation.translatedTo)
-              toLanguage.value = aTranslation.translatedTo;
-
-            if (aTranslation.state)
-              this.state = aTranslation.state;
-
-            // Show attribution for the preferred translator.
-            let engineIndex = Object.keys(Translation.supportedEngines)
-              .indexOf(Translation.translationEngine);
-            if (engineIndex != -1) {
-              this._getAnonElt('translationEngine').selectedIndex = engineIndex;
-            }
-
-            const kWelcomePref = "browser.translation.ui.welcomeMessageShown";
-            if (Services.prefs.prefHasUserValue(kWelcomePref) ||
-                this.translation.browser != gBrowser.selectedBrowser)
-              return;
-
-            this.addEventListener("transitionend", function onShown() {
-              this.removeEventListener("transitionend", onShown);
-
-              // These strings are hardcoded because they need to reach beta
-              // without riding the trains.
-              let localizedStrings = {
-                en: ["Hey look! It's something new!",
-                     "Now the Web is even more accessible with our new in-page translation feature. Click the translate button to try it!",
-                     "Learn more.",
-                     "Thanks"],
-                "es-AR": ["\xA1Mir\xE1! \xA1Hay algo nuevo!",
-                          "Ahora la web es a\xFAn m\xE1s accesible con nuestra nueva funcionalidad de traducci\xF3n integrada. \xA1Hac\xE9 clic en el bot\xF3n traducir para probarla!",
-                          "Conoc\xE9 m\xE1s.",
-                          "Gracias"],
-                "es-ES": ["\xA1Mira! \xA1Hay algo nuevo!",
-                          "Con la nueva funcionalidad de traducci\xF3n integrada, ahora la Web es a\xFAn m\xE1s accesible. \xA1Pulsa el bot\xF3n Traducir y pru\xE9bala!",
-                          "M\xE1s informaci\xF3n.",
-                          "Gracias"],
-                pl: ["Sp\xF3jrz tutaj! To co\u015B nowego!",
-                     "Sie\u0107 sta\u0142a si\u0119 w\u0142a\u015Bnie jeszcze bardziej dost\u0119pna dzi\u0119ki opcji bezpo\u015Bredniego t\u0142umaczenia stron. Kliknij przycisk t\u0142umaczenia, aby spr\xF3bowa\u0107!",
-                     "Dowiedz si\u0119 wi\u0119cej",
-                     "Dzi\u0119kuj\u0119"],
-                tr: ["Bak\u0131n, burada yeni bir \u015Fey var!",
-                     "Yeni sayfa i\xE7i \xE7eviri \xF6zelli\u011Fimiz sayesinde Web art\u0131k \xE7ok daha anla\u015F\u0131l\u0131r olacak. Denemek i\xE7in \xC7evir d\xFC\u011Fmesine t\u0131klay\u0131n!",
-                     "Daha fazla bilgi al\u0131n.",
-                     "Te\u015Fekk\xFCrler"],
-                vi: ["Nh\xECn n\xE0y! \u0110\u1ED3 m\u1EDBi!",
-                     "Gi\u1EDD \u0111\xE2y ch\xFAng ta c\xF3 th\u1EC3 ti\u1EBFp c\u1EADn web d\u1EC5 d\xE0ng h\u01A1n n\u1EEFa v\u1EDBi t\xEDnh n\u0103ng d\u1ECBch ngay trong trang.  Hay nh\u1EA5n n\xFAt d\u1ECBch \u0111\u1EC3 th\u1EED!",
-                     "T\xECm hi\u1EC3u th\xEAm.",
-                     "C\u1EA3m \u01A1n"]
-              };
-
-              let locale = Cc["@mozilla.org/chrome/chrome-registry;1"]
-                             .getService(Ci.nsIXULChromeRegistry)
-                             .getSelectedLocale("browser");
-              if (!(locale in localizedStrings))
-                locale = "en";
-              let strings = localizedStrings[locale];
-
-              this._getAnonElt("welcomeHeadline").setAttribute("value", strings[0]);
-              this._getAnonElt("welcomeBody").textContent = strings[1];
-              this._getAnonElt("learnMore").setAttribute("value", strings[2]);
-              this._getAnonElt("thanksButton").setAttribute("label", strings[3]);
-
-              let panel = this._getAnonElt("welcomePanel");
-              panel.openPopup(this._getAnonElt("messageImage"),
-                              "bottomcenter topleft");
-
-              Services.prefs.setBoolPref(kWelcomePref, true);
-            });
-          ]]>
-        </body>
-      </method>
-
-      <method name="_getAnonElt">
-        <parameter name="aAnonId"/>
-        <body>
-          return document.getAnonymousElementByAttribute(this, "anonid", aAnonId);
-        </body>
-      </method>
-
-      <method name="translate">
-        <body>
-          <![CDATA[
-            if (this.state == Translation.STATE_OFFER) {
-              this._getAnonElt("fromLanguage").value =
-                this._getAnonElt("detectedLanguage").value;
-              this._getAnonElt("toLanguage").value =
-                Translation.defaultTargetLanguage;
-            }
-
-            this.translation.translate(this._getAnonElt("fromLanguage").value,
-                                       this._getAnonElt("toLanguage").value);
-          ]]>
-        </body>
-      </method>
-
-      <!-- To be called when the infobar should be closed per user's wish (e.g.
-           by clicking the notification's close button -->
-      <method name="closeCommand">
-        <body>
-          <![CDATA[
-            this.close();
-            this.translation.infobarClosed();
-          ]]>
-        </body>
-      </method>
-      <method name="_handleButtonHiding">
-        <body>
-          <![CDATA[
-            let originalShown = this.translation.originalShown;
-            this._getAnonElt("showOriginal").hidden = originalShown;
-            this._getAnonElt("showTranslation").hidden = !originalShown;
-          ]]>
-        </body>
-      </method>
-
-      <method name="showOriginal">
-        <body>
-          <![CDATA[
-            this.translation.showOriginalContent();
-            this._handleButtonHiding();
-          ]]>
-        </body>
-      </method>
-
-      <method name="showTranslation">
-        <body>
-          <![CDATA[
-            this.translation.showTranslatedContent();
-            this._handleButtonHiding();
-          ]]>
-        </body>
-      </method>
-
-      <method name="optionsShowing">
-        <body>
-          <![CDATA[
-            // Get the source language name.
-            let lang;
-            if (this.state == Translation.STATE_OFFER)
-              lang = this._getAnonElt("detectedLanguage").value;
-            else {
-              lang = this._getAnonElt("fromLanguage").value;
-
-              // If we have never attempted to translate the page before the
-              // service became unavailable, "fromLanguage" isn't set.
-              if (!lang && this.state == Translation.STATE_UNAVAILABLE)
-                lang = this.translation.detectedLanguage;
-            }
-
-            let langBundle =
-              Cc["@mozilla.org/intl/stringbundle;1"]
-                .getService(Ci.nsIStringBundleService)
-                .createBundle("chrome://global/locale/languageNames.properties");
-            let langName = langBundle.GetStringFromName(lang);
-
-            // Set the label and accesskey on the menuitem.
-            let bundle =
-              Cc["@mozilla.org/intl/stringbundle;1"]
-                .getService(Ci.nsIStringBundleService)
-                .createBundle("chrome://browser/locale/translation.properties");
-            let item = this._getAnonElt("neverForLanguage");
-            const kStrId = "translation.options.neverForLanguage";
-            item.setAttribute("label",
-                              bundle.formatStringFromName(kStrId + ".label",
-                                                          [langName], 1));
-            item.setAttribute("accesskey",
-                              bundle.GetStringFromName(kStrId + ".accesskey"));
-            item.langCode = lang;
-
-            // We may need to disable the menuitems if they have already been used.
-            // Check if translation is already disabled for this language:
-            let neverForLangs =
-              Services.prefs.getCharPref("browser.translation.neverForLanguages");
-            item.disabled = neverForLangs.split(",").indexOf(lang) != -1;
-
-            // Check if translation is disabled for the domain:
-            let uri = this.translation.browser.currentURI;
-            let perms = Services.perms;
-            item = this._getAnonElt("neverForSite");
-            item.disabled =
-              perms.testExactPermission(uri, "translate") == perms.DENY_ACTION;
-          ]]>
-        </body>
-      </method>
-
-      <method name="neverForLanguage">
-        <body>
-          <![CDATA[
-            const kPrefName = "browser.translation.neverForLanguages";
-
-            let val = Services.prefs.getCharPref(kPrefName);
-            if (val)
-              val += ",";
-            val += this._getAnonElt("neverForLanguage").langCode;
-
-            Services.prefs.setCharPref(kPrefName, val);
-
-            this.closeCommand();
-          ]]>
-        </body>
-      </method>
-
-      <method name="neverForSite">
-        <body>
-          <![CDATA[
-            let uri = this.translation.browser.currentURI;
-            let perms = Services.perms;
-            perms.add(uri, "translate", perms.DENY_ACTION);
-
-            this.closeCommand();
-          ]]>
-        </body>
-      </method>
-
-      <method name="openProviderAttribution">
-        <body>
-          <![CDATA[
-            Translation.openProviderAttribution();
-          ]]>
-        </body>
-      </method>
-
-    </implementation>
-  </binding>
-</bindings>
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -52,16 +52,17 @@ DIRS += [
     'securityreporter',
     'sqlite',
     'startup',
     'statusfilter',
     'telemetry',
     'thumbnails',
     'timermanager',
     'tooltiptext',
+    'translation',
     'typeaheadfind',
     'utils',
     'url-classifier',
     'urlformatter',
     'viewconfig',
     'workerloader',
     'xulstore'
 ]
rename from browser/components/translation/BingTranslator.jsm
rename to toolkit/components/translation/BingTranslator.jsm
rename from browser/components/translation/LanguageDetector.jsm
rename to toolkit/components/translation/LanguageDetector.jsm
rename from browser/components/translation/Translation.jsm
rename to toolkit/components/translation/Translation.jsm
rename from browser/components/translation/TranslationContentHandler.jsm
rename to toolkit/components/translation/TranslationContentHandler.jsm
rename from browser/components/translation/TranslationDocument.jsm
rename to toolkit/components/translation/TranslationDocument.jsm
rename from browser/components/translation/YandexTranslator.jsm
rename to toolkit/components/translation/YandexTranslator.jsm
rename from browser/components/translation/cld2/Makefile
rename to toolkit/components/translation/cld2/Makefile
rename from browser/components/translation/cld2/cld-worker.js
rename to toolkit/components/translation/cld2/cld-worker.js
rename from browser/components/translation/cld2/cld-worker.js.mem
rename to toolkit/components/translation/cld2/cld-worker.js.mem
rename from browser/components/translation/cld2/cld.idl
rename to toolkit/components/translation/cld2/cld.idl
rename from browser/components/translation/cld2/cldapp.cc
rename to toolkit/components/translation/cld2/cldapp.cc
rename from browser/components/translation/cld2/internal/LICENSE
rename to toolkit/components/translation/cld2/internal/LICENSE
rename from browser/components/translation/cld2/internal/cld2_dynamic_data.h
rename to toolkit/components/translation/cld2/internal/cld2_dynamic_data.h
rename from browser/components/translation/cld2/internal/cld2_dynamic_data_loader.h
rename to toolkit/components/translation/cld2/internal/cld2_dynamic_data_loader.h
rename from browser/components/translation/cld2/internal/cld2_generated_cjk_compatible.cc
rename to toolkit/components/translation/cld2/internal/cld2_generated_cjk_compatible.cc
rename from browser/components/translation/cld2/internal/cld2_generated_deltaoctachrome0122.cc
rename to toolkit/components/translation/cld2/internal/cld2_generated_deltaoctachrome0122.cc
rename from browser/components/translation/cld2/internal/cld2_generated_distinctoctachrome0122.cc
rename to toolkit/components/translation/cld2/internal/cld2_generated_distinctoctachrome0122.cc
rename from browser/components/translation/cld2/internal/cld2_generated_quadchrome0122_16.cc
rename to toolkit/components/translation/cld2/internal/cld2_generated_quadchrome0122_16.cc
rename from browser/components/translation/cld2/internal/cld2tablesummary.h
rename to toolkit/components/translation/cld2/internal/cld2tablesummary.h
rename from browser/components/translation/cld2/internal/cld_generated_cjk_delta_bi_4.cc
rename to toolkit/components/translation/cld2/internal/cld_generated_cjk_delta_bi_4.cc
rename from browser/components/translation/cld2/internal/cld_generated_cjk_uni_prop_80.cc
rename to toolkit/components/translation/cld2/internal/cld_generated_cjk_uni_prop_80.cc
rename from browser/components/translation/cld2/internal/cld_generated_score_quad_octa_0122_2.cc
rename to toolkit/components/translation/cld2/internal/cld_generated_score_quad_octa_0122_2.cc
rename from browser/components/translation/cld2/internal/cldutil.cc
rename to toolkit/components/translation/cld2/internal/cldutil.cc
rename from browser/components/translation/cld2/internal/cldutil.h
rename to toolkit/components/translation/cld2/internal/cldutil.h
rename from browser/components/translation/cld2/internal/cldutil_shared.cc
rename to toolkit/components/translation/cld2/internal/cldutil_shared.cc
rename from browser/components/translation/cld2/internal/cldutil_shared.h
rename to toolkit/components/translation/cld2/internal/cldutil_shared.h
rename from browser/components/translation/cld2/internal/compact_lang_det.cc
rename to toolkit/components/translation/cld2/internal/compact_lang_det.cc
rename from browser/components/translation/cld2/internal/compact_lang_det_hint_code.cc
rename to toolkit/components/translation/cld2/internal/compact_lang_det_hint_code.cc
rename from browser/components/translation/cld2/internal/compact_lang_det_hint_code.h
rename to toolkit/components/translation/cld2/internal/compact_lang_det_hint_code.h
rename from browser/components/translation/cld2/internal/compact_lang_det_impl.cc
rename to toolkit/components/translation/cld2/internal/compact_lang_det_impl.cc
rename from browser/components/translation/cld2/internal/compact_lang_det_impl.h
rename to toolkit/components/translation/cld2/internal/compact_lang_det_impl.h
rename from browser/components/translation/cld2/internal/debug.h
rename to toolkit/components/translation/cld2/internal/debug.h
rename from browser/components/translation/cld2/internal/debug_empty.cc
rename to toolkit/components/translation/cld2/internal/debug_empty.cc
rename from browser/components/translation/cld2/internal/fixunicodevalue.cc
rename to toolkit/components/translation/cld2/internal/fixunicodevalue.cc
rename from browser/components/translation/cld2/internal/fixunicodevalue.h
rename to toolkit/components/translation/cld2/internal/fixunicodevalue.h
rename from browser/components/translation/cld2/internal/generated_distinct_bi_0.cc
rename to toolkit/components/translation/cld2/internal/generated_distinct_bi_0.cc
rename from browser/components/translation/cld2/internal/generated_entities.cc
rename to toolkit/components/translation/cld2/internal/generated_entities.cc
rename from browser/components/translation/cld2/internal/generated_language.cc
rename to toolkit/components/translation/cld2/internal/generated_language.cc
rename from browser/components/translation/cld2/internal/generated_language.h
rename to toolkit/components/translation/cld2/internal/generated_language.h
rename from browser/components/translation/cld2/internal/generated_ulscript.cc
rename to toolkit/components/translation/cld2/internal/generated_ulscript.cc
rename from browser/components/translation/cld2/internal/generated_ulscript.h
rename to toolkit/components/translation/cld2/internal/generated_ulscript.h
rename from browser/components/translation/cld2/internal/getonescriptspan.cc
rename to toolkit/components/translation/cld2/internal/getonescriptspan.cc
rename from browser/components/translation/cld2/internal/getonescriptspan.h
rename to toolkit/components/translation/cld2/internal/getonescriptspan.h
rename from browser/components/translation/cld2/internal/integral_types.h
rename to toolkit/components/translation/cld2/internal/integral_types.h
rename from browser/components/translation/cld2/internal/lang_script.cc
rename to toolkit/components/translation/cld2/internal/lang_script.cc
rename from browser/components/translation/cld2/internal/lang_script.h
rename to toolkit/components/translation/cld2/internal/lang_script.h
rename from browser/components/translation/cld2/internal/langspan.h
rename to toolkit/components/translation/cld2/internal/langspan.h
rename from browser/components/translation/cld2/internal/offsetmap.cc
rename to toolkit/components/translation/cld2/internal/offsetmap.cc
rename from browser/components/translation/cld2/internal/offsetmap.h
rename to toolkit/components/translation/cld2/internal/offsetmap.h
rename from browser/components/translation/cld2/internal/port.h
rename to toolkit/components/translation/cld2/internal/port.h
rename from browser/components/translation/cld2/internal/scoreonescriptspan.cc
rename to toolkit/components/translation/cld2/internal/scoreonescriptspan.cc
rename from browser/components/translation/cld2/internal/scoreonescriptspan.h
rename to toolkit/components/translation/cld2/internal/scoreonescriptspan.h
rename from browser/components/translation/cld2/internal/stringpiece.h
rename to toolkit/components/translation/cld2/internal/stringpiece.h
rename from browser/components/translation/cld2/internal/tote.cc
rename to toolkit/components/translation/cld2/internal/tote.cc
rename from browser/components/translation/cld2/internal/tote.h
rename to toolkit/components/translation/cld2/internal/tote.h
rename from browser/components/translation/cld2/internal/utf8prop_lettermarkscriptnum.h
rename to toolkit/components/translation/cld2/internal/utf8prop_lettermarkscriptnum.h
rename from browser/components/translation/cld2/internal/utf8repl_lettermarklower.h
rename to toolkit/components/translation/cld2/internal/utf8repl_lettermarklower.h
rename from browser/components/translation/cld2/internal/utf8scannot_lettermarkspecial.h
rename to toolkit/components/translation/cld2/internal/utf8scannot_lettermarkspecial.h
rename from browser/components/translation/cld2/internal/utf8statetable.cc
rename to toolkit/components/translation/cld2/internal/utf8statetable.cc
rename from browser/components/translation/cld2/internal/utf8statetable.h
rename to toolkit/components/translation/cld2/internal/utf8statetable.h
rename from browser/components/translation/cld2/post.js
rename to toolkit/components/translation/cld2/post.js
rename from browser/components/translation/cld2/public/compact_lang_det.h
rename to toolkit/components/translation/cld2/public/compact_lang_det.h
rename from browser/components/translation/cld2/public/encodings.h
rename to toolkit/components/translation/cld2/public/encodings.h
new file mode 100644
--- /dev/null
+++ b/toolkit/components/translation/jar.mn
@@ -0,0 +1,6 @@
+# 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/.
+toolkit.jar:
+       content/global/translation-infobar.xml
+       content/global/microsoft-translator-attribution.png
rename from browser/components/translation/microsoft-translator-attribution.png
rename to toolkit/components/translation/microsoft-translator-attribution.png
rename from browser/components/translation/moz.build
rename to toolkit/components/translation/moz.build
rename from browser/components/translation/test/.eslintrc.js
rename to toolkit/components/translation/test/.eslintrc.js
rename from browser/components/translation/test/bing.sjs
rename to toolkit/components/translation/test/bing.sjs
rename from browser/components/translation/test/browser.ini
rename to toolkit/components/translation/test/browser.ini
rename from browser/components/translation/test/browser_translation_bing.js
rename to toolkit/components/translation/test/browser_translation_bing.js
rename from browser/components/translation/test/browser_translation_exceptions.js
rename to toolkit/components/translation/test/browser_translation_exceptions.js
rename from browser/components/translation/test/browser_translation_infobar.js
rename to toolkit/components/translation/test/browser_translation_infobar.js
rename from browser/components/translation/test/browser_translation_telemetry.js
rename to toolkit/components/translation/test/browser_translation_telemetry.js
rename from browser/components/translation/test/browser_translation_yandex.js
rename to toolkit/components/translation/test/browser_translation_yandex.js
rename from browser/components/translation/test/fixtures/bug1022725-fr.html
rename to toolkit/components/translation/test/fixtures/bug1022725-fr.html
rename from browser/components/translation/test/fixtures/result-da39a3ee5e.txt
rename to toolkit/components/translation/test/fixtures/result-da39a3ee5e.txt
rename from browser/components/translation/test/fixtures/result-yandex-d448894848.json
rename to toolkit/components/translation/test/fixtures/result-yandex-d448894848.json
rename from browser/components/translation/test/unit/.eslintrc.js
rename to toolkit/components/translation/test/unit/.eslintrc.js
rename from browser/components/translation/test/unit/test_cld2.js
rename to toolkit/components/translation/test/unit/test_cld2.js
rename from browser/components/translation/test/unit/xpcshell.ini
rename to toolkit/components/translation/test/unit/xpcshell.ini
rename from browser/components/translation/test/yandex.sjs
rename to toolkit/components/translation/test/yandex.sjs
new file mode 100644
--- /dev/null
+++ b/toolkit/components/translation/translation-infobar.xml
@@ -0,0 +1,441 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE bindings [
+<!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd">
+%notificationDTD;
+<!ENTITY % translationDTD SYSTEM "chrome://browser/locale/translation.dtd" >
+%translationDTD;
+]>
+
+<bindings id="translationBindings"
+          xmlns="http://www.mozilla.org/xbl"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+          xmlns:xbl="http://www.mozilla.org/xbl">
+  <binding id="translationbar" extends="chrome://global/content/bindings/notification.xml#notification" role="xul:alert">
+    <resources>
+      <stylesheet src="chrome://global/skin/notification.css"/>
+    </resources>
+    <content>
+      <xul:hbox class="notification-inner" flex="1" xbl:inherits="type">
+        <xul:hbox anonid="details" align="center" flex="1">
+          <xul:image class="translate-infobar-element messageImage"
+                     anonid="messageImage"/>
+          <xul:panel anonid="welcomePanel" class="translation-welcome-panel"
+                     type="arrow" align="start">
+            <xul:image class="translation-welcome-logo"/>
+            <xul:vbox flex="1" class="translation-welcome-content">
+              <xul:description class="translation-welcome-headline"
+                               anonid="welcomeHeadline"/>
+              <xul:description class="translation-welcome-body" anonid="welcomeBody"/>
+              <xul:hbox align="center">
+                <xul:label anonid="learnMore" class="plain text-link"
+                           onclick="openUILinkIn('https://support.mozilla.org/kb/automatic-translation', 'tab'); this.parentNode.parentNode.parentNode.hidePopup();"/>
+                <xul:spacer flex="1"/>
+                <xul:button class="translate-infobar-element" anonid="thanksButton"
+                            onclick="this.parentNode.parentNode.parentNode.hidePopup();"/>
+              </xul:hbox>
+            </xul:vbox>
+          </xul:panel>
+          <xul:deck anonid="translationStates" selectedIndex="0">
+
+            <!-- offer to translate -->
+            <xul:hbox class="translate-offer-box" align="center">
+              <xul:label class="translate-infobar-element" value="&translation.thisPageIsIn.label;"/>
+              <xul:menulist class="translate-infobar-element" anonid="detectedLanguage">
+                <xul:menupopup/>
+              </xul:menulist>
+              <xul:label class="translate-infobar-element" value="&translation.translateThisPage.label;"/>
+              <xul:button class="translate-infobar-element"
+                          label="&translation.translate.button;"
+                          anonid="translate"
+                          oncommand="document.getBindingParent(this).translate();"/>
+              <xul:button class="translate-infobar-element"
+                          label="&translation.notNow.button;" anonid="notNow"
+                          oncommand="document.getBindingParent(this).closeCommand();"/>
+            </xul:hbox>
+
+            <!-- translating -->
+            <xul:vbox class="translating-box" pack="center">
+              <xul:label class="translate-infobar-element"
+                         value="&translation.translatingContent.label;"/>
+            </xul:vbox>
+
+            <!-- translated -->
+            <xul:hbox class="translated-box" align="center">
+              <xul:label class="translate-infobar-element"
+                         value="&translation.translatedFrom.label;"/>
+              <xul:menulist class="translate-infobar-element"
+                            anonid="fromLanguage"
+                            oncommand="document.getBindingParent(this).translate()">
+                <xul:menupopup/>
+              </xul:menulist>
+              <xul:label class="translate-infobar-element"
+                         value="&translation.translatedTo.label;"/>
+              <xul:menulist class="translate-infobar-element"
+                            anonid="toLanguage"
+                            oncommand="document.getBindingParent(this).translate()">
+                <xul:menupopup/>
+              </xul:menulist>
+              <xul:label class="translate-infobar-element"
+                         value="&translation.translatedToSuffix.label;"/>
+              <xul:button anonid="showOriginal"
+                          class="translate-infobar-element"
+                          label="&translation.showOriginal.button;"
+                          oncommand="document.getBindingParent(this).showOriginal();"/>
+              <xul:button anonid="showTranslation"
+                          class="translate-infobar-element"
+                          label="&translation.showTranslation.button;"
+                          oncommand="document.getBindingParent(this).showTranslation();"/>
+            </xul:hbox>
+
+            <!-- error -->
+            <xul:hbox class="translation-error" align="center">
+              <xul:label class="translate-infobar-element"
+                         value="&translation.errorTranslating.label;"/>
+              <xul:button class="translate-infobar-element"
+                          label="&translation.tryAgain.button;"
+                          anonid="tryAgain"
+                          oncommand="document.getBindingParent(this).translate();"/>
+            </xul:hbox>
+
+            <!-- unavailable -->
+            <xul:vbox class="translation-unavailable" pack="center">
+              <xul:label class="translate-infobar-element"
+                         value="&translation.serviceUnavailable.label;"/>
+            </xul:vbox>
+
+          </xul:deck>
+          <xul:spacer flex="1"/>
+
+          <xul:button type="menu"
+                      class="translate-infobar-element options-menu-button"
+                      anonid="options"
+                      label="&translation.options.menu;">
+            <xul:menupopup class="translation-menupopup cui-widget-panel cui-widget-panelview
+                                  cui-widget-panelWithFooter PanelUI-subView"
+                           onpopupshowing="document.getBindingParent(this).optionsShowing();">
+              <xul:menuitem anonid="neverForLanguage"
+                            oncommand="document.getBindingParent(this).neverForLanguage();"/>
+              <xul:menuitem anonid="neverForSite"
+                            oncommand="document.getBindingParent(this).neverForSite();"
+                            label="&translation.options.neverForSite.label;"
+                            accesskey="&translation.options.neverForSite.accesskey;"/>
+              <xul:menuseparator/>
+              <xul:menuitem oncommand="openPreferences('paneContent');"
+                            label="&translation.options.preferences.label;"
+                            accesskey="&translation.options.preferences.accesskey;"/>
+              <xul:menuitem class="subviewbutton panel-subview-footer"
+                            oncommand="document.getBindingParent(this).openProviderAttribution();">
+                <xul:deck anonid="translationEngine" selectedIndex="0">
+                  <xul:hbox class="translation-attribution">
+                    <xul:label>&translation.options.attribution.beforeLogo;</xul:label>
+                    <xul:image src="chrome://global/content/microsoft-translator-attribution.png"
+                               aria-label="Microsoft Translator"/>
+                    <xul:label>&translation.options.attribution.afterLogo;</xul:label>
+                  </xul:hbox>
+                  <xul:label class="translation-attribution">&translation.options.attribution.yandexTranslate;</xul:label>
+                </xul:deck>
+              </xul:menuitem>
+            </xul:menupopup>
+          </xul:button>
+
+        </xul:hbox>
+        <xul:toolbarbutton ondblclick="event.stopPropagation();"
+                           anonid="closeButton"
+                           class="messageCloseButton close-icon tabbable"
+                           xbl:inherits="hidden=hideclose"
+                           tooltiptext="&closeNotification.tooltip;"
+                           oncommand="document.getBindingParent(this).closeCommand();"/>
+      </xul:hbox>
+    </content>
+    <implementation>
+      <property name="state"
+                onget="return this._getAnonElt('translationStates').selectedIndex;">
+        <setter>
+          <![CDATA[
+          let deck = this._getAnonElt('translationStates');
+
+          let activeElt = document.activeElement;
+          if (activeElt && deck.contains(activeElt))
+            activeElt.blur();
+
+          let stateName;
+          for (let name of ["OFFER", "TRANSLATING", "TRANSLATED", "ERROR"]) {
+            if (Translation["STATE_" + name] == val) {
+              stateName = name.toLowerCase();
+              break;
+            }
+          }
+          this.setAttribute("state", stateName);
+
+          if (val == Translation.STATE_TRANSLATED)
+            this._handleButtonHiding();
+
+          deck.selectedIndex = val;
+          ]]>
+        </setter>
+      </property>
+
+      <method name="init">
+        <parameter name="aTranslation"/>
+        <body>
+          <![CDATA[
+            this.translation = aTranslation;
+            let bundle = Cc["@mozilla.org/intl/stringbundle;1"]
+                           .getService(Ci.nsIStringBundleService)
+                           .createBundle("chrome://global/locale/languageNames.properties");
+            let sortByLocalizedName = function(aList) {
+              return aList.map(code => [code, bundle.GetStringFromName(code)])
+                          .sort((a, b) => a[1].localeCompare(b[1]));
+            };
+
+            // Fill the lists of supported source languages.
+            let detectedLanguage = this._getAnonElt("detectedLanguage");
+            let fromLanguage = this._getAnonElt("fromLanguage");
+            let sourceLanguages =
+              sortByLocalizedName(Translation.supportedSourceLanguages);
+            for (let [code, name] of sourceLanguages) {
+              detectedLanguage.appendItem(name, code);
+              fromLanguage.appendItem(name, code);
+            }
+            detectedLanguage.value = this.translation.detectedLanguage;
+
+            // translatedFrom is only set if we have already translated this page.
+            if (aTranslation.translatedFrom)
+              fromLanguage.value = aTranslation.translatedFrom;
+
+            // Fill the list of supported target languages.
+            let toLanguage = this._getAnonElt("toLanguage");
+            let targetLanguages =
+              sortByLocalizedName(Translation.supportedTargetLanguages);
+            for (let [code, name] of targetLanguages)
+              toLanguage.appendItem(name, code);
+
+            if (aTranslation.translatedTo)
+              toLanguage.value = aTranslation.translatedTo;
+
+            if (aTranslation.state)
+              this.state = aTranslation.state;
+
+            // Show attribution for the preferred translator.
+            let engineIndex = Object.keys(Translation.supportedEngines)
+              .indexOf(Translation.translationEngine);
+            if (engineIndex != -1) {
+              this._getAnonElt('translationEngine').selectedIndex = engineIndex;
+            }
+
+            const kWelcomePref = "browser.translation.ui.welcomeMessageShown";
+            if (Services.prefs.prefHasUserValue(kWelcomePref) ||
+                this.translation.browser != gBrowser.selectedBrowser)
+              return;
+
+            this.addEventListener("transitionend", function onShown() {
+              this.removeEventListener("transitionend", onShown);
+
+              // These strings are hardcoded because they need to reach beta
+              // without riding the trains.
+              let localizedStrings = {
+                en: ["Hey look! It's something new!",
+                     "Now the Web is even more accessible with our new in-page translation feature. Click the translate button to try it!",
+                     "Learn more.",
+                     "Thanks"],
+                "es-AR": ["\xA1Mir\xE1! \xA1Hay algo nuevo!",
+                          "Ahora la web es a\xFAn m\xE1s accesible con nuestra nueva funcionalidad de traducci\xF3n integrada. \xA1Hac\xE9 clic en el bot\xF3n traducir para probarla!",
+                          "Conoc\xE9 m\xE1s.",
+                          "Gracias"],
+                "es-ES": ["\xA1Mira! \xA1Hay algo nuevo!",
+                          "Con la nueva funcionalidad de traducci\xF3n integrada, ahora la Web es a\xFAn m\xE1s accesible. \xA1Pulsa el bot\xF3n Traducir y pru\xE9bala!",
+                          "M\xE1s informaci\xF3n.",
+                          "Gracias"],
+                pl: ["Sp\xF3jrz tutaj! To co\u015B nowego!",
+                     "Sie\u0107 sta\u0142a si\u0119 w\u0142a\u015Bnie jeszcze bardziej dost\u0119pna dzi\u0119ki opcji bezpo\u015Bredniego t\u0142umaczenia stron. Kliknij przycisk t\u0142umaczenia, aby spr\xF3bowa\u0107!",
+                     "Dowiedz si\u0119 wi\u0119cej",
+                     "Dzi\u0119kuj\u0119"],
+                tr: ["Bak\u0131n, burada yeni bir \u015Fey var!",
+                     "Yeni sayfa i\xE7i \xE7eviri \xF6zelli\u011Fimiz sayesinde Web art\u0131k \xE7ok daha anla\u015F\u0131l\u0131r olacak. Denemek i\xE7in \xC7evir d\xFC\u011Fmesine t\u0131klay\u0131n!",
+                     "Daha fazla bilgi al\u0131n.",
+                     "Te\u015Fekk\xFCrler"],
+                vi: ["Nh\xECn n\xE0y! \u0110\u1ED3 m\u1EDBi!",
+                     "Gi\u1EDD \u0111\xE2y ch\xFAng ta c\xF3 th\u1EC3 ti\u1EBFp c\u1EADn web d\u1EC5 d\xE0ng h\u01A1n n\u1EEFa v\u1EDBi t\xEDnh n\u0103ng d\u1ECBch ngay trong trang.  Hay nh\u1EA5n n\xFAt d\u1ECBch \u0111\u1EC3 th\u1EED!",
+                     "T\xECm hi\u1EC3u th\xEAm.",
+                     "C\u1EA3m \u01A1n"]
+              };
+
+              let locale = Cc["@mozilla.org/chrome/chrome-registry;1"]
+                             .getService(Ci.nsIXULChromeRegistry)
+                             .getSelectedLocale("browser");
+              if (!(locale in localizedStrings))
+                locale = "en";
+              let strings = localizedStrings[locale];
+
+              this._getAnonElt("welcomeHeadline").setAttribute("value", strings[0]);
+              this._getAnonElt("welcomeBody").textContent = strings[1];
+              this._getAnonElt("learnMore").setAttribute("value", strings[2]);
+              this._getAnonElt("thanksButton").setAttribute("label", strings[3]);
+
+              let panel = this._getAnonElt("welcomePanel");
+              panel.openPopup(this._getAnonElt("messageImage"),
+                              "bottomcenter topleft");
+
+              Services.prefs.setBoolPref(kWelcomePref, true);
+            });
+          ]]>
+        </body>
+      </method>
+
+      <method name="_getAnonElt">
+        <parameter name="aAnonId"/>
+        <body>
+          return document.getAnonymousElementByAttribute(this, "anonid", aAnonId);
+        </body>
+      </method>
+
+      <method name="translate">
+        <body>
+          <![CDATA[
+            if (this.state == Translation.STATE_OFFER) {
+              this._getAnonElt("fromLanguage").value =
+                this._getAnonElt("detectedLanguage").value;
+              this._getAnonElt("toLanguage").value =
+                Translation.defaultTargetLanguage;
+            }
+
+            this.translation.translate(this._getAnonElt("fromLanguage").value,
+                                       this._getAnonElt("toLanguage").value);
+          ]]>
+        </body>
+      </method>
+
+      <!-- To be called when the infobar should be closed per user's wish (e.g.
+           by clicking the notification's close button -->
+      <method name="closeCommand">
+        <body>
+          <![CDATA[
+            this.close();
+            this.translation.infobarClosed();
+          ]]>
+        </body>
+      </method>
+      <method name="_handleButtonHiding">
+        <body>
+          <![CDATA[
+            let originalShown = this.translation.originalShown;
+            this._getAnonElt("showOriginal").hidden = originalShown;
+            this._getAnonElt("showTranslation").hidden = !originalShown;
+          ]]>
+        </body>
+      </method>
+
+      <method name="showOriginal">
+        <body>
+          <![CDATA[
+            this.translation.showOriginalContent();
+            this._handleButtonHiding();
+          ]]>
+        </body>
+      </method>
+
+      <method name="showTranslation">
+        <body>
+          <![CDATA[
+            this.translation.showTranslatedContent();
+            this._handleButtonHiding();
+          ]]>
+        </body>
+      </method>
+
+      <method name="optionsShowing">
+        <body>
+          <![CDATA[
+            // Get the source language name.
+            let lang;
+            if (this.state == Translation.STATE_OFFER)
+              lang = this._getAnonElt("detectedLanguage").value;
+            else {
+              lang = this._getAnonElt("fromLanguage").value;
+
+              // If we have never attempted to translate the page before the
+              // service became unavailable, "fromLanguage" isn't set.
+              if (!lang && this.state == Translation.STATE_UNAVAILABLE)
+                lang = this.translation.detectedLanguage;
+            }
+
+            let langBundle =
+              Cc["@mozilla.org/intl/stringbundle;1"]
+                .getService(Ci.nsIStringBundleService)
+                .createBundle("chrome://global/locale/languageNames.properties");
+            let langName = langBundle.GetStringFromName(lang);
+
+            // Set the label and accesskey on the menuitem.
+            let bundle =
+              Cc["@mozilla.org/intl/stringbundle;1"]
+                .getService(Ci.nsIStringBundleService)
+                .createBundle("chrome://browser/locale/translation.properties");
+            let item = this._getAnonElt("neverForLanguage");
+            const kStrId = "translation.options.neverForLanguage";
+            item.setAttribute("label",
+                              bundle.formatStringFromName(kStrId + ".label",
+                                                          [langName], 1));
+            item.setAttribute("accesskey",
+                              bundle.GetStringFromName(kStrId + ".accesskey"));
+            item.langCode = lang;
+
+            // We may need to disable the menuitems if they have already been used.
+            // Check if translation is already disabled for this language:
+            let neverForLangs =
+              Services.prefs.getCharPref("browser.translation.neverForLanguages");
+            item.disabled = neverForLangs.split(",").indexOf(lang) != -1;
+
+            // Check if translation is disabled for the domain:
+            let uri = this.translation.browser.currentURI;
+            let perms = Services.perms;
+            item = this._getAnonElt("neverForSite");
+            item.disabled =
+              perms.testExactPermission(uri, "translate") == perms.DENY_ACTION;
+          ]]>
+        </body>
+      </method>
+
+      <method name="neverForLanguage">
+        <body>
+          <![CDATA[
+            const kPrefName = "browser.translation.neverForLanguages";
+
+            let val = Services.prefs.getCharPref(kPrefName);
+            if (val)
+              val += ",";
+            val += this._getAnonElt("neverForLanguage").langCode;
+
+            Services.prefs.setCharPref(kPrefName, val);
+
+            this.closeCommand();
+          ]]>
+        </body>
+      </method>
+
+      <method name="neverForSite">
+        <body>
+          <![CDATA[
+            let uri = this.translation.browser.currentURI;
+            let perms = Services.perms;
+            perms.add(uri, "translate", perms.DENY_ACTION);
+
+            this.closeCommand();
+          ]]>
+        </body>
+      </method>
+
+      <method name="openProviderAttribution">
+        <body>
+          <![CDATA[
+            Translation.openProviderAttribution();
+          ]]>
+        </body>
+      </method>
+
+    </implementation>
+  </binding>
+</bindings>