opral / inlang-paraglide-js

Tree-shakable i18n library build on the inlang ecosystem.
https://inlang.com/m/gerre34r/library-inlang-paraglideJs
23 stars 0 forks source link

Add an optional setting to retrieve translations for all languages instead of one. #107

Closed JoelSatkas closed 2 months ago

JoelSatkas commented 2 months ago

It would be really nice if there was a way to generate message code to get the translation for all languages instead of a single one. Specifically i am looking to get a list of local codes -> name of the language in that language to show for a language selection dialog.

Currently the library generates code like this: image

But im looking for something like this: image

And then whenever a new language is added, the language selection dialog automatically shows the new language based on this generated function.

Maybe this is not how it works but basically im looking for a way to get a translation from all languages instead of just one, without having to hard code the getting of each language.

LorisSigrist commented 2 months ago

Can I ask what you plan to do with the messages once you get them? What does doing this enable you to do?

Also you can emulate this with this helper funciton

function messageMap<P>(
   message : (parms: P , opt: { languageTag : AvailableLanguageTags}) => string
) : Record<AvailableLanguageTags, (params: P)=>stirng> {
   return Object.fromEntries(
      availableLanguageTags.map(languageTag => {
        return [languageTag, (params:P) => message(params, { languageTag })]
      })
   )
}

//example usage
const language_name = messageMap(m.language_name)
language_name.en()
JoelSatkas commented 2 months ago

Can I ask what you plan to do with the messages once you get them? What does doing this enable you to do?

Basically, i am then able to create a language selection component that shows the name of the language in the language itself, instead in local codes. The map has the local code keys for the values to use and the translations will have the language name.

Currently i need to hard code the local -> language name in my component like this:

const m_LanguageTagsToReadableNames: Map<string, string> = new Map([
        ["en", "English"],
        ["zh", "中文"]
    ]);

And then the paraglidJS export of availableLanguageTags is used to get the translation again, but it would be neater if the name of the language was a string inside the languages json file itself. Also then i wouldnt need to update this snippet when a new language is added, a new language json can just be added to the project and the language selector would work, would be super cool.

Also you can emulate this with this helper funciton

Thank you for the suggestion! I was able to get this to work like so:

import {
availableLanguageTags,
languageTag,
setLanguageTag,
type AvailableLanguageTag,
} from "$paraglide/runtime";

function messageMap<P>(
message: (params: P, opt: { languageTag: AvailableLanguageTag }) => string
): Record<AvailableLanguageTag, (params: P) => string> {
return Object.fromEntries(
    availableLanguageTags.map((languageTag) => {
        return [languageTag, (params: P) => message(params, { languageTag })];
    })
) as Record<AvailableLanguageTag, (params: P) => string>;
}

const language_name = messageMap(m.language_name);

// view code:
{#each availableLanguageTags as lang}
<option value={lang} selected={lang === languageTag()}
    >{language_name[`${lang}`]({}) ?? lang}</option
>
{/each}

Which does exactly what i want now, it automatically will add any new languages to the language select component. Thanks!

LorisSigrist commented 2 months ago

Given that the helper seems to cover your use-case I'm going to close this.

We generally want to avoid adding options to the compiler unless they're really necessary. Unless this turns into a common request we likely won't expand the compiler to generate message maps.