Bug 1907350 - Expose genai-settings-chat-title and other chatbot strings for localization r=tarek,fluent-reviewers,mconley,bolsson

Move featuregate title to features.ftl used by about:preferences and about:support; and other strings to genai.ftl. Allow prompts to use l10nId to get fluent attributes. Convert inline strings for menu and shortcuts to fluent. Update simplify, add explain prompts.

Differential Revision: https://phabricator.services.mozilla.com/D218279
This commit is contained in:
Ed Lee 2024-08-03 06:40:26 +00:00
parent 4c62bb6510
commit 9ca4d5dc5a
9 changed files with 99 additions and 18 deletions

View File

@ -1958,9 +1958,10 @@ pref("sidebar.visibility", "always-show");
pref("browser.ml.chat.enabled", false); pref("browser.ml.chat.enabled", false);
pref("browser.ml.chat.hideLocalhost", true); pref("browser.ml.chat.hideLocalhost", true);
pref("browser.ml.chat.prompt.prefix", 'Im on page "%tabTitle%" with "%selection|12000%" selected. '); pref("browser.ml.chat.prompt.prefix", 'Im on page "%tabTitle%" with "%selection|12000%" selected. ');
pref("browser.ml.chat.prompts.0", '{"label":"Summarize","value":"Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.","id":"summarize"}'); pref("browser.ml.chat.prompts.0", '{"id":"summarize","l10nId":"genai-prompts-summarize"}');
pref("browser.ml.chat.prompts.1", '{"label":"Simplify Language","value":"Please rewrite the selection in plain, clear language suitable for a general audience without specialized knowledge. Use all of the following tactics: simple vocabulary; short sentences; active voice; headers and bulleted lists for scannability. Maintain meaning and factual accuracy.","id":"simplify"}'); pref("browser.ml.chat.prompts.1", '{"id":"simplify","l10nId":"genai-prompts-simplify"}');
pref("browser.ml.chat.prompts.2", '{"label":"Quiz Me","value":"Please quiz me on this selection. Ask me a variety of types of questions, for example multiple choice, true or false, and short answer. Wait for my response before moving on to the next question.","id":"quiz","targeting":"!provider|regExpMatch(\'gemini\')"}'); pref("browser.ml.chat.prompts.2", '{"id":"quiz","l10nId":"genai-prompts-quiz","targeting":"!provider|regExpMatch(\'gemini\')"}');
pref("browser.ml.chat.prompts.3", '{"id":"explain","l10nId":"genai-prompts-explain","targeting":"channel==\'nightly\'"}');
pref("browser.ml.chat.provider", ""); pref("browser.ml.chat.provider", "");
pref("browser.ml.chat.shortcuts", true); pref("browser.ml.chat.shortcuts", true);
#ifdef NIGHTLY_BUILD #ifdef NIGHTLY_BUILD

View File

@ -66,6 +66,7 @@
<link rel="localization" href="browser/browserContext.ftl"/> <link rel="localization" href="browser/browserContext.ftl"/>
<link rel="localization" href="browser/browserSets.ftl"/> <link rel="localization" href="browser/browserSets.ftl"/>
<link rel="localization" href="browser/firefoxView.ftl"/> <link rel="localization" href="browser/firefoxView.ftl"/>
<link rel="localization" href="browser/genai.ftl"/>
<link rel="localization" href="browser/identityCredentialNotification.ftl" /> <link rel="localization" href="browser/identityCredentialNotification.ftl" />
<link rel="localization" href="browser/menubar.ftl"/> <link rel="localization" href="browser/menubar.ftl"/>
<link rel="localization" href="browser/originControls.ftl"/> <link rel="localization" href="browser/originControls.ftl"/>

View File

@ -16,6 +16,11 @@ ChromeUtils.defineESModuleGetters(lazy, {
clearTimeout: "resource://gre/modules/Timer.sys.mjs", clearTimeout: "resource://gre/modules/Timer.sys.mjs",
setTimeout: "resource://gre/modules/Timer.sys.mjs", setTimeout: "resource://gre/modules/Timer.sys.mjs",
}); });
ChromeUtils.defineLazyGetter(
lazy,
"l10n",
() => new Localization(["browser/genai.ftl"])
);
XPCOMUtils.defineLazyPreferenceGetter( XPCOMUtils.defineLazyPreferenceGetter(
lazy, lazy,
"chatEnabled", "chatEnabled",
@ -349,10 +354,16 @@ export const GenAI = {
if (lazy.chatShortcutsCustom) { if (lazy.chatShortcutsCustom) {
vbox.appendChild(document.createXULElement("toolbarseparator")); vbox.appendChild(document.createXULElement("toolbarseparator"));
const input = vbox.appendChild(document.createElement("input")); const input = vbox.appendChild(document.createElement("input"));
input.placeholder = `Ask ${ const provider = this.chatProviders.get(
this.chatProviders.get(lazy.chatProvider)?.name ?? lazy.chatProvider
"AI chatbot" )?.name;
}`; document.l10n.setAttributes(
input,
provider
? "genai-input-ask-provider"
: "genai-input-ask-generic",
{ provider }
);
input.style.margin = "var(--arrowpanel-menuitem-margin)"; input.style.margin = "var(--arrowpanel-menuitem-margin)";
input.addEventListener("mouseover", () => input.focus()); input.addEventListener("mouseover", () => input.focus());
input.addEventListener("change", () => { input.addEventListener("change", () => {
@ -418,9 +429,12 @@ export const GenAI = {
if (!lazy.chatEnabled || lazy.chatProvider == "") { if (!lazy.chatEnabled || lazy.chatProvider == "") {
return; return;
} }
menu.label = `Ask ${ const provider = this.chatProviders.get(lazy.chatProvider)?.name;
this.chatProviders.get(lazy.chatProvider)?.name ?? "AI Chatbot" menu.ownerDocument.l10n.setAttributes(
}`; menu,
provider ? "genai-menu-ask-provider" : "genai-menu-ask-generic",
{ provider }
);
menu.menupopup?.remove(); menu.menupopup?.remove();
await this.addAskChatItems( await this.addAskChatItems(
nsContextMenu.browser, nsContextMenu.browser,
@ -437,9 +451,10 @@ export const GenAI = {
* @param {object} context data used for targeting * @param {object} context data used for targeting
* @returns {promise} array of matching prompt objects * @returns {promise} array of matching prompt objects
*/ */
getContextualPrompts(context) { async getContextualPrompts(context) {
// Treat prompt objects as messages to reuse targeting capabilities // Treat prompt objects as messages to reuse targeting capabilities
const messages = []; const messages = [];
const toFormat = [];
Services.prefs.getChildList("browser.ml.chat.prompts.").forEach(pref => { Services.prefs.getChildList("browser.ml.chat.prompts.").forEach(pref => {
try { try {
const promptObj = { const promptObj = {
@ -457,10 +472,20 @@ export const GenAI = {
} }
} catch (ex) {} } catch (ex) {}
messages.push(promptObj); messages.push(promptObj);
if (promptObj.l10nId) {
toFormat.push(promptObj);
}
} catch (ex) { } catch (ex) {
console.error("Failed to get prompt pref " + pref, ex); console.error("Failed to get prompt pref " + pref, ex);
} }
}); });
// Apply localized attributes for prompts
(await lazy.l10n.formatMessages(toFormat.map(obj => obj.l10nId))).forEach(
(msg, idx) =>
msg?.attributes.forEach(attr => (toFormat[idx][attr.name] = attr.value))
);
return lazy.ASRouterTargeting.findMatchingMessage({ return lazy.ASRouterTargeting.findMatchingMessage({
messages, messages,
returnAll: true, returnAll: true,

View File

@ -56,3 +56,24 @@ add_task(async function test_prompt_context() {
"Prompt not added for contextual targeting" "Prompt not added for contextual targeting"
); );
}); });
/**
* Check that prompts can be localized
*/
add_task(async function test_prompt_l10n() {
Services.prefs.setStringPref(
"browser.ml.chat.prompts.test",
JSON.stringify({
l10nId: "genai-prompts-summarize",
label: "bad",
test: true,
})
);
const custom = (await GenAI.getContextualPrompts(DEFAULT_CONTEXT)).find(
prompt => prompt.id == null
);
Assert.ok(custom.test, "Found the custom prompt");
Assert.notEqual(custom.label, "bad", "Localized label takes priority");
Assert.ok(custom.value, "Got localized prompt");
});

View File

@ -54,6 +54,7 @@
<!-- Links below are only used for search-l10n-ids into subdialogs --> <!-- Links below are only used for search-l10n-ids into subdialogs -->
<link rel="localization" href="browser/aboutDialog.ftl"/> <link rel="localization" href="browser/aboutDialog.ftl"/>
<link rel="localization" href="browser/genai.ftl"/>
<link rel="localization" href="browser/preferences/addEngine.ftl"/> <link rel="localization" href="browser/preferences/addEngine.ftl"/>
<link rel="localization" href="browser/preferences/blocklists.ftl"/> <link rel="localization" href="browser/preferences/blocklists.ftl"/>
<link rel="localization" href="browser/preferences/clearSiteData.ftl"/> <link rel="localization" href="browser/preferences/clearSiteData.ftl"/>
@ -67,7 +68,6 @@
<link rel="localization" href="browser/sanitize.ftl"/> <link rel="localization" href="browser/sanitize.ftl"/>
<link rel="localization" href="browser/translations.ftl"/> <link rel="localization" href="browser/translations.ftl"/>
<link rel="localization" href="preview/translations.ftl"/> <link rel="localization" href="preview/translations.ftl"/>
<link rel="localization" href="preview/genai.ftl"/>
<link rel="localization" href="preview/enUS-searchFeatures.ftl"/> <link rel="localization" href="preview/enUS-searchFeatures.ftl"/>
<link rel="localization" href="preview/backupSettings.ftl"/> <link rel="localization" href="preview/backupSettings.ftl"/>
<link rel="localization" href="security/certificates/certManager.ftl"/> <link rel="localization" href="security/certificates/certManager.ftl"/>

View File

@ -4,8 +4,6 @@
## Generative AI (GenAI) Settings section ## Generative AI (GenAI) Settings section
genai-settings-chat-title =
.label = AI chatbot
genai-settings-chat-description = Adds the chatbot of your choice to the sidebar, for quick access as you browse. <a data-l10n-name="connect">Share feedback</a> genai-settings-chat-description = Adds the chatbot of your choice to the sidebar, for quick access as you browse. <a data-l10n-name="connect">Share feedback</a>
genai-settings-chat-choose = Choose a chatbot genai-settings-chat-choose = Choose a chatbot
genai-settings-chat-choose-one-menuitem = genai-settings-chat-choose-one-menuitem =
@ -21,3 +19,40 @@ genai-settings-chat-localhost-links = Bring your own private local chatbot such
genai-settings-chat-shortcuts = genai-settings-chat-shortcuts =
.description = Displays a shortcut to prompts when you select text. { -brand-short-name } sends the text, page title, and prompt to the chatbot. .description = Displays a shortcut to prompts when you select text. { -brand-short-name } sends the text, page title, and prompt to the chatbot.
.label = Show prompts on text select .label = Show prompts on text select
## Chatbot prompts
## Prompts are plain language instructions sent to a chatbot.
## These prompts have been made concise and direct in English because some chatbot providers
## have character restrictions and being direct reduces the chance for misinterpretation.
## When localizing, please be concise and direct, but not at the expense of losing meaning.
# Prompt purpose: help users understand what a selection covers at a glance
genai-prompts-summarize =
.label = Summarize
.value = Please summarize the selection using precise and concise language. Use headers and bulleted lists in the summary, to make it scannable. Maintain the meaning and factual accuracy.
# Prompt purpose: make a selection easier to read
genai-prompts-simplify =
.label = Simplify language
.value = Please rewrite the selection using short sentences and simple words. Maintain the meaning and factual accuracy.
# Prompt purpose: test understanding of selection in an interactive way
genai-prompts-quiz =
.label = Quiz me
.value = Please quiz me on this selection. Ask me a variety of types of questions, for example multiple choice, true or false, and short answer. Wait for my response before moving on to the next question.
# Prompt purpose: helps users understand words, phrases, concepts
genai-prompts-explain =
.label = Explain this
.value = Please explain the key concepts in this selection, using simple words. Also, use examples.
## Chatbot menu shortcuts
genai-menu-ask-generic =
.label = Ask AI chatbot
# $provider (string) - name of the provider
genai-menu-ask-provider =
.label = Ask { $provider }
genai-input-ask-generic =
.placeholder = Ask AI chatbot…
# $provider (string) - name of the provider
genai-input-ask-provider =
.placeholder = Ask { $provider }…

View File

@ -14,7 +14,6 @@
preview/enUS-searchFeatures.ftl (../components/urlbar/content/enUS-searchFeatures.ftl) preview/enUS-searchFeatures.ftl (../components/urlbar/content/enUS-searchFeatures.ftl)
preview/shopping.ftl (../components/shopping/content/shopping.ftl) preview/shopping.ftl (../components/shopping/content/shopping.ftl)
preview/onboarding.ftl (../components/aboutwelcome/content/onboarding.ftl) preview/onboarding.ftl (../components/aboutwelcome/content/onboarding.ftl)
preview/genai.ftl (../locales-preview/genai.ftl)
preview/translations.ftl (../locales-preview/translations.ftl) preview/translations.ftl (../locales-preview/translations.ftl)
preview/credentialChooser.ftl (../../toolkit/components/credentialmanagement/credentialChooser.ftl) preview/credentialChooser.ftl (../../toolkit/components/credentialmanagement/credentialChooser.ftl)
browser (%browser/**/*.ftl) browser (%browser/**/*.ftl)

View File

@ -30,9 +30,6 @@
<link rel="localization" href="toolkit/global/processTypes.ftl"/> <link rel="localization" href="toolkit/global/processTypes.ftl"/>
#ifndef ANDROID #ifndef ANDROID
<link rel="localization" href="toolkit/featuregates/features.ftl"/> <link rel="localization" href="toolkit/featuregates/features.ftl"/>
#if MOZ_BUILD_APP == browser
<link rel="localization" href="preview/genai.ftl" />
#endif
#endif #endif
</head> </head>

View File

@ -51,6 +51,8 @@ experimental-features-auto-pip =
.label = Picture-in-Picture: auto-open on tab switch .label = Picture-in-Picture: auto-open on tab switch
experimental-features-auto-pip-description = Enable Picture-in-Picture on active videos when switching tabs. experimental-features-auto-pip-description = Enable Picture-in-Picture on active videos when switching tabs.
genai-settings-chat-title =
.label = AI chatbot
experimental-features-group-browsing = experimental-features-group-browsing =
.label = Browsing .label = Browsing