Click here to Skip to main content
15,867,568 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I'm using ant design pro boilerplate on top of umijs.
The idea is In the platform we have 2 languages to choose from Fr(French) and En(English),
I want the user when he logs in and change the language to English for example when he logs out and log in again the language should be saved to English so he would be able to see the content in English, I managed to do it, when i login in the backend the preferedLanguage = en, the language toggle in the navbar also = en, the only problem the web page content stays in French (which is the default) it's only change in English when i reload the page.
I think the issue is related to the login page, the login page is set to French as default , let's say my preferred language now is English, if i login from the login page (which is set to french by default). The page content loaded in French only changes when i reload.


What I have tried:

<pre>-This is the umijs documentation : https://umijs.org/docs/max/i18n#setlocale-%E8%AE%BE%E7%BD%AE%E8%AF%AD%E8%A8%80 
please translate it to english with the browser, i'm working with getAllLocales, getLocale, setLocale.

-LanguageDropdown (the toggle where you select the language (Fr or En)


JavaScript
<pre>import type { FC } from 'react';
import React, { useState, useEffect } from 'react';
import { Menu, Dropdown } from 'antd';
import { CaretDownOutlined, CaretUpOutlined, GlobalOutlined } from '@ant-design/icons';
import styles from './index.less';
import { setLocale, getLocale, getAllLocales } from 'umi';

interface Props {
  setUpdateLang: any;
  currentLang: string;
}

const LanguageDropdown: FC<Props> = ({ currentLang, setUpdateLang }) => {
  const [langvisible, setLangVisible] = useState<boolean>(false);
  const [localesList, setLocalesList] = useState<any[]>([]);
  const [currentLocale, setCurrentLocale] = useState<string>('');

  // useEffect(() => {
  //   if (currentLang) {
  //     setLocalesList(getAllLocales());
  //     setCurrentLocale(getLocale());
  //     setLocale(currentLang === 'fr' ? 'fr-FR' : 'en-US');

  //   }
  //    alert(currentLang);
  //    alert(getLocale());
  // }, [currentLang]);

  useEffect(() => {
    setLocalesList(getAllLocales());
    setCurrentLocale(getLocale());

    if (currentLang) {
      // alert(222);
      const selectedLang = currentLang === 'fr' ? 'fr-FR' : 'en-US';
      // setNewLang(selectedLang);
      setLocale(selectedLang, false);
      setCurrentLocale(getLocale());
    }
  }, [currentLang]);

  const onLangVisibleChange = (visibleLang: boolean) => {
    setLangVisible(visibleLang);
  };

  const langNameHandler = (lang: string) => {
    if (lang === 'en-US') return 'EN';
    else if (lang === 'fr-FR') return 'FR';
    return 'FR';
  };

  const setNewLang = (lang: string) => {
    setUpdateLang({ lang: langNameHandler(lang).toLocaleLowerCase(), updated: true });
    setLocale(lang);
  };

  const Langmenu = (
    <Menu>
      {localesList?.map((lang: any) => (
        <Menu.Item key={lang}>
          <a onClick={() => setNewLang(lang)}>{langNameHandler(lang)}</a>
        </Menu.Item>
      ))}
    </Menu>
  );

  return (
    <div className={styles.profileDropdownContainer}>
      <Dropdown
        overlay={Langmenu}
        placement="bottomLeft"
        trigger={['click']}
        onVisibleChange={onLangVisibleChange}
        className={styles.dropdown}
      >
        <div className={styles.langContainer}>
          <span>
            <GlobalOutlined /> {langNameHandler(currentLocale)}
          </span>
          {!langvisible ? <CaretDownOutlined /> : <CaretUpOutlined />}
        </div>
      </Dropdown>
    </div>
  );
};

export default LanguageDropdown;



-RightContext the navbar which holds the languageDropDown toggle


JavaScript
import { Tag } from 'antd';
import type { Settings as ProSettings } from '@ant-design/pro-layout';
import React, { useEffect, useState } from 'react';
import type { ConnectProps } from 'umi';
import type { Dispatch } from 'umi';
import { connect } from 'umi';
import type { ConnectState } from '@/models/connect';
import Avatar from './AvatarDropdown';
import styles from './index.less';
import LanguageDropdown from '../languageDropdown';
import moment from 'moment';

export type GlobalHeaderRightProps = {
  dispatch: Dispatch;
  theme?: ProSettings['navTheme'] | 'realDark';
  auth: any;
  users: any;
  platformLanguage: any;
  data: any;
} & Partial<ConnectProps> &
  Partial<ProSettings>;

const ENVTagColor = {
  dev: 'orange',
  test: 'green',
  pre: '#87d068',
};

const GlobalHeaderRight: React.FC<GlobalHeaderRightProps> = (props) => {
  const [updateLang, setUpdateLang] = useState<{ lang: string; updated: boolean }>({
    lang: '',
    updated: false,
  });
  const [currentLang, setCurrentLang] = useState<any>(null);
  const { theme, layout, auth, platformLanguage, data, dispatch } = props;
  let className = styles.right;

  useEffect(() => setCurrentLang(platformLanguage), [platformLanguage]);

  useEffect(() => {
    if (updateLang.updated) {
      const {
        organization,
        roles,
        email,
        deleted,
        department,
        createdById,
        organizationId,
        ...rest
      } = data;
      const birthdate = moment(rest.birthdate).format('YYYY-MM-DD');
      const workversary = moment(rest.workversary).format('YYYY-MM-DD');
      dispatch({
        type: 'users/updateMe',
        payload: {
          data: { ...rest, birthdate, workversary, platformLanguage: updateLang.lang },
          userId: auth?.currentUser.id,
        },
      });

      setUpdateLang({ ...updateLang, updated: false });
      setCurrentLang(updateLang.lang);
    }
  }, [updateLang]);

  if (theme === 'dark' && layout === 'top') {
    className = `${styles.right}  ${styles.dark}`;
  }

  return (
    <div className={className}>
      {currentLang ? (
        <LanguageDropdown currentLang={currentLang} setUpdateLang={setUpdateLang} />
      ) : null}

      <Avatar />
      {REACT_APP_ENV && (
        <span>
          <Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag>
        </span>
      )}
    </div>
  );
};

export default connect(({ settings, auth, users }: ConnectState) => ({
  theme: settings.navTheme,
  layout: settings.layout,
  auth,
  users,
  platformLanguage: auth?.currentUser?.membership?.platformLanguage,
  data: auth?.currentUser?.membership,
}))(GlobalHeaderRight);

-LoginLayout (login page)

JavaScript
import React, { useEffect, useState } from 'react';
import type { ConnectState } from '@/models/connect';
import type { MenuDataItem } from '@ant-design/pro-layout';
import { getMenuData, getPageTitle } from '@ant-design/pro-layout';
import { useIntl, connect } from 'umi';
import type { ConnectProps } from 'umi';
import { Col, Row } from 'antd';
import { Helmet, HelmetProvider } from 'react-helmet-async';
import LoginImage from '../assets/loginImage.png';
import SignUpAdminImage from '../assets/adminSignup.svg';
import styles from './LoginLayout.less';
import LanguageDropdown from '@/components/languageDropdown';
import SignupSideText from '@/components/SignupSideText';

export type UserLayoutProps = {
  breadcrumbNameMap: Record<string, MenuDataItem>;
} & Partial<ConnectProps>;

const LoginLayout: React.FC<UserLayoutProps> = (props) => {
  const [layoutImage, setLayoutImage] = useState(LoginImage);
  const [updateLang, setUpdateLang] = useState<{ lang: string; updated: boolean }>({
    lang: '',
    updated: false,
  });
  const [currentLang, setCurrentLang] = useState<any>('');

  useEffect(() => {
    if (updateLang.updated) {
      setUpdateLang({ ...updateLang, updated: false });
      setCurrentLang(updateLang.lang);
    }
  }, [updateLang]);

  useEffect(() => {
    if (window.location.pathname === '/user/adminSignup/step1') {
      setLayoutImage(SignUpAdminImage);
    } else if (window.location.pathname === '/user/adminSignup/step2') {
      setLayoutImage('TextSignup');
    } else setLayoutImage(LoginImage);
  }, [window.location.pathname]);
  const {
    route = {
      routes: [],
    },
  } = props;
  const { routes = [] } = route;
  const {
    children,
    location = {
      pathname: '',
    },
  } = props;
  const { formatMessage } = useIntl();
  const { breadcrumb } = getMenuData(routes);
  const title = getPageTitle({
    pathname: location.pathname,
    formatMessage,
    breadcrumb,
    ...props,
  });

  return (
    <>
      <HelmetProvider>
        <Helmet>
          <title>{title}</title>
          <meta name="description" content={title} />
        </Helmet>

        <div className={styles.container}>
          <Col
            xl={{ span: 12, order: 1 }}
            xs={{ span: 0, order: 2 }}
            md={{ span: 0, order: 2 }}
            lg={{ span: 0, order: 2 }}
            style={{ backgroundColor: '#00bfa5' }}
          >
            {layoutImage === 'TextSignup' ? (
              <SignupSideText />
            ) : (
              <img alt="logo" width="100%" height="100%" src={layoutImage} />
            )}
          </Col>
          <Col
            xl={{ span: 12, order: 2 }}
            lg={{ span: 24, order: 2 }}
            sm={{ span: 24, order: 1 }}
            xs={{ span: 24, order: 1 }}
          >
            {' '}
            <Row justify="end" className="languageRow">
              <LanguageDropdown currentLang={currentLang} setUpdateLang={setUpdateLang} />
            </Row>
            {children}
          </Col>
        </div>
      </HelmetProvider>
    </>
  );
};

export default connect(({ settings }: ConnectState) => ({ ...settings }))(LoginLayout);
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900