зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1759782 - Remove Firefox Translations addon from Nightly r=mixedpuppy
Differential Revision: https://phabricator.services.mozilla.com/D141820
This commit is contained in:
Родитель
9ddc42292b
Коммит
b9b8c7c39b
|
@ -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() {
|
||||
// There is no pref for this add-on because it shouldn't be disabled.
|
||||
const ID = "addons-search-detection@mozilla.com";
|
||||
|
@ -2332,9 +2293,6 @@ BrowserGlue.prototype = {
|
|||
this._monitorIonStudies();
|
||||
this._setupSearchDetection();
|
||||
|
||||
if (AppConstants.NIGHTLY_BUILD) {
|
||||
this._monitorTranslationsPref();
|
||||
}
|
||||
this._monitorGPCPref();
|
||||
this._monitorPrivacySegmentationPref();
|
||||
},
|
||||
|
|
|
@ -13,8 +13,3 @@ DIRS += [
|
|||
"pictureinpicture",
|
||||
"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"]
|
Загрузка…
Ссылка в новой задаче