diff --git a/src/components/Layout/Bread.js b/src/components/Layout/Bread.js index dad00a8..ed786e9 100644 --- a/src/components/Layout/Bread.js +++ b/src/components/Layout/Bread.js @@ -2,7 +2,7 @@ import React, { PureComponent, Fragment } from 'react' import PropTypes from 'prop-types' import { Breadcrumb } from 'antd' import { Link, withRouter } from 'umi' -import { t } from "@lingui/macro" +import { i18n } from '@lingui/core' import iconMap from 'utils/iconMap' const { pathToRegexp } = require('path-to-regexp') import { queryAncestors } from 'utils' @@ -44,7 +44,7 @@ class Bread extends PureComponent { routeList[0], { id: 404, - name: t`Not Found`, + name: i18n._('Not Found'), }, ] diff --git a/src/components/Layout/Header.js b/src/components/Layout/Header.js index 503d762..08e3b87 100644 --- a/src/components/Layout/Header.js +++ b/src/components/Layout/Header.js @@ -8,7 +8,7 @@ import { MenuFoldOutlined, MenuUnfoldOutlined, } from '@ant-design/icons' -import { Trans } from "@lingui/macro" +import { i18n } from '@lingui/core' import { getLocale, setLocale } from 'utils' import dayjs from 'dayjs' import classnames from 'classnames' @@ -38,16 +38,16 @@ class Header extends PureComponent { label: ( - Hi, + {i18n._('Hi,')} {username} ), - children: [ + children: [ { key: 'SignOut', - label: Sign out, + label: i18n._('Sign out'), }, ], }, @@ -104,7 +104,7 @@ class Header extends PureComponent { itemLayout="horizontal" dataSource={notifications} locale={{ - emptyText: You have viewed all notifications., + emptyText: i18n._('You have viewed all notifications.'), }} renderItem={item => ( @@ -125,7 +125,7 @@ class Header extends PureComponent { onClick={onAllNotificationsRead} className={styles.clearButton} > - Clear notifications + {i18n._('Clear notifications')} ) : null} diff --git a/src/components/Layout/Sider.js b/src/components/Layout/Sider.js index 74c62ef..fcd51e8 100644 --- a/src/components/Layout/Sider.js +++ b/src/components/Layout/Sider.js @@ -1,8 +1,7 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import { Switch, Layout } from 'antd' -import { t } from "@lingui/macro" -import { Trans } from "@lingui/macro" +import { i18n } from '@lingui/core' import { BulbOutlined } from '@ant-design/icons' import ScrollBar from '../ScrollBar' import { config } from 'utils' @@ -58,7 +57,7 @@ class Sider extends PureComponent {
- Switch Theme + {i18n._('Switch Theme')}
)} diff --git a/src/layouts/index.js b/src/layouts/index.js index 05bf758..f116bbe 100644 --- a/src/layouts/index.js +++ b/src/layouts/index.js @@ -4,7 +4,11 @@ import { ConfigProvider } from 'antd' import { i18n } from "@lingui/core" import { I18nProvider } from '@lingui/react' import { getLocale } from 'utils' +import config from 'utils/config' import { zh, en, pt } from 'make-plural/plurals' +import enMessages from '../locales/en/messages.json' +import zhMessages from '../locales/zh/messages.json' +import ptMessages from '../locales/pt-br/messages.json' import zhCN from 'antd/locale/zh_CN' import enUS from 'antd/locale/en_US' import ptBR from 'antd/locale/pt_BR' @@ -17,6 +21,24 @@ i18n.loadLocaleData({ 'pt-br': { plurals: pt } }) +// Activate the default language synchronously so I18nProvider doesn't render `null` in dev. +// Avoid activating the user-selected language here because its messages may not be loaded yet. +const configuredDefault = (config && config.i18n && config.i18n.defaultLanguage) || 'en' +const _catalogs = { + en: enMessages, + zh: zhMessages, + 'pt-br': ptMessages, +} +try { + const initialCatalog = _catalogs[configuredDefault] + if (initialCatalog) { + i18n.load(configuredDefault, initialCatalog) + } + i18n.activate(configuredDefault) +} catch (e) { + // ignore activation errors during bootstrap +} + // antd const languages = { zh: zhCN, @@ -32,15 +54,23 @@ class Layout extends Component { } componentDidMount() { + let language = getLocale() + if (!languages[language]) language = configuredDefault + this.loadCatalog(language).catch(() => {}) } loadCatalog = async (lan) => { - const catalog = await import( - `../locales/${lan}/messages.json` - ) + const language = lan || i18n.defaultLanguage + try { + const catalogModule = await import(`../locales/${language}/messages.json`) + const catalog = catalogModule && catalogModule.default ? catalogModule.default : catalogModule - i18n.load(lan, catalog) - i18n.activate(lan) + i18n.load(language, catalog) + i18n.activate(language) + } catch (err) { + // If loading fails, fall back to default language and log a warning. + console.warn(`Failed to load messages for locale "${language}":`, err) + } } render() { @@ -48,9 +78,7 @@ class Layout extends Component { let language = getLocale() - if (!languages[language]) language = defaultLanguage - - this.loadCatalog(language) + if (!languages[language]) language = configuredDefault return ( diff --git a/src/pages/index.js b/src/pages/index.js index 346f576..4ab73b9 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,10 +1,10 @@ import React, { PureComponent } from 'react' import { Redirect } from 'umi' -import { t } from "@lingui/macro" +import { i18n } from '@lingui/core' class Index extends PureComponent { render() { - return + return } } diff --git a/src/pages/login/index.js b/src/pages/login/index.js index 0944026..9f0688b 100644 --- a/src/pages/login/index.js +++ b/src/pages/login/index.js @@ -4,7 +4,7 @@ import { connect } from 'umi' import { Button, Row, Input, Form } from 'antd' import { GlobalFooter } from 'components' import { GithubOutlined } from '@ant-design/icons' -import { t, Trans } from "@lingui/macro" +import { i18n } from '@lingui/core' import { setLocale } from 'utils' import config from 'utils/config' @@ -54,11 +54,12 @@ class Login extends PureComponent { - +

- Username + {i18n._('Username')} :guest - Password + {i18n._('Password')} :guest

diff --git a/src/pages/post/components/List.js b/src/pages/post/components/List.js index cde1d4a..99411d1 100644 --- a/src/pages/post/components/List.js +++ b/src/pages/post/components/List.js @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react' import { Table, Avatar } from 'antd' -import { t } from "@lingui/macro" +import { i18n } from '@lingui/core' import { Ellipsis } from 'components' import styles from './List.less' @@ -9,12 +9,12 @@ class List extends PureComponent { const { ...tableProps } = this.props const columns = [ { - title: t`Image`, + title: i18n._('Image'), dataIndex: 'image', render: text => , }, { - title: t`Title`, + title: i18n._('Title'), dataIndex: 'title', render: text => ( @@ -23,31 +23,31 @@ class List extends PureComponent { ), }, { - title: t`Author`, + title: i18n._('Author'), dataIndex: 'author', }, { - title: t`Categories`, + title: i18n._('Categories'), dataIndex: 'categories', }, { - title: t`Tags`, + title: i18n._('Tags'), dataIndex: 'tags', }, { - title: t`Visibility`, + title: i18n._('Visibility'), dataIndex: 'visibility', }, { - title: t`Comments`, + title: i18n._('Comments'), dataIndex: 'comments', }, { - title: t`Views`, + title: i18n._('Views'), dataIndex: 'views', }, { - title: t`Publish Date`, + title: i18n._('Publish Date'), dataIndex: 'date', }, ] @@ -57,7 +57,7 @@ class List extends PureComponent { {...tableProps} pagination={{ ...tableProps.pagination, - showTotal: total => t`Total ${total} Items`, + showTotal: total => i18n._('Total {total} Items', { total }), }} bordered scroll={{ x: 1200 }} diff --git a/src/pages/post/index.js b/src/pages/post/index.js index 28c297c..b192ccf 100644 --- a/src/pages/post/index.js +++ b/src/pages/post/index.js @@ -4,7 +4,7 @@ import { connect } from 'umi' import { Tabs } from 'antd' import { history } from 'umi' import { stringify } from 'qs' -import { t } from "@lingui/macro" +import { i18n } from '@lingui/core' import { Page } from 'components' import List from './components/List' @@ -66,12 +66,12 @@ class Post extends PureComponent { items={[ { key: String(EnumPostStatus.PUBLISHED), - label: t`Publised`, + label: i18n._('Publised'), children: , }, { key: String(EnumPostStatus.UNPUBLISH), - label: t`Unpublished`, + label: i18n._('Unpublished'), children: , }, ]} diff --git a/src/pages/request/index.js b/src/pages/request/index.js index 4067926..253c90b 100644 --- a/src/pages/request/index.js +++ b/src/pages/request/index.js @@ -4,7 +4,7 @@ import { apiPrefix } from 'utils/config' import { Row, Col, Select, Form, Input, Button, List, Tag, Checkbox } from 'antd' import classnames from 'classnames' import { CloseOutlined } from '@ant-design/icons' -import { Trans } from "@lingui/macro" +import { i18n } from '@lingui/core' import api from '@/services/api' import { Page } from 'components' @@ -189,7 +189,7 @@ class RequestPage extends React.Component { onClick={this.handleVisible} size="large" > - Params + {i18n._('Params')} @@ -199,7 +199,7 @@ class RequestPage extends React.Component { style={{ width: 100 }} onClick={this.handleRequest} > - Send + {i18n._('Send')}
@@ -242,7 +242,7 @@ class RequestPage extends React.Component { diff --git a/src/pages/user/components/Filter.js b/src/pages/user/components/Filter.js index 74315c8..6374581 100644 --- a/src/pages/user/components/Filter.js +++ b/src/pages/user/components/Filter.js @@ -2,8 +2,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import dayjs from 'dayjs' import { FilterItem } from 'components' -import { Trans } from "@lingui/macro" -import { t } from "@lingui/macro" +import { i18n } from '@lingui/core' import { Button, Row, Col, DatePicker, Form, Input, Cascader } from 'antd' import city from 'utils/city' @@ -84,9 +83,9 @@ class Filter extends Component { + placeholder={i18n._('Search Name')} + onSearch={this.handleSubmit} + /> @@ -110,7 +109,7 @@ class Filter extends Component { sm={{ span: 12 }} id="createTimeRangePicker" > - + - Search + {i18n._('Search')} diff --git a/src/pages/user/components/List.js b/src/pages/user/components/List.js index 8c80a6b..938c7d8 100644 --- a/src/pages/user/components/List.js +++ b/src/pages/user/components/List.js @@ -2,8 +2,7 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import { Table, Modal, Avatar } from 'antd' import { DropOption } from 'components' -import { t } from "@lingui/macro" -import { Trans } from "@lingui/macro" +import { i18n } from '@lingui/core' import { Link } from 'umi' import styles from './List.less' @@ -17,7 +16,7 @@ class List extends PureComponent { onEditItem(record) } else if (e.key === '2') { confirm({ - title: t`Are you sure delete this record?`, + title: i18n._('Are you sure delete this record?'), onOk() { onDeleteItem(record.id) }, @@ -30,7 +29,7 @@ class List extends PureComponent { const columns = [ { - title: Avatar, + title: i18n._('Avatar'), dataIndex: 'avatar', key: 'avatar', width: '7%', @@ -38,51 +37,51 @@ class List extends PureComponent { render: text => , }, { - title: Name, + title: i18n._('Name'), dataIndex: 'name', key: 'name', render: (text, record) => {text}, }, { - title: NickName, + title: i18n._('NickName'), dataIndex: 'nickName', key: 'nickName', }, { - title: Age, + title: i18n._('Age'), dataIndex: 'age', width: '6%', key: 'age', }, { - title: Gender, + title: i18n._('Gender'), dataIndex: 'isMale', key: 'isMale', width: '7%', - render: text => {text ? 'Male' : 'Female'}, + render: text => {text ? i18n._('Male') : i18n._('Female')}, }, { - title: Phone, + title: i18n._('Phone'), dataIndex: 'phone', key: 'phone', }, { - title: Email, + title: i18n._('Email'), dataIndex: 'email', key: 'email', }, { - title: Address, + title: i18n._('Address'), dataIndex: 'address', key: 'address', }, { - title: CreateTime, + title: i18n._('CreateTime'), dataIndex: 'createTime', key: 'createTime', }, { - title: Operation, + title: i18n._('Operation'), key: 'operation', fixed: 'right', width: '8%', @@ -91,8 +90,8 @@ class List extends PureComponent { this.handleMenuClick(record, e)} menuOptions={[ - { key: '1', name: t`Update` }, - { key: '2', name: t`Delete` }, + { key: '1', name: i18n._('Update') }, + { key: '2', name: i18n._('Delete') }, ]} /> ) @@ -105,7 +104,7 @@ class List extends PureComponent { {...tableProps} pagination={{ ...tableProps.pagination, - showTotal: total => t`Total ${total} Items`, + showTotal: total => i18n._('Total {total} Items', { total }), }} className={styles.table} bordered diff --git a/src/pages/user/components/Modal.js b/src/pages/user/components/Modal.js index f0f3c52..b93a2f7 100644 --- a/src/pages/user/components/Modal.js +++ b/src/pages/user/components/Modal.js @@ -1,9 +1,8 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import { Form, Input, InputNumber, Radio, Modal, Cascader } from 'antd' -import { Trans } from "@lingui/macro" +import { i18n } from '@lingui/core' import city from 'utils/city' -import { t } from "@lingui/macro" const FormItem = Form.Item @@ -43,41 +42,41 @@ class UserModal extends PureComponent { + label={i18n._('Name')} hasFeedback {...formItemLayout}> + label={i18n._('NickName')} hasFeedback {...formItemLayout}> + label={i18n._('Gender')} hasFeedback {...formItemLayout}> - Male + {i18n._('Male')} - Female + {i18n._('Female')} - + - + - + + label={i18n._('Address')} hasFeedback {...formItemLayout}> diff --git a/src/pages/user/index.js b/src/pages/user/index.js index 0c27886..aea806f 100644 --- a/src/pages/user/index.js +++ b/src/pages/user/index.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import { history } from 'umi' import { connect } from 'umi' import { Row, Col, Button, Popconfirm } from 'antd' -import { t } from "@lingui/macro" +import { i18n } from '@lingui/core' import { Page } from 'components' import { stringify } from 'qs' import List from './components/List' @@ -58,7 +58,7 @@ class User extends PureComponent { mask: { closable: false }, confirmLoading: loading.effects[`user/${modalType}`], title: `${ - modalType === 'create' ? t`Create User` : t`Update User` + modalType === 'create' ? i18n._('Create User') : i18n._('Update User') }`, centered: true, onOk: data => { diff --git a/src/utils/index.js b/src/utils/index.js index 85ace7c..a33b3bf 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,7 +1,7 @@ import { cloneDeep } from 'lodash' const { pathToRegexp } = require("path-to-regexp") import store from 'store' -import { i18n } from './config' +import { i18n } from '@lingui/core' import dayjs from 'dayjs' import relativeTime from 'dayjs/plugin/relativeTime' @@ -14,8 +14,8 @@ export config from './config' export request from './request' export { Color } from './theme' -export const languages = i18n ? i18n.languages.map(item => item.key) : [] -export const defaultLanguage = i18n ? i18n.defaultLanguage : '' +export const languages = i18n && i18n.languages ? i18n.languages.map(item => item.key) : [] +export const defaultLanguage = i18n && i18n.defaultLanguage ? i18n.defaultLanguage : 'en' /** * Query objects that specify keys and values in an array where all values are objects.