Bug 1759782 - Remove Firefox Translations addon from Nightly r=mixedpuppy

Differential Revision: https://phabricator.services.mozilla.com/D141820
This commit is contained in:
Andre Natal 2022-03-23 16:53:05 +00:00
Родитель 9ddc42292b
Коммит b9b8c7c39b
32 изменённых файлов: 0 добавлений и 50891 удалений

Просмотреть файл

@ -2023,45 +2023,6 @@ BrowserGlue.prototype = {
}); });
}, },
// Set up a listener to enable/disable the translation extension
// based on its preference.
_monitorTranslationsPref() {
const PREF = "extensions.translations.disabled";
const ID = "firefox-translations@mozilla.org";
const oldID = "firefox-infobar-ui-bergamot-browser-extension@browser.mt";
// First, try to uninstall the old extension, if exists.
(async () => {
let addon = await AddonManager.getAddonByID(oldID);
if (addon) {
addon.uninstall().catch(Cu.reportError);
}
})();
const _checkTranslationsPref = async () => {
let addon = await AddonManager.getAddonByID(ID);
let disabled = Services.prefs.getBoolPref(PREF, false);
if (!addon && disabled) {
// not installed, bail out early.
return;
}
if (!disabled) {
// first time install of addon and install on firefox update
addon =
(await AddonManager.maybeInstallBuiltinAddon(
ID,
"0.4.3",
"resource://builtin-addons/translations/"
)) || addon;
await addon.enable();
} else if (addon) {
await addon.disable();
}
};
Services.prefs.addObserver(PREF, _checkTranslationsPref);
_checkTranslationsPref();
},
async _setupSearchDetection() { async _setupSearchDetection() {
// There is no pref for this add-on because it shouldn't be disabled. // There is no pref for this add-on because it shouldn't be disabled.
const ID = "addons-search-detection@mozilla.com"; const ID = "addons-search-detection@mozilla.com";
@ -2332,9 +2293,6 @@ BrowserGlue.prototype = {
this._monitorIonStudies(); this._monitorIonStudies();
this._setupSearchDetection(); this._setupSearchDetection();
if (AppConstants.NIGHTLY_BUILD) {
this._monitorTranslationsPref();
}
this._monitorGPCPref(); this._monitorGPCPref();
this._monitorPrivacySegmentationPref(); this._monitorPrivacySegmentationPref();
}, },

Просмотреть файл

@ -13,8 +13,3 @@ DIRS += [
"pictureinpicture", "pictureinpicture",
"search-detection", "search-detection",
] ]
if CONFIG["NIGHTLY_BUILD"]:
DIRS += [
"translations",
]

Просмотреть файл

@ -1,20 +0,0 @@
This folder contains the source files for Firefox Translations, which utilizes
the proceedings from Project Bergamot [1].
The feature is developed as a webextension [2] which utilizes a neural machine
translation decoder [3] ported to WebAssembly in order to process the
in page translation. The translation models [4] are downloaded on-demand by the
extension, so there's no need to bundle them too.
The folder `extension_src` contains the entire code of the extension's xpi and
the wasm module (which lies inside the folder wasm), and is automatically
generated by the `import_xpi.py` script, which is responsibile for cloning
the extension repo [2], build it, and generate the `jar.mn` package containing
all the pertinent files necessary for running it.
For any questions, reach out to anatal@mozilla.com.
[1] https://browser.mt/
[2] https://github.com/mozilla-extensions/bergamot-browser-extension
[3] https://github.com/mozilla/bergamot-translator/
[4] https://github.com/mozilla-applied-ml/bergamot-models

Просмотреть файл

@ -1,50 +0,0 @@
{
"extensionName": {
"message": "Firefox Translations",
"description": "Name of the extension"
},
"extensionDescription": {
"message": "Neuronový strojový překlad v prohlížeči",
"description": "Description of the extension."
},
"currentlyDownloadingTranslationEngine": {
"message": "Stahování překladače",
"description": "Informs the user that the translations feature is currently downloading the translation engine."
},
"currentlyDownloadingLanguageModel": {
"message": "Stahování jazykového modelu",
"description": "Informs the user that the translations feature is currently downloading the language model files."
},
"detailedDownloadProgress": {
"message": "Staženo $PERCENTAGE$ % z $MB$ MB",
"description": "Informs the user how the language model file downloading is progressing.",
"placeholders": {
"percentage": {
"content": "$1",
"example": "50"
},
"mb": {
"content": "$2",
"example": "22,2"
}
}
},
"currentlyLoadingLanguageModel": {
"message": "Načítání jazykového modelu",
"description": "Informs the user that the translations feature is currently loading the language model files into memory."
},
"loadedLanguageModel": {
"message": "Jazykový model načten",
"description": "Informs the user that the translations feature has loaded the language model files into memory."
},
"partsLeftToTranslate": {
"message": "Zbývající části k přeložení: $NUM$",
"description": "Informs the user that the translations feature has $NUM$ parts left to translate.",
"placeholders": {
"num": {
"content": "$1",
"example": "3"
}
}
}
}

Просмотреть файл

@ -1,50 +0,0 @@
{
"extensionName": {
"message": "Firefox Translations",
"description": "Name of the extension"
},
"extensionDescription": {
"message": "Neurale Maschine Übersetzung für den Browser.",
"description": "Description of the extension."
},
"currentlyDownloadingTranslationEngine": {
"message": "Derzeit Download Übersetzungs-Engine",
"description": "Informs the user that the translations feature is currently downloading the translation engine."
},
"currentlyDownloadingLanguageModel": {
"message": "Derzeit das Sprachmodell herunterladen",
"description": "Informs the user that the translations feature is currently downloading the language model files."
},
"detailedDownloadProgress": {
"message": "$PERCENTAGE$% von $MB$ mb heruntergeladen",
"description": "Informs the user how the language model file downloading is progressing.",
"placeholders": {
"percentage": {
"content": "$1",
"example": "50"
},
"mb": {
"content": "$2",
"example": "22.2"
}
}
},
"currentlyLoadingLanguageModel": {
"message": "Derzeit ladende Sprachmodell",
"description": "Informs the user that the translations feature is currently loading the language model files into memory."
},
"loadedLanguageModel": {
"message": "Sprachmodell geladen",
"description": "Informs the user that the translations feature has loaded the language model files into memory."
},
"partsLeftToTranslate": {
"message": "Noch zu übersetzende Teile: $NUM$",
"description": "Informs the user that the translations feature has $NUM$ parts left to translate.",
"placeholders": {
"num": {
"content": "$1",
"example": "3"
}
}
}
}

Просмотреть файл

