QuiiBz / next-international

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

usage within a client component inside called inside of a server rendered page #223

Closed JacerOmri closed 11 months ago

JacerOmri commented 11 months ago

Hello,

Is there a way to use translations inside of a client component without having to use a client layout? I couldn't get it to work unless the whole page is a client component. I tried wrapping each individual client component into the client provider but didn't work. Am I missing something or is this by design?

Thank you for the awesome project!

JacerOmri commented 11 months ago

update: this didn't work

'use client';

import { useUser } from '@auth0/nextjs-auth0/client';
import { useRouter } from 'next/navigation';
import UserProfileLogged from './user-profile-logged';
import UserProfileUnlogged from './user-profile-unlogged';
import { I18nProviderClient, useI18n } from '@acme/web/locales/client';

/* eslint-disable-next-line */
export interface UserProfileProps {}

export function UserProfile(props: UserProfileProps) {
  const router = useRouter();
  const { user, error, isLoading } = useUser();
  const t = useI18n();

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>{error.message}</div>;

  return (
    <I18nProviderClient>
      <p>{t('hello.world')}</p>
      {(user && (
        <UserProfileLogged
          user={user}
          onLogout={() => router.push('/api/auth/logout')}
        ></UserProfileLogged>
      )) || (
        <UserProfileUnlogged
          onLogin={() => router.push('/api/auth/login')}
        ></UserProfileUnlogged>
      )}
    </I18nProviderClient>
  );
}

export default UserProfile;

but this worked:

'use client';

import { useUser } from '@auth0/nextjs-auth0/client';
import { useRouter } from 'next/navigation';
import UserProfileLogged from './user-profile-logged';
import UserProfileUnlogged from './user-profile-unlogged';
import { I18nProviderClient, useI18n } from '@acme/web/locales/client';

/* eslint-disable-next-line */
export interface UserProfileProps {}

export function UserProfile(props: UserProfileProps) {
  const router = useRouter();
  const { user, error, isLoading } = useUser();
  const t = useI18n();

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>{error.message}</div>;

  return (
    <>
      <p>{t('hello.world')}</p>
      {(user && (
        <UserProfileLogged
          user={user}
          onLogout={() => router.push('/api/auth/logout')}
        ></UserProfileLogged>
      )) || (
        <UserProfileUnlogged
          onLogin={() => router.push('/api/auth/login')}
        ></UserProfileUnlogged>
      )}
    </>
  );
}

export default (props: UserProfileProps) => {
  return (
    <I18nProviderClient>
      <UserProfile {...props}></UserProfile>
    </I18nProviderClient>
  );
};

Again, I don't know if this is by design, missing feature or just me not knowing to do it correctly.

QuiiBz commented 11 months ago

Is there a way to use translations inside of a client component without having to use a client layout?

Yes, the layout example is only here because it's easier to just wrap your whole app in it.

Your first example doesn't work because you're using useI18n inside a component that then returns I18nProviderClient: your initial component isn't wrapped in I18nProviderClient. You've fixed this in the second example, where the component using useI18n is wrapped by I18nProviderClient.

One thing you can do to have a single I18nProviderClient without having all layouts/pages being client components is https://github.com/QuiiBz/next-international/issues/170#issuecomment-1719794154