【问题标题】:I18Next TFunction translation not working in EJS template renderI18Next TFunction 翻译在 EJS 模板渲染中不起作用
【发布时间】:2026-01-17 04:30:01
【问题描述】:

我有一个渲染 EJS 模板的方法,并通过将 i18next t 函数设置为数据对象的属性来传递 EJS 模板的 i18next.t 函数进行翻译:

const data = {
                email: user.email,
                id: user.id,
                t: i18nT
            };

数据对象被传入ejs.renderFile()。我可以让 EJS 模板中的翻译工作的唯一方法是当我从 i18next.init() 函数回调中将 i18nT 变量设置为 t 函数时。否则它会出现空白。我从控制台输出看到i18next实例的t函数i18nInstance与初始化i18next时回调设置的t函数不同。

function t() {
    var _this$translator;

    return this.translator && (_this$translator = 
       this.translator).translate.apply(_this$translator, arguments);
}

对比:

function () {
    return _this4.t.apply(_this4, arguments);
}

为什么调用 i18next.createInstance() 得到的 i18nInstance 对象的 t 函数与回调中的不同?来自实例对象的那个在 EJS 模板渲染中不起作用。

完整的代码示例:

let i18nInstance: i18n;
let i18nT;

const i18nextInitOptions = {
    backend: {
        loadPath: path.join(__dirname, '/locales/{{lng}}/{{ns}}.json'),
        addPath: path.join(__dirname, '/locales/{{lng}}/{{ns}}.missing.json')
    },
    debug: true,
    fallbackLng: 'da',
    preload: ['da', 'en', 'nl'],
    returnEmptyString: false,
    returnNull: false,
    saveMissing: true
};
i18nInstance = await i18next
    .createInstance();
await i18nInstance
    .use(i18nextBackend)
    .init(i18nextInitOptions, async function (error, t) {
        if (error) {
            console.log(error)
        }
        i18nT = t;
    });


console.log("i18nT: " + i18nT)
/*
The console.log outputs below show that i18nT when set from the callback is different to the 
i18nInstance.t.
i18nT: function () {
  return _this4.t.apply(_this4, arguments);
}
 */

console.log("i18nInstance.t: " + i18nInstance.t)
/*
console output:
i18nInstance.t: function t() {
      var _this$translator;

      return this.translator && (_this$translator = 
         this.translator).translate.apply(_this$translator, arguments);
}
*/

const data1 = {
            email: user.email,
            id: user.id,
            t: i18nT
        };

// Calling htmlFromTemplate with data1 with t = i18nT the translation in the EJS template works.
html = await this.htmlFromTemplate('ejsTemplateName.ejs', data1);

const data2 = {
            email: user.email,
            id: user.id,
            t: i18nextInstance.t
        };

// Calling htmlFromTemplate with data2 with t = i18nextInstance.t the translation in the EJS is empty.
html = await this.htmlFromTemplate('ejsTemplateName.ejs', data2);

private htmlFromTemplate(templateName: string, data: Object): Promise<String> {
        if (!templateName) return;
        const htmlPath = path.join(__dirname, '../assets/mail-templates/' + templateName);
        return new Promise((resolve, reject) => {
            ejs.renderFile(htmlPath, data,(renderErr, str) => {
                if (renderErr) {
                    appLogger.error('MAIL_RENDER: ' + renderErr, { templateName, data });
                    reject(renderErr);
                } else resolve(str);
            });
        });
    }

【问题讨论】:

    标签: ejs i18next


    【解决方案1】:

    只要你像这样传递 t 函数:

        const data2 = {
            email: user.email,
            id: user.id,
            t: i18nextInstance.t
        };
    

    t 函数不再绑定到它原来的“this”...

    这样传递:

        const data2 = {
            email: user.email,
            id: user.id,
            t: i18nextInstance.t.bind(i18nextInstance)
        };
    

    更多信息在这里:https://github.com/i18next/i18next/issues/1528#issuecomment-748263313

    【讨论】: