React国际化react-i18next

框架使用的是umi 搭建的所以用的umi国际化配置(我的都是TS)

npm install react-i18next i18next --save
// 或者
yarn add react-i18next i18next  //推荐
getLocale 获取
setLocale 设置

第一步在app.tsx 同级目录新建locales文件,在locales文件下新建zh-CH.ts,en-US.ts,i18.ts

zh-CH.ts

export default {
  'zh-CN': '中文',
  'en-US': 'English',
  language: '语言',
  mix: '混合菜单布局',
  side: '侧边菜单布局',
  top: '顶部菜单布局',
};

en-US.ts

export default {
  'zh-CN': 'Chinese',
  'en-US': 'English',
  language: 'Language',
  mix: '混合菜单布局',
  side: '侧边菜单布局',
  top: '顶部菜单布局',
};

i18.ts

//i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import zh_CNCommon from './zh-CN';
import en_CNCommon from './en-US';
import { getLanguage } from '@/components/Language/index';  
const resources = {
  en: {
    translation: zh_CNCommon,
  },
  zh: {
    translation: en_CNCommon,
  },
};

i18n.use(initReactI18next).init({
  resources,
  // 默认语言  zh/en  中文/英文
  lng: getLanguage() || 'CN', //当前语音   默认CN
  interpolation: {
    escapeValue: false,
  },
});

export default i18n;

app.tsx  //引入文件

import '@/locales/i18n';

以上为配置,想要实现切换还需要getLanguage()事件

在components下新建Language文件,Language中新建index.tsx,Language.stories.tsx,useLanguageService.ts,

useLanguageService.ts   //代码

import { setLocale } from 'umi';
import { useMount } from 'ahooks';
import { IProps } from '.';
export default function useLanguageService(props: IProps) {
  const { systemLanguages } = props;
  const browserLanguage = (navigator.language || navigator.browserLanguage)
    ?.toLowerCase()
    .split('-')[0];

  /**
   * 优先使用浏览器语言
   */
  useMount(() => {
    const systemBrowserLanguage = systemLanguages.find(
      (item) => item.lang?.toLowerCase().indexOf(browserLanguage) >= 0,
    );
    if (systemLanguages && systemBrowserLanguage) {
      setLocale(systemBrowserLanguage.lang, false);
    }
  });

  return {};
}

Language.stories.tsx

import React from 'react';
import { Meta } from '@storybook/react';
import Language from './index';

export default {
  title: 'MSO/Language',
  component: Language,
  parameters: {
    previewTabs: {
      canvas: {
        hidden: true,
      },
    },
    viewMode: 'docs',
  },
} as Meta;

export const Defalut = (args) => (
  <div style={{ width: '100px' }}>
    <Language {...args} />
  </div>
);

index.tsx,

import TextIcon from '@/components/TextIcon';
import Icon from '@ant-design/icons';
import { Dropdown, Menu } from 'antd';
import 'antd/dist/antd.css';
import { DropDownProps } from 'antd/lib/dropdown/index';
import * as React from 'react';
import styled from 'styled-components';
import { getLocale, setLocale } from 'umi';
import locale from '@/assets/images/locale.png';
import useLanguageService from './useLanguageService';

export enum LauguageEnum {
  English = 'en-US',
  Chinese = 'zh-CN',
}

export enum LanguageIconEnum {
  English = 'US',
  Chinese = 'CN',
}

export type LanguageData = {
  lang: LauguageEnum | string;
  /**  icon为该语种的缩写, 长度最长为两个字符 */
  icon: LanguageIconEnum | string;
};

export type IFormatMessage = (
  key: string,
  attr?: Record<string, any>,
) => string;

