feat(i18n): add /lang command for preferred conversation language

Introduce a language selection command backed by a supported-language
table and per-language response instructions. The chosen code is stored
as `preferred_language` in the user profile and injected into the system
prompt so replies follow the selected language, with an `auto` option
for detection.

Also refreshes the agent and user profile timestamps and appends the
latest conversation context entries.
This commit is contained in:
2026-10-26 15:35:23 -03:00
parent 79a73f8f2e
commit d7f252034e
4 changed files with 199 additions and 3 deletions
+135
View File
@@ -1418,6 +1418,7 @@ def load_user_profile() -> Dict[str, Any]:
"age": "",
"gender": "",
"location": "",
"preferred_language": "english",
"interests": [],
"personality_traits": [],
"preferences": {
@@ -2075,6 +2076,135 @@ async def addtoagentprofile_command(update: Update, context: ContextTypes.DEFAUL
f"✅ Noted on the agent profile:\n{content}",
)
# ===================== LANGUAGE =====================
SUPPORTED_LANGUAGES = {
"en": "English",
"pt": "Portuguese",
"es": "Spanish",
"fr": "French",
"de": "German",
"it": "Italian",
"ja": "Japanese",
"ko": "Korean",
"zh": "Chinese",
"ar": "Arabic",
"hi": "Hindi",
"ru": "Russian",
"nl": "Dutch",
"pl": "Polish",
"tr": "Turkish",
"sv": "Swedish",
"no": "Norwegian",
"da": "Danish",
"fi": "Finnish",
"el": "Greek",
"he": "Hebrew",
"th": "Thai",
"vi": "Vietnamese",
"id": "Indonesian",
"cs": "Czech",
"ro": "Romanian",
"hu": "Hungarian",
"uk": "Ukrainian",
"auto": "Auto-detect",
}
LANGUAGE_INSTRUCTION = {
"en": "Respond in English.",
"pt": "Respond in Portuguese.",
"es": "Respond in Spanish.",
"fr": "Respond in French.",
"de": "Respond in German.",
"it": "Respond in Italian.",
"ja": "Respond in Japanese.",
"ko": "Respond in Korean.",
"zh": "Respond in Chinese.",
"ar": "Respond in Arabic.",
"hi": "Respond in Hindi.",
"ru": "Respond in Russian.",
"nl": "Respond in Dutch.",
"pl": "Respond in Polish.",
"tr": "Respond in Turkish.",
"sv": "Respond in Swedish.",
"no": "Respond in Norwegian.",
"da": "Respond in Danish.",
"fi": "Respond in Finnish.",
"el": "Respond in Greek.",
"he": "Respond in Hebrew.",
"th": "Respond in Thai.",
"vi": "Respond in Vietnamese.",
"id": "Respond in Indonesian.",
"cs": "Respond in Czech.",
"ro": "Respond in Romanian.",
"hu": "Respond in Hungarian.",
"uk": "Respond in Ukrainian.",
}
async def lang_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Handle /lang: set the preferred conversation language.
Stores the language code in the user profile. The AI will be instructed
to respond in that language via the system prompt.
Args:
update: Telegram update.
context: PTB callback context.
Returns:
None.
"""
await auto_detect_chat_id(update)
text = update.message.text.strip()
parts = text.split(maxsplit=1)
if len(parts) < 2 or not parts[1].strip():
lines = ["🌐 Supported languages:"]
for code, name in SUPPORTED_LANGUAGES.items():
lines.append(f" /lang {code} — {name}")
lines.append("")
lines.append("Usage: /lang <code>")
lines.append("Example: /lang pt")
await update.message.reply_text("\n".join(lines))
return
lang_code = parts[1].strip().lower()
if lang_code not in SUPPORTED_LANGUAGES:
await update.message.reply_text(
f"❌ Unsupported language code: {lang_code}\n"
"Use /lang without arguments to see supported languages."
)
return
profile = load_user_profile()
profile["preferred_language"] = lang_code
save_user_profile(profile)
language_name = SUPPORTED_LANGUAGES[lang_code]
instruction = LANGUAGE_INSTRUCTION.get(lang_code, f"Respond in {language_name}.")
await update.message.reply_text(
f"✅ Preferred language set to: {language_name}\n\n"
f"The AI will now respond in this language.\n"
f"Instruction: {instruction}"
)
def get_language_instruction(profile: Dict[str, Any]) -> str:
"""Return the language instruction for the system prompt.
Args:
profile: User profile dict.
Returns:
Language instruction string, or empty string if not set.
"""
lang = profile.get("preferred_language", "")
if not lang or lang == "auto":
return ""
return LANGUAGE_INSTRUCTION.get(lang, "")
# ===================== PROFILE UPDATE =====================
# Regex triggers for "note this in my profile" style commands; paired with the
@@ -2680,6 +2810,9 @@ def build_system_prompt(profile: Dict[str, Any]) -> str:
prompt += f"\n\nCurrent date: {current_date}."
prompt += f"\nCurrent time: {current_time} ({time_period})."
prompt += f"\nConfigured timezone: {get_timezone()}."
language_instruction = get_language_instruction(profile)
if language_instruction:
prompt += f"\n\nLANGUAGE: {language_instruction}"
prompt += (
"\n\nIMPORTANT ABOUT UPDATED INFORMATION:"
"\n- If the user's question asks for something factual, current, news, weather forecast, quote, future/past date, opening hours, updated address, etc., USE WEB SEARCH to answer."
@@ -5678,6 +5811,7 @@ Agent Profile:
/editagentprofile - Edit agent profile fields interactively
/configagentprofile - Configure the agent profile interactively (name, personality, traits, notes)
/addtoagentprofile <text> - Add a note/characteristic to the agent profile
/lang <code> - Set the preferred conversation language (e.g., /lang pt)
Management:
/newconfig - Reset everything and reconfigure the agent from scratch
@@ -6916,6 +7050,7 @@ def main():
app_instance.add_handler(CommandHandler("cancel", cancel_command))
app_instance.add_handler(CommandHandler("addtouserprofile", addtouserprofile_command))
app_instance.add_handler(CommandHandler("addtoagentprofile", addtoagentprofile_command))
app_instance.add_handler(CommandHandler("lang", lang_command))
app_instance.add_handler(CommandHandler("onboarding", onboarding_command))
app_instance.add_handler(CommandHandler("debug", debug_command))
app_instance.add_handler(CommandHandler("reload", reload_command))