@ -1,50 +0,0 @@
{
"extensionName": {
"message": "Firefox Translations",
"description": "Name of the extension"
},
"extensionDescription": {
"message": "Neural Machine Translation for the browser.",
"description": "Description of the extension."
},
"currentlyDownloadingTranslationEngine": {
"message": "Currently downloading translation engine",
"description": "Informs the user that the translations feature is currently downloading the translation engine."
},
"currentlyDownloadingLanguageModel": {
"message": "Currently downloading language model",
"description": "Informs the user that the translations feature is currently downloading the language model files."
},
"detailedDownloadProgress": {
"message": "$PERCENTAGE$% out of $MB$ mb downloaded",
"description": "Informs the user how the language model file downloading is progressing.",
"placeholders": {
"percentage": {
"content": "$1",
"example": "50"
},
"mb": {
"content": "$2",
"example": "22.2"
}
}
},
"currentlyLoadingLanguageModel": {
"message": "Currently loading language model",
"description": "Informs the user that the translations feature is currently loading the language model files into memory."
},
"loadedLanguageModel": {
"message": "Language model loaded",
"description": "Informs the user that the translations feature has loaded the language model files into memory."
},
"partsLeftToTranslate": {
"message": "Parts left to translate: $NUM$",
"description": "Informs the user that the translations feature has $NUM$ parts left to translate.",
"placeholders": {
"num": {
"content": "$1",
"example": "3"
}
}
}
}

Просмотреть файл

@ -1,50 +0,0 @@
{
"extensionName": {
"message": "Firefox Translations",
"description": "Name of the extension"
},
"extensionDescription": {
"message": "Traducción de la Máquina Neural para el navegador.",
"description": "Description of the extension."
},
"currentlyDownloadingTranslationEngine": {
"message": "Motor de traducción de descarga",
"description": "Informs the user that the translations feature is currently downloading the translation engine."
},
"currentlyDownloadingLanguageModel": {
"message": "Actualmente descargando el modelo de idioma",
"description": "Informs the user that the translations feature is currently downloading the language model files."
},
"detailedDownloadProgress": {
"message": "$PERCENTAGE$% de $MB$ mb descargado",
"description": "Informs the user how the language model file downloading is progressing.",
"placeholders": {
"percentage": {
"content": "$1",
"example": "50"
},
"mb": {
"content": "$2",
"example": "22.2"
}
}
},
"currentlyLoadingLanguageModel": {
"message": "Actualmente cargar el modelo de idioma",
"description": "Informs the user that the translations feature is currently loading the language model files into memory."
},
"loadedLanguageModel": {
"message": "Modelo de lenguaje cargado",
"description": "Informs the user that the translations feature has loaded the language model files into memory."
},
"partsLeftToTranslate": {
"message": "Partes que quedan para traducir: $NUM$",
"description": "Informs the user that the translations feature has $NUM$ parts left to translate.",
"placeholders": {
"num": {
"content": "$1",
"example": "3"
}
}
}
}

Просмотреть файл

@ -1,50 +0,0 @@
{
"extensionName": {
"message": "Firefox Translations",
"description": "Name of the extension"
},
"extensionDescription": {
"message": "Neural Machine Translation brauseri jaoks.",
"description": "Description of the extension."
},
"currentlyDownloadingTranslationEngine": {
"message": "Praegu laaditakse tõlkemootor",
"description": "Informs the user that the translations feature is currently downloading the translation engine."
},
"currentlyDownloadingLanguageModel": {
"message": "Praegu allalaadimine keelemudel",
"description": "Informs the user that the translations feature is currently downloading the language model files."
},
"detailedDownloadProgress": {
"message": "$PERCENTAGE$% $MB$ mb allalaaditud",
"description": "Informs the user how the language model file downloading is progressing.",
"placeholders": {
"percentage": {
"content": "$1",
"example": "50"
},
"mb": {
"content": "$2",
"example": "22.2"
}
}
},
"currentlyLoadingLanguageModel": {
"message": "Praegu laadiv keelemudel",
"description": "Informs the user that the translations feature is currently loading the language model files into memory."
},
"loadedLanguageModel": {
"message": "Keelemudel koormatud",
"description": "Informs the user that the translations feature has loaded the language model files into memory."
},
"partsLeftToTranslate": {
"message": "Osad jätta tõlkida: $NUM$",
"description": "Informs the user that the translations feature has $NUM$ parts left to translate.",
"placeholders": {
"num": {
"content": "$1",
"example": "3"
}
}
}
}

Просмотреть файл

@ -1,50 +0,0 @@
{
"extensionName": {
"message": "Firefox Translations",
"description": "Name of the extension"
},
"extensionDescription": {
"message": "Нейронный машинный перевод для браузера.",
"description": "Description of the extension."
},
"currentlyDownloadingTranslationEngine": {
"message": "Скачивание движка перевода",
"description": "Informs the user that the translations feature is currently downloading the translation engine."
},
"currentlyDownloadingLanguageModel": {
"message": "Скачивание языковой модели",
"description": "Informs the user that the translations feature is currently downloading the language model files."
},
"detailedDownloadProgress": {
"message": "$PERCENTAGE$% из $MB$ МБ загружено",
"description": "Informs the user how the language model file downloading is progressing.",
"placeholders": {
"percentage": {
"content": "$1",
"example": "50"
},
"mb": {
"content": "$2",
"example": "22.2"
}
}
},
"currentlyLoadingLanguageModel": {
"message": "Загрузка языковой модели",
"description": "Informs the user that the translations feature is currently loading the language model files into memory."
},
"loadedLanguageModel": {
"message": "Языковая модель загружена",
"description": "Informs the user that the translations feature has loaded the language model files into memory."
},
"partsLeftToTranslate": {
"message": "Осталось частей для перевода: $NUM$",
"description": "Informs the user that the translations feature has $NUM$ parts left to translate.",
"placeholders": {
"num": {
"content": "$1",
"example": "3"
}
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,44 +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/. */
/* global ExtensionAPI, ExtensionCommon, Services */
"use strict";
this.extensionPreferences = class extends ExtensionAPI {
getAPI() {
const { Preferences } = ChromeUtils.import(
"resource://gre/modules/Preferences.jsm",
{},
);
const { ExtensionUtils } = ChromeUtils.import(
"resource://gre/modules/ExtensionUtils.jsm",
{},
);
const { ExtensionError } = ExtensionUtils;
const telemetryInactivityThresholdInSecondsOverridePrefName = `extensions.translations.telemetryInactivityThresholdInSecondsOverride`;
return {
experiments: {
extensionPreferences: {
async getTelemetryInactivityThresholdInSecondsOverridePref() {
try {
const value = Preferences.get(
telemetryInactivityThresholdInSecondsOverridePrefName,
false,
);
if (!value) {
return false;
}
return parseFloat(value);
} catch (error) {
// Surface otherwise silent or obscurely reported errors
console.error(error.message, error.stack);
throw new ExtensionError(error.message);
}
},
},
},
};
}
};

Просмотреть файл

@ -1,15 +0,0 @@
[
{
"namespace": "experiments.extensionPreferences",
"description": "Enables read-only access to specific Extensions-related about:config preferences",
"functions": [
{
"name": "getTelemetryInactivityThresholdInSecondsOverridePref",
"type": "function",
"description": "Get the `extensions.translations.telemetryInactivityThresholdInSecondsOverride` preference's value",
"parameters": [],
"async": true
}
]
}
]

Просмотреть файл

@ -1,40 +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/. */
/* global ExtensionAPI */
"use strict";
this.languageDetector = class extends ExtensionAPI {
getAPI() {
const { LanguageDetector } = ChromeUtils.import(
"resource:///modules/translation/LanguageDetector.jsm",
{},
);
const { ExtensionUtils } = ChromeUtils.import(
"resource://gre/modules/ExtensionUtils.jsm",
{},
);
const { ExtensionError } = ExtensionUtils;
return {
experiments: {
languageDetector: {
/* Detect language */
detectLanguage: async function detectLanguage(str) {
try {
// console.log("Called detectLanguage(str)", str);
return LanguageDetector.detectLanguage(str);
} catch (error) {
// Surface otherwise silent or obscurely reported errors
console.error(error.message, error.stack);
throw new ExtensionError(error.message);
}
},
},
},
};
}
};

Просмотреть файл

@ -1,20 +0,0 @@
[
{
"namespace": "experiments.languageDetector",
"description": "Provides access to the language detector that resides in tree",
"functions": [
{
"name": "detectLanguage",
"type": "function",
"async": true,
"description": "Detect language",
"parameters": [
{
"name": "params",
"type": "any"
}
]
}
]
}
]

Просмотреть файл

@ -1,58 +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/. */
/* global ExtensionAPI, ExtensionCommon, Services */
"use strict";
this.telemetryEnvironment = class extends ExtensionAPI {
getAPI(context) {
const { TelemetryController } = ChromeUtils.import(
"resource://gre/modules/TelemetryController.jsm",
{},
);
const { TelemetryEnvironment } = ChromeUtils.import(
"resource://gre/modules/TelemetryEnvironment.jsm",
{},
);
/**
* These attributes are already sent as part of the telemetry ping envelope
* @returns {{}}
*/
const collectTelemetryEnvironmentBasedAttributes = () => {
const environment = TelemetryEnvironment.currentEnvironment;
// console.debug("TelemetryEnvironment.currentEnvironment", environment);
return {
systemMemoryMb: environment.system.memoryMB,
systemCpuCount: environment.system.cpu.count,
systemCpuCores: environment.system.cpu.cores,
systemCpuVendor: environment.system.cpu.vendor,
systemCpuFamily: environment.system.cpu.family,
systemCpuModel: environment.system.cpu.model,
systemCpuStepping: environment.system.cpu.stepping,
systemCpuL2cacheKB: environment.system.cpu.l2cacheKB,
systemCpuL3cacheKB: environment.system.cpu.l3cacheKB,
systemCpuSpeedMhz: environment.system.cpu.speedMHz,
systemCpuExtensions: environment.system.cpu.extensions,
};
};
return {
experiments: {
telemetryEnvironment: {
async getTranslationRelevantFxTelemetryMetrics() {
await TelemetryController.promiseInitialized();
const telemetryEnvironmentBasedAttributes = collectTelemetryEnvironmentBasedAttributes();
// console.debug("telemetryEnvironmentBasedAttributes", telemetryEnvironmentBasedAttributes);
return {
...telemetryEnvironmentBasedAttributes,
};
},
},
},
};
}
};

Просмотреть файл

@ -1,15 +0,0 @@
[
{
"namespace": "experiments.telemetryEnvironment",
"description": "Enables read-only access to the translation-relevant info from the current telemetry environment",
"functions": [
{
"name": "getTranslationRelevantFxTelemetryMetrics",
"type": "function",
"description": "Get the translation-relevant info from the current telemetry environment",
"parameters": [],
"async": true
}
]
}
]

Просмотреть файл

@ -1,57 +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/. */
/* global ExtensionAPI, ExtensionCommon, Services */
"use strict";
this.telemetryPreferences = class extends ExtensionAPI {
getAPI(context) {
const EventManager = ExtensionCommon.EventManager;
const uploadEnabledPrefName = `datareporting.healthreport.uploadEnabled`;
const cachedClientIDPrefName = `toolkit.telemetry.cachedClientID`;
return {
experiments: {
telemetryPreferences: {
onUploadEnabledPrefChange: new EventManager({
context,
name: "telemetryPreferences.onUploadEnabledPrefChange",
register: fire => {
const callback = () => {
fire.async().catch(() => {}); // ignore Message Manager disconnects
};
Services.prefs.addObserver(uploadEnabledPrefName, callback);
return () => {
Services.prefs.removeObserver(uploadEnabledPrefName, callback);
};
},
}).api(),
async getUploadEnabledPref() {
return Services.prefs.getBoolPref(uploadEnabledPrefName, undefined);
},
onCachedClientIDPrefChange: new EventManager({
context,
name: "telemetryPreferences.onCachedClientIDPrefChange",
register: fire => {
const callback = () => {
fire.async().catch(() => {}); // ignore Message Manager disconnects
};
Services.prefs.addObserver(cachedClientIDPrefName, callback);
return () => {
Services.prefs.removeObserver(cachedClientIDPrefName, callback);
};
},
}).api(),
async getCachedClientIDPref() {
return Services.prefs.getStringPref(
cachedClientIDPrefName,
undefined,
);
},
},
},
};
}
};

Просмотреть файл

@ -1,34 +0,0 @@
[
{
"namespace": "experiments.telemetryPreferences",
"description": "Enables read-only access to specific Telemetry-related about:config preferences",
"events": [
{
"name": "onUploadEnabledPrefChange",
"type": "function",
"parameters": []
},
{
"name": "onCachedClientIDPrefChange",
"type": "function",
"parameters": []
}
],
"functions": [
{
"name": "getUploadEnabledPref",
"type": "function",
"description": "Get the uploadEnabled preference's value",
"parameters": [],
"async": true
},
{
"name": "getCachedClientIDPref",
"type": "function",
"description": "Get the cachedClientID preference's value",
"parameters": [],
"async": true
}
]
}
]

Просмотреть файл

@ -1,320 +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/. */
/* global TranslationBrowserChromeUiNotificationManager */
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "(TranslationBrowserChromeUi)" }]*/
const { setTimeout, clearTimeout } = ChromeUtils.import(
"resource://gre/modules/Timer.jsm",
{},
);
const TranslationInfoBarStates = {
STATE_OFFER: 0,
STATE_TRANSLATING: 1,
STATE_TRANSLATED: 2,
STATE_ERROR: 3,
STATE_UNAVAILABLE: 4,
};
class TranslationBrowserChromeUi {
constructor(Services, browser, context, apiEventEmitter, tabId) {
this.Services = Services;
this.uiState = null;
this.browser = browser;
this.context = context;
this.translationInfoBarShown = false;
this.shouldShowTranslationProgressTimer = undefined;
this.importTranslationNotification();
// The manager instance is injected into the translation notification bar and handles events from therein
this.translationBrowserChromeUiNotificationManager = new TranslationBrowserChromeUiNotificationManager(
browser,
apiEventEmitter,
tabId,
TranslationInfoBarStates,
);
}
get notificationBox() {
return this.browser.ownerGlobal.gBrowser.getNotificationBox(this.browser);
}
importTranslationNotification() {
const chromeWin = this.browser.ownerGlobal;
// As a workaround to be able to load updates for the translation notification on extension reload
// we use the current unix timestamp as part of the element id.
// TODO: Restrict use of Date.now() as cachebuster to development mode only
chromeWin.now = Date.now();
try {
chromeWin.customElements.setElementCreationCallback(
`translation-notification-${chromeWin.now}`,
() => {
this.Services.scriptloader.loadSubScript(
this.context.extension.getURL(
"experiment-apis/translateUi/content/translation-notification.js",
) +
"?cachebuster=" +
chromeWin.now,
chromeWin,
);
},
);
} catch (e) {
console.log(
"Error occurred when attempting to load the translation notification script, but we continue nevertheless",
e,
);
}
}
onUiStateUpdate(uiState) {
// Set all values before showing a new translation infobar.
this.translationBrowserChromeUiNotificationManager.uiState = uiState;
this.setInfobarState(uiState.infobarState);
this.updateTranslationProgress(uiState);
const showInfoBar = this.shouldShowInfoBar(this.browser.contentPrincipal);
if (showInfoBar) {
this.showTranslationInfoBarIfNotAlreadyShown();
} else {
this.hideTranslationInfoBarIfShown();
}
// Always show the url bar icon
this.showURLBarIcon(showInfoBar);
}
/**
* Syncs infobarState with the inner infobar state variable of the infobar
* @param val
*/
setInfobarState(val) {
const notif = this.notificationBox.getNotificationWithValue("translation");
if (notif) {
notif.state = val;
}
}
/**
* Informs the infobar element of the current translation progress
*/
updateTranslationProgress(uiState) {
// Don't bother updating translation progress if not currently translating
if (
this.translationBrowserChromeUiNotificationManager.uiState
.infobarState !== TranslationInfoBarStates.STATE_TRANSLATING
) {
return;
}
const notif = this.notificationBox.getNotificationWithValue("translation");
if (notif) {
const {
modelDownloading,
translationDurationMs,
localizedTranslationProgressText,
} = uiState;
// Always cancel ongoing timers so that we start from a clean state
if (this.shouldShowTranslationProgressTimer) {
clearTimeout(this.shouldShowTranslationProgressTimer);
}
// Only show progress if translation has been going on for at least 3 seconds
// or we are currently downloading a model
let shouldShowTranslationProgress;
const thresholdMsAfterWhichToShouldTranslationProgress = 3000;
if (
translationDurationMs >=
thresholdMsAfterWhichToShouldTranslationProgress ||
modelDownloading
) {
shouldShowTranslationProgress = true;
} else {
// Use a timer to show the translation progress after the threshold
this.shouldShowTranslationProgressTimer = setTimeout(() => {
notif.updateTranslationProgress(
true,
localizedTranslationProgressText,
);
clearTimeout(this.shouldShowTranslationProgressTimer);
}, thresholdMsAfterWhichToShouldTranslationProgress - translationDurationMs);
// Don't show until then
shouldShowTranslationProgress = false;
}
notif.updateTranslationProgress(
shouldShowTranslationProgress,
localizedTranslationProgressText,
);
}
}
shouldShowInfoBar(principal) {
if (
![
TranslationInfoBarStates.STATE_OFFER,
TranslationInfoBarStates.STATE_TRANSLATING,
TranslationInfoBarStates.STATE_TRANSLATED,
TranslationInfoBarStates.STATE_ERROR,
].includes(
this.translationBrowserChromeUiNotificationManager.uiState.infobarState,
)
) {
return false;
}
// Don't show the infobar if we have no language detection results yet
if (
!this.translationBrowserChromeUiNotificationManager.uiState
.detectedLanguageResults
) {
return false;
}
// Don't show the infobar if we couldn't confidently detect the language
if (
!this.translationBrowserChromeUiNotificationManager.uiState
.detectedLanguageResults.confident
) {
return false;
}
// Check if we should never show the infobar for this language.
const neverForLangs = this.Services.prefs.getCharPref(
"browser.translation.neverForLanguages",
);
if (
neverForLangs
.split(",")
.includes(
this.translationBrowserChromeUiNotificationManager.uiState
.detectedLanguageResults.language,
)
) {
// TranslationTelemetry.recordAutoRejectedTranslationOffer();
return false;
}
// or if we should never show the infobar for this domain.
const perms = this.Services.perms;
if (
perms.testExactPermissionFromPrincipal(principal, "translate") ===
perms.DENY_ACTION
) {
// TranslationTelemetry.recordAutoRejectedTranslationOffer();
return false;
}
return true;
}
hideURLBarIcon() {
const chromeWin = this.browser.ownerGlobal;
const PopupNotifications = chromeWin.PopupNotifications;
const removeId = this.translationBrowserChromeUiNotificationManager.uiState
.originalShown
? "translated"
: "translate";
const notification = PopupNotifications.getNotification(
removeId,
this.browser,
);
if (notification) {
PopupNotifications.remove(notification);
}
}
showURLBarIcon(showInfoBar) {
const chromeWin = this.browser.ownerGlobal;
const PopupNotifications = chromeWin.PopupNotifications;
const inactive =
!showInfoBar ||
this.translationBrowserChromeUiNotificationManager.uiState.originalShown;
// Remove existing url bar icon
["translated", "translate"].forEach(id => {
const notification = PopupNotifications.getNotification(id, this.browser);
if (notification) {
PopupNotifications.remove(notification);
}
});
const onClickCallback = (topic /* , aNewBrowser */) => {
if (topic === "swapping") {
const infoBarVisible = this.notificationBox.getNotificationWithValue(
"translation",
);
if (infoBarVisible) {
this.showTranslationInfoBar();
}
return true;
}
if (topic !== "showing") {
return false;
}
const translationNotification = this.notificationBox.getNotificationWithValue(
"translation",
);
if (translationNotification) {
translationNotification.close();
} else {
this.showTranslationInfoBar();
}
return true;
};
const addId = inactive ? "translate" : "translated";
PopupNotifications.show(
this.browser,
addId,
null,
addId + "-notification-icon",
null,
null,
{ dismissed: true, eventCallback: onClickCallback },
);
}
showTranslationInfoBarIfNotAlreadyShown() {
const translationNotification = this.notificationBox.getNotificationWithValue(
"translation",
);
if (!translationNotification && !this.translationInfoBarShown) {
this.showTranslationInfoBar();
}
}
hideTranslationInfoBarIfShown() {
const translationNotification = this.notificationBox.getNotificationWithValue(
"translation",
);
if (translationNotification) {
translationNotification.close();
}
this.translationInfoBarShown = false;
}
showTranslationInfoBar() {
console.debug("showTranslationInfoBar");
this.translationInfoBarShown = true;
const notificationBox = this.notificationBox;
const chromeWin = this.browser.ownerGlobal;
const notif = notificationBox.appendNotification(
"translation",
{
label: "",
priority: notificationBox.PRIORITY_INFO_HIGH,
is: `translation-notification-${chromeWin.now}`,
}
);
notif.init(this.translationBrowserChromeUiNotificationManager);
this.translationBrowserChromeUiNotificationManager.infobarDisplayed(
notif._getSourceLang(),
notif._getTargetLang(),
);
return notif;
}
}

Просмотреть файл

@ -1,80 +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/. */
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "(TranslationBrowserChromeUiNotificationManager)" }]*/
class TranslationBrowserChromeUiNotificationManager {
constructor(browser, apiEventEmitter, tabId, TranslationInfoBarStates) {
this.uiState = null;
this.TranslationInfoBarStates = TranslationInfoBarStates;
this.apiEventEmitter = apiEventEmitter;
this.tabId = tabId;
this.browser = browser;
}
infobarDisplayed(from, to) {
console.log("infobarDisplayed", { from, to });
this.apiEventEmitter.emit("onInfoBarDisplayed", this.tabId, from, to);
}
toLanguageChanged(from, newTo) {
console.log("toLanguageChanged", { from, newTo });
this.apiEventEmitter.emit("onSelectTranslateTo", this.tabId, from, newTo);
}
fromLanguageChanged(newFrom, to) {
console.log("fromLanguageChanged", { newFrom, to });
this.apiEventEmitter.emit("onSelectTranslateFrom", this.tabId, newFrom, to);
}
infobarClosed(from, to) {
console.log("infobarClosed", { from, to });
this.apiEventEmitter.emit("onInfoBarClosed", this.tabId, from, to);
}
neverForLanguage(from, to) {
console.log("neverForLanguage", { from, to });
this.apiEventEmitter.emit(
"onNeverTranslateSelectedLanguage",
this.tabId,
from,
to,
);
}
neverForSite(from, to) {
console.log("neverForSite", { from, to });
this.apiEventEmitter.emit("onNeverTranslateThisSite", this.tabId, from, to);
}
showOriginalContent(from, to) {
console.log("showOriginalContent", { from, to });
this.apiEventEmitter.emit(
"onShowOriginalButtonPressed",
this.tabId,
from,
to,
);
}
showTranslatedContent(from, to) {
console.log("showTranslatedContent", { from, to });
this.apiEventEmitter.emit(
"onShowTranslatedButtonPressed",
this.tabId,
from,
to,
);
}
translate(from, to) {
console.log("translate", { from, to });
this.apiEventEmitter.emit("onTranslateButtonPressed", this.tabId, from, to);
}
notNow(from, to) {
console.log("notNow", { from, to });
this.apiEventEmitter.emit("onNotNowButtonPressed", this.tabId, from, to);
}
}

