aralroca / next-translate

Next.js plugin + i18n API for Next.js 🌍 - Load page translations and use them in an easy way!
MIT License
2.6k stars 209 forks source link

Dynamic paths are not recognized in development mode( next dev ) #442

Open keilind opened 3 years ago

keilind commented 3 years ago

Hi!

I'm experiencing an issue when running a development server, namely the fact that my pages are not found when running in dev mode. When generating a production build of the site this is not the issue. I'll post some screenshots below.

Any insights appreciated.

Image of Production build

Image of development build

Image of file structure

import Layout from '../Layout';
import styled from 'styled-components';
import { withUserAgent, useUserAgent } from 'next-useragent';
import { useCurrentPosition } from 'react-use-geolocation';
import { useEffect, useState, useContext } from 'react';
import { useRouter } from 'next/router';
import DefaultErrorPage from 'next/error';
import useTranslation from 'next-translate/useTranslation';
import getT from 'next-translate/getT';
import Modal from 'react-modal';

const Container = styled.div`
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 100%;
  border: 3px;
  box-sizing: border-box;
  margin: 0 10px;
  border: 3px;
  box-sizing: border-box;
  background: #ffffff;
`;

const Title = styled.h2`
  font-family: Noto Sans;
  font-size: 36px;
  line-height: 48px;
  font-style: normal;
  max-width: 1024px;
  letter-spacing: -0.64px;
  color: #111111;
  flex: none;
  order: 1;
  flex-grow: 0;
  margin: 20px 0;

  @media (max-width: 540px) {
    max-width: 375px;
    display: flex;
    flex-direction: column;
    align-items: center;
    font-style: normal;

    font-size: 24px;
    line-height: 48px;
    padding: 0px;
  }

  @media (max-width: 768px) {
    max-width: 525px;
    display: flex;
    flex-direction: column;
    align-items: center;
    font-style: normal;

    font-size: 24px;
    line-height: 48px;
    padding: 0px;
  }
`;

const Description = styled.p`
  flex: none;
  order: 2;
  font-style: normal;

  font-size: 14px;
  line-height: 24px;
  margin: 20px 0;

  color: #484848;

  @media (max-width: 540px) {
    display: flex;
    flex-direction: column;
    align-items: center;
    font-style: normal;

    font-size: 14px;
    line-height: 24px;
    line-height: 24px;
    padding: 0;
  }

  @media (max-width: 768px) {
    display: flex;
    flex-direction: column;
    align-items: center;
    font-style: normal;
    font-size: 14px;
    line-height: 24px;
    line-height: 24px;
    padding: 0;
  }
`;

const Content = styled.div`
  flex: none;
  order: 3;
  font-family: Noto Sans;
  h2 {

    font-style: normal;

    font-size: 25px;
    line-height: 136%;

    letter-spacing: -0.0042em;
    color: #111111;

    margin: 0px 49px;
  }

  h3 {
    top: 262px;

    font-style: normal;

    font-size: 16px;
    line-height: 150%;
    color: #111111;
    margin: 0px 49px;
  }

  h4 {
    height: 40px;

    font-style: normal;

    font-size: 14px;
    line-height: 143%;
    color: #484848;
    margin: 0px 32px;
  }

  a {
    color: #484848;
    text-decoration: none;
    border-bottom: 1px solid #484848;
  }

  p {
    font-size: 14px;
    font-style: normal;
    line-height: 143%;
  }
`;

const ModalContent = styled.div`
  display: flex;
  flex-direction: column;
`;

const ModalTitle = styled.p`
  font-family: Noto Sans;
  font-style: normal;
  font-size: 25px;
  line-height: 34px;

  letter-spacing: -0.0042em;

  color: #111111;

  flex: none;
  order: 0;
  flex-grow: 0;
  margin: 0px 16px;
`;

const ModalText1 = styled.div`
  font-family: Noto Sans;
  font-style: normal;
  font-weight: normal;
  font-size: 14px;
  line-height: 143%;
  max-width: 410px;

  color: #484848;
  flex: none;
  order: 1;
  flex-grow: 0;
  margin: 12px 16px;
  ::after {
    content: '\n';
    white-space: pre;
  }
`;

const ModalText2 = styled.div`
  font-family: Noto Sans;
  font-style: normal;
  font-weight: normal;
  font-size: 14px;
  line-height: 143%;
  max-width: 410px;

  color: #484848;

  flex: none;
  order: 1;
  flex-grow: 0;
  margin: 0px 16px;
  ::before {
    content: '\n';
    white-space: pre;
  }
`;

const Button = styled.button`
  background-color: ${(props) => (props.primary ? '#111' : '#fff')};
  color: ${(props) => (props.primary ? ' #fff' : '#111')};
  border-radius: 999px;
  border: none;
  width: 450px;
  height: 56px;
  padding: 4px; 12px;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  font-family: Noto Sans;
  font-style: normal;
  font-size: 14px;
  line-height: 142.8%;
  border: ${(props) => (props.primary ? 'none' : '1px solid #DFDFDF')};
  margin: 17px 0;
`;