export type IProps = {
  /**多语言翻译函数, 必传 */
  formatMessage: IFormatMessage;
  /** 多语言数组
   *  不传默认显示中英两种语种
   */
  systemLanguages?: LanguageData[];
} & Omit<DropDownProps, 'overlay'>;
export const DropdownWrapper = styled(Dropdown)`
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  width: 100%;
`;
export const MenuItemWrapper = styled(Menu.Item)<{ isSelected: boolean }>`
  min-width: 124px;
  color: ${(props) =>
    props.isSelected ? props.theme['com-language-highlight-color'] : ''};
  background-color: ${(props) =>
    props.isSelected ? props.theme['com-language-highlight-bg-color'] : ''};
  display: flex;
  align-items: center;
  img {
    height: 12px;
    margin-right: 8px;
  }
`;

const LanguageIcon = () => (
  <img
    style={{ width: '20px', height: '20px', marginRight: '3px' }}
    src={locale}
    alt=""
  />
);


const onSetLocale = (val, bol) => {
  setLocale(val, bol);
  getLanguage();
};
export const getLanguage = () => {
  return getLocale().split('-')[1];
};
export const MedalsoftLanguage = (props: IProps) => {
  const { formatMessage } = props;
  const {} = useLanguageService(props);
  return props.systemLanguages ? (
    <DropdownWrapper
      {...props}
      trigger={['click']}
      overlay={
        <Menu>
          {props.systemLanguages?.map((languageData: LanguageData) => (
            <MenuItemWrapper
              isSelected={languageData.lang === getLocale()}
              onClick={() => onSetLocale(languageData.lang, false)}
              key={languageData.lang}
            >
              <TextIcon
                text={languageData.icon?.slice(0, 2)}
                isSelected={languageData.lang === getLocale()}
              />
              <span>{formatMessage(languageData.lang)}</span>
            </MenuItemWrapper>
          ))}
        </Menu>
      }
    >
      <div>
        <Icon component={LanguageIcon}></Icon>
        <span>{getLocale().split('-')[1]}</span>
      </div>
    </DropdownWrapper>
  ) : null;
};

const defaultProps: IProps = {
  formatMessage: (i) => i,
  placement: 'bottomLeft',
  systemLanguages: [
    { lang: LauguageEnum.Chinese, icon: LanguageIconEnum.Chinese },
    { lang: LauguageEnum.English, icon: LanguageIconEnum.English },
  ],
};
MedalsoftLanguage.defaultProps = defaultProps;

export default { MedalsoftLanguage, getLanguage };  
//MedalsoftLanguage   显示在页面上DOM
//getLanguage  当前语言

 应用 

import { useIntl } from 'umi';

const intl = useIntl();
const t = (id) => intl.formatMessage({ id });

// 为什么不要直接使用 formatMessage 这个语法糖?
// 虽然 formatMessage 使用起来会非常方便,但是它脱离了 react 的生命周期,最严重的问题就是切换语言时无法触发 dom 重新渲染。为了解决这个问题,我们切换语言时会刷新一下浏览器,用户体验很差,所以推荐大家使用 useIntl 或者 injectIntl,可以实现同样的功能。

