Improve translation prompt and add /trans off toggle

- Focus on grammar/sentence structure for language detection
- Ignore code, URLs, tech jargon in language classification
- /trans cycles: local → public → off
- Strip trailing whitespace from LLM responses
- Suppress empty translation results
This commit is contained in:
2026-04-30 19:17:48 +02:00
parent c628a740b0
commit 4db1dfdece
+20 -6
View File
@@ -78,6 +78,7 @@ static struct {
/* Query target (for /q) */ /* Query target (for /q) */
static char query_target[64] = ""; static char query_target[64] = "";
static int translate_public = 0; /* /trans toggle: echo translations to channel */ static int translate_public = 0; /* /trans toggle: echo translations to channel */
static int translate_enabled = 1; /* master toggle for translation */
/* Track nicks who sent us private messages */ /* Track nicks who sent us private messages */
#define MAX_PM_NICKS 32 #define MAX_PM_NICKS 32
@@ -186,7 +187,7 @@ static void ai_config_load(void)
static int needs_translation(const char *text) static int needs_translation(const char *text)
{ {
if (!ai_cfg.enabled) return 0; if (!ai_cfg.enabled || !translate_enabled) return 0;
/* Skip very short messages (nicks, URLs, single words like "ok") */ /* Skip very short messages (nicks, URLs, single words like "ok") */
int words = 0; int words = 0;
for (const char *p = text; *p; p++) for (const char *p = text; *p; p++)
@@ -241,7 +242,7 @@ static void translate_async(const char *text, int level, const char *target)
char body[2048]; char body[2048];
snprintf(body, sizeof(body), snprintf(body, sizeof(body),
"{\"model\":\"%s\",\"messages\":[" "{\"model\":\"%s\",\"messages\":["
"{\"role\":\"system\",\"content\":\"You are a translator for an IRC chat. The user understands %s. If the message is in any of those languages or a mix of them, respond with exactly SKIP. Only translate messages in other languages to %s. Respond with only the translation or SKIP.\"}," "{\"role\":\"system\",\"content\":\"You are a language filter for IRC. Respond with ONLY the word SKIP or a translation. Rules: If the sentence structure and grammar is %s, respond SKIP. Code snippets, function names, URLs, and technical jargon inside a sentence do NOT change the language. Only translate if the grammar itself is in another language. Translate to %s.\"},"
"{\"role\":\"user\",\"content\":\"%s\"}" "{\"role\":\"user\",\"content\":\"%s\"}"
"],\"stream\":false,\"tool_choice\":\"none\"}", "],\"stream\":false,\"tool_choice\":\"none\"}",
ai_cfg.model, ai_cfg.skip_langs, ai_cfg.target_lang, escaped); ai_cfg.model, ai_cfg.skip_langs, ai_cfg.target_lang, escaped);
@@ -1188,9 +1189,18 @@ static void handle_input(char *line)
wprintf(WL_MSG, "* %s %s\n", nick, slap); wprintf(WL_MSG, "* %s %s\n", nick, slap);
} }
} else if (strcasecmp(cmd, "trans") == 0) { } else if (strcasecmp(cmd, "trans") == 0) {
translate_public = !translate_public; if (!translate_enabled) {
wprintf(current_level, "* Translation echo %s\n", translate_enabled = 1;
translate_public ? "ON" : "OFF"); translate_public = 0;
wprintf(current_level, "* Translation ON (local only)\n");
} else if (!translate_public) {
translate_public = 1;
wprintf(current_level, "* Translation ON (public echo)\n");
} else {
translate_enabled = 0;
translate_public = 0;
wprintf(current_level, "* Translation OFF\n");
}
} else if (strcasecmp(cmd, "ctcp") == 0 && args) { } else if (strcasecmp(cmd, "ctcp") == 0 && args) {
char *target = args; char *target = args;
char *ctcp_cmd = strchr(args, ' '); char *ctcp_cmd = strchr(args, ' ');
@@ -1473,8 +1483,12 @@ int main(int argc, char *argv[])
waitpid(translate_pending[ti].pid, NULL, 0); waitpid(translate_pending[ti].pid, NULL, 0);
if (n > 0) { if (n > 0) {
tbuf[n] = '\0'; tbuf[n] = '\0';
/* Strip trailing whitespace */
while (n > 0 && (tbuf[n-1] == '\n' || tbuf[n-1] == '\r' || tbuf[n-1] == ' '))
tbuf[--n] = '\0';
/* Skip if LLM says it's already in a skip language */ /* Skip if LLM says it's already in a skip language */
if (strcasecmp(tbuf, "SKIP") == 0 || if (n == 0 ||
strcasecmp(tbuf, "SKIP") == 0 ||
strncasecmp(tbuf, "SKIP", 4) == 0) { strncasecmp(tbuf, "SKIP", 4) == 0) {
/* do nothing */ /* do nothing */
} else { } else {