Skip to content

Fix translate: working default backend, settings UI, outgoing translation#203

Open
MaikCZE wants to merge 1 commit into
TaterClient:masterfrom
MaikCZE:translate-fixes
Open

Fix translate: working default backend, settings UI, outgoing translation#203
MaikCZE wants to merge 1 commit into
TaterClient:masterfrom
MaikCZE:translate-fixes

Conversation

@MaikCZE

@MaikCZE MaikCZE commented Jul 16, 2026

Copy link
Copy Markdown

Summary

The translate feature (translate.cpp) had no settings UI at all (config-var only), no way to translate your own outgoing messages, and its default backend was silently dead:

  • ftapi.pythonanywhere.com (the default ftapi backend's hosting) is defunct — it now 404s to a generic PythonAnywhere placeholder page. So out of the box, translation simply didn't work, with no indication why.
  • There was no menu UI to configure any of this (backend, target language, auto-translate) — only console vars.
  • There was no way to translate your own messages before sending (only incoming).

Changes

  • New google backend (CTranslateBackendGoogle) that talks directly to the free, unofficial Google Translate endpoint that ftapi itself used to wrap under the hood. No API key, no self-hosting required. Made it the new default (tc_translate_backend default changed from ftapi to google).
  • New Translate section in the TClient settings menu (Settings → TClient → Settings tab): backend dropdown (Google / FreeTranslateAPI / LibreTranslate), incoming-translate toggle with a language dropdown (26 common languages), outgoing-translate toggle with its own language dropdown, and a LibreTranslate endpoint/API key section shown only when that backend is selected. Includes an inline warning when auto-translate is enabled with the ftapi backend, since that backend intentionally can't auto-translate (rate-limit protection, left unchanged).
  • Outgoing translation: new tc_translate_outgoing / tc_translate_outgoing_target config vars and CTranslate::TranslateOutgoing(). Hooked into the chat send path in chat.cpp — translates your typed message before sending so other players see it in the target language. Skips /-prefixed messages so it doesn't mangle server commands (e.g. /w name msg). Falls back to sending the original text if translation fails, so a message is never silently lost.
  • Refactored the backend classes to take an explicit target language parameter (rather than always reading g_Config.m_TcTranslateTarget), since incoming and outgoing now have independent target languages.

Test plan

  • Compiled clean with MSVC (Release, Ninja) on Windows
  • Manually tested in-game: incoming auto-translate, outgoing translate, and the new settings UI (backend/language dropdowns, conditional fields) all work as expected
  • Would appreciate a second pair of eyes on the Google endpoint choice (unofficial API, no key) versus keeping ftapi as default for users who self-host a mirror

🤖 Generated with Claude Code

…orking default backend

- FreeTranslateAPI's hosting (ftapi.pythonanywhere.com) is defunct, so the
  default backend never worked. Add a new "google" backend that talks
  directly to the free, unofficial Google Translate endpoint FTAPI itself
  used to wrap, and make it the default.
- Add a full Translate section to the TClient settings menu (previously the
  feature was config-var only, with no UI at all): backend/language
  dropdowns, incoming auto-translate toggle, and a LibreTranslate
  endpoint/key section shown only when relevant.
- Add outgoing translation: optionally translate your own messages into
  another language before sending, via a new tc_translate_outgoing /
  tc_translate_outgoing_target config pair and CTranslate::TranslateOutgoing().
  Falls back to sending the original text if translation fails, and skips
  "/"-prefixed messages so it doesn't mangle commands like /w.

@SollyBunny SollyBunny left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks mostly alright
The main things are:

  • don't hardcode stuff
  • remove ftapi
  • reduce the diff

The rest are nitpicks and otherwise claude has done a good job


// Translate
MACRO_CONFIG_STR(TcTranslateBackend, tc_translate_backend, 32, "ftapi", CFGFLAG_CLIENT | CFGFLAG_SAVE, "Translate backends (ftapi, libretranslate)")
MACRO_CONFIG_STR(TcTranslateBackend, tc_translate_backend, 32, "google", CFGFLAG_CLIENT | CFGFLAG_SAVE, "Translate backends (google, ftapi, libretranslate). ftapi's hosting is defunct as of 2026, kept for people running their own instance")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

People running their own stuff will just use libretranslate. You can remove this comment and the ftapi backend

"Finnish", "French", "German", "Greek", "Hebrew", "Hindi", "Hungarian", "Italian",
"Japanese", "Korean", "Polish", "Portuguese", "Romanian", "Russian", "Spanish", "Swedish",
"Thai", "Turkish", "Ukrainian", "Vietnamese"};
static const char *s_apTranslateLanguageCodes[] = {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The backend should determine the language options. Google has many more than libretranslate

for(int i = 0; i < NumTranslateLanguages; i++)
if(str_comp_nocase(pCode, s_apTranslateLanguageCodes[i]) == 0)
return i;
return 5; // Fall back to English if unset or a custom code we don't have a name for

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic number! (don't fix by static asserting english is 5)

};

// Talks directly to Google's free, unofficial (undocumented) translate endpoint.
// This is the same endpoint FreeTranslateAPI (ftapi.pythonanywhere.com, now dead) used to wrap.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Link to the repository or a more alive one

};

{
static std::vector<const char *> s_TranslateBackendNames = {"Google", "FreeTranslateAPI (defunct)", "LibreTranslate"};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These values are duplicated from ibackend::name

{
if(m_vJobs.size() > 15)
{
// Too many jobs in flight, don't make the player wait: send untranslated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

, don't make the player wait
The game is an unrelated concept from the chat

else
SendChatQueued(m_Input.GetString());
{
const char *pMessage = m_Input.GetString();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To reduce diff, make translate outgoing swallow messages like ChatDoSpecId above it

@SollyBunny

Copy link
Copy Markdown
Collaborator

Once you've fixed these please rebase onto master_new

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants