Alexandre-Fernandez / astro-i18n

A TypeScript-first internationalization library for Astro.
https://www.npmjs.com/package/astro-i18n
MIT License
249 stars 10 forks source link

l function doesn't translate back to default lang & l & t functions ts error on generic string argument with generated types and astroI18n object has no generated types #1

Closed narduin closed 1 year ago

narduin commented 1 year ago

Hello!

First of all a huge thank you for this plugin. I've been searching and trying to make a multilingual astro site for months! This is by far the simplest way to make i18n work with astro so again, thanks a lot!


Now, I've been trying to implement a way to switch the language of a website from a link in the header, and be taken to the equivalent page in another locale.

I feel like I'm almost there but can't figure out the last part. So far, what's missing is the ability to get the current route name and to navigate to its other languages alternatives.

Here is my component ```astro --- // LanguageSwitcher.astro import { l, astroI18n } from "astro-i18n"; // get the locale currently in use const currentLocale = astroI18n.langCode; // get all the locales available on the website and remove the one currently in use const availableLocales = astroI18n.langCodes.filter( (locale) => locale !== currentLocale ); ---
    { // create a list of available alternative locales availableLocales.map((locale) => (
  • // first parameter is supposed to be a dynamic route name {locale}
  • )) }
```

Using a static route like /articles and having two locales fr (default) and en is working. I can switch from /articles to /en/blog and vice versa. I just can't find a way to do it dynamically.

Also, I can't make it work for the root index page with /

I'm using the folder structure for i18n implementation ```bash index.astro i18n en.json fr.json articles index.astro i18n en.json fr.json ```

Maybe this is not something this module is supposed to be doing, I'm coming from nuxt-i18n where I was able to use a function to navigate to the page:

switchLocalePath() ```vue {{ locale.name }} ```

Any idea on how to make this work? Thanks!

Alexandre-Fernandez commented 1 year ago

Thanks, I didn't include a language switch component because it was difficult to make one that would fit everyone needs. Here's how you can do it :

const routesToSwitchLanguage = astroI18n.langCodes
    .filter(langCode => langCode !== astroI18n.langCode) // optional (excludes current language)
    .map(langCode => l(Astro.url.pathname as any, {}, {}, langCode as any))

However as you can see, with my generated types, I had to use any. I didn't think of this scenario when generating the types, I will try to fix it when I get some time.

narduin commented 1 year ago

Thank you for this! I had tried with Astro.url.pathname but thought it was not the right thing to use because translated routes like articles in french becoming blog in english would not work. Once on /en/blog, I can't go back to /articles, only to /blog. I guess I need to keep articles for both 😄

However, your example throws an error when trying to access the root index /en. I had the same error in some trials I made, don't really know why though…

Cannot read properties of undefined (reading 'endsWith')
/node_modules/.pnpm/astro-i18n@1.1.7/node_modules/astro-i18n/dist/src/index.mjs:13:8731
Alexandre-Fernandez commented 1 year ago

I'm looking into the error, I managed to reproduce it. As for the first part of your comment, I didn't understand what you mean. The l function should translate /fr/articles into /en/blog, if that's the translation you have set in your routeTranslations.

narduin commented 1 year ago

I tried having my route translations inside routeTranslations as well as in en.json with

"{route}": "blog"

But I'm getting the same result:

  1. from root index / -> /articles (static menu link)
  2. from /articles -> /en/blog (lang switcher)
  3. from /en/blog -> /blog which is a 404 (lang switcher)

I'm going to make a small repo available for reproduction for you (and to see if it's not coming from an error eslwhere in my code).

Alexandre-Fernandez commented 1 year ago

I found where the error comes from I will try to fix it today since it's pretty urgent.

Concerning the route translations assuming en is your defaultLangCode : Using astro.i18n.config file :

export default {
  defaultLangCode: "en",
  supportedLangCodes: ["fr"],
  routeTranslations: {
    fr: {
      blog: "articles"
    }
  }
}

Or using page route translations:

// pages/en/blog/i18n/fr.json
{
  "{route}": "articles"
}

Did you try it like this ?

Alexandre-Fernandez commented 1 year ago

I just patched this error out in version 1.1.8, thanks for reporting.

Cannot read properties of undefined (reading 'endsWith')
/node_modules/.pnpm/astro-i18n@1.1.7/node_modules/astro-i18n/dist/src/index.mjs:13:8731

I'm leaving this issue open for your potential bug with routeTranslations and also because generated types need to be changed to not error on l or t string parameters, also the astroI18n object should also be typed.

narduin commented 1 year ago

Hey, I made a small codesandbox reproduction of my problem. I can add you as editor if you provide an email (privately of course).

I hope I did not make a mess with the configuration. Initially, I had the <I18nProvider> only in my template. I tried to use it inside pages and components but no luck…

Alexandre-Fernandez commented 1 year ago

You can navigate to the /en root index but can't go back to the fr.

I just fixed this in 1.1.9.

You can navigate to /articles and switch to /en/blog but can't go back to articles, the link becomes /blog.

I'm looking into this. EDIT: It looks like this is happening because you use the I18nProvider in your component, try using it only as a wrapper to your page. The I18nProvider is meant to be used only once per request at the root level of your application.

narduin commented 1 year ago

I used to put <I18nProvider> in the layout around all the html but it made some weird auto-formating when saving. I tried putting it around the body but the bug persists. Am I not supposed to put it in the layout?

Alexandre-Fernandez commented 1 year ago

I fixed the typescript issues in 1.2.0. Concerning the /blog issue, it's happening because right now the l function doesn't translate back to the default language. This is actually by design, this function was originally made to create translated links from your default language routes. However it is an oversight because language switching should be supported. I'll add this feature as soon as possible.

narduin commented 1 year ago

Thanks a lot for all this, it's awesome!

Alexandre-Fernandez commented 1 year ago

Fixed in 1.3.0, don't hesitate to report any further bugs if you find any. I removed the query string argument from the l function I added a helper to replace it instead: appendQueryString.