diff options
Diffstat (limited to 'browser/components/translation/Translation.jsm')
-rw-r--r-- | browser/components/translation/Translation.jsm | 446 |
1 files changed, 0 insertions, 446 deletions
diff --git a/browser/components/translation/Translation.jsm b/browser/components/translation/Translation.jsm deleted file mode 100644 index 15a847c13..000000000 --- a/browser/components/translation/Translation.jsm +++ /dev/null @@ -1,446 +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/. */ - -"use strict"; - -this.EXPORTED_SYMBOLS = [ - "Translation", - "TranslationTelemetry", -]; - -const {classes: Cc, interfaces: Ci, utils: Cu} = Components; - -const TRANSLATION_PREF_SHOWUI = "browser.translation.ui.show"; -const TRANSLATION_PREF_DETECT_LANG = "browser.translation.detectLanguage"; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Promise.jsm"); -Cu.import("resource://gre/modules/Task.jsm", this); - -this.Translation = { - STATE_OFFER: 0, - STATE_TRANSLATING: 1, - STATE_TRANSLATED: 2, - STATE_ERROR: 3, - STATE_UNAVAILABLE: 4, - - serviceUnavailable: false, - - supportedSourceLanguages: ["bg", "cs", "de", "en", "es", "fr", "ja", "ko", "nl", "no", "pl", "pt", "ru", "tr", "vi", "zh"], - supportedTargetLanguages: ["bg", "cs", "de", "en", "es", "fr", "ja", "ko", "nl", "no", "pl", "pt", "ru", "tr", "vi", "zh"], - - _defaultTargetLanguage: "", - get defaultTargetLanguage() { - if (!this._defaultTargetLanguage) { - this._defaultTargetLanguage = Cc["@mozilla.org/chrome/chrome-registry;1"] - .getService(Ci.nsIXULChromeRegistry) - .getSelectedLocale("global") - .split("-")[0]; - } - return this._defaultTargetLanguage; - }, - - documentStateReceived: function(aBrowser, aData) { - if (aData.state == this.STATE_OFFER) { - if (aData.detectedLanguage == this.defaultTargetLanguage) { - // Detected language is the same as the user's locale. - return; - } - - if (this.supportedSourceLanguages.indexOf(aData.detectedLanguage) == -1) { - // Detected language is not part of the supported languages. - TranslationTelemetry.recordMissedTranslationOpportunity(aData.detectedLanguage); - return; - } - - TranslationTelemetry.recordTranslationOpportunity(aData.detectedLanguage); - } - - if (!Services.prefs.getBoolPref(TRANSLATION_PREF_SHOWUI)) - return; - - if (!aBrowser.translationUI) - aBrowser.translationUI = new TranslationUI(aBrowser); - let trUI = aBrowser.translationUI; - - // Set all values before showing a new translation infobar. - trUI._state = Translation.serviceUnavailable ? Translation.STATE_UNAVAILABLE - : aData.state; - trUI.detectedLanguage = aData.detectedLanguage; - trUI.translatedFrom = aData.translatedFrom; - trUI.translatedTo = aData.translatedTo; - trUI.originalShown = aData.originalShown; - - trUI.showURLBarIcon(); - - if (trUI.shouldShowInfoBar(aBrowser.currentURI)) - trUI.showTranslationInfoBar(); - }, - - openProviderAttribution: function() { - let attribution = this.supportedEngines[this.translationEngine]; - Cu.import("resource:///modules/RecentWindow.jsm"); - RecentWindow.getMostRecentBrowserWindow().openUILinkIn(attribution, "tab"); - }, - - /** - * The list of translation engines and their attributions. - */ - supportedEngines: { - "bing" : "http://aka.ms/MicrosoftTranslatorAttribution", - "yandex" : "http://translate.yandex.com/" - }, - - /** - * Fallback engine (currently Bing Translator) if the preferences seem - * confusing. - */ - get defaultEngine() { - return this.supportedEngines.keys[0]; - }, - - /** - * Returns the name of the preferred translation engine. - */ - get translationEngine() { - let engine = Services.prefs.getCharPref("browser.translation.engine"); - return Object.keys(this.supportedEngines).indexOf(engine) == -1 ? this.defaultEngine : engine; - }, -}; - -/* TranslationUI objects keep the information related to translation for - * a specific browser. This object is passed to the translation - * infobar so that it can initialize itself. The properties exposed to - * the infobar are: - * - detectedLanguage, code of the language detected on the web page. - * - state, the state in which the infobar should be displayed - * - translatedFrom, if already translated, source language code. - * - translatedTo, if already translated, target language code. - * - translate, method starting the translation of the current page. - * - showOriginalContent, method showing the original page content. - * - showTranslatedContent, method showing the translation for an - * already translated page whose original content is shown. - * - originalShown, boolean indicating if the original or translated - * version of the page is shown. - */ -function TranslationUI(aBrowser) { - this.browser = aBrowser; -} - -TranslationUI.prototype = { - get browser() { - return this._browser; - }, - set browser(aBrowser) { - if (this._browser) - this._browser.messageManager.removeMessageListener("Translation:Finished", this); - aBrowser.messageManager.addMessageListener("Translation:Finished", this); - this._browser = aBrowser; - }, - translate: function(aFrom, aTo) { - if (aFrom == aTo || - (this.state == Translation.STATE_TRANSLATED && - this.translatedFrom == aFrom && this.translatedTo == aTo)) { - // Nothing to do. - return; - } - - if (this.state == Translation.STATE_OFFER) { - if (this.detectedLanguage != aFrom) - TranslationTelemetry.recordDetectedLanguageChange(true); - } else { - if (this.translatedFrom != aFrom) - TranslationTelemetry.recordDetectedLanguageChange(false); - if (this.translatedTo != aTo) - TranslationTelemetry.recordTargetLanguageChange(); - } - - this.state = Translation.STATE_TRANSLATING; - this.translatedFrom = aFrom; - this.translatedTo = aTo; - - this.browser.messageManager.sendAsyncMessage( - "Translation:TranslateDocument", - { from: aFrom, to: aTo } - ); - }, - - showURLBarIcon: function() { - let chromeWin = this.browser.ownerGlobal; - let PopupNotifications = chromeWin.PopupNotifications; - let removeId = this.originalShown ? "translated" : "translate"; - let notification = - PopupNotifications.getNotification(removeId, this.browser); - if (notification) - PopupNotifications.remove(notification); - - let callback = (aTopic, aNewBrowser) => { - if (aTopic == "swapping") { - let infoBarVisible = - this.notificationBox.getNotificationWithValue("translation"); - aNewBrowser.translationUI = this; - this.browser = aNewBrowser; - if (infoBarVisible) - this.showTranslationInfoBar(); - return true; - } - - if (aTopic != "showing") - return false; - let notification = this.notificationBox.getNotificationWithValue("translation"); - if (notification) - notification.close(); - else - this.showTranslationInfoBar(); - return true; - }; - - let addId = this.originalShown ? "translate" : "translated"; - PopupNotifications.show(this.browser, addId, null, - addId + "-notification-icon", null, null, - {dismissed: true, eventCallback: callback}); - }, - - _state: 0, - get state() { - return this._state; - }, - set state(val) { - let notif = this.notificationBox.getNotificationWithValue("translation"); - if (notif) - notif.state = val; - this._state = val; - }, - - originalShown: true, - showOriginalContent: function() { - this.originalShown = true; - this.showURLBarIcon(); - this.browser.messageManager.sendAsyncMessage("Translation:ShowOriginal"); - TranslationTelemetry.recordShowOriginalContent(); - }, - - showTranslatedContent: function() { - this.originalShown = false; - this.showURLBarIcon(); - this.browser.messageManager.sendAsyncMessage("Translation:ShowTranslation"); - }, - - get notificationBox() { - return this.browser.ownerGlobal.gBrowser.getNotificationBox(this.browser); - }, - - showTranslationInfoBar: function() { - let notificationBox = this.notificationBox; - let notif = notificationBox.appendNotification("", "translation", null, - notificationBox.PRIORITY_INFO_HIGH); - notif.init(this); - return notif; - }, - - shouldShowInfoBar: function(aURI) { - // Never show the infobar automatically while the translation - // service is temporarily unavailable. - if (Translation.serviceUnavailable) - return false; - - // Check if we should never show the infobar for this language. - let neverForLangs = - Services.prefs.getCharPref("browser.translation.neverForLanguages"); - if (neverForLangs.split(",").indexOf(this.detectedLanguage) != -1) { - TranslationTelemetry.recordAutoRejectedTranslationOffer(); - return false; - } - - // or if we should never show the infobar for this domain. - let perms = Services.perms; - if (perms.testExactPermission(aURI, "translate") == perms.DENY_ACTION) { - TranslationTelemetry.recordAutoRejectedTranslationOffer(); - return false; - } - - return true; - }, - - receiveMessage: function(msg) { - switch (msg.name) { - case "Translation:Finished": - if (msg.data.success) { - this.originalShown = false; - this.state = Translation.STATE_TRANSLATED; - this.showURLBarIcon(); - - // Record the number of characters translated. - TranslationTelemetry.recordTranslation(msg.data.from, msg.data.to, - msg.data.characterCount); - } else if (msg.data.unavailable) { - Translation.serviceUnavailable = true; - this.state = Translation.STATE_UNAVAILABLE; - } else { - this.state = Translation.STATE_ERROR; - } - break; - } - }, - - infobarClosed: function() { - if (this.state == Translation.STATE_OFFER) - TranslationTelemetry.recordDeniedTranslationOffer(); - } -}; - -/** - * Uses telemetry histograms for collecting statistics on the usage of the - * translation component. - * - * NOTE: Metrics are only recorded if the user enabled the telemetry option. - */ -this.TranslationTelemetry = { - - init: function () { - // Constructing histograms. - const plain = (id) => Services.telemetry.getHistogramById(id); - const keyed = (id) => Services.telemetry.getKeyedHistogramById(id); - this.HISTOGRAMS = { - OPPORTUNITIES : () => plain("TRANSLATION_OPPORTUNITIES"), - OPPORTUNITIES_BY_LANG : () => keyed("TRANSLATION_OPPORTUNITIES_BY_LANGUAGE"), - PAGES : () => plain("TRANSLATED_PAGES"), - PAGES_BY_LANG : () => keyed("TRANSLATED_PAGES_BY_LANGUAGE"), - CHARACTERS : () => plain("TRANSLATED_CHARACTERS"), - DENIED : () => plain("DENIED_TRANSLATION_OFFERS"), - AUTO_REJECTED : () => plain("AUTO_REJECTED_TRANSLATION_OFFERS"), - SHOW_ORIGINAL : () => plain("REQUESTS_OF_ORIGINAL_CONTENT"), - TARGET_CHANGES : () => plain("CHANGES_OF_TARGET_LANGUAGE"), - DETECTION_CHANGES : () => plain("CHANGES_OF_DETECTED_LANGUAGE"), - SHOW_UI : () => plain("SHOULD_TRANSLATION_UI_APPEAR"), - DETECT_LANG : () => plain("SHOULD_AUTO_DETECT_LANGUAGE"), - }; - - // Capturing the values of flags at the startup. - this.recordPreferences(); - }, - - /** - * Record a translation opportunity in the health report. - * @param language - * The language of the page. - */ - recordTranslationOpportunity: function (language) { - return this._recordOpportunity(language, true); - }, - - /** - * Record a missed translation opportunity in the health report. - * A missed opportunity is when the language detected is not part - * of the supported languages. - * @param language - * The language of the page. - */ - recordMissedTranslationOpportunity: function (language) { - return this._recordOpportunity(language, false); - }, - - /** - * Record an automatically rejected translation offer in the health - * report. A translation offer is automatically rejected when a user - * has previously clicked "Never translate this language" or "Never - * translate this site", which results in the infobar not being shown for - * the translation opportunity. - * - * These translation opportunities should still be recorded in addition to - * recording the automatic rejection of the offer. - */ - recordAutoRejectedTranslationOffer: function () { - if (!this._canRecord) return; - this.HISTOGRAMS.AUTO_REJECTED().add(); - }, - - /** - * Record a translation in the health report. - * @param langFrom - * The language of the page. - * @param langTo - * The language translated to - * @param numCharacters - * The number of characters that were translated - */ - recordTranslation: function (langFrom, langTo, numCharacters) { - if (!this._canRecord) return; - this.HISTOGRAMS.PAGES().add(); - this.HISTOGRAMS.PAGES_BY_LANG().add(langFrom + " -> " + langTo); - this.HISTOGRAMS.CHARACTERS().add(numCharacters); - }, - - /** - * Record a change of the detected language in the health report. This should - * only be called when actually executing a translation, not every time the - * user changes in the language in the UI. - * - * @param beforeFirstTranslation - * A boolean indicating if we are recording a change of detected - * language before translating the page for the first time. If we - * have already translated the page from the detected language and - * the user has manually adjusted the detected language false should - * be passed. - */ - recordDetectedLanguageChange: function (beforeFirstTranslation) { - if (!this._canRecord) return; - this.HISTOGRAMS.DETECTION_CHANGES().add(beforeFirstTranslation); - }, - - /** - * Record a change of the target language in the health report. This should - * only be called when actually executing a translation, not every time the - * user changes in the language in the UI. - */ - recordTargetLanguageChange: function () { - if (!this._canRecord) return; - this.HISTOGRAMS.TARGET_CHANGES().add(); - }, - - /** - * Record a denied translation offer. - */ - recordDeniedTranslationOffer: function () { - if (!this._canRecord) return; - this.HISTOGRAMS.DENIED().add(); - }, - - /** - * Record a "Show Original" command use. - */ - recordShowOriginalContent: function () { - if (!this._canRecord) return; - this.HISTOGRAMS.SHOW_ORIGINAL().add(); - }, - - /** - * Record the state of translation preferences. - */ - recordPreferences: function () { - if (!this._canRecord) return; - if (Services.prefs.getBoolPref(TRANSLATION_PREF_SHOWUI)) { - this.HISTOGRAMS.SHOW_UI().add(1); - } - if (Services.prefs.getBoolPref(TRANSLATION_PREF_DETECT_LANG)) { - this.HISTOGRAMS.DETECT_LANG().add(1); - } - }, - - _recordOpportunity: function(language, success) { - if (!this._canRecord) return; - this.HISTOGRAMS.OPPORTUNITIES().add(success); - this.HISTOGRAMS.OPPORTUNITIES_BY_LANG().add(language, success); - }, - - /** - * A shortcut for reading the telemetry preference. - * - */ - _canRecord: function () { - return Services.prefs.getBoolPref("toolkit.telemetry.enabled"); - } -}; - -this.TranslationTelemetry.init(); |