Port 1555788 - Migrate about preferences home content to use fluent r=fluent-reviewers,Mardak,pdahiya,flod
This commit is contained in:
Родитель
17e10d4a8a
Коммит
ff7aedaa4a
|
@ -5,7 +5,6 @@
|
|||
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
|
||||
const {actionTypes: at} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
|
||||
|
@ -19,7 +18,7 @@ const PREFS_BEFORE_SECTIONS = [
|
|||
id: "search",
|
||||
pref: {
|
||||
feed: "showSearch",
|
||||
titleString: "prefs_search_header",
|
||||
titleString: "home-prefs-search-header",
|
||||
},
|
||||
icon: "chrome://browser/skin/search-glass.svg",
|
||||
},
|
||||
|
@ -27,8 +26,8 @@ const PREFS_BEFORE_SECTIONS = [
|
|||
id: "topsites",
|
||||
pref: {
|
||||
feed: "feeds.topsites",
|
||||
titleString: "settings_pane_topsites_header",
|
||||
descString: "prefs_topsites_description",
|
||||
titleString: "home-prefs-topsites-header",
|
||||
descString: "home-prefs-topsites-description",
|
||||
},
|
||||
icon: "topsites",
|
||||
maxRows: 4,
|
||||
|
@ -41,8 +40,8 @@ const PREFS_AFTER_SECTIONS = [
|
|||
id: "snippets",
|
||||
pref: {
|
||||
feed: "feeds.snippets",
|
||||
titleString: "settings_pane_snippets_header",
|
||||
descString: "prefs_snippets_description",
|
||||
titleString: "home-prefs-snippets-header",
|
||||
descString: "home-prefs-snippets-description",
|
||||
},
|
||||
icon: "info",
|
||||
},
|
||||
|
@ -149,19 +148,9 @@ this.AboutPreferences = class AboutPreferences {
|
|||
const createAppend = (tag, parent, options) => parent.appendChild(
|
||||
document.createXULElement(tag, options));
|
||||
|
||||
// Helper to get strings and format with values if necessary
|
||||
const formatString = id => {
|
||||
if (typeof id !== "object") {
|
||||
return strings[id] || id;
|
||||
}
|
||||
let string = strings[id.id] || JSON.stringify(id);
|
||||
if (id.values) {
|
||||
Object.entries(id.values).forEach(([key, val]) => {
|
||||
string = string.replace(new RegExp(`{${key}}`, "g"), val);
|
||||
});
|
||||
}
|
||||
return string;
|
||||
};
|
||||
// Helper to get fluentIDs sometimes encase in an object
|
||||
const getString = message =>
|
||||
typeof message !== "object" ? message : message.id;
|
||||
|
||||
// Helper to link a UI element to a preference for updating
|
||||
const linkPref = (element, name, type) => {
|
||||
|
@ -183,11 +172,12 @@ this.AboutPreferences = class AboutPreferences {
|
|||
const contentsGroup = homeGroup.insertAdjacentElement("afterend", homeGroup.cloneNode());
|
||||
contentsGroup.id = "homeContentsGroup";
|
||||
contentsGroup.setAttribute("data-subcategory", "contents");
|
||||
createAppend("label", contentsGroup)
|
||||
.appendChild(document.createElementNS(HTML_NS, "h2"))
|
||||
.textContent = formatString("prefs_home_header");
|
||||
createAppend("description", contentsGroup)
|
||||
.textContent = formatString("prefs_home_description");
|
||||
const homeHeader = createAppend("label", contentsGroup)
|
||||
.appendChild(document.createElementNS(HTML_NS, "h2"));
|
||||
document.l10n.setAttributes(homeHeader, "home-prefs-content-header");
|
||||
|
||||
const homeDescription = createAppend("description", contentsGroup);
|
||||
document.l10n.setAttributes(homeDescription, "home-prefs-content-description");
|
||||
|
||||
// Add preferences for each section
|
||||
prefStructure.forEach(sectionData => {
|
||||
|
@ -201,7 +191,7 @@ this.AboutPreferences = class AboutPreferences {
|
|||
} = sectionData;
|
||||
const {
|
||||
feed: name,
|
||||
titleString,
|
||||
titleString = {},
|
||||
descString,
|
||||
nestedPrefs = [],
|
||||
} = prefData || {};
|
||||
|
@ -220,8 +210,9 @@ this.AboutPreferences = class AboutPreferences {
|
|||
sectionVbox.setAttribute("data-subcategory", id);
|
||||
const checkbox = createAppend("checkbox", sectionVbox);
|
||||
checkbox.classList.add("section-checkbox");
|
||||
checkbox.setAttribute("label", formatString(titleString));
|
||||
checkbox.setAttribute("src", iconUrl);
|
||||
document.l10n.setAttributes(checkbox, getString(titleString), titleString.values);
|
||||
|
||||
linkPref(checkbox, name, "bool");
|
||||
|
||||
// Specially add a link for stories
|
||||
|
@ -233,8 +224,8 @@ this.AboutPreferences = class AboutPreferences {
|
|||
|
||||
const link = createAppend("label", sponsoredHbox, {is: "text-link"});
|
||||
link.classList.add("learn-sponsored");
|
||||
link.setAttribute("href", sectionData.learnMore.link.href);
|
||||
link.textContent = formatString(sectionData.learnMore.link.id);
|
||||
link.setAttribute("href", sectionData.pref.learnMore.link.href);
|
||||
document.l10n.setAttributes(link, sectionData.pref.learnMore.link.id);
|
||||
}
|
||||
|
||||
// Add more details for the section (e.g., description, more prefs)
|
||||
|
@ -243,7 +234,7 @@ this.AboutPreferences = class AboutPreferences {
|
|||
if (descString) {
|
||||
const label = createAppend("label", detailVbox);
|
||||
label.classList.add("indent");
|
||||
label.textContent = formatString(descString);
|
||||
document.l10n.setAttributes(label, getString(descString));
|
||||
|
||||
// Add a rows dropdown if we have a pref to control and a maximum
|
||||
if (rowsPref && maxRows) {
|
||||
|
@ -260,9 +251,8 @@ this.AboutPreferences = class AboutPreferences {
|
|||
menulist.setAttribute("crop", "none");
|
||||
const menupopup = createAppend("menupopup", menulist);
|
||||
for (let num = 1; num <= maxRows; num++) {
|
||||
const plurals = formatString({id: "prefs_section_rows_option", values: {num}});
|
||||
const item = createAppend("menuitem", menupopup);
|
||||
item.setAttribute("label", PluralForm.get(num, plurals));
|
||||
document.l10n.setAttributes(item, "home-prefs-sections-rows-option", { num });
|
||||
item.setAttribute("value", num);
|
||||
}
|
||||
linkPref(menulist, rowsPref, "int");
|
||||
|
@ -277,7 +267,7 @@ this.AboutPreferences = class AboutPreferences {
|
|||
nestedPrefs.forEach(nested => {
|
||||
const subcheck = createAppend("checkbox", detailVbox);
|
||||
subcheck.classList.add("indent");
|
||||
subcheck.setAttribute("label", formatString(nested.titleString));
|
||||
document.l10n.setAttributes(subcheck, nested.titleString);
|
||||
linkPref(subcheck, nested.name, "bool");
|
||||
subChecks.push(subcheck);
|
||||
subcheck.disabled = !pref._value;
|
||||
|
|
|
@ -19,13 +19,19 @@ const BUILT_IN_SECTIONS = {
|
|||
"feeds.section.topstories": options => ({
|
||||
id: "topstories",
|
||||
pref: {
|
||||
titleString: {id: "header_recommended_by", values: {provider: options.provider_name}},
|
||||
descString: {id: "prefs_topstories_description2"},
|
||||
titleString: {id: "home-prefs-recommended-by-header", values: {provider: options.provider_name} },
|
||||
descString: {id: "home-prefs-recommended-by-description"},
|
||||
nestedPrefs: options.show_spocs ? [{
|
||||
name: "showSponsored",
|
||||
titleString: "prefs_topstories_options_sponsored_label",
|
||||
titleString: "home-prefs-recommended-by-option-sponsored-stories",
|
||||
icon: "icon-info",
|
||||
}] : [],
|
||||
learnMore: {
|
||||
link: {
|
||||
href: "https://getpocket.com/firefox/new_tab_learn_more",
|
||||
id: "home-prefs-recommended-by-learn-more",
|
||||
},
|
||||
},
|
||||
},
|
||||
shouldHidePref: options.hidden,
|
||||
eventSource: "TOP_STORIES",
|
||||
|
@ -35,7 +41,6 @@ const BUILT_IN_SECTIONS = {
|
|||
link: {
|
||||
href: "https://getpocket.com/firefox/new_tab_learn_more",
|
||||
message: {id: "newtab-pocket-how-it-works"},
|
||||
id: "pocket_how_it_works",
|
||||
},
|
||||
},
|
||||
privacyNoticeURL: "https://www.mozilla.org/privacy/firefox/#suggest-relevant-content",
|
||||
|
@ -53,20 +58,20 @@ const BUILT_IN_SECTIONS = {
|
|||
"feeds.section.highlights": options => ({
|
||||
id: "highlights",
|
||||
pref: {
|
||||
titleString: {id: "settings_pane_highlights_header"},
|
||||
descString: {id: "prefs_highlights_description"},
|
||||
titleString: {id: "home-prefs-highlights-header"},
|
||||
descString: {id: "home-prefs-highlights-description"},
|
||||
nestedPrefs: [{
|
||||
name: "section.highlights.includeVisited",
|
||||
titleString: "prefs_highlights_options_visited_label",
|
||||
titleString: "home-prefs-highlights-option-visited-pages",
|
||||
}, {
|
||||
name: "section.highlights.includeBookmarks",
|
||||
titleString: "settings_pane_highlights_options_bookmarks",
|
||||
titleString: "home-prefs-highlights-options-bookmarks",
|
||||
}, {
|
||||
name: "section.highlights.includeDownloads",
|
||||
titleString: "prefs_highlights_options_download_label",
|
||||
titleString: "home-prefs-highlights-option-most-recent-download",
|
||||
}, {
|
||||
name: "section.highlights.includePocket",
|
||||
titleString: "prefs_highlights_options_pocket_label",
|
||||
titleString: "home-prefs-highlights-option-saved-to-pocket",
|
||||
}],
|
||||
},
|
||||
shouldHidePref: false,
|
||||
|
|
|
@ -1,42 +1,3 @@
|
|||
# LOCALIZATION NOTE(header_recommended_by): This is followed by the name
|
||||
# of the corresponding content provider.
|
||||
header_recommended_by=Recommended by {provider}
|
||||
|
||||
# LOCALIZATION NOTE (prefs_*, settings_*): These are shown in about:preferences
|
||||
# for a "Firefox Home" section. "Firefox" should be treated as a brand and kept
|
||||
# in English, while "Home" should be localized matching the about:preferences
|
||||
# sidebar mozilla-central string for the panel that has preferences related to
|
||||
# what is shown for the homepage, new windows, and new tabs.
|
||||
prefs_home_header=Firefox Home Content
|
||||
prefs_home_description=Choose what content you want on your Firefox Home screen.
|
||||
|
||||
prefs_content_discovery_description=Content Discovery in Firefox Home allows you to discover high-quality, relevant articles from across the web.
|
||||
|
||||
# LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
|
||||
# plural forms used in a drop down of multiple row options (1 row, 2 rows).
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
prefs_section_rows_option={num} row;{num} rows
|
||||
prefs_search_header=Web Search
|
||||
prefs_topsites_description=The sites you visit most
|
||||
prefs_topstories_description2=Great content from around the web, personalized for you
|
||||
prefs_topstories_options_sponsored_label=Sponsored Stories
|
||||
prefs_topstories_sponsored_learn_more=Learn more
|
||||
prefs_highlights_description=A selection of sites that you’ve saved or visited
|
||||
prefs_highlights_options_visited_label=Visited Pages
|
||||
prefs_highlights_options_download_label=Most Recent Download
|
||||
prefs_highlights_options_pocket_label=Pages Saved to Pocket
|
||||
prefs_snippets_description=Updates from Mozilla and Firefox
|
||||
settings_pane_topsites_header=Top Sites
|
||||
settings_pane_highlights_header=Highlights
|
||||
settings_pane_highlights_options_bookmarks=Bookmarks
|
||||
# LOCALIZATION NOTE(settings_pane_snippets_header): For the "Snippets" feature
|
||||
# traditionally on about:home. Alternative translation options: "Small Note" or
|
||||
# something that expresses the idea of "a small message, shortened from
|
||||
# something else, and non-essential but also not entirely trivial and useless."
|
||||
settings_pane_snippets_header=Snippets
|
||||
|
||||
pocket_how_it_works=How it works
|
||||
|
||||
# LOCALIZATION NOTE (firstrun_*). These strings are displayed only once, on the
|
||||
# firstrun of the browser, they give an introduction to Firefox and Sync.
|
||||
firstrun_title=Take Firefox with You
|
||||
|
|
|
@ -153,6 +153,12 @@ describe("AboutPreferences Feed", () => {
|
|||
const testRender = () => instance.renderPreferences({
|
||||
document: {
|
||||
createXULElement: sandbox.stub().returns(node),
|
||||
l10n: {
|
||||
setAttributes(el, id , args) {
|
||||
el.setAttribute("data-l10n-id", id);
|
||||
el.setAttribute("data-l10n-args", JSON.stringify(args));
|
||||
},
|
||||
},
|
||||
createProcessingInstruction: sandbox.stub(),
|
||||
createElementNS: sandbox.stub().callsFake((NS, el) => node),
|
||||
getElementById: sandbox.stub().returns(node),
|
||||
|
@ -183,42 +189,27 @@ describe("AboutPreferences Feed", () => {
|
|||
};
|
||||
gHomePane = {toggleRestoreDefaultsBtn: sandbox.stub()};
|
||||
});
|
||||
describe("#formatString", () => {
|
||||
it("should fall back to string id if missing", () => {
|
||||
testRender();
|
||||
|
||||
assert.equal(node.textContent, "prefs_home_description");
|
||||
});
|
||||
it("should use provided plain string", () => {
|
||||
strings = {prefs_home_description: "hello"};
|
||||
describe("#getString", () => {
|
||||
it("should not fail if titleString is not provided", () => {
|
||||
prefStructure = [{pref: {}}];
|
||||
|
||||
testRender();
|
||||
|
||||
assert.equal(node.textContent, "hello");
|
||||
assert.calledWith(node.setAttribute, "data-l10n-id", sinon.match.typeOf("undefined"));
|
||||
});
|
||||
it("should fall back to string object if missing", () => {
|
||||
const titleString = {id: "foo"};
|
||||
it("should return the string id if titleString is just a string", () => {
|
||||
const titleString = "foo";
|
||||
prefStructure = [{pref: {titleString}}];
|
||||
|
||||
testRender();
|
||||
|
||||
assert.calledWith(node.setAttribute, "label", JSON.stringify(titleString));
|
||||
assert.calledWith(node.setAttribute, "data-l10n-id", titleString);
|
||||
});
|
||||
it("should use provided string object id", () => {
|
||||
strings = {foo: "bar"};
|
||||
prefStructure = [{pref: {titleString: {id: "foo"}}}];
|
||||
it("should set id and args if titleString is an object with id and values", () => {
|
||||
const titleString = {id: "foo", values: { provider: "bar"}};
|
||||
prefStructure = [{pref: {titleString}}];
|
||||
|
||||
testRender();
|
||||
|
||||
assert.calledWith(node.setAttribute, "label", "bar");
|
||||
});
|
||||
it("should use values in string object", () => {
|
||||
strings = {foo: "l{n}{n}t"};
|
||||
prefStructure = [{pref: {titleString: {id: "foo", values: {n: 3}}}}];
|
||||
|
||||
testRender();
|
||||
|
||||
assert.calledWith(node.setAttribute, "label", "l33t");
|
||||
assert.calledWith(node.setAttribute, "data-l10n-id", titleString.id);
|
||||
assert.calledWith(node.setAttribute, "data-l10n-args", JSON.stringify(titleString.values));
|
||||
});
|
||||
});
|
||||
describe("#linkPref", () => {
|
||||
|
@ -268,11 +259,11 @@ describe("AboutPreferences Feed", () => {
|
|||
|
||||
testRender();
|
||||
|
||||
assert.calledWith(node.setAttribute, "label", titleString);
|
||||
assert.calledWith(node.setAttribute, "data-l10n-id", titleString);
|
||||
});
|
||||
it("should add a link for top stories", () => {
|
||||
const href = "https://disclaimer/";
|
||||
prefStructure = [{learnMore: {link: {href}}, id: "topstories", pref: {feed: "feed"}}];
|
||||
prefStructure = [{id: "topstories", pref: {feed: "feed", learnMore: {link: {href}}}}];
|
||||
|
||||
testRender();
|
||||
assert.calledWith(node.setAttribute, "href", href);
|
||||
|
@ -285,7 +276,7 @@ describe("AboutPreferences Feed", () => {
|
|||
|
||||
testRender();
|
||||
|
||||
assert.equal(node.textContent, descString);
|
||||
assert.calledWith(node.setAttribute, "data-l10n-id", descString);
|
||||
});
|
||||
it("should render rows dropdown with appropriate number", () => {
|
||||
prefStructure = [{rowsPref: "row_pref", maxRows: 3, pref: {descString: "foo"}}];
|
||||
|
@ -305,7 +296,7 @@ describe("AboutPreferences Feed", () => {
|
|||
it("should render a nested pref", () => {
|
||||
testRender();
|
||||
|
||||
assert.calledWith(node.setAttribute, "label", titleString);
|
||||
assert.calledWith(node.setAttribute, "data-l10n-id", titleString);
|
||||
});
|
||||
it("should add a change event", () => {
|
||||
testRender();
|
||||
|
|
Загрузка…
Ссылка в новой задаче