Просмотреть файл

@ -1,177 +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/. */
/* global ExtensionAPI */
"use strict";
this.translateUi = class extends ExtensionAPI {
getAPI(context) {
const { Services } = ChromeUtils.import(
"resource://gre/modules/Services.jsm",
{},
);
const now = Date.now();
/* global TranslationBrowserChromeUiManager */
Services.scriptloader.loadSubScript(
context.extension.getURL(
"experiment-apis/translateUi/TranslationBrowserChromeUiManager.js",
) +
"?cachebuster=" +
now,
);
/* global TranslationBrowserChromeUi */
Services.scriptloader.loadSubScript(
context.extension.getURL(
"experiment-apis/translateUi/TranslationBrowserChromeUi.js",
) +
"?cachebuster=" +
now,
);
const { ExtensionCommon } = ChromeUtils.import(
"resource://gre/modules/ExtensionCommon.jsm",
{},
);
const { EventManager, EventEmitter } = ExtensionCommon;
const apiEventEmitter = new EventEmitter();
const { ExtensionUtils } = ChromeUtils.import(
"resource://gre/modules/ExtensionUtils.jsm",
{},
);
const { ExtensionError } = ExtensionUtils;
/**
* Boilerplate-reducing factory method translating between
* apiEventEmitter.emit("translateUi.onFoo", ...args)
* and the actual web extension event being emitted
*
* @param {string} eventRef the event reference, eg "onFoo"
* @returns {void}
*/
const eventManagerFactory = eventRef => {
const eventId = `translateUi.${eventRef}`;
return new EventManager({
context,
name: eventId,
register: fire => {
const listener = (event, ...args) => fire.async(...args);
apiEventEmitter.on(eventRef, listener);
return () => {
apiEventEmitter.off(eventRef, listener);
};
},
});
};
const { tabManager } = context.extension;
const translationBrowserChromeUiInstancesByTabId = new Map();
const getTranslationBrowserChromeUiInstanceByTabId = tabId => {
if (translationBrowserChromeUiInstancesByTabId.has(tabId)) {
return translationBrowserChromeUiInstancesByTabId.get(tabId);
}
const tab = tabManager.get(tabId);
const { browser } = tab;
const translationBrowserChromeUi = new TranslationBrowserChromeUi(
Services,
browser,
context,
apiEventEmitter,
tabId,
);
translationBrowserChromeUiInstancesByTabId.set(
tabId,
translationBrowserChromeUi,
);
return translationBrowserChromeUi;
};
return {
experiments: {
translateUi: {
/* Start reacting to translation state updates */
start: async function start() {
try {
console.log("Called start()");
console.log(
"Inactivating legacy built-in translation feature (by setting browser.translation.ui.show and browser.translation.detectLanguage to false)",
);
Services.prefs.setBoolPref(`browser.translation.ui.show`, false);
Services.prefs.setBoolPref(
`browser.translation.detectLanguage`,
false,
);
return undefined;
} catch (error) {
// Surface otherwise silent or obscurely reported errors
console.error(error.message, error.stack);
throw new ExtensionError(error.message);
}
},
/* Set current ui state */
setUiState: async function setUiState(tabId, uiState) {
try {
// console.log("Called setUiState(tabId, uiState)", {tabId,uiState});
const translationBrowserChromeUi = getTranslationBrowserChromeUiInstanceByTabId(
tabId,
);
translationBrowserChromeUi.onUiStateUpdate(uiState);
return undefined;
} catch (error) {
// Surface otherwise silent or obscurely reported errors
console.error(error.message, error.stack);
throw new ExtensionError(error.message);
}
},
/* Stop reacting to translation state updates */
stop: async function stop() {
try {
console.log("Called stop()");
return undefined;
} catch (error) {
// Surface otherwise silent or obscurely reported errors
console.error(error.message, error.stack);
throw new ExtensionError(error.message);
}
},
/* Event boilerplate with listeners that forwards all but the first argument to the web extension event */
onInfoBarDisplayed: eventManagerFactory("onInfoBarDisplayed").api(),
onSelectTranslateTo: eventManagerFactory("onSelectTranslateTo").api(),
onSelectTranslateFrom: eventManagerFactory(
"onSelectTranslateFrom",
).api(),
onInfoBarClosed: eventManagerFactory("onInfoBarClosed").api(),
onNeverTranslateSelectedLanguage: eventManagerFactory(
"onNeverTranslateSelectedLanguage",
).api(),
onNeverTranslateThisSite: eventManagerFactory(
"onNeverTranslateThisSite",
).api(),
onShowOriginalButtonPressed: eventManagerFactory(
"onShowOriginalButtonPressed",
).api(),
onShowTranslatedButtonPressed: eventManagerFactory(
"onShowTranslatedButtonPressed",
).api(),
onTranslateButtonPressed: eventManagerFactory(
"onTranslateButtonPressed",
).api(),
onNotNowButtonPressed: eventManagerFactory(
"onNotNowButtonPressed",
).api(),
},
},
};
}
};

Просмотреть файл

@ -1,443 +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/. */
/* global MozElements */
"use strict";
window.MozTranslationNotification = class extends MozElements.Notification {
static get markup() {
return `
<hbox anonid="details" align="center" flex="1">
<image class="messageImage"/>
<panel anonid="welcomePanel" class="translation-welcome-panel" type="arrow" align="start">
<image class="translation-welcome-logo"/>
<vbox flex="1" class="translation-welcome-content">
<description class="translation-welcome-headline" anonid="welcomeHeadline"/>
<description class="translation-welcome-body" anonid="welcomeBody"/>
<hbox align="center">
<label anonid="learnMore" class="plain" onclick="openTrustedLinkIn('https://support.mozilla.org/kb/automatic-translation', 'tab'); this.parentNode.parentNode.parentNode.hidePopup();" is="text-link"/>
<spacer flex="1"/>
<button anonid="thanksButton" onclick="this.parentNode.parentNode.parentNode.hidePopup();"/>
</hbox>
</vbox>
</panel>
<deck anonid="translationStates" selectedIndex="0">
<hbox class="translate-offer-box" align="center">
<label value="&translation.thisPageIsIn.label;"/>
<menulist class="notification-button" anonid="detectedLanguage">
<menupopup/>
</menulist>
<label value="&translation.translateThisPage.label;"/>
<button class="notification-button primary" label="&translation.translate.button;" anonid="translate" oncommand="this.closest('notification').translate();"/>
<button class="notification-button" label="&translation.notNow.button;" anonid="notNow" oncommand="this.closest('notification').notNow();"/>
</hbox>
<vbox class="translating-box" pack="center">
<hbox><label value="&translation.translatingContent.label;"/><label anonid="progress-label" value=""/></hbox>
</vbox>
<hbox class="translated-box" align="center">
<label value="&translation.translatedFrom.label;" style="margin-inline-end: 4px;"/>
<label anonid="fromLanguage" style="margin-inline:0;font-weight: bold;"/>
<label value="&translation.translatedTo.label;" style="margin-inline:3px;"/>
<label anonid="toLanguage" style="margin-inline:0;font-weight: bold;"/>
<label value="&translation.translatedToSuffix.label;"/>
<button anonid="showOriginal" class="notification-button" label="&translation.showOriginal.button;" oncommand="this.closest('notification').showOriginal();"/>
<button anonid="showTranslation" class="notification-button" label="&translation.showTranslation.button;" oncommand="this.closest('notification').showTranslation();"/>
</hbox>
<hbox class="translation-error" align="center">
<label value="&translation.errorTranslating.label;"/>
<button class="notification-button" label="&translation.tryAgain.button;" anonid="tryAgain" oncommand="this.closest('notification').translate();"/>
</hbox>
<vbox class="translation-unavailable" pack="center">
<label value="&translation.serviceUnavailable.label;"/>
</vbox>
</deck>
<spacer flex="1"/>
<button type="menu" class="notification-button" anonid="options" label="&translation.options.menu;">
<menupopup class="translation-menupopup" onpopupshowing="this.closest('notification').optionsShowing();">
<menuitem anonid="neverForLanguage" oncommand="this.closest('notification').neverForLanguage();"/>
<menuitem anonid="neverForSite" oncommand="this.closest('notification').neverForSite();" label="&translation.options.neverForSite.label;" accesskey="&translation.options.neverForSite.accesskey;"/>
<menuseparator/>
<menuitem oncommand="openPreferences('paneGeneral');" label="&translation.options.preferences.label;" accesskey="&translation.options.preferences.accesskey;"/>
</menupopup>
</button>
</hbox>
<toolbarbutton anonid="closeButton" ondblclick="event.stopPropagation();"
class="messageCloseButton close-icon tabbable"
tooltiptext="&closeNotification.tooltip;"
oncommand="this.parentNode.closeCommand();"/>
`;
}
static get entities() {
return [
"chrome://global/locale/notification.dtd",
"chrome://browser/locale/translation.dtd",
];
}
connectedCallback() {
this.appendChild(this.constructor.fragment);
for (const [propertyName, selector] of [
["details", "[anonid=details]"],
["messageImage", ".messageImage"],
["spacer", "[anonid=spacer]"],
]) {
this[propertyName] = this.querySelector(selector);
}
}
async updateTranslationProgress(
shouldShowTranslationProgress,
localizedTranslationProgressText,
) {
const progressLabelValue = shouldShowTranslationProgress
? localizedTranslationProgressText
: "";
this._getAnonElt("progress-label").setAttribute(
"value",
progressLabelValue,
);
}
set state(val) {
const deck = this._getAnonElt("translationStates");
const activeElt = document.activeElement;
if (activeElt && deck.contains(activeElt)) {
activeElt.blur();
}
let stateName;
for (const name of ["OFFER", "TRANSLATING", "TRANSLATED", "ERROR"]) {
if (Translation["STATE_" + name] === val) {
stateName = name.toLowerCase();
break;
}
}
this.setAttribute("state", stateName);
if (val === this.translation.TranslationInfoBarStates.STATE_TRANSLATED) {
this._handleButtonHiding();
}
deck.selectedIndex = val;
}
get state() {
return this._getAnonElt("translationStates").selectedIndex;
}
init(translationBrowserChromeUiNotificationManager) {
this.translation = translationBrowserChromeUiNotificationManager;
this.localizedLanguagesByCode = {};
const sortByLocalizedName = function(list) {
const names = Services.intl.getLanguageDisplayNames(undefined, list);
return list
.map((code, i) => [code, names[i]])
.sort((a, b) => a[1].localeCompare(b[1]));
};
// Fill the lists of supported source languages.
const detectedLanguage = this._getAnonElt("detectedLanguage");
const sourceLanguages = sortByLocalizedName(
this.translation.uiState.supportedSourceLanguages,
);
for (const [code, name] of sourceLanguages) {
detectedLanguage.appendItem(name, code);
this.localizedLanguagesByCode[code] = name;
}
detectedLanguage.value = this.translation.uiState.detectedLanguageResults.language;
// translatedFrom is only set if we have already translated this page.
const fromLanguage = this._getAnonElt("fromLanguage");
if (translationBrowserChromeUiNotificationManager.uiState.translatedFrom) {
for (const [code, name] of sourceLanguages) {
detectedLanguage.appendItem(name, code);
}
fromLanguage.setAttribute(
"value",
this.localizedLanguagesByCode[
translationBrowserChromeUiNotificationManager.uiState.translatedFrom
],
);
}
// Fill the list of supported target languages.
const toLanguage = this._getAnonElt("toLanguage");
const targetLanguages = sortByLocalizedName(
this.translation.uiState.supportedTargetLanguages,
);
for (const [code, name] of targetLanguages) {
this.localizedLanguagesByCode[code] = name;
}
if (translationBrowserChromeUiNotificationManager.uiState.translatedTo) {
toLanguage.setAttribute(
"value",
this.localizedLanguagesByCode[
translationBrowserChromeUiNotificationManager.uiState.translatedTo
],
);
}
if (translationBrowserChromeUiNotificationManager.uiState.infobarState) {
this.state =
translationBrowserChromeUiNotificationManager.uiState.infobarState;
}
/*
// The welcome popup/notification is currently disabled
const kWelcomePref = "browser.translation.ui.welcomeMessageShown";
if (
Services.prefs.prefHasUserValue(kWelcomePref) ||
this.translation.browser !== gBrowser.selectedBrowser
) {
return;
}
this.addEventListener(
"transitionend",
function() {
// These strings are hardcoded because they need to reach beta
// without riding the trains.
const 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 = Services.locale.appLocaleAsBCP47;
if (!(locale in localizedStrings)) {
locale = "en";
}
const 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]);
// TODO: Figure out why this shows a strangely rendered popup at the corner of the window instead next to the URL bar
const panel = this._getAnonElt("welcomePanel");
panel.openPopup(
this._getAnonElt("messageImage"),
"bottomcenter topleft",
);
Services.prefs.setBoolPref(kWelcomePref, true);
},
{ once: true },
);
*/
}
_getAnonElt(anonId) {
return this.querySelector("[anonid=" + anonId + "]");
}
fromLanguageChanged() {
this.translation.fromLanguageChanged(
this._getSourceLang(),
this._getTargetLang(),
);
this.translate();
}
toLanguageChanged() {
this.translation.toLanguageChanged(
this._getSourceLang(),
this._getTargetLang(),
);
this.translate();
}
translate() {
const from = this._getSourceLang();
const to = this._getTargetLang();
// Initiate translation
this.translation.translate(from, to);
// Store the values used in the translation in the from and to inputs
if (
this.translation.uiState.infobarState ===
this.translation.TranslationInfoBarStates.STATE_OFFER
) {
this._getAnonElt("fromLanguage").setAttribute(
"value",
this.localizedLanguagesByCode[from],
);
this._getAnonElt("toLanguage").setAttribute(
"value",
this.localizedLanguagesByCode[to],
);
}
}
/**
* To be called when the infobar should be closed per user's wish (e.g.
* by clicking the notification's close button, the not now button or choosing never to translate)
*/
closeCommand() {
const from = this._getSourceLang();
const to = this._getTargetLang();
this.close();
this.translation.infobarClosed(from, to);
}
/**
* To be called when the infobar should be closed per user's wish
* by clicking the Not now button
*/
notNow() {
this.translation.notNow(this._getSourceLang(), this._getTargetLang());
this.closeCommand();
}
_handleButtonHiding() {
const originalShown = this.translation.uiState.originalShown;
this._getAnonElt("showOriginal").hidden = originalShown;
this._getAnonElt("showTranslation").hidden = !originalShown;
}
showOriginal() {
this.translation.showOriginalContent(
this._getSourceLang(),
this._getTargetLang(),
);
this._handleButtonHiding();
}
showTranslation() {
this.translation.showTranslatedContent(
this._getSourceLang(),
this._getTargetLang(),
);
this._handleButtonHiding();
}
_getSourceLang() {
const lang = this._getAnonElt("detectedLanguage").value;
if (!lang) {
throw new Error("Source language is not defined");
}
return lang;
}
_getTargetLang() {
return this.translation.uiState.defaultTargetLanguage;
}
optionsShowing() {
const lang = this._getSourceLang();
// Get the source language name.
const langName = Services.intl.getLanguageDisplayNames(undefined, [
lang,
])[0];
// Set the label and accesskey on the menuitem.
const bundle = Services.strings.createBundle(
"chrome://browser/locale/translation.properties",
);
let item = this._getAnonElt("neverForLanguage");
const kStrId = "translation.options.neverForLanguage";
item.setAttribute(
"label",
bundle.formatStringFromName(kStrId + ".label", [langName]),
);
item.setAttribute(
"accesskey",
bundle.GetStringFromName(kStrId + ".accesskey"),
);
// We may need to disable the menuitems if they have already been used.
// Check if translation is already disabled for this language:
const neverForLangs = Services.prefs.getCharPref(
"browser.translation.neverForLanguages",
);
item.disabled = neverForLangs.split(",").includes(lang);
// Check if translation is disabled for the domain:
const principal = this.translation.browser.contentPrincipal;
const perms = Services.perms;
item = this._getAnonElt("neverForSite");
item.disabled =
perms.testExactPermissionFromPrincipal(principal, "translate") ===
perms.DENY_ACTION;
}
neverForLanguage() {
const kPrefName = "browser.translation.neverForLanguages";
const sourceLang = this._getSourceLang();
let val = Services.prefs.getCharPref(kPrefName);
if (val) {
val += ",";
}
val += sourceLang;
Services.prefs.setCharPref(kPrefName, val);
this.translation.neverForLanguage(
this._getSourceLang(),
this._getTargetLang(),
);
this.closeCommand();
}
neverForSite() {
const principal = this.translation.browser.contentPrincipal;
const perms = Services.perms;
perms.addFromPrincipal(principal, "translate", perms.DENY_ACTION);
this.translation.neverForSite(this._getSourceLang(), this._getTargetLang());
this.closeCommand();
}
};
customElements.define(
`translation-notification-${window.now}`,
window.MozTranslationNotification,
{
extends: "notification",
},
);

Просмотреть файл

@ -1,100 +0,0 @@
[
{
"namespace": "experiments.translateUi",
"description": "Provides browser chrome UI that reacts to translation states and fires events on user interaction",
"functions": [
{
"name": "start",
"type": "function",
"async": true,
"description": "Start reacting to translation state updates",
"parameters": []
},
{
"name": "setUiState",
"type": "function",
"async": true,
"description": "Set current ui state",
"parameters": [
{
"name": "tabId",
"type": "number"
},
{
"name": "uiState",
"type": "any"
}
]
},
{
"name": "stop",
"type": "function",
"async": true,
"description": "Stop reacting to translation state updates",
"parameters": []
}
],
"events": [
{
"name": "onInfoBarDisplayed",
"type": "function",
"description": "Foo",
"parameters": []
},
{
"name": "onSelectTranslateTo",
"type": "function",
"description": "Foo",
"parameters": []
},
{
"name": "onSelectTranslateFrom",
"type": "function",
"description": "Foo",
"parameters": []
},
{
"name": "onInfoBarClosed",
"type": "function",
"description": "Foo",
"parameters": []
},
{
"name": "onNeverTranslateSelectedLanguage",
"type": "function",
"description": "Foo",
"parameters": []
},
{
"name": "onNeverTranslateThisSite",
"type": "function",
"description": "Foo",
"parameters": []
},
{
"name": "onShowOriginalButtonPressed",
"type": "function",
"description": "Foo",
"parameters": []
},
{
"name": "onShowTranslatedButtonPressed",
"type": "function",
"description": "Foo",
"parameters": []
},
{
"name": "onTranslateButtonPressed",
"type": "function",
"description": "Foo",
"parameters": []
},
{
"name": "onNotNowButtonPressed",
"type": "function",
"description": "Foo",
"parameters": []
}
]
}
]

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 750 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.7 KiB

Просмотреть файл

@ -1,136 +0,0 @@
{
"manifest_version": 2,
"name": "Firefox Translations",
"description": "__MSG_extensionDescription__",
"version": "0.4.3",
"incognito": "spanning",
"default_locale": "en_US",
"background": {
"scripts": [
"commons.js",
"background.js"
]
},
"content_scripts": [
{
"js": [
"commons.js"
],
"matches": [
"<all_urls>"
],
"all_frames": true,
"run_at": "document_idle",
"match_about_blank": false
},
{
"js": [
"dom-translation-content-script.js"
],
"matches": [
"<all_urls>"
],
"all_frames": true,
"run_at": "document_idle",
"match_about_blank": false
}
],
"permissions": [
"<all_urls>",
"storage"
],
"web_accessible_resources": [
"commons.js.map",
"background.js.map",
"dom-translation-content-script.js.map",
"translation-worker.js.map"
],
"icons": {
"16": "icons/translation.16x16.png",
"32": "icons/translation.32x32.png"
},
"hidden": false,
"experiment_apis": {
"extensionPreferences": {
"schema": "./experiment-apis/extensionPreferences/schema.json",
"parent": {
"scopes": [
"addon_parent"
],
"script": "./experiment-apis/extensionPreferences/api.js",
"paths": [
[
"experiments",
"extensionPreferences"
]
]
}
},
"languageDetector": {
"schema": "./experiment-apis/languageDetector/schema.json",
"parent": {
"scopes": [
"addon_parent"
],
"script": "./experiment-apis/languageDetector/api.js",
"paths": [
[
"experiments",
"languageDetector"
]
]
}
},
"telemetryEnvironment": {
"schema": "./experiment-apis/telemetryEnvironment/schema.json",
"parent": {
"scopes": [
"addon_parent"
],
"script": "./experiment-apis/telemetryEnvironment/api.js",
"paths": [
[
"experiments",
"telemetryEnvironment"
]
]
}
},
"telemetryPreferences": {
"schema": "./experiment-apis/telemetryPreferences/schema.json",
"parent": {
"scopes": [
"addon_parent"
],
"script": "./experiment-apis/telemetryPreferences/api.js",
"paths": [
[
"experiments",
"telemetryPreferences"
]
]
}
},
"translateUi": {
"schema": "./experiment-apis/translateUi/schema.json",
"parent": {
"scopes": [
"addon_parent"
],
"script": "./experiment-apis/translateUi/api.js",
"paths": [
[
"experiments",
"translateUi"
]
]
}
}
},
"applications": {
"gecko": {
"id": "firefox-translations@mozilla.org",
"strict_min_version": "90.0a1"
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,127 +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/.
# script to pull and import Firefox Translations's extension source code
import os.path
from zipfile import ZipFile
import subprocess
import shutil
import sys
# the version number is the only part of this script that needs to be updated
# in order to update the in-tree version with the latest xpi version
extension_version = input(
"Type the extension's version (tag) on Github you want to import: "
)
print("Importing version:", extension_version)
if not extension_version:
sys.exit("Value can't be empty.")
extension_folder = "firefox-translations-src"
if not os.path.exists("import_xpi.py"):
sys.exit("This script is intended to be executed from its local folder")
have_xpi = "N"
local_xpi_file = (
"firefox-translations-src/dist/production/firefox/"
"firefox-infobar-ui/firefox-translations-" + extension_version + ".xpi"
)
if os.path.isfile(local_xpi_file):
have_xpi = input(
"Extension xpi exists. Press Y to use it or any other key to rebuild it."
)
if have_xpi.lower() != "y":
# deleting old files if any
shutil.rmtree(extension_folder, ignore_errors=True)
# cloning the extension
subprocess.call(
(
"git clone -b v" + extension_version + " "
"https://github.com/mozilla-extensions/firefox-translations/ "
+ extension_folder
+ " "
).split()
)
# setting up the repo
subprocess.call("yarn install".split(), cwd=extension_folder)
# pulling bergamot-translator submodule, the repo containing the port of the
# neural machine translation engine to wasm
subprocess.call(
"git submodule update --init --recursive".split(),
cwd=extension_folder,
)
# build the wasm nmt module
subprocess.call(
"./bergamot-translator/build-wasm.sh".split(),
cwd=extension_folder,
)
# import the generated wasm module to the extension
subprocess.call(
"./import-bergamot-translator.sh ./bergamot-translator/build-wasm/".split(),
cwd=extension_folder,
)
# build the final xpi
env = {
**os.environ,
"MC": str(1),
}
subprocess.call(
"yarn build:firefox-infobar-ui".split(), cwd=extension_folder, env=env
)
shutil.rmtree("extension", ignore_errors=True)
os.mkdir("extension")
file_exceptions = [
"META-INF",
".md",
"BRANCH",
"COMMITHASH",
"LASTCOMMITDATETIME",
"VERSION",
".map",
".yaml",
]
def isValidFile(filename):
for exception in file_exceptions:
if exception in filename:
return False
return True
file_set = set()
# read xpi files
with ZipFile(local_xpi_file, "r") as zip:
namelist = zip.namelist()
cleared_namelist = []
for filename in namelist:
if isValidFile(filename):
full_file_path = zip.extract(filename, "extension")
if filename.endswith(".js"):
filename = "browser/extensions/translations/{}".format(full_file_path)
subprocess.call(
str(
"./mach lint --linter license {} --fix".format(filename)
).split(),
cwd="../../../",
)
# patching BrowserGlue.jsm
with open("../../components/BrowserGlue.jsm") as fp:
count = 0
Lines = fp.readlines()
for line in Lines:
if "resource://builtin-addons/translations/" in line:
Lines[count - 1] = ' "{}",\n'.format(extension_version)
with open("../../components/BrowserGlue.jsm", "w") as outfile:
outfile.write("".join(Lines))
break
count += 1
print("Import finalized successfully")

Просмотреть файл

@ -1,8 +0,0 @@
##### This file was automatically generated by the import_xpi.py script ####
# 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:
% resource builtin-addons %builtin-addons/ contentaccessible=yes
builtin-addons/translations/ (extension/**)

Просмотреть файл

@ -1,4 +0,0 @@
with Files("**"):
BUG_COMPONENT = ("Firefox", "Translations")
JAR_MANIFESTS += ["jar.mn"]