muse icon indicating copy to clipboard operation
muse copied to clipboard

Localization support

Open udany opened this issue 4 years ago • 13 comments

I'm opening this issue more as a discussion/proposal to see how you'd feel about that

Since it's a self-hosted bot I was thinking it would be pretty cool to be able to change the messages it sends, either to translate them or just as a customization option.

So I did a little work and implemented a very bare bones solution, but before moving forward I'd like to hear your thoughts about it :D

udany avatar Sep 14 '21 16:09 udany

I think this is a great idea! You could then have a "southern" Muse or something instead of just midwestern 😛.

Would be happy to look over a PR implementing this. I would expect a few things:

  • A standard library for internalization / localization is used, doesn't make sense to roll our own
  • Allow bundling multiple localization files with Muse for different personalities / languages
  • Allow a user to load a custom localization file

codetheweb avatar Sep 14 '21 17:09 codetheweb

I did some benchmarking and most i18n libs either:

  • Don't have good ts typings
  • Aren't well mantained
  • Are overly focused on frontend usage (even being bound reac/vue/etc)

So I was thinking, since the bots needs are rather well contained, couldn't we just use simpler code? Something like:

interface MuseLocale {
  loadingMessageIcons: string[];
  loadingMessage: string;
  doneMessage: string;
  leaveMessage: string;

  addedSongsMessage: (songs: QueuedSong[], addToFrontOfQueue: boolean, extraMsg: string) => string;

  skipMessage: (skipCount: number) => string;
  ...
}

Then locale files could just implement the interface:

export const baseLocale: MuseLocale = {
  loadingMessage: 'cows! count \'em',
  loadingMessageIcons: ['🐮', '🐴', '🐄'],
  doneMessage: 'u betcha',
  leaveMessage: 'u betcha',

  addedSongsMessage: (songs: QueuedSong[], addToFrontOfQueue: boolean, extraMsg: string) => {
    const firstSong = songs[0];

    if (songs.length === 1) {
      return `u betcha, **${firstSong.title}** added to the${addToFrontOfQueue ? ' front of the' : ''} queue${extraMsg}`;
    }

    return `u betcha, **${firstSong.title}** and ${songs.length - 1} other songs were added to the queue${extraMsg}`;
  },

  skipMessage: () => 'keep \'er movin\''
};

udany avatar Sep 14 '21 23:09 udany

Hmm, I didn't consider cases where there's dynamic content injected into strings as you pointed out. Looks like various localization libraries support that, but we'd still have to potentially load a user provided JS/TS file at runtime...

I would be ok doing our own solution as long as it's typesafe and warns users if their file is missing translations. I don't really have any experience with transpiling TS at runtime so you're on your own there. 😛

codetheweb avatar Sep 15 '21 17:09 codetheweb

A few other thoughts I had about localization:

  • Not sure how other bots handle this, but might be nice if commands (.e.g .play) were localized as well
  • Would be cool to allow users to add custom soundbites for their localization (things like packers)

codetheweb avatar Sep 16 '21 13:09 codetheweb

Did anything happen with this? I would like to customise the text

samrudd avatar Sep 03 '22 09:09 samrudd

Intl.MessageFormat and a simple JSON config could be used, I could implement this if this is fine as an implementation.

lang/en-US.json:

{
    "skip": "u betcha, **{title}** was skipped"
    // etc
}

Intl.MessageFormat also allows for language plurality. For example:

new Intl.MessageFormat(
  `You have {numPhotos, plural,
      =0 {no photos.}
      =1 {one photo.}
      other {# photos.}
    }`,
  'en-US'
).format({numPhotos: 1000})
// Result: You have 1,000 photos.

zoeleu avatar Oct 23 '22 00:10 zoeleu

I don't think the JSON solution would be type-safe. We do transpile TS at runtime now though, so that's no longer an issue.

codetheweb avatar Oct 23 '22 01:10 codetheweb

I don't think the JSON solution would be type-safe. We do transpile TS at runtime now though, so that's no longer an issue.

I could make a typescript file as constants

zoeleu avatar Oct 23 '22 02:10 zoeleu

Sounds good to me!

codetheweb avatar Oct 23 '22 02:10 codetheweb

just now i am starting to work on this and i realize this is probably not the best approach

is something like i18next doable? since messages wont change i dont see a point in making very strict typing for this

zoeleu avatar Nov 28 '22 17:11 zoeleu

Yeah, i18next is fine with me as long as there's an easy way for users to provide their own translations.

codetheweb avatar Nov 29 '22 02:11 codetheweb