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

Support for getServerSideProps #652

Closed
thomb opened this issue Mar 16, 2020 · 43 comments
Closed

Support for getServerSideProps #652

thomb opened this issue Mar 16, 2020 · 43 comments

Comments

@thomb
Copy link

thomb commented Mar 16, 2020

Is your feature request related to a problem? Please describe.

When using getServerSideProps as opposed to getInitialProps results in a namespacesRequired warning, despite the fact that I am returning namespacesRequired inside the required props key

I don't know if this is factual or not, or if the warning is a red herring

Describe the solution you'd like

Ideally I'd like getServerSideProps to be supported.

Apologies if this is vague or unclear, or a completely unreasonable request.

Thanks in advance

@isaachinman
Copy link
Contributor

NextJs 9.3 was released a week ago. None of the new data fetching methods are supported yet, but in general I'd lean towards getStaticProps over getServerSideProps. Typically it's better to associate translation changes with releases, rather than having changes at runtime.

The next-i18next package will be entirely rewritten once NextJs plugin support lands, as quite a few things have changed since its inception.

@HsnVahedi
Copy link

HsnVahedi commented Mar 17, 2020

I'm kind of newbie so sorry for asking this question. As I've figured out your amazing library currently fully supports Next js 9.2, right? Can I start my project using Next js 9.2 and stick to next-i18next 4.2.1 for the next few months?

@isaachinman
Copy link
Contributor

It fully supports NextJs 9.3 as well, just not the new data fetching methods.

@isaachinman
Copy link
Contributor

That is entirely false. That'd be a breaking change, and would go against semver. Read the docs.

No deprecations are introduced and getInitialProps will continue to function as it currently does.

@kahoowkh
Copy link

It fully supports NextJs 9.3 as well, just not the new data fetching methods.

May I know if there is any schedule for supporting getServerSideProps and getStaticProps?

@isaachinman
Copy link
Contributor

I do not currently have much time for development on this project due to other factors in life. I don't see this changing for the next few weeks, at least.

As I've stated, next-i18next will be rewritten once plugin support (finally) lands. If you'd like to see this (and many other features) supported, please let the NextJs team know that you are waiting for plugin support!

@maxmalov
Copy link

Just noticed that you can use i18next inside getServerSideProps in the same way as you would do it in the express application, i.e. create & configure plain i18next instance and use it instead

@isaachinman
Copy link
Contributor

@maxmalov Can you explain what you mean? We still have a dependency on the i18next browser detector middleware.

@maxmalov
Copy link

maxmalov commented Mar 26, 2020

getServerSideProps is being called on the server-side only, consider the example

import i18next from 'i18next';

const createI18Next = (lang) => {
  // create & configure i18next instance 
}

export const serverSideMethod = ({ params, req, res }) => {
  // detect lang from req somehow (probably can reuse express middleware)
  const lang = detect(req);
  const i18n = createI18Next(lang);
  const { t } = i18n;

  // do whatever you want with t
} 

So later one can use serverSideMethod inside getServerSideProps and get already translated content.

// somewhere in pages directory

import { serverSideMethod } from '...';

export const getServerSideProps = ctx => serverSideMethod(ctx)

export default props => { ... }

For now, it's just a theory. We're working on the AMP first app and have to reuse the existing 18next resources we use in the separate single-page app. So in a few days, we eventually find out whether it works or not

@isaachinman
Copy link
Contributor

Yes, that approach will work if you want to roll your own implementation, but has nothing to do with this package. Let's keep discussion here on topic.

@pettomartino
Copy link

Any updates here?
It can be a workaround for now, or a way to silence

You have not declared a namespacesRequired array on your page-level component: Page. This will cause all namespaces to be sent down to the client, possibly negatively impacting the performance of your app. For more info, see: https://github.com/isaachinman/next-i18next#4-declaring-namespace-dependencies"

Thanks

@isaachinman
Copy link
Contributor

Hey @pettomartino - no update from my side. You can always silence warnings by setting strictMode to false. Please do feel free to contribute if you so choose!

@pettomartino
Copy link

pettomartino commented Apr 26, 2020

@isaachinman thank for so quick reply. Gonna try to implement something then. Any hints?

@isaachinman
Copy link
Contributor

@pettomartino Do you mean contributing to next-i18next? If we want to support getServerSideProps, we'll need to update the appWithTranslation HOC to also look for that data fetching method in addition to getInitialProps.

@s875515
Copy link

s875515 commented May 9, 2020

@pettomartino there is a demonstration that the i18n solution works in SSG, Hope it helps.
vercel/next.js#11841

@icrona
Copy link

icrona commented Jun 16, 2020

since we cant use serverSideProps together with initialProps. we can make use of React FunctionComponent.defaultProps
here is the workaround that works for me, and it still works with initialProps (#615 (comment))

  1. particular page
Page.defaultProps = {
      i18nNamespaces: ['home-page']
}
  1. main app / _app.tsx
MyApp.getInitialProps = async (appContext: AppContextType<Router>) => {
    const appProps = await App.getInitialProps(appContext)
    const defaultProps = appContext.Component.defaultProps
    return {
        ...appProps,
        pageProps: {
            namespacesRequired: [...(appProps.pageProps.namespacesRequired || []), ...(defaultProps?.i18nNamespaces || [])]
        }
    }
}

@icecold21
Copy link

since we cant use serverSideProps together with initialProps. we can make use of React FunctionComponent.defaultProps
here is the workaround that works for me, and it still works with initialProps (#615 (comment))

  1. particular page
Page.defaultProps = {
      i18nNamespaces: ['home-page']
}
  1. main app / _app.tsx
MyApp.getInitialProps = async (appContext: AppContextType<Router>) => {
    const appProps = await App.getInitialProps(appContext)
    const defaultProps = appContext.Component.defaultProps
    return {
        ...appProps,
        pageProps: {
            namespacesRequired: [...(appProps.pageProps.namespacesRequired || []), ...(defaultProps?.i18nNamespaces || [])]
        }
    }
}

this works. thanks!

@rparree

This comment has been minimized.

@rparree
Copy link

rparree commented Jul 24, 2020

I'm using this version, so that it picks up recursive namespaces from WrappedComponents when using HOC

MyApp.getInitialProps = async (appContext: AppContextType<Router>) => {

    const recursiveNamespaces = (component: NextComponentType & { WrappedComponent?: NextComponentType }, acc: string[] = []): string[] => {

        const ns = component.defaultProps?.i18nNamespaces;
        const a = (typeof ns === "string") ? [...acc, ns] : [...acc, ...(ns || [])];
        let wrappedComponent = component.WrappedComponent;
        if (wrappedComponent) {
            return recursiveNamespaces(wrappedComponent, a)
        } else
            return a
    }

    const appProps = await App.getInitialProps(appContext)
    const namespaces: any = recursiveNamespaces(appContext.Component)
    return {
        ...appProps,
        pageProps: {
            namespacesRequired: [
                ...(appProps.pageProps.namespacesRequired || []),
                ...namespaces]
        }
    }
}

It allows to use your defaultProps like this:

TotoComponent.defaultProps = {
    i18nNamespaces: ['toto','bar']
}

export default withTranslation('toto')(TotoComponent);

@isaachinman
Copy link
Contributor

@rparree I think you're commenting on the wrong issue. This issue is about getServerSideProps.

@rparree
Copy link

rparree commented Jul 24, 2020

@isaachinman I was referring to the comment with the workaround submitted by @icrona above (#652 (comment))

@isaachinman
Copy link
Contributor

Sorry, what exactly is that workaround achieving?

@rparree
Copy link

rparree commented Jul 24, 2020

With the solution in their comment you can use defaultProps to set the namespaces when using a component that uses getServerSideProps. My code looks for defaultProps recursively when using a HOC.

@isaachinman
Copy link
Contributor

As far as I can tell, that doesn't achieve anything except slightly modifying the API. It won't enable SSG.

@sebastienlabine
Copy link

since we cant use serverSideProps together with initialProps. we can make use of React FunctionComponent.defaultProps
here is the workaround that works for me, and it still works with initialProps (#615 (comment))

  1. particular page
Page.defaultProps = {
      i18nNamespaces: ['home-page']
}
  1. main app / _app.tsx
MyApp.getInitialProps = async (appContext: AppContextType<Router>) => {
    const appProps = await App.getInitialProps(appContext)
    const defaultProps = appContext.Component.defaultProps
    return {
        ...appProps,
        pageProps: {
            namespacesRequired: [...(appProps.pageProps.namespacesRequired || []), ...(defaultProps?.i18nNamespaces || [])]
        }
    }
}

how would that work for typescript?

@rparree
Copy link

rparree commented Jul 26, 2020

@isaachinman It does the trick for me. I am able to use a component like this (and it will be SSR)

export const getServerSideProps = async function (ctx: NextPageContext) {
  
 return {
    props: {
      totoProp : ""
   }
 } 
}

TotoComponent.defaultProps = {
    i18nNamespaces: ['toto','bar']
}

export default withTranslation('toto')(TotoComponent);

@mattcrn
Copy link

mattcrn commented Jul 28, 2020

since we cant use serverSideProps together with initialProps. we can make use of React FunctionComponent.defaultProps
here is the workaround that works for me, and it still works with initialProps (#615 (comment))

1. particular page
Page.defaultProps = {
      i18nNamespaces: ['home-page']
}
1. main app / _app.tsx
MyApp.getInitialProps = async (appContext: AppContextType<Router>) => {
    const appProps = await App.getInitialProps(appContext)
    const defaultProps = appContext.Component.defaultProps
    return {
        ...appProps,
        pageProps: {
            namespacesRequired: [...(appProps.pageProps.namespacesRequired || []), ...(defaultProps?.i18nNamespaces || [])]
        }
    }
}

This approach breaks SSR for me. Only the keys are loaded initially and after a delay they are replaced by the translation.

Edit: nvm this works great, I just missed that the defaultProp is called i18nNamespaces instead of namespacesRequired

@mattcrn
Copy link

mattcrn commented Jul 29, 2020

To get all namespaces loaded in case none are defined on the page, you would have to adapt icronas solution like this:

NextApp.getInitialProps = async (appContext) => {
  const appProps = await App.getInitialProps(appContext);
  const { defaultProps } = appContext.Component;
  let pageProps = {}
  if(appProps.pageProps.namespacesRequired || defaultProps?.i18nNamespaces) {
    pageProps = {
      namespacesRequired: [...(appProps.pageProps.namespacesRequired || []), ...(defaultProps?.i18nNamespaces || [])],
    }
  }
  return {
    ...appProps,
    pageProps
  };
};

@isaachinman
Copy link
Contributor

@mattcrn The next-i18next package will already load in all namespaces if you don't define any on the page. Let's keep this issue strictly about the support of getServerSideProps.

@mattcrn
Copy link

mattcrn commented Jul 29, 2020

@isaachinman yes, but using icrona's solution will break this functionality since it will return an empty array for namespacesRequired and the package is simpy checking if namespacesRequired is defined for loading all namespaces.
So, namespacesRequired: [] means no namespaces are being loaded.

@mattcrn
Copy link

mattcrn commented Jul 31, 2020

@pettomartino Do you mean contributing to next-i18next? If we want to support getServerSideProps, we'll need to update the appWithTranslation HOC to also look for that data fetching method in addition to getInitialProps.

As far as I understand it, getServerSideProps is not part of the page component, so we would have to create a higher order function to wrap the pages getServerSideProps. Or is there a better way?

nicholasio added a commit to ufersa/plataforma-sabia that referenced this issue Aug 2, 2020
* feat(tech): fetch a single tech by id or slug

* refactor(techs): extract logic to query scope

* feat(button): add info variant

* feat(tech): map technology object

* feat(tech): initial header design

* feat(button): improve font-size

* feat(tech): create provider

* fix(button): proptype variants

* feat(tech): useTechnology hook

* refactor(tech): componentize

* feat(tech): add react-tabs package

* feat(tech): make it responsiveness

* feat(tech): improve styles

* feat(tabs): extract components

* chore(deps): remove unused package

* feat(tech): show data with filters

* feat(tech): add optional params

* style(tech): tabs content title

tks @lcnogueira 🙂

* refactor(tech): rename components

* style(tech): description value

* style(tech): improve title container metrics

* fix(tech): error when not found

* style(tech): hide buttons container

* chore(tech): add col wrapper to future updates

* chore(tech): getInitialProps to getServerSideProps

* chore(tech): code style

* feat(tech): render error component when necessary

* test(tech): initial fetch feature

* test(tech): fix fetch and expected status

* test(tech): making assertions

* refactor(tech): prevent error on build

move styles from dedicated file to internal component file

tks @lcnogueira 👍

* style(tech): improve titles

* style(tech): image shadow

* style(tech): improve metrics and colors

* fix: i18n namespaces with getServerSideProps

tks @icrona

based on i18next/next-i18next#652

* style(tech): improve margins

* style(tech): fix tab title width

* style(tech): improve padding

* feat(helpers): unslugify

* chore: remove unslugify

* feat(tech): list some taxonomies

* fix(edit): trying to fix tests

* style(tech): improve readability

* fix(home): technologies list

* fix: prevent erros

* refactor(tech): extract components to another path

* feat(tech): only render if section has children

* refactor(tabs): make props more readable

* refactor(tech): styles

* test(hooks): useTechnology coverage

* fix(techs): error when database is empty

resolver #305

* fix(techs): error when database is empty

resolves #305

* test(tech): remove unnecessary data

* fix(error): propTypes validation

resolves #324

* tests(edit/new): trying to fix

* fix: 🔥 remove getServerSideProps 💥

also add 't' technology prefix

* style(tech): remove css vendor prefix

* feat(tech): reactivate buttons

* refactor(tech): early bail out if

* test(tech): remove unnecessary mock properties

* refactor(tabs): use global row and cell

* refactor(tech): early bail out if

* fix(tech): mobile title responsivity

* refactor(tech): rename section component

* feat(error): define 400 as default error code

* refactor(home): technologies as object of arrays

* feat(tech): normalize taxonomies

* test(tech): normalize taxonomies

* refactor(tech): redirect to error page when not found

* test(tech): redirect to 404

* chore(tech): remove unused prop

* fix(card): redirect without refresh page

resolves #328

* Quick fixces

* Increasing timeouts

* Updating snapshots

* Adding a wait period before fetching last email

Co-authored-by: Nícholas Oliveira <[email protected]>
@ckeeney
Copy link

ckeeney commented Aug 20, 2020

I think when this feature lands, it would be ideal to support both getServerSideProps and getStaticProps. For most users of this library, local translations and staticProps will be fine, but the serverSideProps may be useful in projects that are using https://locize.com/ or something similar, where translations are managed outside of the project.

@isaachinman
Copy link
Contributor

@ckeeney Agreed.

@theoludwig
Copy link

Any update since then ?
Looking forward to have this thing implemented. 👍

@isaachinman
Copy link
Contributor

@divlo Feel free to submit a PR.

@maxgfr
Copy link

maxgfr commented Oct 1, 2020

+1

@SalahAdDin
Copy link

since we cant use serverSideProps together with initialProps. we can make use of React FunctionComponent.defaultProps
here is the workaround that works for me, and it still works with initialProps (#615 (comment))

  1. particular page
Page.defaultProps = {
      i18nNamespaces: ['home-page']
}
  1. main app / _app.tsx
MyApp.getInitialProps = async (appContext: AppContextType<Router>) => {
    const appProps = await App.getInitialProps(appContext)
    const defaultProps = appContext.Component.defaultProps
    return {
        ...appProps,
        pageProps: {
            namespacesRequired: [...(appProps.pageProps.namespacesRequired || []), ...(defaultProps?.i18nNamespaces || [])]
        }
    }
}

Well, i thought it would work good, but it works with delay:
Screen Capture_select-area_20201201232330

At the first loading, it does not load the skill-test namespaces, i need to reload it to get that namespace active and the proper localization strings.

Inspecting it for the first time we get this:
Screen Capture_select-area_20201201232220

After reloading, we can find the required namespace:
image

Both namespaces are in the option, but just the first one, defined on _app.js by getInitialProps, is loaded.

Why does this happen?

@SalahAdDin SalahAdDin mentioned this issue Dec 1, 2020
@isaachinman
Copy link
Contributor

@SalahAdDin This will be solved by #869.

@isaachinman
Copy link
Contributor

Fixed in [email protected].

@belgattitude
Copy link
Contributor

Thanks a lot for this @isaachinman

@SalahAdDin
Copy link

@isaachinman Does the new release mean we must deleted the whole workaround for this matter and use the new hook? It is not so much clear for me.

@isaachinman
Copy link
Contributor

@SalahAdDin Correct, there is no need for a workaround in v8.

@syamjayaraj
Copy link

Import the serverSideTranslations

import { serverSideTranslations } from "next-i18next/serverSideTranslations";

Now from the getServerSideProps, pass the ..(await serverSideTranslations(locale, ["common"])), with the props.

export const getServerSideProps: GetStaticProps = async ({
  locale,
  locales,
  query
}: any) => {
  return {
    props: {
      ...(await serverSideTranslations(locale, ["common"])),
    }
  }
};

Now add your language string inside
/public/locales/en/common.json

For example

{
  "home": {
    "Test": "Test"
  }
}

You can add more language strings inside the locales directory.

Restart your Next.js app. It will work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests