museofficial / muse

🎧 a self-hosted midwestern Discord music bot that doesn't suck
MIT License
865 stars 224 forks source link

Localization support #319

Open udany opened 3 years ago

udany commented 3 years ago

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

codetheweb commented 3 years ago

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:

udany commented 3 years ago

I did some benchmarking and most i18n libs either:

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\''
};
codetheweb commented 3 years ago

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 commented 3 years ago

A few other thoughts I had about localization:

samrudd commented 2 years ago

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

zoeleu commented 1 year ago

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.
codetheweb commented 1 year ago

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.

zoeleu commented 1 year ago

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

codetheweb commented 1 year ago

Sounds good to me!

zoeleu commented 1 year ago

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

codetheweb commented 1 year ago

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

Toarulle commented 4 months ago

Has anyone implemented this in a working way yet? :) Very interested in making my bot "roleplay" specific characters hehh.

zoeleu commented 4 months ago

Has anyone implemented this in a working way yet? :) Very interested in making my bot "roleplay" specific characters hehh.

sorry, stopped working on it, should be easy to implement though