Compare commits

..
7 Commits
Author SHA1 Message Date
Jarek Radosz da55eb31d0 DEV: Deprecate the plugin 2025-07-14 18:14:14 +02:00
Roman Rizzi 6a4dbd8126 FEATURE: Use Personas in Automation's llm_report script (#1499) 2025-07-14 12:47:21 -03:00
Roman Rizzi 89bcf9b1f0 FIX: Process succesfully generated embeddings even if some failed (#1500) 2025-07-10 17:51:01 -03:00
Martin Brennan 6b5ea38644 DEV: Improve AI bot conversation submit upload handling (#1497)
Try fix a flaky spec in /ai_bot/homepage_spec.rb by using ember
data rather than inspecting the DOM directly to see if there
are any in-progress uploads.

Also add missing translation for in progress uploads warning.
2025-07-10 17:06:39 +10:00
Natalie Tay d54cd1f602 DEV: Normalize locales that are similar (e.g. en and en_GB) so they do not get translated (#1495)
This commit
- normalizes locales like en_GB and variants to en. With this, the feature will not translate en_GB posts to en (or similarly pt_BR to pt_PT)
- consolidates whether the feature is enabled in `DiscourseAi::Translation.enabled?`
- similarly for backfill in  `DiscourseAi::Translation.backfill_enabled?`
  - turns off backfill if `ai_translation_backfill_max_age_days` is 0 to keep true to what it says. Set it to a high number to backfill everything
2025-07-09 22:21:51 +08:00
Keegan George cf7288e1bf DEV: Surface topic_id in errors of summarization backfill (#1493)
This update ensures that the `topic_id` related to the error when summarizing is surfaced in the logs, which should help track down the reason for the errors.
2025-07-09 06:39:36 -07:00
Discourse Translator Bot 027d7f1199 Update translations (#1492) 2025-07-09 15:27:19 +02:00
61 changed files with 595 additions and 232 deletions
+3
View File
@@ -1,5 +1,8 @@
# **Discourse AI** Plugin
> [!IMPORTANT]
> This plugin has now been bundled into Discourse core. See: https://meta.discourse.org/t/bundling-more-popular-plugins-with-discourse-core/373574
**Plugin Summary**
For more information, please see: https://meta.discourse.org/t/discourse-ai/259214?u=falco
+5 -4
View File
@@ -6,8 +6,7 @@ module Jobs
sidekiq_options retry: false
def execute(args)
return if !SiteSetting.discourse_ai_enabled
return if !SiteSetting.ai_translation_enabled
return if !DiscourseAi::Translation.enabled?
return if args[:post_id].blank?
post = Post.find_by(id: args[:post_id])
@@ -36,12 +35,14 @@ module Jobs
end
end
return if detected_locale.blank?
locales = SiteSetting.content_localization_supported_locales.split("|")
return if locales.blank?
locales.each do |locale|
next if locale == detected_locale
next if post.post_localizations.exists?(locale:)
next if DiscourseAi::Translation::LocaleNormalizer.is_same?(locale, detected_locale)
regionless_locale = locale.split("_").first
next if post.post_localizations.where("locale LIKE ?", "#{regionless_locale}%").exists?
begin
DiscourseAi::Translation::PostLocalizer.localize(post, locale)
+5 -4
View File
@@ -6,8 +6,7 @@ module Jobs
sidekiq_options retry: false
def execute(args)
return if !SiteSetting.discourse_ai_enabled
return if !SiteSetting.ai_translation_enabled
return if !DiscourseAi::Translation.enabled?
return if args[:topic_id].blank?
topic = Topic.find_by(id: args[:topic_id])
@@ -34,12 +33,14 @@ module Jobs
end
end
return if detected_locale.blank?
locales = SiteSetting.content_localization_supported_locales.split("|")
return if locales.blank?
locales.each do |locale|
next if locale == detected_locale
next if topic.topic_localizations.exists?(locale:)
next if DiscourseAi::Translation::LocaleNormalizer.is_same?(locale, detected_locale)
regionless_locale = locale.split("_").first
next if topic.topic_localizations.where("locale LIKE ?", "#{regionless_locale}%").exists?
begin
DiscourseAi::Translation::TopicLocalizer.localize(topic, locale)
+3 -6
View File
@@ -6,21 +6,17 @@ module Jobs
sidekiq_options retry: false
def execute(args)
return if !DiscourseAi::Translation.enabled?
limit = args[:limit]
raise Discourse::InvalidParameters.new(:limit) if limit.nil?
return if limit <= 0
return if !SiteSetting.discourse_ai_enabled
return if !SiteSetting.ai_translation_enabled
locales = SiteSetting.content_localization_supported_locales.split("|")
return if locales.blank?
categories = Category.where("locale IS NOT NULL")
if SiteSetting.ai_translation_backfill_limit_to_public_content
categories = categories.where(read_restricted: false)
end
categories = categories.order(:id).limit(limit)
return if categories.empty?
@@ -33,6 +29,7 @@ module Jobs
missing_locales = locales - existing_locales - [category.locale]
missing_locales.each do |locale|
break if remaining_limit <= 0
next if DiscourseAi::Translation::LocaleNormalizer.is_same?(locale, category.locale)
begin
DiscourseAi::Translation::CategoryLocalizer.localize(category, locale)
+8 -14
View File
@@ -9,23 +9,25 @@ module Jobs
limit = args[:limit]
raise Discourse::InvalidParameters.new(:limit) if limit.blank? || limit <= 0
return if !SiteSetting.discourse_ai_enabled
return if !SiteSetting.ai_translation_enabled
return if !DiscourseAi::Translation.backfill_enabled?
locales = SiteSetting.content_localization_supported_locales.split("|")
return if locales.blank?
locales.each do |locale|
base_locale = locale.split("_").first
posts =
Post
.joins(
"LEFT JOIN post_localizations pl ON pl.post_id = posts.id AND pl.locale = #{ActiveRecord::Base.connection.quote(locale)}",
"LEFT JOIN post_localizations pl ON pl.post_id = posts.id AND pl.locale LIKE '#{base_locale}%'",
)
.where(
"posts.created_at > ?",
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
)
.where(deleted_at: nil)
.where("posts.user_id > 0")
.where.not(raw: [nil, ""])
.where.not(locale: nil)
.where.not(locale: locale)
.where("posts.locale NOT LIKE '#{base_locale}%'")
.where("pl.id IS NULL")
posts = posts.joins(:topic)
@@ -46,14 +48,6 @@ module Jobs
)
end
if SiteSetting.ai_translation_backfill_max_age_days > 0
posts =
posts.where(
"posts.created_at > ?",
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
)
end
posts = posts.order(updated_at: :desc).limit(limit)
next if posts.empty?
+8 -14
View File
@@ -9,22 +9,24 @@ module Jobs
limit = args[:limit]
raise Discourse::InvalidParameters.new(:limit) if limit.blank? || limit <= 0
return if !SiteSetting.discourse_ai_enabled
return if !SiteSetting.ai_translation_enabled
return if !DiscourseAi::Translation.backfill_enabled?
locales = SiteSetting.content_localization_supported_locales.split("|")
return if locales.blank?
locales.each do |locale|
base_locale = locale.split("_").first
topics =
Topic
.joins(
"LEFT JOIN topic_localizations tl ON tl.topic_id = topics.id AND tl.locale = #{ActiveRecord::Base.connection.quote(locale)}",
"LEFT JOIN topic_localizations tl ON tl.topic_id = topics.id AND tl.locale LIKE '#{base_locale}%'",
)
.where(
"topics.created_at > ?",
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
)
.where(deleted_at: nil)
.where("topics.user_id > 0")
.where.not(locale: nil)
.where.not(locale: locale)
.where("topics.locale NOT LIKE '#{base_locale}%'")
.where("tl.id IS NULL")
if SiteSetting.ai_translation_backfill_limit_to_public_content
@@ -43,14 +45,6 @@ module Jobs
)
end
if SiteSetting.ai_translation_backfill_max_age_days > 0
topics =
topics.where(
"topics.created_at > ?",
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
)
end
topics = topics.order(updated_at: :desc).limit(limit)
next if topics.empty?
@@ -7,10 +7,7 @@ module Jobs
cluster_concurrency 1
def execute(args)
return if !SiteSetting.discourse_ai_enabled
return if !SiteSetting.ai_translation_enabled
limit = SiteSetting.ai_translation_backfill_hourly_rate
return if limit == 0
return if !DiscourseAi::Translation.backfill_enabled?
categories = Category.where(locale: nil)
@@ -18,6 +15,7 @@ module Jobs
categories = categories.where(read_restricted: false)
end
limit = SiteSetting.ai_translation_backfill_hourly_rate
categories = categories.limit(limit)
return if categories.empty?
@@ -6,11 +6,8 @@ module Jobs
cluster_concurrency 1
def execute(args)
return if !SiteSetting.discourse_ai_enabled
return if !SiteSetting.ai_translation_enabled
return if SiteSetting.content_localization_supported_locales.blank?
return if !DiscourseAi::Translation.backfill_enabled?
limit = SiteSetting.ai_translation_backfill_hourly_rate
return if limit == 0
Jobs.enqueue(:localize_categories, limit:)
end
@@ -6,10 +6,8 @@ module Jobs
cluster_concurrency 1
def execute(args)
return if !SiteSetting.discourse_ai_enabled
return if !SiteSetting.ai_translation_enabled
return if !DiscourseAi::Translation.backfill_enabled?
return if SiteSetting.content_localization_supported_locales.blank?
limit = SiteSetting.ai_translation_backfill_hourly_rate / (60 / 5) # this job runs in 5-minute intervals
return if limit == 0
@@ -7,16 +7,16 @@ module Jobs
cluster_concurrency 1
def execute(args)
return if !SiteSetting.discourse_ai_enabled
return if !SiteSetting.ai_translation_enabled
return if !DiscourseAi::Translation.backfill_enabled?
limit = SiteSetting.ai_translation_backfill_hourly_rate / (60 / 5) # this job runs in 5-minute intervals
return if limit == 0
posts =
Post
.where(locale: nil)
.where(deleted_at: nil)
.where("posts.user_id > 0")
.where("posts.created_at > ?", SiteSetting.ai_translation_backfill_max_age_days.days.ago)
.where.not(raw: [nil, ""])
if SiteSetting.ai_translation_backfill_limit_to_public_content
@@ -33,14 +33,6 @@ module Jobs
)
end
if SiteSetting.ai_translation_backfill_max_age_days > 0
posts =
posts.where(
"posts.created_at > ?",
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
)
end
posts = posts.order(updated_at: :desc).limit(limit)
return if posts.empty?
+6 -1
View File
@@ -36,7 +36,12 @@ module ::Jobs
existing_summary = strategy.existing_summary
if existing_summary.blank? || existing_summary.outdated
strategy.summarize(user)
begin
strategy.summarize(user)
rescue => e
Rails.logger.error("Error summarizing topic #{topic.id}: #{e.class.name} - #{e.message}")
raise e
end
else
# Hiding or deleting a post, and creating a small action alters the Topic#highest_post_number.
# We use this as a quick way to select potential backfill candidates without relying on original_content_sha.
@@ -6,13 +6,9 @@ module Jobs
cluster_concurrency 1
def execute(args)
return if !SiteSetting.discourse_ai_enabled
return if !SiteSetting.ai_translation_enabled
return if !DiscourseAi::Translation.backfill_enabled?
return if SiteSetting.content_localization_supported_locales.blank?
limit = SiteSetting.ai_translation_backfill_hourly_rate / (60 / 5) # this job runs in 5-minute intervals
return if limit == 0
Jobs.enqueue(:localize_topics, limit:)
end
end
@@ -7,12 +7,15 @@ module Jobs
cluster_concurrency 1
def execute(args)
return if !SiteSetting.discourse_ai_enabled
return if !SiteSetting.ai_translation_enabled
limit = SiteSetting.ai_translation_backfill_hourly_rate / (60 / 5) # this job runs in 5-minute intervals
return if limit == 0
return if !DiscourseAi::Translation.backfill_enabled?
topics = Topic.where(locale: nil, deleted_at: nil).where("topics.user_id > 0")
limit = SiteSetting.ai_translation_backfill_hourly_rate / (60 / 5) # this job runs in 5-minute intervals
topics =
Topic
.where(locale: nil, deleted_at: nil)
.where("topics.user_id > 0")
.where("topics.created_at > ?", SiteSetting.ai_translation_backfill_max_age_days.days.ago)
if SiteSetting.ai_translation_backfill_limit_to_public_content
topics =
@@ -28,14 +31,6 @@ module Jobs
)
end
if SiteSetting.ai_translation_backfill_max_age_days > 0
topics =
topics.where(
"topics.created_at > ?",
SiteSetting.ai_translation_backfill_max_age_days.days.ago,
)
end
topics = topics.order(updated_at: :desc).limit(limit)
return if topics.empty?
@@ -260,10 +260,11 @@ export default class AiBotConversations extends Component {
@action
async prepareAndSubmitToBot() {
// Pass uploads to the service before submitting
this.aiBotConversationsHiddenSubmit.uploads = this.uploads;
try {
await this.aiBotConversationsHiddenSubmit.submitToBot();
await this.aiBotConversationsHiddenSubmit.submitToBot({
uploads: this.uploads,
inProgressUploadsCount: this.inProgressUploads.length,
});
this.uploads = new TrackedArray();
} catch (error) {
popupAjaxError(error);
@@ -18,7 +18,6 @@ export default class AiBotConversationsHiddenSubmit extends Service {
personaId;
targetUsername;
uploads = [];
inputValue = "";
@@ -32,7 +31,7 @@ export default class AiBotConversationsHiddenSubmit extends Service {
}
@action
async submitToBot() {
async submitToBot(uploadData) {
if (
this.inputValue.length <
this.siteSettings.min_personal_message_post_length
@@ -48,7 +47,7 @@ export default class AiBotConversationsHiddenSubmit extends Service {
}
// Don't submit if there are still uploads in progress
if (document.querySelector(".ai-bot-upload--in-progress")) {
if (uploadData.inProgressUploadsCount > 0) {
return this.dialog.alert({
message: i18n("discourse_ai.ai_bot.conversations.uploads_in_progress"),
});
@@ -61,10 +60,10 @@ export default class AiBotConversationsHiddenSubmit extends Service {
let rawContent = this.inputValue;
// Append upload markdown if we have uploads
if (this.uploads && this.uploads.length > 0) {
if (uploadData.uploads && uploadData.uploads.length > 0) {
rawContent += "\n\n";
this.uploads.forEach((upload) => {
uploadData.uploads.forEach((upload) => {
const uploadMarkdown = getUploadMarkdown(upload);
rawContent += uploadMarkdown + "\n";
});
@@ -83,7 +82,6 @@ export default class AiBotConversationsHiddenSubmit extends Service {
});
// Reset uploads after successful submission
this.uploads = [];
this.inputValue = "";
this.appEvents.trigger("discourse-ai:bot-pm-created", {
+2
View File
@@ -158,6 +158,8 @@ ar:
reset: "إعادة التعيين"
search:
name: "البحث"
embeddings:
name: "التضمينات"
ai_helper:
name: "المساعد"
proofread: تدقيق النص لغويًا
+82 -8
View File
@@ -29,6 +29,22 @@ de:
label: "Sortieren nach"
tag:
label: "Schlagwort"
logs:
staff_actions:
actions:
create_ai_llm_model: "LLM-Modell erstellen"
update_ai_llm_model: "LLM-Modell aktualisieren"
delete_ai_llm_model: "LLM-Modell löschen"
create_ai_persona: "KI-Persona erstellen"
update_ai_persona: "KI-Persona aktualisieren"
delete_ai_persona: "KI-Persona löschen"
create_ai_tool: "KI-Tool erstellen"
update_ai_tool: "KI-Tool aktualisieren"
delete_ai_tool: "KI-Tool löschen"
create_ai_embedding: "KI-Einbettung erstellen"
update_ai_embedding: "KI-Einbettung aktualisieren"
delete_ai_embedding: "KI-Einbettung löschen"
update_ai_spam_settings: "KI-Spam-Einstellungen aktualisieren"
js:
discourse_automation:
scriptables:
@@ -98,21 +114,21 @@ de:
fields:
model:
label: "Modell"
description: "Das für die Triage verwendete Standard-Sprachmodell"
description: "Das für die Sichtung verwendete Standard-Sprachmodell"
tool:
label: "Werkzeug"
description: "Werkzeug für die Triage (das Werkzeug darf keine Parameter definiert haben)"
label: "Tool"
description: "Tool für die Sichtung (das Tool darf keine Parameter definiert haben)"
llm_persona_triage:
fields:
persona:
label: "Persona"
description: "KI-Persona, die für die Triage verwendet werden soll (Standard-LLM und -Benutzer müssen eingestellt sein)"
description: "KI-Persona, die für die Sichtung verwendet werden soll (Standard-LLM und -Benutzer müssen eingestellt sein)"
whisper:
label: "Als Flüstern antworten"
description: "Ob die Antwort der Persona ein Flüstern sein soll"
silent_mode:
label: "Stiller Modus"
description: "Im stillen Modus empfängt die Persona den Inhalt, schreibt aber nichts in das Forum - nützlich bei der Triage mit Tools"
description: "Im stillen Modus empfängt die Persona den Inhalt, schreibt aber nichts in das Forum - nützlich bei der Sichtung mit Tools"
llm_triage:
fields:
system_prompt:
@@ -177,6 +193,7 @@ de:
llm:
one: "LLM:"
other: "LLM:"
no_llm: "Kein LLM ausgewählt"
no_persona: "Nicht festgelegt"
no_groups: "Keiner"
edit: "Bearbeiten"
@@ -184,35 +201,73 @@ de:
one: "(%{count} weitere)"
other: "(%{count} weitere)"
collapse_list: "(weniger anzeigen)"
bot:
bot: "Chatbot"
name: "Bot"
description: "Ein Chatbot, der Fragen beantworten und Benutzern in persönlichen Nachrichten, im Forum und im Chat helfen kann"
nav:
configured: "Konfiguriert"
unconfigured: "Nicht konfiguriert"
filters:
all: "Gesamt"
text: "Suche nach Funktionen, Personas, LLMs oder Gruppen..."
no_results: "Es wurden keine Funktionen gefunden, die deinen Filtern entsprechen."
reset: "Zurücksetzen"
summarization:
name: "Zusammenfassungen"
description: "Stellt eine Schaltfläche für Zusammenfassungen zur Verfügung, mit der Besucher Themen zusammenfassen können"
topic_summaries: "Themenzusammenfassungen"
gists: "Kurze Zusammenfassungen der in Themenliste"
search:
name: "Suche"
description: "Verbessert das Sucherlebnis durch KI-generierte Antworten auf Suchanfragen"
discoveries: "Entdeckungen"
embeddings:
name: "Einbettungen"
description: "Ermöglicht Funktionen wie „Verwandte Themen“ und „KI-Suche“ durch die Erstellung semantischer Textdarstellungen"
hyde: "HyDE"
discord:
name: "Discord-Integration"
description: "Fügt die Möglichkeit hinzu, Discord-Kanäle zu durchsuchen"
search: "Discord-Suche"
inference:
name: "Abgeleitete Konzepte"
description: "Ordnet Themen und Beiträge in Interessensgebiete / Labels."
match_concepts: "Passende Konzepte"
ai_helper:
name: "Helfer"
description: "Unterstützt Benutzer bei der Interaktion in der Community, z. B. beim Erstellen von Themen, Verfassen von Beiträgen und Lesen von Inhalten"
proofread: Text korrekturlesen
title_suggestions: "Titel vorschlagen"
explain: "Erklären"
illustrate_post: "Beitrag illustrieren"
smart_dates: "Intelligente Termine"
translate: "Übersetzen"
markdown_tables: "Markdown-Tabelle generieren"
custom_prompt: "Benutzerdefinierte Eingabeaufforderung"
image_caption: "Bildbeschriftungen"
translator: "Übersetzer"
translation:
name: "Übersetzen"
description: "Übersetzt Inhalte in unterstützte Sprachen"
locale_detector: "Sprachdetektor"
post_raw_translator: "Übersetzer für die Roheingabe des Beitrags"
topic_title_translator: "Thementitel-Übersetzer"
short_text_translator: "Kurztext-Übersetzer"
spam:
name: "Spam"
description: "Identifiziert potenziellen Spam mithilfe des ausgewählten LLMs und meldet ihn den Moderatoren der Website in der Warteschlange zur Überprüfung."
inspect_posts: "Beiträge prüfen"
modals:
select_option: "Wähle eine Option aus..."
layout:
table: "Tabelle"
card: "Karte"
spam:
short_title: "Spam"
title: "Spam-Behandlung konfigurieren"
select_llm: "LLM auswählen"
select_persona: "Persona auswählen"
custom_instructions: "Benutzerdefinierte Anweisungen"
custom_instructions_help: "Benutzerdefinierte Anweisungen speziell für deine Website, die der KI beim Identifizieren von Spam helfen, z. B. „Gehe beim Scannen von Posts, die nicht in englischer Sprache sind, aggressiver vor.“"
last_seven_days: "Letzte 7 Tage"
@@ -293,6 +348,9 @@ de:
name: "Name"
edit: "Bearbeiten"
export: "Exportieren"
import: "Importieren"
import_error_conflict: "Beim Importieren von %{name} wurde ein Konflikt erkannt. Möchtest du die vorhandene Persona aktualisieren?"
overwrite: "Überschreiben"
description: "Beschreibung"
no_llm_selected: "Kein Sprachmodell ausgewählt"
use_parent_llm: "Verwende das Personas Sprachmodell"
@@ -370,7 +428,10 @@ de:
title: "KI-Bot-Optionen"
save_first: "Weitere KI-Bot-Optionen werden verfügbar, sobald du die Persona gespeichert hast."
filters:
text: "Finde eine Persona"
reset: "Zurücksetzen"
no_results: "Es wurden keine Personas gefunden, die deinen Filtern entsprechen."
all_features: "Jede Funktion"
features_list:
one: "Funktion:"
other: "Funktionen:"
@@ -401,11 +462,14 @@ de:
back: "Zurück"
short_title: "Tools"
export: "Exportieren"
import: "Importieren"
import_error_conflict: "Tool existiert bereits, möchtest du es aktualisieren?"
overwrite: "Überschreiben"
no_tools: "Du hast noch keine Tools erstellt"
name: "Name"
name_help: "Der Name wird in der Discourse-Benutzeroberfläche angezeigt und ist die Kurzkennung, die Du verwendest, um das Werkzeug in verschiedenen Einstellungen zu finden. Er sollte eindeutig sein (er ist erforderlich)."
name_help: "Der Name wird in der Discourse-Benutzeroberfläche angezeigt und ist die Kurzkennung, die du verwendest, um das Tool in verschiedenen Einstellungen zu finden. Er sollte eindeutig sein (er ist erforderlich)."
new: "Neues Tool"
tool_name: "Werkzeugname"
tool_name: "Name des Tools"
tool_name_help: "Der Werkzeugname wird dem großen Sprachmodell präsentiert. Es ist nicht eindeutig, aber es ist von Person zu Person unterschiedlich. (Persona wird beim Speichern validiert)"
description: "Beschreibung"
description_help: "Eine klare Beschreibung des Zwecks des Tools für das Sprachmodell"
@@ -486,14 +550,18 @@ de:
ai_summarization: "Zusammenfassen"
ai_embeddings_semantic_search: "KI-Suche"
ai_spam: "Spam"
automation: "Automatisierung (%{name})"
automation: "Automatisierung (%{persona})"
in_use_warning:
one: "Dieses Modell wird derzeit von %{settings} verwendet. Wenn es falsch konfiguriert ist, wird die Funktion nicht wie erwartet funktionieren."
other: "Dieses Modell wird derzeit verwendet von: %{settings}. Wenn es falsch konfiguriert ist, werden die Funktionen nicht wie erwartet funktionieren. "
model_description:
none: "Allgemeine Einstellungen, die für die meisten Sprachmodelle funktionieren"
anthropic-claude-opus-4-0: "Das intelligenteste Modell von Anthropic"
anthropic-claude-sonnet-4-0: "Optimales Gleichgewicht zwischen Geschwindigkeit und Kosten"
anthropic-claude-3-7-sonnet-latest: "Optimales Gleichgewicht zwischen Geschwindigkeit und Kosten (vorherige Generation)"
anthropic-claude-3-5-haiku-latest: "Schnell und kosteneffizient"
google-gemini-2-5-pro: "Großes multimodales Modell, das eine Vielzahl von Aufgaben bewältigen kann"
google-gemini-2-0-flash: "Leicht, schnell und kosteneffizient mit multimodaler Argumentation (vorherige Generation)"
google-gemini-2-5-flash: "Leicht, schnell und kosteneffizient mit multimodaler Argumentation"
google-gemini-2-0-flash-lite: "Kosteneffizientes Modell mit niedriger Latenz"
open_ai-o3: "Das leistungsfähigste Argumentationsmodell von Open AI"
@@ -505,6 +573,9 @@ de:
samba_nova-Meta-Llama-3-3-70B-Instruct": "Leistungsstarkes Mehrzweckmodell"
mistral-mistral-large-latest: "Das leistungsstärkste Modell von Mistral"
mistral-pixtral-large-latest: "Das leistungsstärkste Modell von Mistral mit Sichtfunktion"
open_router-x-ai-grok-3-beta: "Das neueste Modell von xAI"
open_router-deepseek-deepseek-r1-0528-free: "DeepSeeks neuestes Argumentationsmodell"
open_router-meta-llama-3-3-70b-instruct: "Leistungsstarkes mehrsprachiges Modell"
preseeded_model_description: "Vorkonfiguriertes Open-Source-Modell unter Verwendung von %{model}"
configured:
title: "Konfigurierte LLMs"
@@ -565,6 +636,7 @@ de:
reasoning_tokens: "Anzahl der für die Argumentation verwendeten Token"
disable_temperature: "Temperatur deaktivieren (einige Denkmodelle unterstützen keine Temperatur)"
disable_top_p: "Top P deaktivieren (einige Denkmodelle unterstützen Top P nicht)"
enable_responses_api: "Aktiviere die Antwort-API (bei bestimmten OpenAI-Modellen erforderlich)"
related_topics:
title: "Verwandte Themen"
pill: "Verwandt"
@@ -583,6 +655,7 @@ de:
trigger: "KI fragen"
loading: "KI generiert"
cancel: "Abbrechen"
regen: "Erneut versuchen"
confirm: "Bestätigen"
discard: "Verwerfen"
changes: "Empfohlene Änderungen"
@@ -759,6 +832,7 @@ de:
today: "Heute"
last_7_days: "Letzte 7 Tage"
last_30_days: "Letzte 30 Tage"
upload_files: "Dateien hochladen"
sentiments:
dashboard:
title: "Stimmung"
+4
View File
@@ -106,6 +106,9 @@ en:
top_p:
label: "Top P"
description: "Top P to use for the LLM, increase to increase randomness (leave empty to use model default)"
persona_id:
label: "Persona"
description: "AI Persona to use for report generation"
llm_tool_triage:
fields:
@@ -872,6 +875,7 @@ en:
last_7_days: "Last 7 days"
last_30_days: "Last 30 days"
upload_files: "Upload files"
uploads_in_progress: "Cannot submit while uploads are in progress"
sentiments:
dashboard:
title: "Sentiment"
+2
View File
@@ -154,6 +154,8 @@ es:
reset: "Restablecer"
search:
name: "Buscar"
embeddings:
name: "Incrustaciones"
ai_helper:
name: "Ayudante"
proofread: Corregir el texto
+2
View File
@@ -154,6 +154,8 @@ fi:
reset: "Palauta"
search:
name: "Hae"
embeddings:
name: "Upotukset"
ai_helper:
name: "Apuri"
proofread: Oikolue teksti
+2
View File
@@ -154,6 +154,8 @@ fr:
reset: "Réinitialiser"
search:
name: "Recherche"
embeddings:
name: "Intégrations"
ai_helper:
name: "Assistant"
proofread: Relisez le texte
+22 -1
View File
@@ -185,6 +185,7 @@ he:
two: "LLMים:"
many: "LLMים:"
other: "LLMים:"
no_llm: "לא נבחר מש״ג/LLM"
no_persona: "לא מוגדר"
no_groups: "ללא"
edit: "עריכה"
@@ -196,24 +197,44 @@ he:
collapse_list: "(להציג פחות)"
bot:
name: "בוט"
description: "צ׳אט בוט שיכול לענות על שאלות ולסייע למשתמשים בהודעות אישיות, בפורום ובצ׳אט"
filters:
all: "הכול"
text: "חיפוש יכולות, דמויות, LLMים/מש״גים או קבוצות…"
reset: "איפוס"
summarization:
name: "סיכומים"
description: "להנגיש את כפתור הסיכום שמאפשר למבקרים לסכם נושאים"
topic_summaries: "תקצירי נושאים."
search:
name: "חיפוש"
description: "שיפור חוויית החיפוש על ידי אספקת תשובות שנוצרו על ידי בינה מלאכותית לשאילתות"
discoveries: "תגליות"
embeddings:
name: "הטמעות"
discord:
name: "שילוב מול Discord"
description: "הוספת היכולת לחפש בערוצי Discord"
search: "חיפוש ב־Discord"
inference:
generate_concepts: "הסקת תפיסות"
ai_helper:
name: "מסייע"
proofread: הגהת הטקסט
title_suggestions: "הצעת כותרות"
explain: "הסבר"
illustrate_post: "איור פוסט"
smart_dates: "תאריכים חכמים"
translate: "תרגום"
markdown_tables: "יצירת טבלה ב־Markdown"
custom_prompt: "בקשה מותאמת אישית"
image_caption: "הוספת כותרות לתמונות"
translation:
description: "תרגום תוכן לשפות נתמכות"
locale_detector: "מזהה שפה ומקום"
post_raw_translator: "מתרגם פוסטים גולמי"
topic_title_translator: "מתרגם כותרות נושאים"
short_text_translator: "מתרגם טקסטים קצרים"
spam:
name: "ספאם"
modals:
@@ -491,7 +512,7 @@ he:
ai_summarization: "סיכום"
ai_embeddings_semantic_search: "חיפוש בינה מלאכותית"
ai_spam: "ספאם"
automation: "אוטומציה (%{name})"
automation: "אוטומציה (%{persona})"
in_use_warning:
one: "המודל הזה משמש את %{settings}. אם לא מוגדר כראוי, היכולת לא תעבוד כמצופה."
two: "המודל הזה משמש את: %{settings}. אם ההגדרות שגויות היכולת לא תעבודנה כמצופה."
+2
View File
@@ -154,6 +154,8 @@ it:
reset: "Annulla"
search:
name: "Cerca"
embeddings:
name: "Integrazioni"
ai_helper:
name: "Assistente"
proofread: Testo corretto
+2
View File
@@ -157,6 +157,8 @@ ja:
reset: "リセット"
search:
name: "検索"
embeddings:
name: "埋め込み"
ai_helper:
name: "ヘルパー"
proofread: テキストを構成
+2
View File
@@ -154,6 +154,8 @@ nl:
reset: "Resetten"
search:
name: "Zoeken"
embeddings:
name: "Insluitingen"
ai_helper:
name: "Helper"
proofread: Tekst proeflezen
+2
View File
@@ -154,6 +154,8 @@ pt_BR:
reset: "Redefinir"
search:
name: "Pesquisar"
embeddings:
name: "Incorporações"
ai_helper:
name: "Ajudante"
proofread: Revisar texto
+2
View File
@@ -156,6 +156,8 @@ ru:
reset: "Сбросить"
search:
name: "Искать"
embeddings:
name: "Встраивания"
ai_helper:
name: "Помощник"
proofread: Вычитать текст
+2
View File
@@ -154,6 +154,8 @@ tr_TR:
reset: "Sıfırla"
search:
name: "Ara"
embeddings:
name: "Gömmeler"
ai_helper:
name: "Yardımcı"
proofread: Yazım hataları düzeltilmiş metin
+2
View File
@@ -173,6 +173,8 @@ zh_CN:
reset: "重置"
search:
name: "搜索"
embeddings:
name: "嵌入向量"
ai_helper:
name: "助手"
proofread: 审校文本
+39 -3
View File
@@ -14,10 +14,10 @@ de:
spam_silence: "Als Spam melden, Beitrag ausblenden und Benutzer stummschalten"
scriptables:
llm_tool_triage:
title: Triage von Beiträgen mit dem KI-Tool
description: "Triage von Beiträgen mit benutzerdefinierter Logik in einem KI-Tool"
title: Sichtung von Beiträgen mit dem KI-Tool
description: "Sichtung von Beiträgen mit benutzerdefinierter Logik in einem KI-Tool"
llm_persona_triage:
title: Triage von Posts mit KI-Persona
title: Sichtung von Beiträgen mit KI-Persona
description: "Reagiere auf Beiträge mit einer bestimmten KI-Persona"
llm_triage:
title: Beiträge mithilfe von KI sortieren
@@ -31,6 +31,7 @@ de:
description: "Regelmäßiger Bericht auf der Grundlage eines großen Sprachmodells"
site_settings:
discourse_ai_enabled: "Aktiviere das Discourse-KI-Plug-in."
ai_artifact_security: "Das KI-Artefaktsystem generiert IFRAMEs mit ausführbarem Code. Der strikte Modus erfordert einen zusätzlichen Klick zum Ausführen des Codes. Der laxe Modus führt Code sofort aus. Im Hybridmodus kann der Benutzer data-ai-artifact-autorun angeben, um den Code sofort anzuzeigen. Der deaktivierte Modus deaktiviert das Artefaktsystem."
ai_toxicity_enabled: "Aktiviere das Toxizitätsmodul."
ai_toxicity_inference_service_api_endpoint: "URL, unter der die API für das Toxizitätsmodul läuft"
ai_toxicity_inference_service_api_key: "API-Schlüssel für die Toxizitäts-API"
@@ -111,6 +112,11 @@ de:
ai_discord_search_persona: "Die Persona, die für die Discord-Suche verwendet wird."
ai_discord_allowed_guilds: "Discord-Gilden (Server), auf denen der Bot suchen darf"
ai_bot_enable_dedicated_ux: "Erlaube eine Vollbild-Bot-Oberfläche anstelle einer PM"
ai_translation_enabled: "Aktiviert die KI-Übersetzungsfunktion"
ai_translation_model: "Das Modell, das für die Übersetzung verwendet werden soll. Dieses Modell muss die Übersetzung unterstützen. Personas können diese Einstellung überschreiben."
ai_translation_backfill_limit_to_public_content: "Wenn diese Option aktiviert ist, werden nur Inhalte in öffentlichen Kategorien übersetzt. Wenn sie deaktiviert ist, werden auch Inhalte in Gruppen-PMs und privaten Kategorien zur Übersetzung gesendet."
ai_translation_max_post_length: "Die maximale Länge eines zu übersetzenden Beitrags. Längere Beiträge werden nicht übersetzt."
ai_translation_backfill_max_age_days: "Das maximale Alter eines zu übersetzenden Beitrags und Themas. Ältere Beiträge und Themen werden nicht übersetzt."
reviewables:
reasons:
flagged_by_toxicity: Das KI-Plug-in meldete dies nach der Klassifizierung als toxisch.
@@ -210,9 +216,15 @@ de:
description: "Beiträge, die per KI unter Verwendung des Modells „SamLowe/roberta-base-go_emotions“ mit der Emotion „Überraschung“ klassifiziert wurden."
discourse_ai:
ai_artifact:
errors:
max_keys_exceeded:
one: "Du kannst nur %{count} Schlüssel im Artefakt haben."
other: "Du kannst nur %{count} Schlüssel im Artefakt haben."
link: "In neuem Tab anzeigen"
view_source: "Quelle anzeigen"
view_changes: "Änderungen anzeigen"
change_description: "Beschreibung ändern"
copied: "Wurde in Zwischenablage kopiert"
unknown_model: "Unbekanntes KI-Modell"
tools:
custom_name: "%{name} (benutzerdefiniert)"
@@ -265,6 +277,7 @@ de:
unexpected: "Ein unerwarteter Fehler ist aufgetreten"
bot_user_update_failed: "Aktualisierung des Spam-Scan-Bot-Benutzers fehlgeschlagen"
configuration_missing: "Die Konfiguration der KI-Spamerkennung fehlt. Füge die Konfiguration in „Administration > Plug-ins > Discourse KI > Spam“ hinzu, bevor du sie aktivierst."
logging_subject: "Spam-Erkennung"
ai_bot:
reply_error: "Entschuldigung, es sieht so aus, als ob unser System beim Versuch, zu antworten, auf ein unerwartetes Problem gestoßen ist.\n\n[details='Fehlerdetails']\n%{details}\n[/details]"
default_pm_prefix: "[KI-Bot-PN ohne Titel]"
@@ -352,6 +365,24 @@ de:
image_captioner:
name: "Bildbeschriftungen"
description: "Standard-Persona für die Bildbeschriftungsfunktion des Helfers"
locale_detector:
name: "Sprachdetektor"
description: "Unterstützt die Übersetzungsfunktion durch Erkennen der Sprache eines bestimmten Textes (Beiträge, Titel usw.)."
post_raw_translator:
name: "Beitragsübersetzer"
description: "Unterstützt die Übersetzungsfunktion durch die Übersetzung von Beiträgen, die Discourse Markdown enthalten"
topic_title_translator:
name: "Thementitel-Übersetzer"
description: "Unterstützt die Übersetzungsfunktion durch die Übersetzung von Thementiteln"
short_text_translator:
name: "Kurztext-Übersetzer"
description: "Betreibt die Übersetzungsfunktion als generischer Textübersetzer, der für kurze Texte wie Kategorienamen oder Schlagwörter verwendet wird."
spam_detector:
name: "Spam-Detektor"
description: "Standard-Persona, die unsere Spam-Erkennungsfunktion betreibt"
content_creator:
name: "Inhaltsersteller"
description: "Standard-Persona für die HyDE-Suche"
topic_not_found: "Zusammenfassung nicht verfügbar, Thema nicht gefunden!"
summarizing: "Thema zusammenfassen"
searching: "Suche nach: „%{query}“"
@@ -534,6 +565,7 @@ de:
set_llm_first: "Stelle zuerst %{setting} ein"
model_unreachable: "Wir konnten keine Antwort von diesem Modell abrufen. Überprüfe zuerst deine Einstellungen."
invalid_seeded_model: "Du kannst dieses Modell nicht mit dieser Funktion verwenden"
invalid_persona_response_format: "Die ausgewählte Persona muss ein Antwortformat mit einem booleschen Feld namens „spam“ haben."
must_select_model: "Du musst zuerst ein LLM auswählen"
endpoints:
not_configured: "%{display_name} (nicht konfiguriert)"
@@ -571,6 +603,10 @@ de:
no_default_llm: Die Persona muss eine default_llm definiert haben.
user_not_allowed: Der Benutzer darf nicht am Thema teilnehmen.
prompt_message_length: Die Nachricht %{idx} hat die 1000-Zeichen-Grenze überschritten.
persona_already_exists: Eine Persona mit dem Namen %{name} existiert bereits.
custom_tool_exists:
one: "Ein benutzerdefiniertes Tool mit dem Namen %{names} existiert bereits."
other: "Benutzerdefinierte Tools mit den Namen %{names} existieren bereits."
dashboard:
problem:
ai_llm_status: "Bei dem LLM-Modell: %{model_name} treten Probleme auf. Bitte überprüfe <a href='%{url}'>die Konfigurationsseite des Modells</a>."

Some files were not shown because too many files have changed in this diff Show More