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

next-international requires manual reload to change the language #346

Closed
Abbosbek-cloud opened this issue Feb 6, 2024 · 6 comments · Fixed by #352
Closed

next-international requires manual reload to change the language #346

Abbosbek-cloud opened this issue Feb 6, 2024 · 6 comments · Fixed by #352
Labels
bug Something isn't working

Comments

@Abbosbek-cloud
Copy link

next-international requires reload to change the language
After adding next-international to my next application it requires manual reload to change the language even I have already changed the language using useChangeLanguage hook.

Expected behavior
I expected to change page's locale immediately when user interacts with change language buttons.

About:

  • next-international version [^1.1.4]
  • Next.js version [14.0.4]

Additional context
Using next-international with pages directory of nextjs.

@Abbosbek-cloud Abbosbek-cloud added the bug Something isn't working label Feb 6, 2024
@Abbosbek-cloud
Copy link
Author

next.config.json

const withPlugins = require('next-compose-plugins');
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
  openAnalyzer: false,
});

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  distDir: '.next',
  i18n: {
    locales: ['ru', 'uz'],
    defaultLocale: 'uz',
  },
  crossOrigin: 'use-credentials',
  images: {
    remotePatterns: [...],
  },
};

module.exports = withPlugins([withBundleAnalyzer], nextConfig);

_app.tsx

import { I18nProvider } from 'locales';
import { Page } from 'types/page';
import { AppProps } from 'next/app';
import Router from 'next/router';
import nProgress from 'nprogress';
import { FC, Fragment, useEffect, useState } from 'react';
import MuiThemeProvider from 'theme';
import { CurrencyProvider } from 'utils/context/CurrencyContext';
import Head from 'next/head';
import ErrorBoundary from 'utils/context/ErrorBoundary';
import { Hydrate, QueryClient, QueryClientProvider } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';
import { ReduxProvider } from 'utils/redux/Provider';
import { ToastContainer } from 'react-toastify';

// styles
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import 'react-toastify/dist/ReactToastify.css';

type OrientWebAppProps = AppProps & {
  Component: Page;
};

Router.events.on('routeChangeStart', () => nProgress.start());
Router.events.on('routeChangeComplete', () => nProgress.done());
Router.events.on('routeChangeError', () => nProgress.done());

nProgress.configure({
  showSpinner: false,
});

export const OrientWebApp: FC<OrientWebAppProps> = ({ Component, pageProps, router }) => {
  const [queryClient] = useState(
    new QueryClient({
      defaultOptions: {
        queries: {
          retry: false,
          refetchOnWindowFocus: false,
        },
      },
    })
  );

  const getLayout = Component.getLayout ?? ((page: React.ReactNode) => page);

  useEffect(() => {
    const jssStyles = document.querySelector('#jss-server-side');
    if (jssStyles && jssStyles.parentElement) {
      jssStyles.parentElement.removeChild(jssStyles);
    }
    unregister();
  }, []);

  function unregister() {
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.getRegistrations().then(function (registrations) {
        for (const registration of registrations) {
          registration.unregister();
        }
      });
    }
  }

  return (
    <Fragment>
      <Head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      </Head>
      <ErrorBoundary>
        <CurrencyProvider>
          <QueryClientProvider client={queryClient}>
            <Hydrate state={pageProps.dehydratedState}>
              <ReduxProvider>
                <I18nProvider locale={pageProps.locale}>
                  <MuiThemeProvider>{getLayout(<Component {...pageProps} />)}</MuiThemeProvider>
                </I18nProvider>
                <ToastContainer />
              </ReduxProvider>
              <ReactQueryDevtools initialIsOpen={false} />
            </Hydrate>
          </QueryClientProvider>
        </CurrencyProvider>
      </ErrorBoundary>
    </Fragment>
  );
};

export default OrientWebApp;

_document.tsx

import createEmotionCache from 'theme/createEmotionCache';
import { CacheProvider } from '@emotion/react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
import React from 'react';
import { AppProps } from 'next/app';

export default class OrientMotorsDocument extends Document {
  render() {
    return (
      <Html lang="uz">
        <Head>
          <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
          <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
          <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />

          <meta name="apple-mobile-web-app-capable" content="yes" />
          <meta name="apple-mobile-web-app-status-bar-style" content="black" />
          <meta name="theme-color" content="#000000" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

OrientMotorsDocument.getInitialProps = async (ctx) => {
  const originalRenderPage = ctx.renderPage;
  const cache = createEmotionCache();
  const { extractCriticalToChunks } = createEmotionServer(cache);

  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App: React.ComponentType<AppProps>) => (props: AppProps) => {
        return (
          <CacheProvider value={cache}>
            <App {...props} />
          </CacheProvider>
        );
      },
    });

  const initialProps = await Document.getInitialProps(ctx);

  const emotionStyles = extractCriticalToChunks(initialProps.html);
  const emotionStyleTags = emotionStyles.styles?.map((style) => (
    <style
      data-emotion={`${style.key} ${style.ids.join(' ')}`}
      key={style.key} // eslint-disable-next-line react/no-danger
      dangerouslySetInnerHTML={{
        __html: style.css,
      }}
    />
  ));
  return {
    ...initialProps,
    styles: [...React.Children.toArray(initialProps.styles), ...emotionStyleTags],
  };
};

@QuiiBz
Copy link
Owner

QuiiBz commented Feb 9, 2024

Seems like a regression of #314. Will check asap

@Abbosbek-cloud
Copy link
Author

Seems like a regression of #314. Will check asap

I will wait for your response after checking this one!

@FleetAdmiralJakob
Copy link

I have the same problem here: https://weather-app-git-move-to-next-830f94-creative-programming-group.vercel.app/settings

Just press the buttons and then you see that the cached locales are not changing.

Code: The-Creative-Programming-Group/Weather-App#213

@QuiiBz
Copy link
Owner

QuiiBz commented Feb 10, 2024

@Abbosbek-cloud
Copy link
Author

Fix released in https://github.com/QuiiBz/next-international/releases/tag/1.2.4!

Thank you, bro!

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

Successfully merging a pull request may close this issue.

3 participants