I18n

Supporting different languages

Seyfert has a i18n built-in feature that allows you to create language files and use them in your bot.

For this section we are going to follow the setup we did in Getting Started for example purposes

Updating seyfert config

Before starting this chapter we could update seyfert.config.mjs to tell seyfert where our languages file will be.

seyfert.config.mjs
// @ts-check
import {  } from "seyfert";
 
export default .({
  : .. ?? "",
  : ["Guilds"],
  : {
    : "dist",
    : "commands",
    : "events",
    : "languages" // - src/languages will be our languages directory
  }
});

Creating a language file

Each language file shall export by default an object containing the translations for the language.

languages/en.ts
export default {
  : "Each key value pair will be the translation for the key",
  : {
    : "You may nest objects to create a more complex language file",
    : () => `You may also use functions to pass variables to the translation and add some logic`,
    : ({  }: { : number }) => `The ping is ${}`
  },
  : [
    "You may also use arrays to create a list of translations",
    "This is the second item in the list"
  ].("\n")
}

You can create as many language files as you want, seyfert will load them and they will be available to use in your bot.

languages/es.ts
import type English from "./en";
 
export default {
  hello: "Hola, mundo!",
  foo: {
    bar: "Puedes anidar objetos para crear un archivo de idioma más complejo",
    baz: () => `Puedes usar funciones para pasar variables a la traducción y agregar lógica`,
    ping: ({ ping }) => `El ping es ${ping}`
  },
  qux: [
    "También puedes usar arrays para crear una lista de traducciones",
    "Este es el segundo elemento de la lista"
  ].join("\n")
} satisfies typeof English; // This is a utility type to ensure that object is the same across languages

Each key should return either a string or a function that returns a string.

The name of the file will be the language code, that you will use to get the language translations.

Next we must do some updates to the declare module on index file:

src/index.ts
import type English from './languages/en';
import { Client, type ParseClient, type ParseLocales } from "seyfert";
 
const client = new Client();
 
client.start();
 
declare module 'seyfert' {
  interface UsingClient extends ParseClient<Client<true>> { }
  // interface UsingClient extends ParseClient<HttpClient> { } // If you are using the rest api
 
  interface DefaultLocale extends ParseLocales<typeof English> { }
}

Preventing errors

You can assign a default language to avoid getting undefined.

import {  } from "seyfert";
const  = new ();
// ---cut--- snoopy
.({ : { : 'en-US' } });

You can pass any of the language files to the DefaultLocale interface since they should be the same object structure.

After doing this, you can use the language in your commands, events, components, etc.

Using translations in your commands

Let's see an example with our ping command by adding an option to respond in a specific language

src/commands/ping.ts
import {
  ,
  ,
  ,
  ,
  ,
  type 
} from 'seyfert';
import {  } from 'seyfert/lib/types';
 
const  = {
  : ({
    : "Hide command output",
  }),
  : ({
    : "Language to respond in",
    : [
      { : "English", : "en" },
      { : "Spanish", : "es" }
    ]
  })
}
 
@({
  : 'ping',
  : 'Show the ping with discord'
})
@()
export default class  extends  {
 
  async (: <typeof >) {
    const  = .. ? . : ;
    const  = ..;
 
    // Get the translations for the language
    const  = ..();
 
    // average latency between shards
    const  = ...;
 
    await .({
      : ..({  }),
      ,
    });
  }
 
}

Below is the current file tree of the project if you did follow the previous steps.

src
commands
ping.ts
events
botReady.ts
guildDelete.ts
languages
en.ts
es.ts
index.ts
package.json
seyfert.config.mjs
.env
tsconfig.json

On this page