grammyjs / grammY

The Telegram Bot Framework.
https://grammy.dev
MIT License
2.17k stars 110 forks source link

Updating i18n locale files at runtime #525

Closed awohsen closed 7 months ago

awohsen commented 7 months ago

Hey there,

I'm implementing a new feature which allows bot admins to be able to change bot texts and/or adding new languages to the bot. However for this to work (changes to key-values at locale files get applied), bot needs to restart.

Is there any hacks or possible solution to this? Thanks a lot.

KnorpelSenf commented 7 months ago

You can

That way, your bot will always automatically use the latest strings, and you do not even need to restart anything.

awohsen commented 7 months ago

Thanks for reply, I tried this:

const localesPath = `${process.env.DATA_PATH}/locales`;

if (!existsSync(localesPath)) {
  this.log.info(
    "No data/locales folder found! creating one from ./locales folder"
  );
  cpSync("locales", localesPath, {
    recursive: true,
  });
}
this.i18n.loadLocalesDirSync(localesPath);
// this.tg.use(this.i18n);
this.tg.lazy(this.i18n.middleware);

But receiving this error:

Unknown error: TypeError: Cannot read properties of undefined (reading 'fluent')
    at middleware (/node_modules/@grammyjs/i18n/script/src/i18n.js:102:32)
    at /node_modules/grammy/out/composer.js:530:38
    at /node_modules/grammy/out/composer.js:51:41
    at /node_modules/grammy/out/composer.js:61:19
    at /node_modules/@grammyjs/conversations/out/conversation.js:272:15
    at /node_modules/grammy/out/composer.js:51:41
    at /node_modules/grammy/out/composer.js:61:19
    at /node_modules/grammy/out/convenience/session.js:65:15
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async /node_modules/grammy/out/composer.js:61:13

Perhaps I've misplaced middleware factory required for lazy loading

middleware(): MiddlewareFn<C & I18nFlavor>
KnorpelSenf commented 7 months ago

Check out the example in the API ref: https://deno.land/x/grammy@v1.20.3/mod.ts?s=Composer&p=prototype.lazy

I was referring to

let i18n: I18n;

async function initI18n() {
  i18n = new I18n(..);
  // do setup here
}

await initI18n();
bot.lazy(() => i18n)

// when translations update, just call
await initI18n();
// again
awohsen commented 7 months ago

Works perfectly, thanks a lot!