richard pushed to branch tor-browser-115.10.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits: 5fd3baa6 by Henry Wilkes at 2024-04-16T21:57:16+00:00 fixup! Bug 40458: Implement .tor.onion aliases
Bug 42206: Migrate ruleset strings to Fluent.
- - - - - 7b790cf6 by Henry Wilkes at 2024-04-16T21:57:16+00:00 fixup! Tor Browser strings
Bug 42206: Migrate ruleset strings to Fluent.
- - - - - caed3ae7 by Henry Wilkes at 2024-04-16T21:57:16+00:00 fixup! Add TorStrings module for localization
Bug 42206: Migrate ruleset strings to Fluent.
- - - - - 8c14330e by Henry Wilkes at 2024-04-16T21:57:16+00:00 fixup! Tor Browser localization migration scripts.
Bug 42206: Migrate ruleset strings to Fluent.
- - - - -
7 changed files:
- browser/components/rulesets/RulesetsParent.sys.mjs - browser/components/rulesets/content/aboutRulesets.html - browser/components/rulesets/content/aboutRulesets.js - browser/locales/en-US/browser/tor-browser.ftl - toolkit/modules/TorStrings.sys.mjs - − toolkit/torbutton/chrome/locale/en-US/rulesets.properties - + tools/torbrowser/l10n/migrations/bug-42206-rulesets.py
Changes:
===================================== browser/components/rulesets/RulesetsParent.sys.mjs ===================================== @@ -1,6 +1,5 @@ // Copyright (c) 2022, The Tor Project, Inc.
-import { TorStrings } from "resource://gre/modules/TorStrings.sys.mjs"; import { OnionAliasStore, OnionAliasStoreTopics, @@ -8,8 +7,8 @@ import {
const kShowWarningPref = "torbrowser.rulesets.show_warning";
-// This class allows about:rulesets to get TorStrings and to load/save the -// preference for skipping the warning +// This class allows about:rulesets to load/save the preference for skipping the +// warning export class RulesetsParent extends JSWindowActorParent { constructor(...args) { super(...args); @@ -53,7 +52,6 @@ export class RulesetsParent extends JSWindowActorParent { return OnionAliasStore.getChannels(); case "rulesets:get-init-args": return { - TorStrings, showWarning: Services.prefs.getBoolPref(kShowWarningPref, true), }; case "rulesets:set-channel":
===================================== browser/components/rulesets/content/aboutRulesets.html ===================================== @@ -11,13 +11,19 @@ rel="stylesheet" href="chrome://browser/content/rulesets/aboutRulesets.css" /> + + <link rel="localization" href="branding/brand.ftl" /> + <link rel="localization" href="browser/tor-browser.ftl" /> </head> <body> <!-- Warning --> <div id="warning-wrapper"> <div id="warning"> - <h1 id="warning-title"></h1> - <p id="warning-description"></p> + <h1 id="warning-title" data-l10n-id="rulesets-warning-heading"></h1> + <p + id="warning-description" + data-l10n-id="rulesets-warning-description" + ></p> <p> <label> <input @@ -25,11 +31,18 @@ type="checkbox" checked="checked" /> - <span id="warning-enable-label"></span> + <span + id="warning-enable-label" + data-l10n-id="rulesets-warning-checkbox" + ></span> </label> </p> <div id="warning-buttonbar"> - <button id="warning-button" autofocus="autofocus"></button> + <button + id="warning-button" + autofocus="autofocus" + data-l10n-id="rulesets-warning-continue-button" + ></button> </div> </div> </div> @@ -37,11 +50,20 @@ <div id="main-content"> <!-- Ruleset list --> <aside> - <div id="ruleset-heading"></div> + <div + id="ruleset-heading" + data-l10n-id="rulesets-side-panel-heading" + ></div> <div id="ruleset-list-container"> <div id="ruleset-list-empty"> - <p id="ruleset-list-empty-title"></p> - <p id="ruleset-list-empty-description"></p> + <p + id="ruleset-list-empty-title" + data-l10n-id="rulesets-side-panel-no-rules" + ></p> + <p + id="ruleset-list-empty-description" + data-l10n-id="rulesets-side-panel-no-rules-description" + ></p> </div> <ul id="ruleset-list"> <li id="ruleset-template"> @@ -59,24 +81,40 @@ <section id="ruleset-details"> <div class="title"> <h1 id="ruleset-title"></h1> - <button id="ruleset-edit" class="ghost-button"></button> + <button + id="ruleset-edit" + class="ghost-button" + data-l10n-id="rulesets-details-edit-button" + ></button> </div> <dl> - <dt id="ruleset-jwk-label"></dt> + <dt id="ruleset-jwk-label" data-l10n-id="rulesets-details-jwk"></dt> <dd id="ruleset-jwk-value"></dd> - <dt id="ruleset-path-prefix-label"></dt> + <dt + id="ruleset-path-prefix-label" + data-l10n-id="rulesets-details-path" + ></dt> <dd> <a id="ruleset-path-prefix-value" target="_blank"></a> </dd> - <dt id="ruleset-scope-label"></dt> + <dt + id="ruleset-scope-label" + data-l10n-id="rulesets-details-scope" + ></dt> <dd id="ruleset-scope-value"></dd> </dl> <label id="ruleset-enable"> <input type="checkbox" id="ruleset-enable-checkbox" /> - <span id="ruleset-enable-label"></span> + <span + id="ruleset-enable-label" + data-l10n-id="rulesets-details-enable-checkbox" + ></span> </label> <div id="ruleset-buttonbar"> - <button id="ruleset-update-button"></button> + <button + id="ruleset-update-button" + data-l10n-id="rulesets-details-update-button" + ></button> </div> <hr /> <p id="ruleset-updated"></p> @@ -89,24 +127,52 @@ </div> <form id="edit-ruleset-form"> <label> - <div id="edit-jwk-label"></div> - <textarea id="edit-jwk-textarea" rows="10"></textarea> + <div id="edit-jwk-label" data-l10n-id="rulesets-details-jwk"></div> + <textarea + id="edit-jwk-textarea" + rows="10" + data-l10n-id="rulesets-details-jwk-input" + ></textarea> </label> <label> - <div id="edit-path-prefix-label"></div> - <input id="edit-path-prefix-input" type="text" /> + <div + id="edit-path-prefix-label" + data-l10n-id="rulesets-details-path" + ></div> + <input + id="edit-path-prefix-input" + type="text" + data-l10n-id="rulesets-details-path-input" + /> </label> <label> - <div id="edit-scope-label"></div> - <input id="edit-scope-input" type="text" /> + <div + id="edit-scope-label" + data-l10n-id="rulesets-details-scope" + ></div> + <input + id="edit-scope-input" + type="text" + data-l10n-id="rulesets-details-scope-input" + /> </label> <label id="edit-enable"> <input type="checkbox" id="edit-enable-checkbox" /> - <span id="edit-enable-label"></span> + <span + id="edit-enable-label" + data-l10n-id="rulesets-details-enable-checkbox" + ></span> </label> <div id="edit-buttonbar"> - <button id="edit-save" class="primary"></button> - <button id="edit-cancel"></button> + <button + id="edit-save" + class="primary" + data-l10n-id="rulesets-details-save-button" + ></button> + <button + id="edit-cancel" + data-l10n-id="rulesets-details-cancel-button" + ></button> </div> </form> </section>
===================================== browser/components/rulesets/content/aboutRulesets.js ===================================== @@ -2,8 +2,6 @@
/* globals RPMAddMessageListener, RPMSendQuery, RPMSendAsyncMessage */
-let TorStrings; - const Orders = Object.freeze({ Name: "name", NameDesc: "name-desc", @@ -19,55 +17,35 @@ const States = Object.freeze({
function setUpdateDate(ruleset, element) { if (!ruleset.enabled) { - element.textContent = TorStrings.rulesets.disabled; + document.l10n.setAttributes(element, "rulesets-update-rule-disabled"); return; } if (!ruleset.currentTimestamp) { - element.textContent = TorStrings.rulesets.neverUpdated; + document.l10n.setAttributes(element, "rulesets-update-never"); return; }
- const formatter = new Intl.DateTimeFormat(navigator.languages, { - year: "numeric", - month: "long", - day: "numeric", + document.l10n.setAttributes(element, "rulesets-update-last", { + date: ruleset.currentTimestamp * 1000, }); - element.textContent = TorStrings.rulesets.lastUpdated.replace( - "%S", - formatter.format(new Date(ruleset.currentTimestamp * 1000)) - ); }
class WarningState { - selectors = Object.freeze({ - wrapper: "#warning-wrapper", - title: "#warning-title", - description: "#warning-description", - enableCheckbox: "#warning-enable-checkbox", - enableLabel: "#warning-enable-label", - button: "#warning-button", - }); - - elements = Object.freeze({ - wrapper: document.querySelector(this.selectors.wrapper), - title: document.querySelector(this.selectors.title), - description: document.querySelector(this.selectors.description), - enableCheckbox: document.querySelector(this.selectors.enableCheckbox), - enableLabel: document.querySelector(this.selectors.enableLabel), - button: document.querySelector(this.selectors.button), - }); + elements = { + enableCheckbox: document.getElementById("warning-enable-checkbox"), + button: document.getElementById("warning-button"), + };
constructor() { - const elements = this.elements; - elements.title.textContent = TorStrings.rulesets.warningTitle; - elements.description.textContent = TorStrings.rulesets.warningDescription; - elements.enableLabel.textContent = TorStrings.rulesets.warningEnable; - elements.button.textContent = TorStrings.rulesets.warningButton; - elements.enableCheckbox.addEventListener( + this.elements.enableCheckbox.addEventListener( "change", this.onEnableChange.bind(this) ); - elements.button.addEventListener("click", this.onButtonClick.bind(this)); + + this.elements.button.addEventListener( + "click", + this.onButtonClick.bind(this) + ); }
show() { @@ -89,50 +67,28 @@ class WarningState { }
class DetailsState { - selectors = Object.freeze({ - title: "#ruleset-title", - edit: "#ruleset-edit", - jwkLabel: "#ruleset-jwk-label", - jwkValue: "#ruleset-jwk-value", - pathPrefixLabel: "#ruleset-path-prefix-label", - pathPrefixValue: "#ruleset-path-prefix-value", - scopeLabel: "#ruleset-scope-label", - scopeValue: "#ruleset-scope-value", - enableCheckbox: "#ruleset-enable-checkbox", - enableLabel: "#ruleset-enable-label", - updateButton: "#ruleset-update-button", - updated: "#ruleset-updated", - }); - - elements = Object.freeze({ - title: document.querySelector(this.selectors.title), - edit: document.querySelector(this.selectors.edit), - jwkLabel: document.querySelector(this.selectors.jwkLabel), - jwkValue: document.querySelector(this.selectors.jwkValue), - pathPrefixLabel: document.querySelector(this.selectors.pathPrefixLabel), - pathPrefixValue: document.querySelector(this.selectors.pathPrefixValue), - scopeLabel: document.querySelector(this.selectors.scopeLabel), - scopeValue: document.querySelector(this.selectors.scopeValue), - enableCheckbox: document.querySelector(this.selectors.enableCheckbox), - enableLabel: document.querySelector(this.selectors.enableLabel), - updateButton: document.querySelector(this.selectors.updateButton), - updated: document.querySelector(this.selectors.updated), - }); + elements = { + title: document.getElementById("ruleset-title"), + jwkValue: document.getElementById("ruleset-jwk-value"), + pathPrefixValue: document.getElementById("ruleset-path-prefix-value"), + scopeValue: document.getElementById("ruleset-scope-value"), + enableCheckbox: document.getElementById("ruleset-enable-checkbox"), + updateButton: document.getElementById("ruleset-update-button"), + updated: document.getElementById("ruleset-updated"), + };
constructor() { - const elements = this.elements; - elements.edit.textContent = TorStrings.rulesets.edit; - elements.edit.addEventListener("click", this.onEdit.bind(this)); - elements.jwkLabel.textContent = TorStrings.rulesets.jwk; - elements.pathPrefixLabel.textContent = TorStrings.rulesets.pathPrefix; - elements.scopeLabel.textContent = TorStrings.rulesets.scope; - elements.enableCheckbox.addEventListener( + document + .getElementById("ruleset-edit") + .addEventListener("click", this.onEdit.bind(this)); + this.elements.enableCheckbox.addEventListener( "change", this.onEnable.bind(this) ); - elements.enableLabel.textContent = TorStrings.rulesets.enable; - elements.updateButton.textContent = TorStrings.rulesets.checkUpdates; - elements.updateButton.addEventListener("click", this.onUpdate.bind(this)); + this.elements.updateButton.addEventListener( + "click", + this.onUpdate.bind(this) + ); }
show(ruleset) { @@ -179,61 +135,22 @@ class DetailsState { }
class EditState { - selectors = Object.freeze({ - form: "#edit-ruleset-form", - title: "#edit-title", - nameGroup: "#edit-name-group", - nameLabel: "#edit-name-label", - nameInput: "#edit-name-input", - jwkLabel: "#edit-jwk-label", - jwkTextarea: "#edit-jwk-textarea", - pathPrefixLabel: "#edit-path-prefix-label", - pathPrefixInput: "#edit-path-prefix-input", - scopeLabel: "#edit-scope-label", - scopeInput: "#edit-scope-input", - enableCheckbox: "#edit-enable-checkbox", - enableLabel: "#edit-enable-label", - save: "#edit-save", - cancel: "#edit-cancel", - }); - - elements = Object.freeze({ - form: document.querySelector(this.selectors.form), - title: document.querySelector(this.selectors.title), - jwkLabel: document.querySelector(this.selectors.jwkLabel), - jwkTextarea: document.querySelector(this.selectors.jwkTextarea), - pathPrefixLabel: document.querySelector(this.selectors.pathPrefixLabel), - pathPrefixInput: document.querySelector(this.selectors.pathPrefixInput), - scopeLabel: document.querySelector(this.selectors.scopeLabel), - scopeInput: document.querySelector(this.selectors.scopeInput), - enableCheckbox: document.querySelector(this.selectors.enableCheckbox), - enableLabel: document.querySelector(this.selectors.enableLabel), - save: document.querySelector(this.selectors.save), - cancel: document.querySelector(this.selectors.cancel), - }); + elements = { + form: document.getElementById("edit-ruleset-form"), + title: document.getElementById("edit-title"), + jwkTextarea: document.getElementById("edit-jwk-textarea"), + pathPrefixInput: document.getElementById("edit-path-prefix-input"), + scopeInput: document.getElementById("edit-scope-input"), + enableCheckbox: document.getElementById("edit-enable-checkbox"), + };
constructor() { - const elements = this.elements; - elements.jwkLabel.textContent = TorStrings.rulesets.jwk; - elements.jwkTextarea.setAttribute( - "placeholder", - TorStrings.rulesets.jwkPlaceholder - ); - elements.pathPrefixLabel.textContent = TorStrings.rulesets.pathPrefix; - elements.pathPrefixInput.setAttribute( - "placeholder", - TorStrings.rulesets.pathPrefixPlaceholder - ); - elements.scopeLabel.textContent = TorStrings.rulesets.scope; - elements.scopeInput.setAttribute( - "placeholder", - TorStrings.rulesets.scopePlaceholder - ); - elements.enableLabel.textContent = TorStrings.rulesets.enable; - elements.save.textContent = TorStrings.rulesets.save; - elements.save.addEventListener("click", this.onSave.bind(this)); - elements.cancel.textContent = TorStrings.rulesets.cancel; - elements.cancel.addEventListener("click", this.onCancel.bind(this)); + document + .getElementById("edit-save") + .addEventListener("click", this.onSave.bind(this)); + document + .getElementById("edit-cancel") + .addEventListener("click", this.onCancel.bind(this)); }
show(ruleset) { @@ -276,7 +193,9 @@ class EditState { elements.jwkTextarea.setCustomValidity(""); } catch (err) { console.error("Invalid JSON or invalid JWK", err); - elements.jwkTextarea.setCustomValidity(TorStrings.rulesets.jwkInvalid); + elements.jwkTextarea.setCustomValidity( + await document.l10n.formatValue("rulesets-details-jwk-input-invalid") + ); valid = false; }
@@ -285,7 +204,7 @@ class EditState { const url = new URL(pathPrefix); if (url.protocol !== "http:" && url.protocol !== "https:") { elements.pathPrefixInput.setCustomValidity( - TorStrings.rulesets.pathPrefixInvalid + await document.l10n.formatValue("rulesets-details-path-input-invalid") ); valid = false; } else { @@ -294,7 +213,7 @@ class EditState { } catch (err) { console.error("The path prefix is not a valid URL", err); elements.pathPrefixInput.setCustomValidity( - TorStrings.rulesets.pathPrefixInvalid + await document.l10n.formatValue("rulesets-details-path-input-invalid") ); valid = false; } @@ -304,7 +223,9 @@ class EditState { scope = new RegExp(elements.scopeInput.value.trim()); elements.scopeInput.setCustomValidity(""); } catch (err) { - elements.scopeInput.setCustomValidity(TorStrings.rulesets.scopeInvalid); + elements.scopeInput.setCustomValidity( + await document.l10n.formatValue("rulesets-details-scope-input-invalid") + ); valid = false; }
@@ -342,39 +263,17 @@ class NoRulesetsState { }
class RulesetList { - selectors = Object.freeze({ - heading: "#ruleset-heading", - list: "#ruleset-list", - emptyContainer: "#ruleset-list-empty", - emptyTitle: "#ruleset-list-empty-title", - emptyDescription: "#ruleset-list-empty-description", - itemTemplate: "#ruleset-template", - itemName: ".name", - itemDescr: ".description", - }); - - elements = Object.freeze({ - heading: document.querySelector(this.selectors.heading), - list: document.querySelector(this.selectors.list), - emptyContainer: document.querySelector(this.selectors.emptyContainer), - emptyTitle: document.querySelector(this.selectors.emptyTitle), - emptyDescription: document.querySelector(this.selectors.emptyDescription), - itemTemplate: document.querySelector(this.selectors.itemTemplate), - }); + elements = { + list: document.getElementById("ruleset-list"), + emptyContainer: document.getElementById("ruleset-list-empty"), + itemTemplate: document.getElementById("ruleset-template"), + };
nameAttribute = "data-name";
rulesets = [];
constructor() { - const elements = this.elements; - - // Header - elements.heading.textContent = TorStrings.rulesets.rulesets; - // Empty - elements.emptyTitle.textContent = TorStrings.rulesets.noRulesets; - elements.emptyDescription.textContent = TorStrings.rulesets.noRulesetsDescr; - RPMAddMessageListener( "rulesets:channels-change", this.onRulesetsChanged.bind(this) @@ -438,14 +337,10 @@ class RulesetList { const item = this.elements.itemTemplate.cloneNode(true); item.removeAttribute("id"); item.classList.add("item"); - item.querySelector(this.selectors.itemName).textContent = ruleset.name; - const descr = item.querySelector(this.selectors.itemDescr); - if (ruleset.enabled) { - setUpdateDate(ruleset, descr); - } else { - descr.textContent = TorStrings.rulesets.disabled; - item.classList.add("disabled"); - } + item.querySelector(".name").textContent = ruleset.name; + const descr = item.querySelector(".description"); + setUpdateDate(ruleset, descr); + item.classList.toggle("disabled", !ruleset.enabled); item.setAttribute(this.nameAttribute, ruleset.name); item.addEventListener("click", () => { this.onRulesetClick(ruleset); @@ -478,7 +373,6 @@ class AboutRulesets {
async init() { const args = await RPMSendQuery("rulesets:get-init-args"); - TorStrings = args.TorStrings; const showWarning = args.showWarning;
this.list = new RulesetList();
===================================== browser/locales/en-US/browser/tor-browser.ftl ===================================== @@ -557,3 +557,53 @@ downloads-tor-warning-title = Be careful opening downloads downloads-tor-warning-description = Some files may connect to the internet when opened without using Tor. To be safe, open the files while offline or use a portable operating system like <a data-l10n-name="tails-link">Tails</a>. # Button to dismiss the warning forever. downloads-tor-warning-dismiss-button = Got it + +## Initial warning page in about:rulesets. In Tor Browser, each ruleset is a set of rules for converting a ".tor.onion" address to a normal ".onion" address (used by SecureDrop). The feature is taken from the discontinued "HTTPS Everywhere". + +rulesets-warning-heading = Proceed with Caution +rulesets-warning-description = Adding or modifying rulesets can cause attackers to hijack your browser. Proceed only if you know what you are doing. +rulesets-warning-checkbox = Warn me when I attempt to access these preferences +rulesets-warning-continue-button = Accept the Risk and Continue + +## Side panel in about:rulesets. In Tor Browser, each ruleset is a set of rules for converting a ".tor.onion" address to a normal ".onion" address (used by SecureDrop). The feature is taken from the discontinued "HTTPS Everywhere". + +rulesets-side-panel-heading = Rulesets +rulesets-side-panel-no-rules = No rulesets found +# -brand-short-name refers to 'Tor Browser', localized. +rulesets-side-panel-no-rules-description = When you save a ruleset in { -brand-short-name }, it will show up here. + +## Ruleset update date in about:rulesets. + +# $date (Date) - The update date. The DATETIME function will format the $date according to the locale, using a "long" style. E.g. "January 1, 2000" for English (US), "١ يناير ٢٠٠٠" for Arabic, "2000년 1월 1일" in Korean, and "1 января 2000 г." in Russian. +rulesets-update-last = Last updated { DATETIME($date, dateStyle: "long") } +rulesets-update-never = Never updated, or last update failed +# Shown when the ruleset is disabled. +rulesets-update-rule-disabled = Disabled + +## Ruleset details in about:rulesets. In Tor Browser, each ruleset is a set of rules for converting a ".tor.onion" address to a normal ".onion" address (used by SecureDrop). The feature is taken from the discontinued "HTTPS Everywhere". + +rulesets-details-edit-button = Edit +rulesets-details-enable-checkbox = Enable this ruleset +rulesets-details-update-button = Check for Updates +rulesets-details-save-button = Save +rulesets-details-cancel-button = Cancel +# "JWK" refers to "JSON Web Key" and likely should not be translated. +rulesets-details-jwk = JWK +# "JWK" refers to "JSON Web Key" and likely should not be translated. +rulesets-details-jwk-input = + .placeholder = The key used to sign this ruleset in the JWK (JSON Web Key) format +# "JWK" refers to "JSON Web Key" and likely should not be translated. +rulesets-details-jwk-input-invalid = The JWK could not be parsed, or it is not a valid key +# "Path" refers to the URL domain this rule applies to. +rulesets-details-path = Path Prefix +rulesets-details-path-input = + .placeholder = URL prefix that contains the files needed by the ruleset +# "HTTP(S)" refers to "HTTP or HTTPS". +rulesets-details-path-input-invalid = The path prefix is not a valid HTTP(S) URL +# "Scope" refers to the breadth of URLs this rule applies to (as a regular expression). +rulesets-details-scope = Scope +# "Regular expression" refers to the computing term for a special pattern used for matching: https://en.wikipedia.org/wiki/Regular_expression. +rulesets-details-scope-input = + .placeholder = Regular expression for the scope of the rules +# "Regular expression" refers to the computing term for a special pattern used for matching: https://en.wikipedia.org/wiki/Regular_expression. +rulesets-details-scope-input-invalid = The scope could not be parsed as a regular expression
===================================== toolkit/modules/TorStrings.sys.mjs ===================================== @@ -429,54 +429,6 @@ const Loader = { learnMoreURLNotification: `https://tb-manual.torproject.org/$%7BgetLocale()%7D/onion-services/%60, }; } /* OnionLocation */, - - /* - Rulesets - */ - rulesets() { - const strings = { - // Initial warning - warningTitle: "Proceed with Caution", - warningDescription: - "Adding or modifying rulesets can cause attackers to hijack your browser. Proceed only if you know what you are doing.", - warningEnable: "Warn me when I attempt to access these preferences", - warningButton: "Accept the Risk and Continue", - // Ruleset list - rulesets: "Rulesets", - noRulesets: "No rulesets found", - noRulesetsDescr: - "When you save a ruleset in Tor Browser, it will show up here.", - lastUpdated: "Last updated %S", - neverUpdated: "Never updated, or last update failed", - enabled: "Enabled", - disabled: "Disabled", - // Ruleset details - edit: "Edit", - name: "Name", - jwk: "JWK", - pathPrefix: "Path Prefix", - scope: "Scope", - enable: "Enable this ruleset", - checkUpdates: "Check for Updates", - // Add ruleset - jwkPlaceholder: - "The key used to sign this ruleset in the JWK (JSON Web Key) format", - jwkInvalid: "The JWK could not be parsed, or it is not a valid key", - pathPrefixPlaceholder: - "URL prefix that contains the files needed by the ruleset", - pathPrefixInvalid: "The path prefix is not a valid HTTP(S) URL", - scopePlaceholder: "Regular expression for the scope of the rules", - scopeInvalid: "The scope could not be parsed as a regular expression", - save: "Save", - cancel: "Cancel", - }; - - const tsb = new TorPropertyStringBundle( - ["chrome://torbutton/locale/rulesets.properties"], - "rulesets." - ); - return tsb.getStrings(strings); - } /* Rulesets */, };
export const TorStrings = { @@ -507,11 +459,4 @@ export const TorStrings = { } return this._onionLocation; }, - - get rulesets() { - if (!this._rulesets) { - this._rulesets = Loader.rulesets(); - } - return this._rulesets; - }, };
===================================== toolkit/torbutton/chrome/locale/en-US/rulesets.properties deleted ===================================== @@ -1,35 +0,0 @@ -# Copyright (c) 2022, The Tor Project, Inc. -# 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/. - -# about:rulesets strings. -rulesets.warningTitle=Proceed with Caution -rulesets.warningDescription=Adding or modifying rulesets can cause attackers to hijack your browser. Proceed only if you know what you are doing. -rulesets.warningEnable=Warn me when I attempt to access these preferences -rulesets.warningButton=Accept the Risk and Continue -# Ruleset list -rulesets.rulesets=Rulesets -rulesets.noRulesets=No rulesets found -rulesets.noRulesetsDescr=When you save a ruleset in Tor Browser, it will show up here. -# LOCALIZATION NOTE: %S will be replaced by the update date (automatically formatted by Firefox's l10n component) -rulesets.lastUpdated=Last updated %S -rulesets.neverUpdated=Never updated, or last update failed -rulesets.enabled=Enabled -rulesets.disabled=Disabled -# Ruleset details/edit ruleset -rulesets.edit=Edit -rulesets.name=Name -rulesets.jwk=JWK -rulesets.pathPrefix=Path Prefix -rulesets.scope=Scope -rulesets.enable=Enable this ruleset -rulesets.checkUpdates=Check for Updates -rulesets.jwkPlaceholder=The key used to sign this ruleset in the JWK (JSON Web Key) format -rulesets.jwkInvalid=The JWK could not be parsed, or it is not a valid key -rulesets.pathPrefixPlaceholder=URL prefix that contains the files needed by the ruleset -rulesets.pathPrefixInvalid=The path prefix is not a valid HTTP(S) URL -rulesets.scopePlaceholder=Regular expression for the scope of the rules -rulesets.scopeInvalid=The scope could not be parsed as a regular expression -rulesets.save=Save -rulesets.cancel=Cancel
===================================== tools/torbrowser/l10n/migrations/bug-42206-rulesets.py ===================================== @@ -0,0 +1,70 @@ +import fluent.syntax.ast as FTL +from fluent.migrate.helpers import transforms_from +from fluent.migrate.transforms import REPLACE + + +def migrate(ctx): + legacy_path = "rulesets.properties" + + ctx.add_transforms( + "tor-browser.ftl", + "tor-browser.ftl", + transforms_from( + """ +rulesets-warning-heading = { COPY(path, "rulesets.warningTitle") } +rulesets-warning-description = { COPY(path, "rulesets.warningDescription") } +rulesets-warning-checkbox = { COPY(path, "rulesets.warningEnable") } +rulesets-warning-continue-button = { COPY(path, "rulesets.warningButton") } + +rulesets-side-panel-heading = { COPY(path, "rulesets.rulesets") } +rulesets-side-panel-no-rules = { COPY(path, "rulesets.noRulesets") } + +rulesets-update-never = { COPY(path, "rulesets.neverUpdated") } +rulesets-update-rule-disabled = { COPY(path, "rulesets.disabled") } + +rulesets-details-edit-button = { COPY(path, "rulesets.edit") } +rulesets-details-enable-checkbox = { COPY(path, "rulesets.enable") } +rulesets-details-update-button = { COPY(path, "rulesets.checkUpdates") } +rulesets-details-save-button = { COPY(path, "rulesets.save") } +rulesets-details-cancel-button = { COPY(path, "rulesets.cancel") } +rulesets-details-jwk-input = + .placeholder = { COPY(path, "rulesets.jwkPlaceholder") } +rulesets-details-jwk-input-invalid = { COPY(path, "rulesets.jwkInvalid") } +rulesets-details-path = { COPY(path, "rulesets.pathPrefix") } +rulesets-details-path-input = + .placeholder = { COPY(path, "rulesets.pathPrefixPlaceholder") } +rulesets-details-path-input-invalid = { COPY(path, "rulesets.pathPrefixInvalid") } +rulesets-details-scope = { COPY(path, "rulesets.scope") } +rulesets-details-scope-input = + .placeholder = { COPY(path, "rulesets.scopePlaceholder") } +rulesets-details-scope-input-invalid = { COPY(path, "rulesets.scopeInvalid") } +""", + path=legacy_path, + ) + + [ + # Replace "%1$S" with "{ DATETIME($date, dateStyle: "long") }" + FTL.Message( + FTL.Identifier("rulesets-update-last"), + value=REPLACE( + legacy_path, + "rulesets.lastUpdated", + { + "%1$S": FTL.FunctionReference( + FTL.Identifier("DATETIME"), + arguments=FTL.CallArguments( + positional=[ + FTL.VariableReference(FTL.Identifier("date")) + ], + named=[ + FTL.NamedArgument( + FTL.Identifier("dateStyle"), + value=FTL.StringLiteral("long"), + ) + ], + ), + ) + }, + ), + ), + ], + )
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/08ed48f...