import React from 'react';
import { PlusOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import { useIntl } from 'umi';   //国际化
import {
  Button,
  Table,
  Space,
  Form,
  Row,
  Col,
  DatePicker,
  Select,
  Input,
} from 'antd';
import { list } from './dataList';
import './style.less';
import useService from './items';
import {
  ContainerDiv,
  WrapperDiv,
  SearchDiv,
  TableWrapDiv,
  TableTopDiv,
  TableTitleDiv,
  BreadcrumbDiv,
  ButtonDiv,
} from '@/assets/style/bdreport';
import { Breadcrumb } from 'antd';
export default (props: any) => {
  const columns: any = [
    {
      title: '项目名称',
      dataIndex: 'name',
      key: 'name',
      ellipsis: true,
    },
    {
      title: '创建人',
      dataIndex: 'created',
      key: 'created',
      ellipsis: true,
    },
    {
      title: '创建时间',
      dataIndex: 'time',
      key: 'time',
      ellipsis: true,
    },
    {
      title: '状态',
      dataIndex: 'type',
      key: 'type',
      render: (text) => (
        <span>
          {/* 0 已发布,1 待审核,2 已退回*/}
          {text == '0' ? '已发布' : text == '1' ? '待审核' : '已退回'}
        </span>
      ),
    },
    {
      title: '操作',
      dataIndex: 'operation',
      key: 'operation',
      align: 'center',
      width: 250,
      render: () => (
        <Space size="middle">
          <a className="see border_bottom">通过</a>
          <a className="close border_bottom">退回</a>
          <a className="see border_bottom">查看</a>
          <a className="close border_bottom">关闭</a>
          <a className="codeWord border_bottom">口令集</a>
        </Space>
      ),
    },
  ];
  // 设置奇偶行颜色
  const setRowClassName = (record, index) => {
    let rowColor = index % 2 === 0 ? '' : 'even'; //判断单双行,赋予不同样式
    return rowColor;
  };
  const layout: any = {
    requiredMark: true,
    labelCol: { flex: '80px' },
  };
  const { form, formSearch, onChange, onOk } = useService(props);
  const intl = useIntl();
  const t = (id) => intl.formatMessage({ id });
  return (
    <ContainerDiv>
      <BreadcrumbDiv separator=">">
        <Breadcrumb.Item>所有项目</Breadcrumb.Item>
      </BreadcrumbDiv>
      <WrapperDiv>
        <div>{t('language')}</div>
        <SearchDiv>
          <Form form={form} {...layout}>
            <Row gutter={24}>
              {/* <Col span={22}>
                <Row gutter={24}> */}
              <Col xs={24} sm={24} md={24} lg={8} xl={8}>
                <Form.Item label="创建时间">
                  <DatePicker
                    onChange={onChange}
                    onOk={onOk}
                    showTime
                    placeholder="请选择创建时间"
                  />
                </Form.Item>
              </Col>
              <Col xs={24} sm={24} md={24} lg={8} xl={8}>
                <Form.Item label="项目名称">
                  <Select placeholder="请输入项目名称"></Select>
                </Form.Item>
              </Col>
              <Col xs={24} sm={24} md={24} lg={8} xl={8}>
                <Form.Item label="状态">
                  <Select placeholder="请选择状态"></Select>
                </Form.Item>
              </Col>
              <Col xs={24} sm={24} md={24} lg={8} xl={8}>
                <Form.Item label="关键字">
                  <Input placeholder="请输入关键字" />
                </Form.Item>
              </Col>
              {/* </Row>
              </Col> */}
              <Col
                xs={24}
                sm={24}
                md={24}
                lg={16}
                xl={16}
                style={{
                  display: 'flex',
                  alignItems: 'flex-end',
                  justifyContent: 'flex-end',
                }}
              >
                <Button
                  type="primary"
                  htmlType="submit"
                  style={{ marginBottom: 24 }}
                  onClick={formSearch}
                >
                  搜索
                </Button>
                {/* <Button style={{ marginBottom: 24 }} className="reset">
                  重置
                </Button> */}
              </Col>
            </Row>
          </Form>
        </SearchDiv>
        <TableWrapDiv>
          <TableTopDiv>
            <TableTitleDiv>
              <span style={{ verticalAlign: 'middle', paddingRight: 12 }}>
                项目列表
              </span>
            </TableTitleDiv>
            <ButtonDiv>
              <Button icon={<PlusOutlined />}>新建</Button>
            </ButtonDiv>
          </TableTopDiv>
          <div>
            <Table
              rowKey={(record) => `${record.id}${Math.random()}`}
              columns={columns}
              dataSource={list}
              rowClassName={setRowClassName}
            ></Table>
          </div>
        </TableWrapDiv>
      </WrapperDiv>
    </ContainerDiv>
  );
};

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jim-zf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值