Port 1555788 - Migrate about preferences home content to use fluent r=fluent-reviewers,Mardak,pdahiya,flod

This commit is contained in:
Ed Lee 2019-07-02 21:29:00 -07:00
Родитель 17e10d4a8a
Коммит ff7aedaa4a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 40B7250312F03605
4 изменённых файлов: 59 добавлений и 112 удалений

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

@ -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 youve 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();