-
-
Notifications
You must be signed in to change notification settings - Fork 206
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
[DISCUSSION] How to evolve to 1.0.0 #129
Comments
Great! I've played with similar ideas for a while. My thoughts:
With this approach even static routes as
So, maybe application needs "unknown" language state for this case with upd: brain-dumped ideas here — https://github.com/lastw/next-multilanguage-ssg-example (demo: https://next-multilanguage-ssg-example.now.sh/) |
@lastw thank you a lot for your feedback!!
That's a good idea to avoid to use a HOC in each page. I like it. So we can start simplifying using one HOC over
Right now I'm not understanding well the problem. I think tomorrow I'm going to experiment with it to reproduce this problem in order to understand it well. As I understand the if (router.isFallback) {
return <div>Loading the page...</div>
} I didn't understand what you mean with
Thanks a lot for sharing this ❤️ |
For single-language website this is solution, check With multiple languages on the build phase there will be generated only one page for all languages:
As |
Apologies in advance if this is not the best place to ask, and congrats for all the work so far. For 1.0.0 are you guys planning adding support for fully localized routes? eg:
(note that absence of a locale prefix in the URL path) The reason behind this kind of routing is often SEO, which is one of the things that attracts many to Next.js in the first place. It would be great if we found a way to achieve this that also supported SSG (and the new SPR). Thank you! |
I'd like to see an example of how dynamic routes would work with |
I have an example page using I just need to figure out how to handle unsupported languages. |
I figured out how to handle unsupported languages with gSSP: justincy@2598b75#diff-bf033b67d0d5f822460e19faed094669 |
How are you guys going about language detection? I've got the Tutorbook site setup such that requests to non-localized URLs (e.g. In rewrites() {
return [
{
// We redirect the user to their appropriate locale directory based on
// their browser request cookies (via the `/api/redirect` endpoint).
// @see {@link https://github.com/tutorbookapp/covid-tutoring/issues/35}
source: '/',
destination: '/api/redirect',
},
{
// Don't redirect if there's a locale already in the requested URL. We
// also don't redirect if the browser's just trying to fetch favicons.
// @see {@link https://github.com/UnlyEd/next-right-now/pull/42}
// @see {@link https://github.com/pillarjs/path-to-regexp/issues/223}
source: `/:locale((?!${locales.join('|')}|favicon)[^/]+)(.*)`,
destination: '/api/redirect',
},
];
}, In /**
* Redirects to a locale based on the HTTP request `Accept-Language` header.
* This API endpoint is called via the experimental Next.js rewrites feature
* (see the `next.config.js` file in the root of this repository).
*
* @example `/` => `/fr`
* @example `/search` => `/de/search`
* @example `/end` => `/en/end`
*
* @see {@link https://github.com/zeit/next.js/issues/9081}
* @see {@link https://github.com/UnlyEd/next-right-now/pull/42}
* @see {@link https://github.com/tutorbookapp/covid-tutoring/issues/35}
*/
export default function redirect(
req: NextApiRequest,
res: NextApiResponse<void>
): void {
const locale: string =
parser.pick(locales, req.headers['accept-language'] || '') || defaultLocale;
console.log(`[DEBUG] Redirecting to locale (${locale})...`);
res.statusCode = 302;
res.setHeader('Location', `/${locale}${req.url}`);
res.end();
console.log(`[DEBUG] Redirected '${req.url}' to '/${locale}${req.url}'.`);
} Once they're redirected, all See this issue for more info on how I got that all setup. |
Another thing to think about @aralroca is how you'll provide automatic static optimization when adding the For example, let's say I want a dashboard to be at But, by adding a The best solution to that problem IMO is to add a helper that lets you use static optimization and then takes care of fetching static JSON translations and updating the |
I just opened this issue in the Next.js repository that should address the static optimization problem described above. |
I just wrote a proposal to simplify i18n. Feedbacks are welcome! |
I hope I understood you correctly, @javiercr . But actually including the locale prefix in the URL is better for SEO. URLs without language prefixes confuse Google and are advised against. Instead of subdirectories, you can use subdomains or TLDs, but relying only on cookies or accept-language headers is a bad idea. source: https://support.google.com/webmasters/answer/182192?hl=en |
We actually use different TLDs (domains) for each locale, and all of them point to the same Next.js app. In our case, it's the either the host (domain) or the path string (
Does that make sense? :) |
Hi @aralroca and all, I've been working on this i18n example: https://github.com/omarryhan/nextjs-i18n-example the past couple of days. It builds on the work done in with-dynamic-routes example as well as other examples from the Next.js community. 1, 2. You can read about the differences in the README. However, I want to highlight one particular pain point that I can't find a very good solution for. That is loading the translations for You might ask, why even load them in the As a temporary workaround I wrote a function that loads all the translation JSON files found in the translations (locale) folder and passes them as props to the page. But this will significantly increase the bundle size of your app very quickly because it loads all the translations of all pages. Needless to say, it's not a very sustainable solution. I would love to hear your thoughts on that or any potential solutions. I mentioned this here, because I think this is a discussion that must be discussed for this library as well. Also, I'd prefer to use a lightweight library like this one rather than roll my own i18n logic from scratch. |
I just had an idea regarding the pain point I mentioned in my comment above. Instead of either having to:
We can export a e.g. // pages/index.jsx
import FooComponent, { neededTranslations as neededTranslationsFooComponent } from './components/FooComponent/';
export default = () => (
<FooComponent />
)
export const getServerSideProps = async ({
params,
}) => ({
props: {
...await getI18nProps({
language: params?.language as string,
paths: [
...neededTranslationsFooComponent
],
}),
},
}); // components/FooComponent.jsx
import BarComponent, { neededTranslations as neededTranslationsBarComponent } from './BarComponent';
const neededTranslations = 'components/FooComponent'
export default () => {
const { t } = useTranslations(neededTranslations);
return (
<div>
foo
<BarComponent />
</div>
)
);
export const neededTranslations = [
neededTranslations,
...neededTranslationsBarComponent
] // components/BarComponent.jsx
export default () => (
<p>
bar
</p>
)
export const neededTranslations = [
'components/BarComponent'
] An alternative would be: Instead of exporting // components/FooComponent.jsx
const Component = () => (
<p>
foo
</p>
)
Component.neededTranslations = [
'components/FooComponent'
]
export default Component; Unfortunately Typescript won't allow you to do this, because you can't attach custom properties to the I Would love to hear your thoughts. Also, I would love to hear your thoughts about the way I am structuring the namespaces themselves. For those who didn't see the example I mentioned above, I am structuring the namespace tree identically to the way you structure your components and pages. Here's an example
I think this way is more natural and more suited to React (and component based frameworks in general). |
@omarryhan maybe adding one file (i18n.json) at the component's root instead of having multiple files in a separate folder:
|
I like that better. But where do you keep the translations for pages? Maybe in a special |
maybe something like this will do it, nextjs don't generate a page for i18n.json, and a (my-page/index.tsx is equivalent to my-page.tsx):
|
About having one file instead of multiple, if you do that, you won't be able to tree shake the translations. So, for every page you load, you'll have to download all the translations in all languages for that particular page. About the structure itself, I think it will get messy pretty quickly to not have the translations in a dedicated translations folder. Especially if you have more than 2 languages. On the other hand, if you put them in a translations folder, the Next.js router might create a page for it, not sure though. Another solution is to strictly only translate components, but that's a bit prohibitive imo. |
Any progress on this? Would be great to be able to dynamically generate locale routes rather than using a custom build step. Another alternative to a |
A new open RFC about i18n in Next.js is open, this time from the Next.js team: vercel/next.js#17078 Version 1.0 of this library will conform 100% to the final implementation of this RFC. |
it might make sense to talk to @ijjk about this. Whether they/he are/is already at the point, that |
🚨 NEWS! I adapted under I updated the examples of the repo according to adapt the breaking changes. I tried to add backwards compatibility to almost every change + I think this is the first step for version 1.0.0. In 0.19.0 we will still have the "build step" but much more adapted to the next.js way and it is only used to encapsulate the namespaces on each page. |
It would be great if somebody can try version 0.19.0-experimental.6 to see how everything works in real projects. Now what I need is some feedback from people, if I see that several people can migrate their projects successfully then I will probably do the 0.19 release (That is a big step before 1.0). I have updated the examples: https://github.com/vinissimus/next-translate/tree/i18n-routing/examples Thanks a lot! |
I added a new example in the repo; without the "build step" and without the https://github.com/vinissimus/next-translate/tree/master/examples/without-build-step I think it can also be a good alternative, although it requires a little more configuration it's not a big headache. However, as I understood, the Next.js the next step they will do after i18n routing will be to load translations, so maybe for now it's worth keeping the "build step" because it's the simplest way, and when this will be done, we will release the 1.0.0 without the build step. |
Proposal: #303 |
About this proposal: If someone wants to experiment, I did a first experimental version under This experimental version has:
Things are still missing, so several things may still fail, but I prefer you to experiment it, and if you find something, report it here (please don't do PR yet to that branch). |
https://github.com/vinissimus/next-translate/blob/master/src/I18nProvider.js#L80 |
@popuguytheparrot can you explain it a little bit further, maybe with an example. Sorry but I didn't understand It. |
Call useRouter in parent(_app) and call again in I18nProvider. export default function MyApp({ Component, pageProps }) {
const router = useRouter();
return (
<I18nProvider lang={router.locale} namespaces={pageProps._ns}>
<Component {...pageProps} />
</I18nProvider>
</>
);
} export default function I18nProvider({
lang: lng,
namespaces = {},
children,
logger = missingKeyLogger,
}) {
const { locale } = useRouter() || {} |
Ah @popuguytheparrot , you say that because of the example in the repo: https://github.com/vinissimus/next-translate/blob/master/examples/without-build-step/pages/_app.js It's funny, I encourage you to try the example and eliminate the "lang" of the However, in the |
The migration guide to 1.0.0 is still available on https://github.com/vinissimus/next-translate/blob/1.0.0-experimental/docs/migration-guide-1.0.0.md (replacing the version to the latest experimental prerelease it should work). Everything is already quite stabilized, in a short time we will surely go from the experimental version to the canary, since it looks like we will finally evolve around here. And I hope that the final version 1.0.0 will be available in December. It would help a lot if you could try the latest prerelease and report possible problems; things in the documentation, issues... 🙏 |
Can someone who has windows confirm that it works well in the development environment? |
is it possible to type locales with this feature? |
Yes @popuguytheparrot . And feel free to PR. I don't really have much experience with TypeScript and I'm sure you can do much better than I. |
I did a short demo video about 1.0:
I hope you find this useful 😊 (sorry my English) |
It doesn't work with nextjs 10 and SSG (static export). |
@aralroca I've tried running a basic example on windows. It doesn't seem to work in both development and production environments. But a without-loader example is work fine. Environments
|
@vimutti77 Thanks to report It! It looks like it is the fault of the absolute import on the default https://github.com/vinissimus/next-translate/runs/1457587510 defaultLoader: (l, n) =>
import(`D:\a\next-translate\next-translate/locales/${l}/${n}`).then(
(m) => m.default
), Do you know how this import would be for it to be valid? I suppose that fixing the string would work already. Or another solution will be using an alias in webpack instead. When I have some time I fix it, I already asked if someone could look at it in Windows because I was afraid it would not work after see the failing test. If you add the Thank you very much |
@aralroca This is what I got when run
|
Closing this. Already fixed on 1.0.0-canary.1. The 1.0 will be released approximately 1-2 weeks. 😊 |
I did a working example in the repo as an alternative to "build step", using dynamic routing.
It requires (for the moment) more configuration, but it also works for Automatic Static Optimization.
I invite you to experiment with the example that I did.
After achieving this, I'm asking myself how to evolve this library to the next major 1.0.0 release.
To be honest, I would like to remove the "build step" because it's a temporal workaround. And using dynamic routes is the natural way to achieve this in Next.js.
The problem that I see with dynamic routes is that requires three steps for each page:
lang
paths togetStaticPaths
lang
and namespaces props togetStaticProps
I18nProvider
on top of your page. (I used a HOC in the example)And doing this for every page can be very cumbersome.
I open this issue in order to discuss if we really want to evolve simplifying this and removing the "build step", or not. And in the case that we really want to remove the "build step", how we can simplify this to avoid this cumbersome configuration.
Any feedback will be very welcome 👏
Update:
I'll remove the https://github.com/vinissimus/next-translate/tree/master/examples/with-dynamic-routes example, now there is a i18n routing support on Next.js and is a better way to evolve this library. The first step to 1.0 is the 0.19 release, adapting the i18n routing to this library.
The text was updated successfully, but these errors were encountered: