Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translations do not work on the first render of Client component when used in Layout #75

Open
bluelakee02 opened this issue Oct 20, 2023 · 9 comments
Labels
bug Something isn't working

Comments

@bluelakee02
Copy link
Contributor

What version of this package are you using?
2.6.1

What operating system, Node.js, and npm version?
latest

I have created a code sandbox
link
just go there and type /test to the end of url of the app and hit Enter

as a temporary solution I am using this workaround:
const label = globalThis.__NEXT_TRANSLATE__ ? t(href) : fallbackImportedJSON[href];

because NEXT_TRANSLATE is missing on the first render

I tried to look at the code, but could not find a solution.

Are you willing to submit a pull request to fix this bug?
yes

@bluelakee02
Copy link
Contributor Author

@aralroca I think it is very common use case, since you will want to have Navigation component in the layout. And it has to be a client component since it is using Link component.

@aralroca
Copy link
Owner

Thanks to report it @bluelakee02. Looks weird, is rendering the children before the provider.

Plugin code:

return <AppDirI18nProvider lang={__lang} namespaces={namespaces} config={JSON.parse(JSON.stringify(config))}><${pageVariableName} {...props} /></AppDirI18nProvider>

Logs:

Screenshot 2023-10-21 at 11 46 22

@aralroca aralroca added the bug Something isn't working label Oct 21, 2023
@bluelakee02
Copy link
Contributor Author

bluelakee02 commented Oct 21, 2023

@aralroca well, after some testing, I think it is caused by this:

${routeType !== '/page'
// Related with https://github.com/aralroca/next-translate/issues/1090
// Early return to avoid conflicts with /layout or /loading that don't have detectedLang
? `if (globalThis.__NEXT_TRANSLATE__ && !detectedLang) return <${pageVariableName} {...props} />`
: ''
}

@aralroca
Copy link
Owner

This templateRCCPage is only executed on client pages (RCCPage = React Client Component Page), but it's not the case because your layout is RSCPage.

@bluelakee02
Copy link
Contributor Author

bluelakee02 commented Oct 21, 2023

@aralroca sorry, I linked wrong part - the same code is also in RSCPage

@bluelakee02
Copy link
Contributor Author

@aralroca

${routeType !== '/page'
// Related with https://github.com/aralroca/next-translate/issues/1090
// Early return to avoid conflicts with /layout or /loading that don't have detectedLang
? `if (globalThis.__NEXT_TRANSLATE__ && !detectedLang) return <${pageVariableName} {...props} />`
: ''
}

but I think it is not necessary now since

Dynamic Segments are passed as the params prop to layout, page, route, and generateMetadata functions.

https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes#convention

@bluelakee02
Copy link
Contributor Author

@aralroca yeah, but the new next is acting weird when using [lang] in the app directory

@bluelakee02
Copy link
Contributor Author

bluelakee02 commented Nov 2, 2023

@aralroca I have made a custom solution that works on app dir nextjs 13

  1. there are jsons with translations
  2. those are attached on server's globalThis in the root layout and send to the context provider
  3. provider sets it on client's globalThis, so client uses global this and context as a fallback
  4. in page, loading, error components it is necessary use useLocalesAsync for either server's globalThis or make a dynamic import like this
export const useLocales = ( (...) // this is for client

(...)

export const useLocalesAsync = async (nameSpace: string, lang = DEFAULT) => {
	if (typeof globalThis !== "undefined" && globalThis.__YOU_NAME_IT__) {
		console.info("using globalThis on the server");
		return globalThis.__YOU_NAME_IT__[nameSpace];
	}

	const res = await import(`./../../locales/${lang}/${nameSpace}.json`)
		.then((module) => module.default)
		.then((result) => result)
		.catch((error) => {
			console.error(error);
			return { notFound: "not found translation" };
		});

	if (res) {
		console.info("using import on the server");
		return res;
	}

Routing is done via middleware, I have just one language at the moment but planning to use ?lang=secondLang in the future

if you are interested I would suggest to make a lightweight package targeted on app router usage doing just this, it is the only way I made it work and be stable for production app. I could prepare it and you would think about how to intergrate with current solution.

@kristian240
Copy link

Any update on this one @aralroca? It would be really helpful if we can create a test suite for this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants