michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: "use strict"; michael@0: michael@0: this.EXPORTED_SYMBOLS = ["Translation"]; michael@0: michael@0: const {classes: Cc, interfaces: Ci, utils: Cu} = Components; michael@0: michael@0: Cu.import("resource://gre/modules/Promise.jsm"); michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: michael@0: this.Translation = { michael@0: supportedSourceLanguages: ["en", "zh", "ja", "es", "de", "fr", "ru", "ar", "ko", "pt"], michael@0: supportedTargetLanguages: ["en", "pl", "tr", "vi"], michael@0: michael@0: _defaultTargetLanguage: "", michael@0: get defaultTargetLanguage() { michael@0: if (!this._defaultTargetLanguage) { michael@0: this._defaultTargetLanguage = Cc["@mozilla.org/chrome/chrome-registry;1"] michael@0: .getService(Ci.nsIXULChromeRegistry) michael@0: .getSelectedLocale("global") michael@0: .split("-")[0]; michael@0: } michael@0: return this._defaultTargetLanguage; michael@0: }, michael@0: michael@0: languageDetected: function(aBrowser, aDetectedLanguage) { michael@0: if (this.supportedSourceLanguages.indexOf(aDetectedLanguage) != -1 && michael@0: aDetectedLanguage != this.defaultTargetLanguage) { michael@0: if (!aBrowser.translationUI) michael@0: aBrowser.translationUI = new TranslationUI(aBrowser); michael@0: michael@0: aBrowser.translationUI.showTranslationUI(aDetectedLanguage); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: /* TranslationUI objects keep the information related to translation for michael@0: * a specific browser. This object is passed to the translation michael@0: * infobar so that it can initialize itself. The properties exposed to michael@0: * the infobar are: michael@0: * - detectedLanguage, code of the language detected on the web page. michael@0: * - state, the state in which the infobar should be displayed michael@0: * - STATE_{OFFER,TRANSLATING,TRANSLATED,ERROR} constants. michael@0: * - translatedFrom, if already translated, source language code. michael@0: * - translatedTo, if already translated, target language code. michael@0: * - translate, method starting the translation of the current page. michael@0: * - showOriginalContent, method showing the original page content. michael@0: * - showTranslatedContent, method showing the translation for an michael@0: * already translated page whose original content is shown. michael@0: * - originalShown, boolean indicating if the original or translated michael@0: * version of the page is shown. michael@0: */ michael@0: function TranslationUI(aBrowser) { michael@0: this.browser = aBrowser; michael@0: } michael@0: michael@0: TranslationUI.prototype = { michael@0: STATE_OFFER: 0, michael@0: STATE_TRANSLATING: 1, michael@0: STATE_TRANSLATED: 2, michael@0: STATE_ERROR: 3, michael@0: michael@0: get doc() this.browser.contentDocument, michael@0: michael@0: translate: function(aFrom, aTo) { michael@0: this.state = this.STATE_TRANSLATING; michael@0: this.translatedFrom = aFrom; michael@0: this.translatedTo = aTo; michael@0: }, michael@0: michael@0: showURLBarIcon: function(aTranslated) { michael@0: let chromeWin = this.browser.ownerGlobal; michael@0: let PopupNotifications = chromeWin.PopupNotifications; michael@0: let removeId = aTranslated ? "translate" : "translated"; michael@0: let notification = michael@0: PopupNotifications.getNotification(removeId, this.browser); michael@0: if (notification) michael@0: PopupNotifications.remove(notification); michael@0: michael@0: let callback = aTopic => { michael@0: if (aTopic != "showing") michael@0: return false; michael@0: if (!this.notificationBox.getNotificationWithValue("translation")) michael@0: this.showTranslationInfoBar(); michael@0: return true; michael@0: }; michael@0: michael@0: let addId = aTranslated ? "translated" : "translate"; michael@0: PopupNotifications.show(this.browser, addId, null, michael@0: addId + "-notification-icon", null, null, michael@0: {dismissed: true, eventCallback: callback}); michael@0: }, michael@0: michael@0: _state: 0, michael@0: get state() this._state, michael@0: set state(val) { michael@0: let notif = this.notificationBox.getNotificationWithValue("translation"); michael@0: if (notif) michael@0: notif.state = val; michael@0: this._state = val; michael@0: }, michael@0: michael@0: originalShown: true, michael@0: showOriginalContent: function() { michael@0: this.showURLBarIcon(); michael@0: this.originalShown = true; michael@0: }, michael@0: michael@0: showTranslatedContent: function() { michael@0: this.showURLBarIcon(true); michael@0: this.originalShown = false; michael@0: }, michael@0: michael@0: get notificationBox() this.browser.ownerGlobal.gBrowser.getNotificationBox(), michael@0: michael@0: showTranslationInfoBar: function() { michael@0: let notificationBox = this.notificationBox; michael@0: let notif = notificationBox.appendNotification("", "translation", null, michael@0: notificationBox.PRIORITY_INFO_HIGH); michael@0: notif.init(this); michael@0: return notif; michael@0: }, michael@0: michael@0: showTranslationUI: function(aDetectedLanguage) { michael@0: this.detectedLanguage = aDetectedLanguage; michael@0: michael@0: // Reset all values before showing a new translation infobar. michael@0: this.state = 0; michael@0: this.translatedFrom = ""; michael@0: this.translatedTo = ""; michael@0: this.originalShown = true; michael@0: michael@0: this.showURLBarIcon(); michael@0: return this.showTranslationInfoBar(); michael@0: } michael@0: };