const ModalTextContainer = styled.div`
  margin-top: 16px;
  margin-bottom: 25px;
`;

const modalStyles = {
  content: {
    top: '50%',
    left: '50%',
    right: 'auto',
    bottom: 'auto',
    marginRight: '-50%',
    transform: 'translate(-50%, -50%)',
    borderRadius: '8px',
    fontFamily: 'Noto Sans',
  },
};

const Doc = ({
  data,
  userAgent,
  ua,
  lang,
  country,
  link,
  error,
  statusCode,
}) => {
  if (!data) return <div>Loading...</div>;
  const [isOpen, SetIsOpen] = useState(true);

  const router = useRouter();

  if (router.isFallback) {
    return <div>Loading...</div>;
  }

  if (!data) {
    return <DefaultErrorPage statusCode={500} />;
  }

  return (
    <Layout
      title={data.title}
      desc={data.description}
      country={country}
      link={link}
    >
      <Container>
        <Modal isOpen={isOpen} style={modalStyles} ariaHideApp={false}>
          <ModalContent>
            <ModalTitle>Knowledge base {country}</ModalTitle>
            <ModalTextContainer>
              <ModalText1>
                Are you visiting Knowledge.blabla.com, from outside the US?
              </ModalText1>
              <ModalText2>
                You will find more relevant information on the website for the
                country where you are located.
              </ModalText2>
            </ModalTextContainer>
            <Button
              primary
              onClick={() => {
                SetIsOpen(false);
              }}
            >
              Continue to {lang} site
            </Button>
            <Button
              onClick={() => {
                document.location.href = link;
              }}
            >
              Go to blabla.com
            </Button>
          </ModalContent>
        </Modal>
        <Title>{data.title}</Title>
        <Description>{data.description}</Description>
        <Content dangerouslySetInnerHTML={{ __html: data.content }} />
      </Container>
    </Layout>
  );
};

const handleError = (err) => {
  console.warn(err);
  return new Response(
    JSON.stringify({
      code: 400,
      message: 'Stupid network Error',
    })
  );
};

export async function getStaticPaths() {
  const res = await fetch(
    'https://veta.rzrs.de/serviceconnector/swagger/../services/rest/content/search?cb=1_438&lang=nl&gk_singlerequest=true&query=*&limit=800&api_key=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIvaWtlYXRlY2gxIiwiaXNzIjoidXN1a2NlbnRlcjYwLnJ6cnMuZGUiLCJpYXQiOjE1ODc2NTI3NTksImp0aSI6IjNkZmVjNGZjLWZlYTgtNDRhMS04NDljLWJkNjMxMTRhNDk2MDoxIn0.WvDV-RrMsiJHzP4YaX5F9ZghzjPIpK1VUvFRkmFi8uE'
  );
  const docs = await res.json();
  const paths = docs.entries.map((doc) => ({
    params: { id: doc.metadata.docGUID },
  }));

  return { paths, fallback: true };
}

export async function getStaticProps({ params, locale }) {
  let error = false;
  const res = await fetch(
    `https://veta.rzrs.de/serviceconnector/swagger/../services/rest/documents/${params.id}?lang=nl&api_key=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIvaWtlYXRlY2gxIiwiaXNzIjoidXN1a2NlbnRlcjYwLnJ6cnMuZGUiLCJpYXQiOjE1ODc2NTI3NTksImp0aSI6IjNkZmVjNGZjLWZlYTgtNDRhMS04NDljLWJkNjMxMTRhNDk2MDoxIn0.WvDV-RrMsiJHzP4YaX5F9ZghzjPIpK1VUvFRkmFi8uE&gk_singlerequest=true`
  ).catch((err) => {
    console.log(err);

    if (err !== '') {
      error = true;
    }
  });

  const t = await getT('nl', 'doc');

  const data = await res.json();

  if (!error) {
    return {
      revalidate: 1,
      props: {
        data,
        lang: t('country_lang'),
        country: t('country'),
        link: t('country_link'),
        locale,
      },
    };
  } else {
    return {
      revalidate: 1,
      props: {
        data: null,
        error: true,
        statusCode: 404,
      },
    };
  }
}

export default Doc;
aralroca commented 3 years ago

@keilind you do not need to have the language within a directory within pages, this is managed by the i18n routing of Next.js.

So instead of:

pages
β”œβ”€β”€ en
β”‚Β Β  └── somepage.js
└── nl
    └── somepage.js

You can directly use:

pages
β”œβ”€β”€  somepage.js

Then it would be great to know what version of next-translate and Next.js you are using and how is your file i18n.js. πŸ™