Right now our bot translates to english the language it detects.

We need to do 2 things now:

1) manually set the from language 2) change the to language

We will provide the users of our bot these 2 commands:

  • /from <language> will change the origin language to a specific one (if nothing is specified, we’ll get back to guessing the from language)
  • /to <language> will translate messages to that language. In this case we don’t allow an empty option.

Let’s do it!

First we add a from command. We look at the parameter passed, and we determine the language we need to set, doing some rough validation for the language code:


bot.command('from', ctx => {
  const lang = ctx.message.text.substring(6)

  if (lang.length > 2 || lang.length === 1) {
    ctx.reply('🤔 language code must be 2 chars, e.g. "en" or "fr"')
    return
  }

  ctx.reply(lang ? '✅ "from" language set to ' + lang : '✅ autodetect "from" language')
})

Then we add this parameter to the context session, which allows us to store some piece of data to the user chat:

const session = require('telegraf/session')
//...
bot.use(session())
//...

bot.command('from', ctx => {
  const lang = ctx.message.text.substring(6)
  //...validation

  ctx.session.from = lang
})

Now we do the same for to. We detect the language code, by using substring() on ctx.message.text, then we do a little bit of validation and we set it to the ctx.session.to property:

bot.command('to', ctx => {
  const lang = ctx.message.text.substring(4)
  if (lang.length === 0) {
    ctx.reply('🤔 please specify a language code! It must be 2 chars, e.g. "en" or "fr"')
    return
  }

  if (lang.length > 2 || lang.length === 1) {
    ctx.reply('🤔 language code must be 2 chars, e.g. "en" or "fr"')
    return
  }

  ctx.session.to = lang
  ctx.reply('✅ "to" language set to ' + lang)
})

In this case, just to be different, we don’t allow an empty value for the to language. We could have defaulted to english.

Last, we must use this language in the on() method which listens for messages, to translate to the correct language.

I use a ternary operator to determine the lang value in a concise way:

const lang = (ctx.session.from ? ctx.session.from + '-' : '') + (ctx.session.to || 'en')

This line means: if there is a from value, add it and add -. If there is no from value, just use the to value, and fallback to en.

Here it is this line in use:

bot.on('message', ctx => {
  const lang = (ctx.session.from ? ctx.session.from + '-' : '') + (ctx.session.to || 'en')
  console.log(lang)
  axios.get('https://translate.yandex.net/api/v1.5/tr.json/translate', {
    params: {
      key: process.env.YANDEX_API_KEY,
      text: ctx.message.text,
      lang: lang
    }
  }).then(res => {
    ctx.reply(res.data.text[0])
  })
})

Sticky session data

There is a problem however, if the program relaunches, the session data is lost.

We can use a session storage middleware to solve this.

There are many options available on npm: https://www.npmjs.com/search?q=telegraf-session

I picked https://www.npmjs.com/package/telegraf-session-local which allows us to save the session to a local file. We’ll store it to .data/session.json in Glitch, as .data is a smart folder that’s not copied over when a project is remixed.

Install telegraf-session-local using npm.

The usage is super simple. Just require it:

const LocalSession = require('telegraf-session-local')

and now instead of calling

bot.use(session())

like we did above, run

bot.use((new LocalSession({ database: '.data/session.json' })).middleware())

This will make sure the session data is stored in the JSON file specified, and now if the app reloads, the session data will stick!

The current bot code is available at https://glitch.com/edit/#!/node-course-project-telegram-bot-a?path=bot.js


Go to the next lesson