Description
Changing AutoTranslate_ServiceProvider while AutoTranslate_Enabled is true does not rebind the message translation callback. New messages keep being sent to the previously selected provider until Auto-Translate is toggled off and on again (or the server restarts).
The failure is invisible in the admin UI: read paths such as autotranslate.getSupportedLanguages resolve the active provider at call time, so the target-language dropdown correctly reflects the new provider while message translation still goes to the old one.
Steps to reproduce
- Set
AutoTranslate_Enabled = true with the default provider (google-translate), no API key.
- Switch
AutoTranslate_ServiceProvider to libre-translate (or any other provider) and configure it correctly.
- Send a message in a channel where another member has auto-translate enabled.
Expected behavior
The message is translated by the newly selected provider.
Actual behavior
The message is handed to the previously selected provider. With an unconfigured Google provider the server logs show (minutes after the provider was switched):
{"level":50,...,"msg":"Error translating message","err":{"type":"Error","message":"Forbidden","stack":"Error: Forbidden\n at GoogleAutoTranslate._translateMessage (app/autotranslate/server/googleTranslate.ts:154:12)..."}}
while at the same time GET /api/v1/autotranslate.getSupportedLanguages correctly requests http://libretranslate:5000/languages.
Toggling AutoTranslate_Enabled off and on immediately fixes it — the next message is translated by the new provider.
Root cause
In apps/meteor/app/autotranslate/server/autotranslate.ts, TranslationProviderRegistry.registerCallbacks() registers the afterSaveMessage callback with the provider instance captured in a closure, under the fixed id autotranslate:
static registerCallbacks(): void {
if (!TranslationProviderRegistry.enabled) {
callbacks.remove('afterSaveMessage', 'autotranslate');
return;
}
const provider = TranslationProviderRegistry.getActiveProvider();
if (!provider) {
return;
}
callbacks.add(
'afterSaveMessage',
(message, { room }) => provider.translateMessage(message, { room }),
callbacks.priority.MEDIUM,
'autotranslate',
);
}
setCurrentProvider() calls registerCallbacks() again after a provider change, but Callbacks.add() in apps/meteor/server/lib/callbacks/callbacksBase.ts is a no-op when a callback with the same id is already registered:
const callbacks = this.getCallbacks(hook);
if (callbacks.some((cb) => cb.id === id)) {
return () => {
this.remove(hook, id);
};
}
So the closure bound to the old provider stays registered. setEnable(false) goes through callbacks.remove, which is why toggling the enabled setting works around it.
Suggested fix
Either remove before re-adding in registerCallbacks():
callbacks.remove('afterSaveMessage', 'autotranslate');
callbacks.add('afterSaveMessage', ...);
or resolve the provider at call time instead of capturing it:
callbacks.add(
'afterSaveMessage',
(message, { room }) => TranslationProviderRegistry.getActiveProvider()?.translateMessage(message, { room }),
callbacks.priority.MEDIUM,
'autotranslate',
);
The second variant also removes the ordering sensitivity between the AutoTranslate_ServiceProvider and AutoTranslate_Enabled settings watchers at startup.
Possibly related
#41100 (DeepL AutoTranslate not working after upgrade to 8.5.1) may share this root cause if the provider or enabled settings were changed at runtime.
Server setup information
- Version of Rocket.Chat Server: 8.6.0 (bug also present on current
develop, apps/meteor/app/autotranslate/server/autotranslate.ts @ 2f91e02)
- License Type: Community
- Number of Running Instances: 1 (monolith)
- DB Replicaset Oplog: enabled
- NodeJS Version: bundled (official docker image
registry.rocket.chat/rocketchat/rocket.chat:8.6.0)
- MongoDB Version: 8.2
Additional context
Reproduced with Google → LibreTranslate, but the mechanism is provider-agnostic.
Description
Changing
AutoTranslate_ServiceProviderwhileAutoTranslate_Enabledis true does not rebind the message translation callback. New messages keep being sent to the previously selected provider until Auto-Translate is toggled off and on again (or the server restarts).The failure is invisible in the admin UI: read paths such as
autotranslate.getSupportedLanguagesresolve the active provider at call time, so the target-language dropdown correctly reflects the new provider while message translation still goes to the old one.Steps to reproduce
AutoTranslate_Enabled = truewith the default provider (google-translate), no API key.AutoTranslate_ServiceProvidertolibre-translate(or any other provider) and configure it correctly.Expected behavior
The message is translated by the newly selected provider.
Actual behavior
The message is handed to the previously selected provider. With an unconfigured Google provider the server logs show (minutes after the provider was switched):
while at the same time
GET /api/v1/autotranslate.getSupportedLanguagescorrectly requestshttp://libretranslate:5000/languages.Toggling
AutoTranslate_Enabledoff and on immediately fixes it — the next message is translated by the new provider.Root cause
In
apps/meteor/app/autotranslate/server/autotranslate.ts,TranslationProviderRegistry.registerCallbacks()registers theafterSaveMessagecallback with the provider instance captured in a closure, under the fixed idautotranslate:setCurrentProvider()callsregisterCallbacks()again after a provider change, butCallbacks.add()inapps/meteor/server/lib/callbacks/callbacksBase.tsis a no-op when a callback with the same id is already registered:So the closure bound to the old provider stays registered.
setEnable(false)goes throughcallbacks.remove, which is why toggling the enabled setting works around it.Suggested fix
Either remove before re-adding in
registerCallbacks():or resolve the provider at call time instead of capturing it:
The second variant also removes the ordering sensitivity between the
AutoTranslate_ServiceProviderandAutoTranslate_Enabledsettings watchers at startup.Possibly related
#41100 (DeepL AutoTranslate not working after upgrade to 8.5.1) may share this root cause if the provider or enabled settings were changed at runtime.
Server setup information
develop,apps/meteor/app/autotranslate/server/autotranslate.ts@ 2f91e02)registry.rocket.chat/rocketchat/rocket.chat:8.6.0)Additional context
Reproduced with Google → LibreTranslate, but the mechanism is provider-agnostic.