QuiiBz / next-international

Type-safe internationalization (i18n) for Next.js
https://next-international.vercel.app
MIT License
1.26k stars 59 forks source link

Incorrect typescript types for parameters using dot notation #197

Closed kristofferso closed 11 months ago

kristofferso commented 11 months ago

Describe the bug Using dot notation for a translation in a Typescript file with parameters ruins the type for the params argument in the t() function. Using object notation works fine. This results in the error Expected 1 arguments, but got 2 from Typescript, which is inferring the parameter types to be never.

To Reproduce Steps to reproduce the behavior:

  1. Add a translation using a dot notation from your default language translation file (only tested with .ts), with a parameter. Example: export default {'welcome.user': 'Hello {name}!'} as const
  2. Use the translation in a React Server Component like a page.tsx:
    export default async function Page(){
    const t = await getI18n();
    ... 
    return <p>{t("welcome.user", {name: "Phil"})}</p>
    }

Expected behavior Expected types for the second argument of t() to show parameter types. Instead it is inferred as never.

About:

QuiiBz commented 11 months ago

I'm not able to reproduce the issue using the example: https://github.com/QuiiBz/next-international/tree/main/examples/next-app

Screenshot 2023-09-28 at 08 29 01

Have you set strict: true inside your tsconfig.json file? You could also try to upgrade your TypeScript version. Otherwise, I'll need a reproduction to check why you're getting this error.

kristofferso commented 11 months ago

Yes, I'm using strict: true. Strangely, when I set it to false all the locale strings complain about missing a required parameter for params. My typescript is 5.2.2 so that shouldn't be the problem I think.

How do I run your example locally? I tried forking the entire repo and running pnpm run dev from examples/next-app but I'm getting an error that it can't find the package next-international/middleware

QuiiBz commented 11 months ago

You have to build packages/next-international and packages/international-types before running the example. You can also check the codesandbox here that doesn't have the issue: https://codesandbox.io/p/sandbox/jovial-paper-skkprk?file=%2Fapp%2F%5Blocale%5D%2Fpage.tsx%3A1%2C1

gustaveWPM commented 11 months ago

Hmmm, I had the same kind of issues with the Expected 1 arguments, but got 2 error. And also something like the missing required argument params.

I think it could be related to an import issue or something like.

Could I see the error details, and also your createI18nClient and createI18nServer functions? I know it is a weird question, but I would like to check something.

gustaveWPM commented 11 months ago

ping @kristofferso ?

gustaveWPM commented 11 months ago

Maybe related: https://github.com/QuiiBz/next-international/issues/231

QuiiBz commented 11 months ago

We'll have to see your createI18nClient / createI18nServer methods to see if it's related to #231 or not. If no response in the next few days, I'll go ahead and close the issue.

kristofferso commented 11 months ago

Sorry about the late response here :(

This is my client.ts:

import { createI18nClient } from 'next-international/client';

export const {
  useI18n,
  useScopedI18n,
  I18nProviderClient,
  useChangeLocale,
  useCurrentLocale,
} = createI18nClient({
  no: () => import('./no'),
  se: () => import('./se'),
});

server.ts

import { createI18nServer } from 'next-international/server';

export const { getI18n, getScopedI18n, getStaticParams, getCurrentLocale } =
  createI18nServer({
    no: () => import('./no'),
    se: () => import('./se'),
  });

I'm not doing anything special as I can see.

kristofferso commented 11 months ago

And here is the error:

Expected 1 arguments, but got 2.ts(2554)
⚠ Error(TS2554)  | 
Expected 1 arguments, but got 2.
bilde

I'll do some more testing with the example repo

kristofferso commented 11 months ago

So I was able to recreate this in the codesandbox example. Just add any type of nesting to the locale file together with a parameter string and you get the error.

Example:

export default {
  hello: "Hello",
  "hello.world": "Hello world!",
  "hello.world.welcome": "Hello {name}!",
  welcome: "Hello {name}!",
  test: {
    anything: "all at once",
  },
} as const;
QuiiBz commented 11 months ago

Thanks, I found that it's because you're mixing dot and object notation at the same time. This sounds like a bug that shouldn't happen so I'll fix it asap, but in the meantime you can use only dot notation or only object notation.

QuiiBz commented 11 months ago

The fix (#236) will be released soon.

QuiiBz commented 11 months ago

Released in next-international@1.1.2!

kristofferso commented 11 months ago

Very nice 👏