DEV: Use site locale for composer helper translations (#698)

This commit is contained in:
Keegan George 2024-07-04 08:23:37 -07:00 committed by GitHub
parent 38153608f8
commit eab2f74b58
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 70 additions and 22 deletions

View File

@ -12,6 +12,7 @@ module DiscourseAi
def suggest
input = get_text_param!
force_default_locale = params[:force_default_locale] || false
prompt = CompletionPrompt.find_by(id: params[:mode])
@ -31,6 +32,7 @@ module DiscourseAi
prompt,
input,
current_user,
force_default_locale,
),
status: 200
end

View File

@ -8,6 +8,7 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
import { caretPosition, getCaretPosition } from "discourse/lib/utilities";
import { INPUT_DELAY } from "discourse-common/config/environment";
import { afterRender, bind, debounce } from "discourse-common/utils/decorators";
import I18n from "discourse-i18n";
import { showComposerAIHelper } from "../../lib/show-ai-helper";
export default class AiHelperContextMenu extends Component {
@ -76,7 +77,28 @@ export default class AiHelperContextMenu extends Component {
prompts = prompts
.filter((p) => p.location.includes("composer"))
.filter((p) => p.name !== "generate_titles");
.filter((p) => p.name !== "generate_titles")
.map((p) => {
// AI helper by default returns interface locale on translations
// Since we want site default translations (and we are using: force_default_locale)
// we need to replace the translated_name with the site default locale name
const siteLocale = this.siteSettings.default_locale;
const availableLocales = JSON.parse(
this.siteSettings.available_locales
);
const locale = availableLocales.find((l) => l.value === siteLocale);
const translatedName = I18n.t(
"discourse_ai.ai_helper.context_menu.translate_prompt",
{
language: locale.name,
}
);
if (p.name === "translate") {
return { ...p, translated_name: translatedName };
}
return p;
});
// Find the custom_prompt object and move it to the beginning of the array
const customPromptIndex = prompts.findIndex(
@ -367,6 +389,7 @@ export default class AiHelperContextMenu extends Component {
mode: option.id,
text: this.selectedText,
custom_prompt: this.customPromptValue,
force_default_locale: true,
},
});

View File

@ -292,6 +292,7 @@ en:
title: "Custom Prompt"
placeholder: "Enter a custom prompt..."
submit: "Send Prompt"
translate_prompt: "Translate to %{language}"
post_options_menu:
trigger: "Ask AI"
title: "Ask AI"

View File

@ -158,7 +158,7 @@ en:
errors:
completion_request_failed: "Something went wrong while trying to provide suggestions. Please, try again."
prompts:
translate: Translate to English
translate: Translate to %{language}
generate_titles: Suggest topic titles
proofread: Proofread text
markdown_table: Generate Markdown table

View File

@ -11,7 +11,7 @@ module DiscourseAi
prompt_cache.flush!
end
def available_prompts
def available_prompts(user)
key = "prompt_cache_#{I18n.locale}"
self
.class
@ -27,9 +27,19 @@ module DiscourseAi
prompts =
prompts.map do |prompt|
translation =
I18n.t("discourse_ai.ai_helper.prompts.#{prompt.name}", default: nil) ||
prompt.translated_name || prompt.name
if prompt.name == "translate"
locale = user.effective_locale
locale_hash = LocaleSiteSetting.language_names[locale]
translation =
I18n.t(
"discourse_ai.ai_helper.prompts.translate",
language: locale_hash["nativeName"],
) || prompt.translated_name || prompt.name
else
translation =
I18n.t("discourse_ai.ai_helper.prompts.#{prompt.name}", default: nil) ||
prompt.translated_name || prompt.name
end
{
id: prompt.id,
@ -44,9 +54,9 @@ module DiscourseAi
end
end
def custom_locale_instructions(user = nil)
def custom_locale_instructions(user = nil, force_default_locale)
locale = SiteSetting.default_locale
locale = user.locale || SiteSetting.default_locale if SiteSetting.allow_user_locale && user
locale = user.effective_locale if !force_default_locale
locale_hash = LocaleSiteSetting.language_names[locale]
if locale != "en" && locale_hash
@ -57,15 +67,17 @@ module DiscourseAi
end
end
def localize_prompt!(prompt, user = nil)
locale_instructions = custom_locale_instructions(user)
def localize_prompt!(prompt, user = nil, force_default_locale)
locale_instructions = custom_locale_instructions(user, force_default_locale)
if locale_instructions
prompt.messages[0][:content] = prompt.messages[0][:content] + locale_instructions
end
if prompt.messages[0][:content].include?("%LANGUAGE%")
locale = SiteSetting.default_locale
locale = user.locale if SiteSetting.allow_user_locale && user&.locale.present?
locale = user.effective_locale if user && !force_default_locale
locale_hash = LocaleSiteSetting.language_names[locale]
prompt.messages[0][:content] = prompt.messages[0][:content].gsub(
@ -75,10 +87,10 @@ module DiscourseAi
end
end
def generate_prompt(completion_prompt, input, user, &block)
def generate_prompt(completion_prompt, input, user, force_default_locale = false, &block)
llm = DiscourseAi::Completions::Llm.proxy(SiteSetting.ai_helper_model)
prompt = completion_prompt.messages_with_input(input)
localize_prompt!(prompt, user)
localize_prompt!(prompt, user, force_default_locale)
llm.generate(
prompt,
@ -90,8 +102,8 @@ module DiscourseAi
)
end
def generate_and_send_prompt(completion_prompt, input, user)
completion_result = generate_prompt(completion_prompt, input, user)
def generate_and_send_prompt(completion_prompt, input, user, force_default_locale = false)
completion_result = generate_prompt(completion_prompt, input, user, force_default_locale)
result = { type: completion_prompt.prompt_type }
result[:suggestions] = (

View File

@ -38,7 +38,7 @@ module DiscourseAi
end,
) do
ActiveModel::ArraySerializer.new(
DiscourseAi::AiHelper::Assistant.new.available_prompts,
DiscourseAi::AiHelper::Assistant.new.available_prompts(scope.user),
root: false,
)
end

View File

@ -16,17 +16,27 @@ RSpec.describe DiscourseAi::AiHelper::Assistant do
describe("#custom_locale_instructions") do
it "Properly generates the per locale system instruction" do
SiteSetting.default_locale = "ko"
expect(subject.custom_locale_instructions).to eq(
expect(subject.custom_locale_instructions(user, false)).to eq(
"It is imperative that you write your answer in Korean (한국어), you are interacting with a Korean (한국어) speaking user. Leave tag names in English.",
)
SiteSetting.allow_user_locale = true
user.update!(locale: "he")
expect(subject.custom_locale_instructions(user)).to eq(
expect(subject.custom_locale_instructions(user, false)).to eq(
"It is imperative that you write your answer in Hebrew (עברית), you are interacting with a Hebrew (עברית) speaking user. Leave tag names in English.",
)
end
it "returns sytstem instructions using Site locale if force_default_locale is true" do
SiteSetting.default_locale = "ko"
SiteSetting.allow_user_locale = true
user.update!(locale: "he")
expect(subject.custom_locale_instructions(user, true)).to eq(
"It is imperative that you write your answer in Korean (한국어), you are interacting with a Korean (한국어) speaking user. Leave tag names in English.",
)
end
end
describe("#available_prompts") do
@ -36,7 +46,7 @@ RSpec.describe DiscourseAi::AiHelper::Assistant do
end
it "returns all available prompts" do
prompts = subject.available_prompts
prompts = subject.available_prompts(user)
expect(prompts.length).to eq(6)
expect(prompts.map { |p| p[:name] }).to contain_exactly(
@ -56,7 +66,7 @@ RSpec.describe DiscourseAi::AiHelper::Assistant do
end
it "returns the illustrate_post prompt in the list of all prompts" do
prompts = subject.available_prompts
prompts = subject.available_prompts(user)
expect(prompts.length).to eq(7)
expect(prompts.map { |p| p[:name] }).to contain_exactly(

View File

@ -21,7 +21,7 @@ describe DiscourseAi::AiHelper::EntryPoint do
parsed["current_user"]["ai_helper_prompts"].find { |prompt| prompt["name"] == "translate" }
expect(translate_prompt["translated_name"]).to eq(
I18n.t("discourse_ai.ai_helper.prompts.translate"),
I18n.t("discourse_ai.ai_helper.prompts.translate", language: "English (US)"),
)
I18n.with_locale("fr") do
@ -32,7 +32,7 @@ describe DiscourseAi::AiHelper::EntryPoint do
parsed["current_user"]["ai_helper_prompts"].find { |prompt| prompt["name"] == "translate" }
expect(translate_prompt["translated_name"]).to eq(
I18n.t("discourse_ai.ai_helper.prompts.translate", locale: "fr"),
I18n.t("discourse_ai.ai_helper.prompts.translate", locale: "fr", language: "Français"),
)
end
end