mirror of
https://github.com/wekan/wekan.git
synced 2026-11-05 01:20:07 -05:00
fix: notification emails ignored the user's language and were sent in English
On the server only the default (English) translation bundle is loaded at startup. Translating a notification to a user's language called TAPi18n.__(key, params, lang) with lng=lang, but that resource bundle was never added on the server, so i18next fell back to English — every notification email went out in English regardless of the user's profile language. (The client works because switching language calls setLanguage, which loads the bundle.) Add TAPi18n.ensureLanguageLoaded(language), which loads the bundle on demand if i18next does not already have it, and await it before translating in the email notification, EmailLocalization.sendEmail and outgoing webhook paths. Closes #5875 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
e5edb54a53
commit
22f996903b
4 files changed
+23
-1
No files matched your search
@@ -113,6 +113,16 @@ export const TAPi18n = {
|
||||
await this.i18n.changeLanguage(language);
|
||||
this.current.set(language);
|
||||
},
|
||||
// Make sure the resource bundle for `language` is available before a
|
||||
// synchronous __() call. On the server only the default (English) bundle is
|
||||
// loaded at startup, so translating to a user's language (e.g. notification
|
||||
// emails) otherwise silently fell back to English. See #5875.
|
||||
async ensureLanguageLoaded(language) {
|
||||
if (!language || !this.i18n) return;
|
||||
if (!this.isLanguageSupported(language)) return;
|
||||
if (this.i18n.hasResourceBundle(language, DEFAULT_NAMESPACE)) return;
|
||||
await this.loadLanguage(language);
|
||||
},
|
||||
// Return translation by key
|
||||
__(key, options, language) {
|
||||
this.current.dep.depend();
|
||||
|
||||
@@ -34,6 +34,10 @@ const EmailLocalization = {
|
||||
lang = TAPi18n.getLanguage() || 'en';
|
||||
}
|
||||
|
||||
// #5875: ensure the chosen language's bundle is loaded on the server before
|
||||
// translating, otherwise __() falls back to English.
|
||||
await TAPi18n.ensureLanguageLoaded(lang);
|
||||
|
||||
// Translate subject and text using the determined language
|
||||
const subject = TAPi18n.__(options.subject, options.params || {}, lang);
|
||||
let text = options.text;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Notifications } from '/server/notifications/notifications';
|
||||
|
||||
// buffer each user's email text in a queue, then flush them in single email
|
||||
Meteor.startup(() => {
|
||||
Notifications.subscribe('email', (user, title, description, params) => {
|
||||
Notifications.subscribe('email', async (user, title, description, params) => {
|
||||
try {
|
||||
if (
|
||||
!user ||
|
||||
@@ -19,6 +19,11 @@ Meteor.startup(() => {
|
||||
return;
|
||||
}
|
||||
|
||||
// #5875: the server only loads the English bundle at startup, so make sure
|
||||
// the recipient's language is loaded before translating the subject/body —
|
||||
// otherwise notification emails silently fall back to English.
|
||||
await TAPi18n.ensureLanguageLoaded(user.getLanguage());
|
||||
|
||||
// add quote to make titles easier to read in email text
|
||||
const quoteParams = { ...params };
|
||||
['card', 'list', 'oldList', 'board', 'comment'].forEach(key => {
|
||||
|
||||
@@ -135,6 +135,9 @@ Meteor.methods({
|
||||
if (!user || typeof user.getLanguage !== 'function') {
|
||||
return;
|
||||
}
|
||||
// #5875: load the recipient's language bundle on the server before
|
||||
// translating, otherwise it falls back to English.
|
||||
await TAPi18n.ensureLanguageLoaded(user.getLanguage());
|
||||
const descriptionText = TAPi18n.__(
|
||||
description,
|
||||
quoteParams,
|
||||
|
||||
Reference in new issue
Block a user